All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] linux-omap-psp: add OCF support
@ 2011-01-05 20:39 Chase Maupin
  2011-01-05 20:39 ` [PATCH 2/3] kernel class: stage ocf directory Chase Maupin
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Chase Maupin @ 2011-01-05 20:39 UTC (permalink / raw)
  To: openembedded-devel; +Cc: Chase Maupin

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3186650 bytes --]

* Add a patch to put OCF support into the linux-omap-psp kernel
  for am37x-evm devices, which is the only device that this has
  been validated on.
* Add support to the defconfig file for am37x-evm for OCF
* Bump the MACHINE_KERNEL_PR

Signed-off-by: Chase Maupin <Chase.Maupin@ti.com>
---
 conf/machine/include/omap3.inc                     |    2 +-
 ...x-omap3-PSP-3.0.1.6-kernel-with-OCF-Linux.patch |88794 ++++++++++++++++++++
 .../linux-omap-psp-2.6.32/am37x-evm/defconfig      |   21 +
 recipes/linux/linux-omap-psp_2.6.32.bb             |    2 +
 4 files changed, 88818 insertions(+), 1 deletions(-)
 create mode 100644 recipes/linux/linux-omap-psp-2.6.32/am37x-evm/0001-linux-omap3-PSP-3.0.1.6-kernel-with-OCF-Linux.patch

diff --git a/conf/machine/include/omap3.inc b/conf/machine/include/omap3.inc
index 36f11b0..9bcfe48 100644
--- a/conf/machine/include/omap3.inc
+++ b/conf/machine/include/omap3.inc
@@ -4,7 +4,7 @@ TARGET_ARCH = "arm"
 require conf/machine/include/tune-cortexa8.inc
 PREFERRED_PROVIDER_virtual/kernel = "linux-omap"
 # Increase this everytime you change something in the kernel
-MACHINE_KERNEL_PR = "r97"
+MACHINE_KERNEL_PR = "r98"
 
 KERNEL_IMAGETYPE = "uImage"
 
diff --git a/recipes/linux/linux-omap-psp-2.6.32/am37x-evm/0001-linux-omap3-PSP-3.0.1.6-kernel-with-OCF-Linux.patch b/recipes/linux/linux-omap-psp-2.6.32/am37x-evm/0001-linux-omap3-PSP-3.0.1.6-kernel-with-OCF-Linux.patch
new file mode 100644
index 0000000..044e3b6
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.32/am37x-evm/0001-linux-omap3-PSP-3.0.1.6-kernel-with-OCF-Linux.patch
@@ -0,0 +1,88794 @@
+From 5cf66ebe920ac1fd26c6cf99ee9aed77acba1434 Mon Sep 17 00:00:00 2001
+From: Greg Turner <gregturner@ti.com>
+Date: Tue, 4 Jan 2011 15:12:06 -0600
+Subject: [PATCH] linux-omap3: PSP 3.0.1.6 kernel with OCF-Linux
+
+* PSP 3.0.1.6 kernel source patched with OCF-Linux 20100325
+* OCF-Linux is from community source code
+* Header file cryptodev.h is moved to include/crypto
+
+Signed-off-by: Greg Turner <gregturner@ti.com>
+---
+ crypto/Kconfig                                     |    3 +
+ crypto/Makefile                                    |    2 +
+ crypto/ocf/Config.in                               |   36 +
+ crypto/ocf/Kconfig                                 |  119 +
+ crypto/ocf/Makefile                                |  124 +
+ crypto/ocf/README                                  |  167 ++
+ crypto/ocf/c7108/Makefile                          |   12 +
+ crypto/ocf/c7108/aes-7108.c                        |  839 ++++++
+ crypto/ocf/c7108/aes-7108.h                        |  134 +
+ crypto/ocf/criov.c                                 |  215 ++
+ crypto/ocf/crypto.c                                | 1784 +++++++++++
+ crypto/ocf/cryptocteon/Makefile                    |   17 +
+ crypto/ocf/cryptocteon/cavium_crypto.c             | 2283 ++++++++++++++
+ crypto/ocf/cryptocteon/cryptocteon.c               |  574 ++++
+ crypto/ocf/cryptodev.c                             | 1061 +++++++
+ crypto/ocf/cryptodev.h                             |  479 +++
+ crypto/ocf/cryptosoft.c                            | 1210 ++++++++
+ crypto/ocf/ep80579/Makefile                        |  119 +
+ crypto/ocf/ep80579/icp_asym.c                      | 1334 +++++++++
+ crypto/ocf/ep80579/icp_common.c                    |  773 +++++
+ crypto/ocf/ep80579/icp_ocf.h                       |  376 +++
+ crypto/ocf/ep80579/icp_sym.c                       | 1153 ++++++++
+ crypto/ocf/hifn/Makefile                           |   13 +
+ crypto/ocf/hifn/hifn7751.c                         | 2976 +++++++++++++++++++
+ crypto/ocf/hifn/hifn7751reg.h                      |  540 ++++
+ crypto/ocf/hifn/hifn7751var.h                      |  369 +++
+ crypto/ocf/hifn/hifnHIPP.c                         |  420 +++
+ crypto/ocf/hifn/hifnHIPPreg.h                      |   46 +
+ crypto/ocf/hifn/hifnHIPPvar.h                      |   93 +
+ crypto/ocf/ixp4xx/Makefile                         |  104 +
+ crypto/ocf/ixp4xx/ixp4xx.c                         | 1324 +++++++++
+ crypto/ocf/kirkwood/Makefile                       |   19 +
+ crypto/ocf/kirkwood/cesa/AES/mvAes.h               |   62 +
+ crypto/ocf/kirkwood/cesa/AES/mvAesAlg.c            |  317 ++
+ crypto/ocf/kirkwood/cesa/AES/mvAesAlg.h            |   19 +
+ crypto/ocf/kirkwood/cesa/AES/mvAesApi.c            |  312 ++
+ crypto/ocf/kirkwood/cesa/mvCesa.c                  | 3126 ++++++++++++++++++++
+ crypto/ocf/kirkwood/cesa/mvCesa.h                  |  412 +++
+ crypto/ocf/kirkwood/cesa/mvCesaDebug.c             |  484 +++
+ crypto/ocf/kirkwood/cesa/mvCesaRegs.h              |  357 +++
+ crypto/ocf/kirkwood/cesa/mvCesaTest.c              | 3096 +++++++++++++++++++
+ crypto/ocf/kirkwood/cesa/mvLru.c                   |  158 +
+ crypto/ocf/kirkwood/cesa/mvLru.h                   |  112 +
+ crypto/ocf/kirkwood/cesa/mvMD5.c                   |  349 +++
+ crypto/ocf/kirkwood/cesa/mvMD5.h                   |   93 +
+ crypto/ocf/kirkwood/cesa/mvSHA1.c                  |  239 ++
+ crypto/ocf/kirkwood/cesa/mvSHA1.h                  |   88 +
+ crypto/ocf/kirkwood/cesa_ocf_drv.c                 | 1296 ++++++++
+ crypto/ocf/kirkwood/mvHal/common/mv802_3.h         |  213 ++
+ crypto/ocf/kirkwood/mvHal/common/mvCommon.c        |  277 ++
+ crypto/ocf/kirkwood/mvHal/common/mvCommon.h        |  308 ++
+ crypto/ocf/kirkwood/mvHal/common/mvDebug.c         |  326 ++
+ crypto/ocf/kirkwood/mvHal/common/mvDebug.h         |  178 ++
+ crypto/ocf/kirkwood/mvHal/common/mvDeviceId.h      |  225 ++
+ crypto/ocf/kirkwood/mvHal/common/mvHalVer.h        |   73 +
+ crypto/ocf/kirkwood/mvHal/common/mvStack.c         |  100 +
+ crypto/ocf/kirkwood/mvHal/common/mvStack.h         |  140 +
+ crypto/ocf/kirkwood/mvHal/common/mvTypes.h         |  245 ++
+ crypto/ocf/kirkwood/mvHal/dbg-trace.c              |  110 +
+ crypto/ocf/kirkwood/mvHal/dbg-trace.h              |   24 +
+ .../mvHal/kw_family/boardEnv/mvBoardEnvLib.c       | 2513 ++++++++++++++++
+ .../mvHal/kw_family/boardEnv/mvBoardEnvLib.h       |  376 +++
+ .../mvHal/kw_family/boardEnv/mvBoardEnvSpec.c      |  848 ++++++
+ .../mvHal/kw_family/boardEnv/mvBoardEnvSpec.h      |  262 ++
+ crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.c    |  320 ++
+ crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.h    |   99 +
+ .../mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c     |  296 ++
+ .../mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h     |  203 ++
+ .../mvHal/kw_family/ctrlEnv/mvCtrlEnvAsm.h         |   98 +
+ .../mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.c         | 1825 ++++++++++++
+ .../mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.h         |  185 ++
+ .../mvHal/kw_family/ctrlEnv/mvCtrlEnvRegs.h        |  419 +++
+ .../mvHal/kw_family/ctrlEnv/mvCtrlEnvSpec.h        |  257 ++
+ .../mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.c      | 1048 +++++++
+ .../mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.h      |  130 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h  |  143 +
+ .../kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.c | 1036 +++++++
+ .../kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.h |  120 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvCpuIfRegs.h      |  304 ++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysAudio.c       |  324 ++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysAudio.h       |  123 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysCesa.c        |  382 +++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysCesa.h        |  100 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysDram.c        |  348 +++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysDram.h        |   80 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysGbe.c         |  658 ++++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysGbe.h         |  113 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysPex.c         | 1697 +++++++++++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysPex.h         |  348 +++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysSata.c        |  430 +++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysSata.h        |  128 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.c       |  427 +++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.h       |  125 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysTdm.c         |  462 +++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysTdm.h         |  106 +
+ .../kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.c |  591 ++++
+ .../kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.h |  110 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysUsb.c         |  497 ++++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysUsb.h         |  125 +
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysXor.c         |  662 +++++
+ .../mvHal/kw_family/ctrlEnv/sys/mvSysXor.h         |  140 +
+ .../ocf/kirkwood/mvHal/kw_family/device/mvDevice.c |   75 +
+ .../ocf/kirkwood/mvHal/kw_family/device/mvDevice.h |   74 +
+ .../kirkwood/mvHal/kw_family/device/mvDeviceRegs.h |  101 +
+ crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.c         |  211 ++
+ crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.h         |  423 +++
+ crypto/ocf/kirkwood/mvHal/linux_oss/mvOsSata.h     |  158 +
+ crypto/ocf/kirkwood/mvHal/mvSysHwConfig.h          |  375 +++
+ crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.c   |  376 +++
+ crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.h   |  121 +
+ .../ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmrRegs.h  |  121 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.c  |  207 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.h  |  213 ++
+ .../ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.c   |  143 +
+ .../ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.h   |  151 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.c   | 1479 +++++++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.h   |  191 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.c | 1599 ++++++++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.h |  179 ++
+ .../kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfConfig.h  |  192 ++
+ .../kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfRegs.h    |  306 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.c   | 1855 ++++++++++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.h   |  172 ++
+ .../kirkwood/mvHal/mv_hal/ddr2/mvDramIfConfig.h    |  157 +
+ .../ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfRegs.h  |  423 +++
+ .../mvHal/mv_hal/ddr2/mvDramIfStaticInit.h         |  179 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.c  | 1474 +++++++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.h  |  192 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEth.c   | 2952 ++++++++++++++++++
+ .../ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.c |  748 +++++
+ .../ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.h |  146 +
+ .../ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthGbe.h   |  751 +++++
+ .../ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthRegs.h  |  700 +++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/eth/mvEth.h       |  356 +++
+ crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.c       |  362 +++
+ crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.h       |  118 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGppRegs.h   |  116 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.c  |  669 +++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.h  |  134 +
+ .../ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIfRegs.h |  245 ++
+ .../mvHal/mv_hal/pci-if/pci_util/mvPciUtils.c      | 1006 +++++++
+ .../mvHal/mv_hal/pci-if/pci_util/mvPciUtils.h      |  323 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.c       | 1047 +++++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.h       |  185 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPciRegs.h   |  411 +++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.c       | 1143 +++++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.h       |  168 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPexRegs.h   |  751 +++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.c |  313 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.h |   82 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.c | 1522 ++++++++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.h |  166 ++
+ .../kirkwood/mvHal/mv_hal/sflash/mvSFlashSpec.h    |  233 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.c       |  576 ++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.h       |   94 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.c   |  249 ++
+ crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.h   |   82 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiSpec.h   |   98 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.c     | 1023 +++++++
+ crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.h     |  121 +
+ crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsiSpec.h |  160 +
+ crypto/ocf/ocf-bench.c                             |  436 +++
+ crypto/ocf/ocf-compat.h                            |  294 ++
+ crypto/ocf/ocfnull/Makefile                        |   12 +
+ crypto/ocf/ocfnull/ocfnull.c                       |  203 ++
+ crypto/ocf/pasemi/Makefile                         |   12 +
+ crypto/ocf/pasemi/pasemi.c                         | 1009 +++++++
+ crypto/ocf/pasemi/pasemi_fnu.h                     |  410 +++
+ crypto/ocf/random.c                                |  322 ++
+ crypto/ocf/rndtest.c                               |  300 ++
+ crypto/ocf/rndtest.h                               |   54 +
+ crypto/ocf/safe/Makefile                           |   12 +
+ crypto/ocf/safe/md5.c                              |  308 ++
+ crypto/ocf/safe/md5.h                              |   76 +
+ crypto/ocf/safe/safe.c                             | 2288 ++++++++++++++
+ crypto/ocf/safe/safereg.h                          |  421 +++
+ crypto/ocf/safe/safevar.h                          |  230 ++
+ crypto/ocf/safe/sha1.c                             |  279 ++
+ crypto/ocf/safe/sha1.h                             |   72 +
+ crypto/ocf/talitos/Makefile                        |   12 +
+ crypto/ocf/talitos/talitos.c                       | 1359 +++++++++
+ crypto/ocf/talitos/talitos_dev.h                   |  277 ++
+ crypto/ocf/talitos/talitos_soft.h                  |   77 +
+ crypto/ocf/uio.h                                   |   54 +
+ drivers/char/random.c                              |   65 +
+ fs/fcntl.c                                         |    1 +
+ include/crypto/cryptodev.h                         |  479 +++
+ include/linux/miscdevice.h                         |    1 +
+ include/linux/random.h                             |   29 +
+ kernel/pid.c                                       |    1 +
+ 190 files changed, 87205 insertions(+), 0 deletions(-)
+ create mode 100644 crypto/ocf/Config.in
+ create mode 100644 crypto/ocf/Kconfig
+ create mode 100644 crypto/ocf/Makefile
+ create mode 100644 crypto/ocf/README
+ create mode 100644 crypto/ocf/c7108/Makefile
+ create mode 100644 crypto/ocf/c7108/aes-7108.c
+ create mode 100644 crypto/ocf/c7108/aes-7108.h
+ create mode 100644 crypto/ocf/criov.c
+ create mode 100644 crypto/ocf/crypto.c
+ create mode 100644 crypto/ocf/cryptocteon/Makefile
+ create mode 100644 crypto/ocf/cryptocteon/cavium_crypto.c
+ create mode 100644 crypto/ocf/cryptocteon/cryptocteon.c
+ create mode 100644 crypto/ocf/cryptodev.c
+ create mode 100644 crypto/ocf/cryptodev.h
+ create mode 100644 crypto/ocf/cryptosoft.c
+ create mode 100644 crypto/ocf/ep80579/Makefile
+ create mode 100644 crypto/ocf/ep80579/icp_asym.c
+ create mode 100644 crypto/ocf/ep80579/icp_common.c
+ create mode 100644 crypto/ocf/ep80579/icp_ocf.h
+ create mode 100644 crypto/ocf/ep80579/icp_sym.c
+ create mode 100644 crypto/ocf/hifn/Makefile
+ create mode 100644 crypto/ocf/hifn/hifn7751.c
+ create mode 100644 crypto/ocf/hifn/hifn7751reg.h
+ create mode 100644 crypto/ocf/hifn/hifn7751var.h
+ create mode 100644 crypto/ocf/hifn/hifnHIPP.c
+ create mode 100644 crypto/ocf/hifn/hifnHIPPreg.h
+ create mode 100644 crypto/ocf/hifn/hifnHIPPvar.h
+ create mode 100644 crypto/ocf/ixp4xx/Makefile
+ create mode 100644 crypto/ocf/ixp4xx/ixp4xx.c
+ create mode 100644 crypto/ocf/kirkwood/Makefile
+ create mode 100644 crypto/ocf/kirkwood/cesa/AES/mvAes.h
+ create mode 100644 crypto/ocf/kirkwood/cesa/AES/mvAesAlg.c
+ create mode 100644 crypto/ocf/kirkwood/cesa/AES/mvAesAlg.h
+ create mode 100644 crypto/ocf/kirkwood/cesa/AES/mvAesApi.c
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvCesa.c
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvCesa.h
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvCesaDebug.c
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvCesaRegs.h
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvCesaTest.c
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvLru.c
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvLru.h
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvMD5.c
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvMD5.h
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvSHA1.c
+ create mode 100644 crypto/ocf/kirkwood/cesa/mvSHA1.h
+ create mode 100644 crypto/ocf/kirkwood/cesa_ocf_drv.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mv802_3.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvCommon.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvCommon.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvDebug.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvDebug.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvDeviceId.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvHalVer.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvStack.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvStack.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/common/mvTypes.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/dbg-trace.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/dbg-trace.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAsm.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvSpec.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIfRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/kw_family/device/mvDeviceRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/linux_oss/mvOsSata.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mvSysHwConfig.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmrRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfConfig.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfConfig.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfStaticInit.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEth.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthGbe.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/eth/mvEth.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGppRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIfRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPciRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPexRegs.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlashSpec.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiSpec.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.c
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.h
+ create mode 100644 crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsiSpec.h
+ create mode 100644 crypto/ocf/ocf-bench.c
+ create mode 100644 crypto/ocf/ocf-compat.h
+ create mode 100644 crypto/ocf/ocfnull/Makefile
+ create mode 100644 crypto/ocf/ocfnull/ocfnull.c
+ create mode 100644 crypto/ocf/pasemi/Makefile
+ create mode 100644 crypto/ocf/pasemi/pasemi.c
+ create mode 100644 crypto/ocf/pasemi/pasemi_fnu.h
+ create mode 100644 crypto/ocf/random.c
+ create mode 100644 crypto/ocf/rndtest.c
+ create mode 100644 crypto/ocf/rndtest.h
+ create mode 100644 crypto/ocf/safe/Makefile
+ create mode 100644 crypto/ocf/safe/md5.c
+ create mode 100644 crypto/ocf/safe/md5.h
+ create mode 100644 crypto/ocf/safe/safe.c
+ create mode 100644 crypto/ocf/safe/safereg.h
+ create mode 100644 crypto/ocf/safe/safevar.h
+ create mode 100644 crypto/ocf/safe/sha1.c
+ create mode 100644 crypto/ocf/safe/sha1.h
+ create mode 100644 crypto/ocf/talitos/Makefile
+ create mode 100644 crypto/ocf/talitos/talitos.c
+ create mode 100644 crypto/ocf/talitos/talitos_dev.h
+ create mode 100644 crypto/ocf/talitos/talitos_soft.h
+ create mode 100644 crypto/ocf/uio.h
+ create mode 100644 include/crypto/cryptodev.h
+
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index 81c185a..9f1c30f 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -822,3 +822,6 @@ config CRYPTO_ANSI_CPRNG
+ source "drivers/crypto/Kconfig"
+
+ endif	# if CRYPTO
++
++source "crypto/ocf/Kconfig"
++
+diff --git a/crypto/Makefile b/crypto/Makefile
+index 9e8f619..79631fc 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -85,6 +85,8 @@ 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/Config.in b/crypto/ocf/Config.in
+new file mode 100644
+index 0000000..d722cba
+--- /dev/null
++++ b/crypto/ocf/Config.in
+@@ -0,0 +1,36 @@
++#############################################################################
++
++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 '  Micronas c7108 (HW crypto engine)' \
++				CONFIG_OCF_C7108 $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 100644
+index 0000000..b9c24ff
+--- /dev/null
++++ b/crypto/ocf/Kconfig
+@@ -0,0 +1,119 @@
++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_CRYPTOCTEON
++	tristate "cryptocteon (HW crypto engine)"
++	depends on OCF_OCF
++	help
++	  OCF driver for the Cavium OCTEON Processors.
++
++config OCF_KIRKWOOD
++	tristate "kirkwood (HW crypto engine)"
++	depends on OCF_OCF
++	help
++	  OCF driver for the Marvell Kirkwood (88F6xxx) Processors.
++
++config OCF_C7108
++	tristate "Micronas 7108 (HW crypto engine)"
++	depends on OCF_OCF
++	help
++	  OCF driver for the Microna 7108 Cipher processors.
++
++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 100644
+index 0000000..fa951f4
+--- /dev/null
++++ b/crypto/ocf/Makefile
+@@ -0,0 +1,124 @@
++# 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_CRYPTOCTEON) += cryptocteon$(_slash)
++$(_obj)-$(CONFIG_OCF_KIRKWOOD) += kirkwood$(_slash)
++$(_obj)-$(CONFIG_OCF_OCFNULL) += ocfnull$(_slash)
++$(_obj)-$(CONFIG_OCF_C7108) += c7108$(_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.33-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/README b/crypto/ocf/README
+new file mode 100644
+index 0000000..5ac39f7
+--- /dev/null
++++ b/crypto/ocf/README
+@@ -0,0 +1,167 @@
++README - ocf-linux-20100325
++---------------------------
++
++This README provides instructions for getting ocf-linux compiled and
++operating in a generic linux environment.  For other information you
++might like to visit the home page for this project:
++
++    http://ocf-linux.sourceforge.net/
++
++Adding OCF to linux
++-------------------
++
++    Not much in this file for now,  just some notes.  I usually build
++    the ocf support as modules but it can be built into the kernel as
++    well.  To use it:
++
++    * mknod /dev/crypto c 10 70
++
++    * to add OCF to your kernel source,  you have two options.  Apply
++      the kernel specific patch:
++
++          cd linux-2.4*; gunzip < ocf-linux-24-XXXXXXXX.patch.gz | patch -p1
++          cd linux-2.6*; gunzip < ocf-linux-26-XXXXXXXX.patch.gz | patch -p1
++
++      if you do one of the above,  then you can proceed to the next step,
++      or you can do the above process by hand with using the patches against
++      linux-2.4.35 and 2.6.33 to include the ocf code under crypto/ocf.
++      Here's how to add it:
++
++      for 2.4.35 (and later)
++
++          cd linux-2.4.35/crypto
++          tar xvzf ocf-linux.tar.gz
++          cd ..
++          patch -p1 < crypto/ocf/patches/linux-2.4.35-ocf.patch
++
++      for 2.6.23 (and later),  find the kernel patch specific (or nearest)
++      to your kernel versions and then:
++
++          cd linux-2.6.NN/crypto
++          tar xvzf ocf-linux.tar.gz
++          cd ..
++          patch -p1 < crypto/ocf/patches/linux-2.6.NN-ocf.patch
++
++      It should be easy to take this patch and apply it to other more
++      recent versions of the kernels.  The same patches should also work
++      relatively easily on kernels as old as 2.6.11 and 2.4.18.
++
++    * under 2.4 if you are on a non-x86 platform,  you may need to:
++
++        cp linux-2.X.x/include/asm-i386/kmap_types.h linux-2.X.x/include/asm-YYY
++
++      so that you can build the kernel crypto support needed for the cryptosoft
++      driver.
++
++    * For simplicity you should enable all the crypto support in your kernel
++      except for the test driver.  Likewise for the OCF options.  Do not
++      enable OCF crypto drivers for HW that you do not have (for example
++      ixp4xx will not compile on non-Xscale systems).
++
++    * make sure that cryptodev.h (from ocf-linux.tar.gz) is installed as
++      crypto/cryptodev.h in an include directory that is used for building
++      applications for your platform.  For example on a host system that
++      might be:
++
++              /usr/include/crypto/cryptodev.h
++
++    * patch your openssl-0.9.8n code with the openssl-0.9.8n.patch.
++      (NOTE: there is no longer a need to patch ssh). The patch is against:
++      openssl-0_9_8e
++
++      If you need a patch for an older version of openssl,  you should look
++      to older OCF releases.  This patch is unlikely to work on older
++      openssl versions.
++
++      openssl-0.9.8n.patch
++                - enables --with-cryptodev for non BSD systems
++                - adds -cpu option to openssl speed for calculating CPU load
++                  under linux
++                - fixes null pointer in openssl speed multi thread output.
++                - fixes test keys to work with linux crypto's more stringent
++                  key checking.
++                - adds MD5/SHA acceleration (Ronen Shitrit), only enabled
++                  with the --with-cryptodev-digests option
++                - fixes bug in engine code caching.
++
++    * build crypto-tools-XXXXXXXX.tar.gz if you want to try some of the BSD
++      tools for testing OCF (ie., cryptotest).
++
++How to load the OCF drivers
++---------------------------
++
++    First insert the base modules:
++
++        insmod ocf
++        insmod cryptodev
++
++    You can then install the software OCF driver with:
++
++        insmod cryptosoft
++
++    and one or more of the OCF HW drivers with:
++
++        insmod safe
++        insmod hifn7751
++        insmod ixp4xx
++        ...
++
++    all the drivers take a debug option to enable verbose debug so that
++    you can see what is going on.  For debug you load them as:
++
++        insmod ocf crypto_debug=1
++        insmod cryptodev cryptodev_debug=1
++        insmod cryptosoft swcr_debug=1
++
++    You may load more than one OCF crypto driver but then there is no guarantee
++    as to which will be used.
++
++    You can also enable debug at run time on 2.6 systems with the following:
++
++        echo 1 > /sys/module/ocf/parameters/crypto_debug
++        echo 1 > /sys/module/cryptodev/parameters/cryptodev_debug
++        echo 1 > /sys/module/cryptosoft/parameters/swcr_debug
++        echo 1 > /sys/module/hifn7751/parameters/hifn_debug
++        echo 1 > /sys/module/safe/parameters/safe_debug
++        echo 1 > /sys/module/ixp4xx/parameters/ixp_debug
++        ...
++
++Testing the OCF support
++-----------------------
++
++    run "cryptotest",  it should do a short test for a couple of
++    des packets.  If it does everything is working.
++
++    If this works,  then ssh will use the driver when invoked as:
++
++        ssh -c 3des username@host
++
++    to see for sure that it is operating, enable debug as defined above.
++
++    To get a better idea of performance run:
++
++        cryptotest 100 4096
++
++    There are more options to cryptotest,  see the help.
++
++    It is also possible to use openssl to test the speed of the crypto
++    drivers.
++
++        openssl speed -evp des -engine cryptodev -elapsed
++        openssl speed -evp des3 -engine cryptodev -elapsed
++        openssl speed -evp aes128 -engine cryptodev -elapsed
++
++    and multiple threads (10) with:
++
++        openssl speed -evp des -engine cryptodev -elapsed -multi 10
++        openssl speed -evp des3 -engine cryptodev -elapsed -multi 10
++        openssl speed -evp aes128 -engine cryptodev -elapsed -multi 10
++
++    for public key testing you can try:
++
++        cryptokeytest
++        openssl speed -engine cryptodev rsa -elapsed
++        openssl speed -engine cryptodev dsa -elapsed
++
++David McCullough
++david_mccullough@mcafee.com
+diff --git a/crypto/ocf/c7108/Makefile b/crypto/ocf/c7108/Makefile
+new file mode 100644
+index 0000000..e7e634b
+--- /dev/null
++++ b/crypto/ocf/c7108/Makefile
+@@ -0,0 +1,12 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++obj-$(CONFIG_OCF_C7108) += aes-7108.o
++
++obj ?= .
++EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff --git a/crypto/ocf/c7108/aes-7108.c b/crypto/ocf/c7108/aes-7108.c
+new file mode 100644
+index 0000000..a5ac054
+--- /dev/null
++++ b/crypto/ocf/c7108/aes-7108.c
+@@ -0,0 +1,839 @@
++/*
++ * Copyright (C) 2006 Micronas USA
++ *
++ * 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.
++ *
++ */
++
++//#include <linux/config.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/io.h>
++#include <asm/delay.h>
++//#include <asm/scatterlist.h>
++#include <linux/scatterlist.h>
++#include <linux/dma-mapping.h>
++#include <linux/highmem.h>
++#include <cryptodev.h>
++#include <uio.h>
++#include <aes-7108.h>
++
++/* Runtime mode */
++static int c7108_crypto_mode = C7108_AES_CTRL_MODE_CTR;
++//static int c7108_crypto_mode = C7108_AES_CTRL_MODE_CBC;
++
++static int32_t c7108_id = -1;
++static struct cipher_7108 **c7108_sessions = NULL;
++static u_int32_t c7108_sesnum = 0;
++static unsigned long iobar;
++
++/* Crypto entry points */
++static	int c7108_process(void *, struct cryptop *, int);
++static	int c7108_newsession(void *, u_int32_t *, struct cryptoini *);
++static	int c7108_freesession(void *, u_int64_t);
++
++/* Globals */
++static int debug = 0;
++static spinlock_t csr_mutex;
++
++/* Generic controller-based lock */
++#define AES_LOCK()\
++          spin_lock(&csr_mutex)
++#define AES_UNLOCK()\
++          spin_unlock(&csr_mutex)
++
++/* 7108 AES register access */
++#define c7108_reg_wr8(a,d)   iowrite8(d, (void*)(iobar+(a)))
++#define c7108_reg_wr16(a,d)  iowrite16(d, (void*)(iobar+(a)))
++#define c7108_reg_wr32(a,d)  iowrite32(d, (void*)(iobar+(a)))
++#define c7108_reg_rd8(a)     ioread8((void*)(iobar+(a)))
++#define c7108_reg_rd16(a)    ioread16((void*)(iobar+(a)))
++#define c7108_reg_rd32(a)    ioread32((void*)(iobar+(a)))
++
++static int
++c7108_xlate_key(int klen, u8* k8ptr, u32* k32ptr)
++{
++        int i, nw=0;
++	nw = ((klen >= 256) ? 8 : (klen >= 192) ? 6 : 4);
++	for ( i = 0; i < nw; i++) {
++	    k32ptr[i] =    (k8ptr[i+3] << 24) | (k8ptr[i+2] << 16) |
++		           (k8ptr[i+1] << 8)  | k8ptr[i];
++
++	}
++	return 0;
++}
++
++static int
++c7108_cache_key(int klen, u32* k32ptr, u8* k8ptr)
++{
++        int i, nb=0;
++	u8* ptr = (u8*)k32ptr;
++	nb = ((klen >= 256) ? 32 : (klen >= 192) ? 24 : 16);
++	for ( i = 0; i < nb; i++)
++	    k8ptr[i] = ptr[i];
++	return 0;
++}
++
++static int
++c7108_aes_setup_dma(u32 src, u32 dst, u32 len)
++{
++        if (len < 16) {
++	    printk("len < 16\n");
++	    return -10;
++	}
++	if (len % 16) {
++	    printk("len not multiple of 16\n");
++	    return -11;
++	}
++	c7108_reg_wr16(C7108_AES_DMA_SRC0_LO, (u16) src);
++	c7108_reg_wr16(C7108_AES_DMA_SRC0_HI, (u16)((src & 0xffff0000) >> 16));
++	c7108_reg_wr16(C7108_AES_DMA_DST0_LO, (u16) dst);
++	c7108_reg_wr16(C7108_AES_DMA_DST0_HI, (u16)((dst & 0xffff0000) >> 16));
++	c7108_reg_wr16(C7108_AES_DMA_LEN, (u16) ((len / 16) - 1));
++
++	return 0;
++}
++
++static int
++c7108_aes_set_hw_iv(u8 iv[16])
++{
++        c7108_reg_wr16(C7108_AES_IV0_LO, (u16) ((iv[1] << 8) | iv[0]));
++	c7108_reg_wr16(C7108_AES_IV0_HI, (u16) ((iv[3] << 8) | iv[2]));
++	c7108_reg_wr16(C7108_AES_IV1_LO, (u16) ((iv[5] << 8) | iv[4]));
++	c7108_reg_wr16(C7108_AES_IV1_HI, (u16) ((iv[7] << 8) | iv[6]));
++	c7108_reg_wr16(C7108_AES_IV2_LO, (u16) ((iv[9] << 8) | iv[8]));
++	c7108_reg_wr16(C7108_AES_IV2_HI, (u16) ((iv[11] << 8) | iv[10]));
++	c7108_reg_wr16(C7108_AES_IV3_LO, (u16) ((iv[13] << 8) | iv[12]));
++	c7108_reg_wr16(C7108_AES_IV3_HI, (u16) ((iv[15] << 8) | iv[14]));
++
++    return 0;
++}
++
++static void
++c7108_aes_read_dkey(u32 * dkey)
++{
++        dkey[0] = (c7108_reg_rd16(C7108_AES_EKEY0_HI) << 16) |
++	           c7108_reg_rd16(C7108_AES_EKEY0_LO);
++	dkey[1] = (c7108_reg_rd16(C7108_AES_EKEY1_HI) << 16) |
++	           c7108_reg_rd16(C7108_AES_EKEY1_LO);
++	dkey[2] = (c7108_reg_rd16(C7108_AES_EKEY2_HI) << 16) |
++	           c7108_reg_rd16(C7108_AES_EKEY2_LO);
++	dkey[3] = (c7108_reg_rd16(C7108_AES_EKEY3_HI) << 16) |
++	           c7108_reg_rd16(C7108_AES_EKEY3_LO);
++	dkey[4] = (c7108_reg_rd16(C7108_AES_EKEY4_HI) << 16) |
++                   c7108_reg_rd16(C7108_AES_EKEY4_LO);
++	dkey[5] = (c7108_reg_rd16(C7108_AES_EKEY5_HI) << 16) |
++                   c7108_reg_rd16(C7108_AES_EKEY5_LO);
++	dkey[6] = (c7108_reg_rd16(C7108_AES_EKEY6_HI) << 16) |
++                   c7108_reg_rd16(C7108_AES_EKEY6_LO);
++	dkey[7] = (c7108_reg_rd16(C7108_AES_EKEY7_HI) << 16) |
++                   c7108_reg_rd16(C7108_AES_EKEY7_LO);
++}
++
++static int
++c7108_aes_cipher(int op,
++		 u32 dst,
++		 u32 src,
++		 u32 len,
++		 int klen,
++		 u16 mode,
++		 u32 key[8],
++		 u8 iv[16])
++{
++        int rv = 0, cnt=0;
++	u16 ctrl = 0, stat = 0;
++
++	AES_LOCK();
++
++	/* Setup key length */
++	if (klen == 128) {
++	    ctrl |= C7108_AES_KEY_LEN_128;
++	} else if (klen == 192) {
++	    ctrl |= C7108_AES_KEY_LEN_192;
++	} else if (klen == 256) {
++	    ctrl |= C7108_AES_KEY_LEN_256;
++	} else {
++	    AES_UNLOCK();
++	    return -3;
++	}
++
++	/* Check opcode */
++	if (C7108_AES_ENCRYPT == op) {
++	    ctrl |= C7108_AES_ENCRYPT;
++	} else if (C7108_AES_DECRYPT == op) {
++	    ctrl |= C7108_AES_DECRYPT;
++	} else {
++	    AES_UNLOCK();
++	    return -4;
++	}
++
++	/* check mode */
++	if ( (mode != C7108_AES_CTRL_MODE_CBC) &&
++	     (mode != C7108_AES_CTRL_MODE_CFB) &&
++	     (mode != C7108_AES_CTRL_MODE_OFB) &&
++	     (mode != C7108_AES_CTRL_MODE_CTR) &&
++	     (mode != C7108_AES_CTRL_MODE_ECB) ) {
++	    AES_UNLOCK();
++	    return -5;
++	}
++
++	/* Now set mode */
++	ctrl |= mode;
++
++	/* For CFB, OFB, and CTR, neither backward key
++	 * expansion nor key inversion is required.
++	 */
++	if ( (C7108_AES_DECRYPT == op) &&
++	     (C7108_AES_CTRL_MODE_CBC == mode ||
++	      C7108_AES_CTRL_MODE_ECB == mode ) ){
++
++	    /* Program Key */
++	    c7108_reg_wr16(C7108_AES_KEY0_LO, (u16) key[4]);
++	    c7108_reg_wr16(C7108_AES_KEY0_HI, (u16) (key[4] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY1_LO, (u16) key[5]);
++	    c7108_reg_wr16(C7108_AES_KEY1_HI, (u16) (key[5] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY2_LO, (u16) key[6]);
++	    c7108_reg_wr16(C7108_AES_KEY2_HI, (u16) (key[6] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY3_LO, (u16) key[7]);
++	    c7108_reg_wr16(C7108_AES_KEY3_HI, (u16) (key[7] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY6_LO, (u16) key[2]);
++	    c7108_reg_wr16(C7108_AES_KEY6_HI, (u16) (key[2] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY7_LO, (u16) key[3]);
++	    c7108_reg_wr16(C7108_AES_KEY7_HI, (u16) (key[3] >> 16));
++
++
++	    if (192 == klen) {
++		c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[7]);
++		c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[7] >> 16));
++		c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[7]);
++		c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[7] >> 16));
++
++	    } else if (256 == klen) {
++		/* 256 */
++		c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[0]);
++		c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[0] >> 16));
++		c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[1]);
++		c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[1] >> 16));
++
++	    }
++
++	} else {
++	    /* Program Key */
++	    c7108_reg_wr16(C7108_AES_KEY0_LO, (u16) key[0]);
++	    c7108_reg_wr16(C7108_AES_KEY0_HI, (u16) (key[0] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY1_LO, (u16) key[1]);
++	    c7108_reg_wr16(C7108_AES_KEY1_HI, (u16) (key[1] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY2_LO, (u16) key[2]);
++	    c7108_reg_wr16(C7108_AES_KEY2_HI, (u16) (key[2] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY3_LO, (u16) key[3]);
++	    c7108_reg_wr16(C7108_AES_KEY3_HI, (u16) (key[3] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[4]);
++	    c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[4] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[5]);
++	    c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[5] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY6_LO, (u16) key[6]);
++	    c7108_reg_wr16(C7108_AES_KEY6_HI, (u16) (key[6] >> 16));
++	    c7108_reg_wr16(C7108_AES_KEY7_LO, (u16) key[7]);
++	    c7108_reg_wr16(C7108_AES_KEY7_HI, (u16) (key[7] >> 16));
++
++	}
++
++	/* Set IV always */
++	c7108_aes_set_hw_iv(iv);
++
++	/* Program DMA addresses */
++	if ((rv = c7108_aes_setup_dma(src, dst, len)) < 0) {
++	    AES_UNLOCK();
++	    return rv;
++	}
++
++
++	/* Start AES cipher */
++	c7108_reg_wr16(C7108_AES_CTRL, ctrl | C7108_AES_GO);
++
++	//printk("Ctrl: 0x%x\n", ctrl | C7108_AES_GO);
++	do {
++	    /* TODO: interrupt mode */
++	    //        printk("aes_stat=0x%x\n", stat);
++	    //udelay(100);
++	} while ((cnt++ < 1000000) &&
++		 !((stat=c7108_reg_rd16(C7108_AES_CTRL))&C7108_AES_OP_DONE));
++
++
++	if ((mode == C7108_AES_CTRL_MODE_ECB)||
++	    (mode == C7108_AES_CTRL_MODE_CBC)) {
++	    /* Save out key when the lock is held ... */
++	    c7108_aes_read_dkey(key);
++	}
++
++	AES_UNLOCK();
++	return 0;
++
++}
++
++/*
++ * Generate a new crypto device session.
++ */
++static int
++c7108_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
++{
++	struct cipher_7108 **swd;
++	u_int32_t i;
++	char *algo;
++	int mode, xfm_type;
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid == NULL || cri == NULL) {
++		dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	if (c7108_sessions) {
++		for (i = 1; i < c7108_sesnum; i++)
++			if (c7108_sessions[i] == NULL)
++				break;
++	} else
++		i = 1;		/* NB: to silence compiler warning */
++
++	if (c7108_sessions == NULL || i == c7108_sesnum) {
++	    if (c7108_sessions == NULL) {
++		i = 1; /* We leave c7108_sessions[0] empty */
++		c7108_sesnum = CRYPTO_SW_SESSIONS;
++	    } else
++		c7108_sesnum *= 2;
++
++	    swd = kmalloc(c7108_sesnum * sizeof(struct cipher_7108 *),
++			  GFP_ATOMIC);
++	    if (swd == NULL) {
++		/* Reset session number */
++		if (c7108_sesnum == CRYPTO_SW_SESSIONS)
++		    c7108_sesnum = 0;
++		else
++		    c7108_sesnum /= 2;
++		dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
++		return ENOBUFS;
++	    }
++	    memset(swd, 0, c7108_sesnum * sizeof(struct cipher_7108 *));
++
++	    /* Copy existing sessions */
++	    if (c7108_sessions) {
++		memcpy(swd, c7108_sessions,
++		       (c7108_sesnum / 2) * sizeof(struct cipher_7108 *));
++		kfree(c7108_sessions);
++	    }
++
++	    c7108_sessions = swd;
++
++	}
++
++	swd = &c7108_sessions[i];
++	*sid = i;
++
++	while (cri) {
++		*swd = (struct cipher_7108 *)
++		    kmalloc(sizeof(struct cipher_7108), GFP_ATOMIC);
++		if (*swd == NULL) {
++		    c7108_freesession(NULL, i);
++		    dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		    return ENOBUFS;
++		}
++		memset(*swd, 0, sizeof(struct cipher_7108));
++
++		algo = NULL;
++		mode = 0;
++		xfm_type = HW_TYPE_CIPHER;
++
++		switch (cri->cri_alg) {
++
++		case CRYPTO_AES_CBC:
++			algo = "aes";
++			mode = CRYPTO_TFM_MODE_CBC;
++			c7108_crypto_mode = C7108_AES_CTRL_MODE_CBC;
++			break;
++#if 0
++		case CRYPTO_AES_CTR:
++			algo = "aes_ctr";
++			mode = CRYPTO_TFM_MODE_CBC;
++			c7108_crypto_mode = C7108_AES_CTRL_MODE_CTR;
++			break;
++		case CRYPTO_AES_ECB:
++			algo = "aes_ecb";
++			mode = CRYPTO_TFM_MODE_CBC;
++			c7108_crypto_mode = C7108_AES_CTRL_MODE_ECB;
++			break;
++		case CRYPTO_AES_OFB:
++			algo = "aes_ofb";
++			mode = CRYPTO_TFM_MODE_CBC;
++			c7108_crypto_mode = C7108_AES_CTRL_MODE_OFB;
++			break;
++		case CRYPTO_AES_CFB:
++			algo = "aes_cfb";
++			mode = CRYPTO_TFM_MODE_CBC;
++			c7108_crypto_mode = C7108_AES_CTRL_MODE_CFB;
++			break;
++#endif
++		default:
++		        printk("unsupported crypto algorithm: %d\n",
++			       cri->cri_alg);
++			return -EINVAL;
++			break;
++		}
++
++
++		if (!algo || !*algo) {
++		    printk("cypher_7108_crypto: Unknown algo 0x%x\n",
++			   cri->cri_alg);
++		    c7108_freesession(NULL, i);
++		    return EINVAL;
++		}
++
++		if (xfm_type == HW_TYPE_CIPHER) {
++		    if (debug) {
++			dprintk("%s key:", __FUNCTION__);
++			for (i = 0; i < (cri->cri_klen + 7) / 8; i++)
++			    dprintk("%s0x%02x", (i % 8) ? " " : "\n    ",
++				    cri->cri_key[i]);
++			dprintk("\n");
++		    }
++
++		} else if (xfm_type == SW_TYPE_HMAC ||
++			   xfm_type == SW_TYPE_HASH) {
++		    printk("cypher_7108_crypto: HMAC unsupported!\n");
++		    return -EINVAL;
++		    c7108_freesession(NULL, i);
++		} else {
++		    printk("cypher_7108_crypto: "
++			   "Unhandled xfm_type %d\n", xfm_type);
++		    c7108_freesession(NULL, i);
++		    return EINVAL;
++		}
++
++		(*swd)->cri_alg = cri->cri_alg;
++		(*swd)->xfm_type = xfm_type;
++
++		cri = cri->cri_next;
++		swd = &((*swd)->next);
++	}
++	return 0;
++}
++
++/*
++ * Free a session.
++ */
++static int
++c7108_freesession(void *arg, u_int64_t tid)
++{
++	struct cipher_7108 *swd;
++	u_int32_t sid = CRYPTO_SESID2LID(tid);
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid > c7108_sesnum || c7108_sessions == NULL ||
++			c7108_sessions[sid] == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return(EINVAL);
++	}
++
++	/* Silently accept and return */
++	if (sid == 0)
++		return(0);
++
++	while ((swd = c7108_sessions[sid]) != NULL) {
++		c7108_sessions[sid] = swd->next;
++		kfree(swd);
++	}
++	return 0;
++}
++
++/*
++ * Process a hardware request.
++ */
++static int
++c7108_process(void *arg, struct cryptop *crp, int hint)
++{
++	struct cryptodesc *crd;
++	struct cipher_7108 *sw;
++	u_int32_t lid;
++	int type;
++	u32 hwkey[8];
++
++#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 >= c7108_sesnum || lid == 0 || c7108_sessions == NULL ||
++			c7108_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 = c7108_sessions[lid];
++		 sw && sw->cri_alg != crd->crd_alg;
++		 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;
++		type = CRYPTO_BUF_SKBUF;
++
++		sg_num = 0;
++		sg_len = 0;
++
++		if (skip < skb_headlen(skb)) {
++		    //sg[sg_num].page   = virt_to_page(skb->data + skip);
++			//sg[sg_num].offset = offset_in_page(skb->data + skip);
++		    len = skb_headlen(skb) - skip;
++		    if (len + sg_len > crd->crd_len)
++			len = crd->crd_len - sg_len;
++		    //sg[sg_num].length = len;
++		    sg_set_page(&sg[sg_num], virt_to_page(skb->data + skip), len, offset_in_page(skb->data + skip));
++			sg_len += sg[sg_num].length;
++		    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) {
++			//sg[sg_num].page   = skb_shinfo(skb)->frags[i].page;
++			//sg[sg_num].offset = skb_shinfo(skb)->frags[i].page_offset + skip;
++			len = skb_shinfo(skb)->frags[i].size - skip;
++			if (len + sg_len > crd->crd_len)
++			    len = crd->crd_len - sg_len;
++			//sg[sg_num].length = len;
++			sg_set_page(&sg[sg_num], skb_shinfo(skb)->frags[i].page, len, skb_shinfo(skb)->frags[i].page_offset + skip);
++			sg_len += sg[sg_num].length;
++			sg_num++;
++			skip = 0;
++		    } else
++			skip -= skb_shinfo(skb)->frags[i].size;
++		}
++	    } else if (crp->crp_flags & CRYPTO_F_IOV) {
++		int len;
++		type = CRYPTO_BUF_IOV;
++		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) {
++			//sg[sg_num].page   =			    virt_to_page(uiop->uio_iov[sg_num].iov_base+skip);
++			//sg[sg_num].offset =			   offset_in_page(uiop->uio_iov[sg_num].iov_base+skip);
++			len = uiop->uio_iov[sg_num].iov_len - skip;
++			if (len + sg_len > crd->crd_len)
++			    len = crd->crd_len - sg_len;
++			//sg[sg_num].length = 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 += sg[sg_num].length;
++			skip = 0;
++		    } else
++			skip -= uiop->uio_iov[sg_num].iov_len;
++		}
++	    } else {
++		type = CRYPTO_BUF_CONTIG;
++		//sg[0].page   = virt_to_page(crp->crp_buf + skip);
++		//sg[0].offset = offset_in_page(crp->crp_buf + skip);
++		sg_len = (crp->crp_ilen - skip);
++		if (sg_len > crd->crd_len)
++		    sg_len = crd->crd_len;
++		//sg[0].length = sg_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->xfm_type) {
++
++	    case HW_TYPE_CIPHER: {
++
++		unsigned char iv[64];
++		unsigned char *ivp = iv;
++		int i;
++		int ivsize = 16;    /* fixed for AES */
++		int blocksize = 16; /* fixed for AES */
++
++		if (sg_len < blocksize) {
++		    crp->crp_etype = EINVAL;
++		    dprintk("%s,%d: EINVAL len %d < %d\n",
++			    __FILE__, __LINE__,
++			    sg_len,
++			    blocksize);
++		    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_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_buf,
++					  crd->crd_inject,
++					  ivsize,
++					  (caddr_t)ivp);
++		    }
++
++		    c7108_xlate_key(crd->crd_klen,
++				    (u8*)crd->crd_key, (u32*)hwkey);
++
++		    /* Encrypt SG list */
++		    for (i = 0; i < sg_num; i++) {
++			sg[i].dma_address =
++			    dma_map_single(NULL,
++					   kmap(sg_page(&sg[i])) + sg[i].offset, sg_len, DMA_BIDIRECTIONAL);
++#if 0
++			printk("sg[%d]:0x%08x, off 0x%08x "
++			       "kmap 0x%08x phys 0x%08x\n",
++			       i, sg[i].page, sg[i].offset,
++			       kmap(sg[i].page) + sg[i].offset,
++			       sg[i].dma_address);
++#endif
++			c7108_aes_cipher(C7108_AES_ENCRYPT,
++					 sg[i].dma_address,
++					 sg[i].dma_address,
++					 sg_len,
++					 crd->crd_klen,
++					 c7108_crypto_mode,
++					 hwkey,
++					 ivp);
++
++			if ((c7108_crypto_mode == C7108_AES_CTRL_MODE_CBC)||
++			    (c7108_crypto_mode == C7108_AES_CTRL_MODE_ECB)) {
++			    /* Read back expanded key and cache it in key
++			     * context.
++			     * NOTE: for ECB/CBC modes only (not CTR, CFB, OFB)
++			     *       where you set the key once.
++			     */
++			    c7108_cache_key(crd->crd_klen,
++					    (u32*)hwkey, (u8*)crd->crd_key);
++#if 0
++			    printk("%s expanded key:", __FUNCTION__);
++			    for (i = 0; i < (crd->crd_klen + 7) / 8; i++)
++				printk("%s0x%02x", (i % 8) ? " " : "\n    ",
++				       crd->crd_key[i]);
++			    printk("\n");
++#endif
++			}
++		    }
++		}
++		else { /*decrypt */
++
++		    if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
++			ivp = crd->crd_iv;
++		    } else {
++			crypto_copydata(crp->crp_buf, crd->crd_inject,
++				  ivsize, (caddr_t)ivp);
++		    }
++
++		    c7108_xlate_key(crd->crd_klen,
++				    (u8*)crd->crd_key, (u32*)hwkey);
++
++		    /* Decrypt SG list */
++		    for (i = 0; i < sg_num; i++) {
++			sg[i].dma_address =
++			    dma_map_single(NULL,
++					   kmap(sg_page(&sg[i])) + sg[i].offset,
++					   sg_len, DMA_BIDIRECTIONAL);
++
++#if 0
++			printk("sg[%d]:0x%08x, off 0x%08x "
++			       "kmap 0x%08x phys 0x%08x\n",
++			       i, sg[i].page, sg[i].offset,
++			       kmap(sg[i].page) + sg[i].offset,
++			       sg[i].dma_address);
++#endif
++			c7108_aes_cipher(C7108_AES_DECRYPT,
++					 sg[i].dma_address,
++					 sg[i].dma_address,
++					 sg_len,
++					 crd->crd_klen,
++					 c7108_crypto_mode,
++					 hwkey,
++					 ivp);
++		    }
++		}
++	    } break;
++	    case SW_TYPE_HMAC:
++	    case SW_TYPE_HASH:
++		crp->crp_etype = EINVAL;
++		goto done;
++		break;
++
++	    case SW_TYPE_COMP:
++		crp->crp_etype = EINVAL;
++		goto done;
++		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 struct {
++	softc_device_decl sc_dev;
++} a7108dev;
++
++static device_method_t a7108_methods = {
++/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession, c7108_newsession),
++	DEVMETHOD(cryptodev_freesession, c7108_freesession),
++	DEVMETHOD(cryptodev_process, c7108_process),
++	DEVMETHOD(cryptodev_kprocess, NULL)
++};
++
++static int
++cypher_7108_crypto_init(void)
++{
++	dprintk("%s(%p)\n", __FUNCTION__, cypher_7108_crypto_init);
++
++	iobar = (unsigned long)ioremap(CCU_AES_REG_BASE, 0x4000);
++	printk("7108: AES @ 0x%08x (0x%08x phys) %s mode\n",
++	       iobar, CCU_AES_REG_BASE,
++	       c7108_crypto_mode & C7108_AES_CTRL_MODE_CBC ? "CBC" :
++	       c7108_crypto_mode & C7108_AES_CTRL_MODE_ECB ? "ECB" :
++	       c7108_crypto_mode & C7108_AES_CTRL_MODE_CTR ? "CTR" :
++	       c7108_crypto_mode & C7108_AES_CTRL_MODE_CFB ? "CFB" :
++	       c7108_crypto_mode & C7108_AES_CTRL_MODE_OFB ? "OFB" : "???");
++	csr_mutex  = SPIN_LOCK_UNLOCKED;
++
++	memset(&a7108dev, 0, sizeof(a7108dev));
++	softc_device_init(&a7108dev, "aes7108", 0, a7108_methods);
++
++		c7108_id = crypto_get_driverid(softc_get_device(&a7108dev), CRYPTOCAP_F_HARDWARE);
++	if (c7108_id < 0)
++		panic("7108: crypto device cannot initialize!");
++
++//	crypto_register(c7108_id, CRYPTO_AES_CBC, 0, 0, c7108_newsession, c7108_freesession, c7108_process, NULL);
++	crypto_register(c7108_id, CRYPTO_AES_CBC, 0, 0);
++
++	return(0);
++}
++
++static void
++cypher_7108_crypto_exit(void)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	crypto_unregister_all(c7108_id);
++	c7108_id = -1;
++}
++
++module_init(cypher_7108_crypto_init);
++module_exit(cypher_7108_crypto_exit);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_DESCRIPTION("Cypher 7108 Crypto (OCF module for kernel crypto)");
+diff --git a/crypto/ocf/c7108/aes-7108.h b/crypto/ocf/c7108/aes-7108.h
+new file mode 100644
+index 0000000..0c7bfcb
+--- /dev/null
++++ b/crypto/ocf/c7108/aes-7108.h
+@@ -0,0 +1,134 @@
++/*
++ * Copyright (C) 2006 Micronas USA
++ *
++ * 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 __AES_7108_H__
++#define __AES_7108_H__
++
++/* Cypher 7108 AES Controller Hardware */
++#define CCU_REG_BASE       0x1b500000
++#define CCU_AES_REG_BASE   (CCU_REG_BASE + 0x100)
++#define C7108_AES_KEY0_LO        (0x0000)
++#define C7108_AES_KEY0_HI        (0x0004)
++#define C7108_AES_KEY1_LO        (0x0008)
++#define C7108_AES_KEY1_HI        (0x000c)
++#define C7108_AES_KEY2_LO        (0x0010)
++#define C7108_AES_KEY2_HI        (0x0014)
++#define C7108_AES_KEY3_LO        (0x0018)
++#define C7108_AES_KEY3_HI        (0x001c)
++#define C7108_AES_KEY4_LO        (0x0020)
++#define C7108_AES_KEY4_HI        (0x0024)
++#define C7108_AES_KEY5_LO        (0x0028)
++#define C7108_AES_KEY5_HI        (0x002c)
++#define C7108_AES_KEY6_LO        (0x0030)
++#define C7108_AES_KEY6_HI        (0x0034)
++#define C7108_AES_KEY7_LO        (0x0038)
++#define C7108_AES_KEY7_HI        (0x003c)
++#define C7108_AES_IV0_LO         (0x0040)
++#define C7108_AES_IV0_HI         (0x0044)
++#define C7108_AES_IV1_LO         (0x0048)
++#define C7108_AES_IV1_HI         (0x004c)
++#define C7108_AES_IV2_LO         (0x0050)
++#define C7108_AES_IV2_HI         (0x0054)
++#define C7108_AES_IV3_LO         (0x0058)
++#define C7108_AES_IV3_HI         (0x005c)
++
++#define C7108_AES_DMA_SRC0_LO    (0x0068) /* Bits 0:15 */
++#define C7108_AES_DMA_SRC0_HI    (0x006c) /* Bits 27:16 */
++#define C7108_AES_DMA_DST0_LO    (0x0070) /* Bits 0:15 */
++#define C7108_AES_DMA_DST0_HI    (0x0074) /* Bits 27:16 */
++#define C7108_AES_DMA_LEN        (0x0078)  /*Bytes:(Count+1)x16 */
++
++/* AES/Copy engine control register */
++#define C7108_AES_CTRL           (0x007c) /* AES control */
++#define C7108_AES_CTRL_RS        (1<<0)     /* Which set of src/dst to use */
++
++/* AES Cipher mode, controlled by setting Bits 2:0 */
++#define C7108_AES_CTRL_MODE_CBC     0
++#define C7108_AES_CTRL_MODE_CFB     (1<<0)
++#define C7108_AES_CTRL_MODE_OFB     (1<<1)
++#define C7108_AES_CTRL_MODE_CTR     ((1<<0)|(1<<1))
++#define C7108_AES_CTRL_MODE_ECB     (1<<2)
++
++/* AES Key length , Bits 5:4 */
++#define C7108_AES_KEY_LEN_128         0       /* 00 */
++#define C7108_AES_KEY_LEN_192         (1<<4)  /* 01 */
++#define C7108_AES_KEY_LEN_256         (1<<5)  /* 10 */
++
++/* AES Operation (crypt/decrypt), Bit 3 */
++#define C7108_AES_DECRYPT             (1<<3)   /* Clear for encrypt */
++#define C7108_AES_ENCRYPT              0
++#define C7108_AES_INTR                (1<<13) /* Set on done trans from 0->1*/
++#define C7108_AES_GO                  (1<<14) /* Run */
++#define C7108_AES_OP_DONE             (1<<15) /* Set when complete */
++
++
++/* Expanded key registers */
++#define C7108_AES_EKEY0_LO            (0x0080)
++#define C7108_AES_EKEY0_HI            (0x0084)
++#define C7108_AES_EKEY1_LO            (0x0088)
++#define C7108_AES_EKEY1_HI            (0x008c)
++#define C7108_AES_EKEY2_LO            (0x0090)
++#define C7108_AES_EKEY2_HI            (0x0094)
++#define C7108_AES_EKEY3_LO            (0x0098)
++#define C7108_AES_EKEY3_HI            (0x009c)
++#define C7108_AES_EKEY4_LO            (0x00a0)
++#define C7108_AES_EKEY4_HI            (0x00a4)
++#define C7108_AES_EKEY5_LO            (0x00a8)
++#define C7108_AES_EKEY5_HI            (0x00ac)
++#define C7108_AES_EKEY6_LO            (0x00b0)
++#define C7108_AES_EKEY6_HI            (0x00b4)
++#define C7108_AES_EKEY7_LO            (0x00b8)
++#define C7108_AES_EKEY7_HI            (0x00bc)
++#define C7108_AES_OK                  (0x00fc) /* Reset: "OK" */
++
++#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
++
++/* Software session entry */
++
++#define HW_TYPE_CIPHER	0
++#define SW_TYPE_HMAC	1
++#define SW_TYPE_AUTH2	2
++#define SW_TYPE_HASH	3
++#define SW_TYPE_COMP	4
++
++struct cipher_7108 {
++	int			xfm_type;
++	int			cri_alg;
++	union {
++		struct {
++			char sw_key[HMAC_BLOCK_LEN];
++			int  sw_klen;
++			int  sw_authlen;
++		} hmac;
++	} u;
++	struct cipher_7108	*next;
++};
++
++
++
++#endif /* __C7108_AES_7108_H__ */
+diff --git a/crypto/ocf/criov.c b/crypto/ocf/criov.c
+new file mode 100644
+index 0000000..6d7d3ad
+--- /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@mcafee.com>
++ * Copyright (C) 2006-2010 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 100644
+index 0000000..9735f0c
+--- /dev/null
++++ b/crypto/ocf/crypto.c
+@@ -0,0 +1,1784 @@
++/*-
++ * Linux port done by David McCullough <david_mccullough@mcafee.com>
++ * Copyright (C) 2006-2010 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
++ */
++static 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 */
++
++	int		cc_unqblocked;		/* (q) symmetric q blocked */
++	int		cc_unkqblocked;		/* (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
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
++#include <linux/sched.h>
++#define	kill_proc(p,s,v)	send_sig(s,find_task_by_vpid(p),0)
++#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");
++
++/*
++ * This parameter controls the maximum number of crypto operations to
++ * do consecutively in the crypto kernel thread before scheduling to allow
++ * other processes to run. Without it, it is possible to get into a
++ * situation where the crypto thread never allows any other processes to run.
++ * Default to 1000 which should be less than one second.
++ */
++static int crypto_max_loopcount = 1000;
++module_param(crypto_max_loopcount, int, 0644);
++MODULE_PARM_DESC(crypto_max_loopcount,
++	   "Maximum number of crypto ops to do before yielding to other processes");
++
++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);
++static  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;
++			cap->cc_unqblocked = 0;
++			crypto_all_qblocked = 0;
++		}
++		if (what & CRYPTO_ASYMQ) {
++			cap->cc_kqblocked = 0;
++			cap->cc_unkqblocked = 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;
++	int result = -1;
++	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++;
++
++	/* make sure we are starting a fresh run on this crp. */
++	crp->crp_flags &= ~CRYPTO_F_DONE;
++	crp->crp_etype = 0;
++
++	/*
++	 * Caller marked the request to be processed immediately; dispatch
++	 * it directly to the driver unless the driver is currently blocked.
++	 */
++	if ((crp->crp_flags & CRYPTO_F_BATCH) == 0) {
++		int hid = CRYPTO_SESID2HID(crp->crp_sid);
++		cap = crypto_checkdriver(hid);
++		/* Driver cannot disappear when there is an active session. */
++		KASSERT(cap != NULL, ("%s: Driver disappeared.", __func__));
++		if (!cap->cc_qblocked) {
++			crypto_all_qblocked = 0;
++			crypto_drivers[hid].cc_unqblocked = 1;
++			CRYPTO_Q_UNLOCK();
++			result = crypto_invoke(cap, crp, 0);
++			CRYPTO_Q_LOCK();
++			if (result == ERESTART)
++				if (crypto_drivers[hid].cc_unqblocked)
++					crypto_drivers[hid].cc_qblocked = 1;
++			crypto_drivers[hid].cc_unqblocked = 0;
++		}
++	}
++	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.
++		 */
++		list_add(&crp->crp_next, &crp_q);
++		cryptostats.cs_blocks++;
++		result = 0;
++	} else if (result == -1) {
++		TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
++		result = 0;
++	}
++	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;
++	int loopcount = 0;
++
++	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_unqblocked = 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++;
++				if (crypto_drivers[hid].cc_unqblocked)
++					crypto_drivers[hid].cc_qblocked=0;
++				crypto_drivers[hid].cc_unqblocked=0;
++			}
++			crypto_drivers[hid].cc_unqblocked = 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);
++			loopcount = 0;
++			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++;
++		} else if (loopcount > crypto_max_loopcount) {
++			/*
++			 * Give other processes a chance to run if we've
++			 * been using the CPU exclusively for a while.
++			 */
++			loopcount = 0;
++			schedule();
++		}
++		loopcount++;
++	}
++	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
++
++
++static int
++crypto_init(void)
++{
++	int error;
++
++	dprintk("%s(%p)\n", __FUNCTION__, (void *) 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(p, SIGTERM, 1);
++	wake_up_interruptible(&cryptoproc_wait);
++	CRYPTO_DRIVER_UNLOCK();
++
++	wait_for_completion(&cryptoproc_exited);
++
++	CRYPTO_DRIVER_LOCK();
++	p = cryptoretproc;
++	cryptoretproc = (pid_t) -1;
++	kill_proc(p, SIGTERM, 1);
++	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@mcafee.com>");
++MODULE_DESCRIPTION("OCF (OpenBSD Cryptographic Framework)");
+diff --git a/crypto/ocf/cryptocteon/Makefile b/crypto/ocf/cryptocteon/Makefile
+new file mode 100644
+index 0000000..eeed0d6
+--- /dev/null
++++ b/crypto/ocf/cryptocteon/Makefile
+@@ -0,0 +1,17 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++obj-$(CONFIG_OCF_CRYPTOCTEON) += cryptocteon.o
++
++obj ?= .
++EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
++
++ifdef CONFIG_OCF_CRYPTOCTEON
++# you need the cavium crypto component installed
++EXTRA_CFLAGS += -I$(ROOTDIR)/prop/include
++endif
++
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff --git a/crypto/ocf/cryptocteon/cavium_crypto.c b/crypto/ocf/cryptocteon/cavium_crypto.c
+new file mode 100644
+index 0000000..ceaf77c
+--- /dev/null
++++ b/crypto/ocf/cryptocteon/cavium_crypto.c
+@@ -0,0 +1,2283 @@
++/*
++ * Copyright (c) 2009 David McCullough <david.mccullough@securecomputing.com>
++ *
++ * Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). 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 Cavium Networks
++ * 4. Cavium Networks' name may not be used to endorse or promote products
++ * derived from this software without specific prior written permission.
++ *
++ * This Software, including technical data, may be subject to U.S. export
++ * control laws, including the U.S. Export Administration Act and its
++ * associated regulations, and may be subject to export or import regulations
++ * in other countries. You warrant that You will comply strictly in all
++ * respects with all such regulations and acknowledge that you have the
++ * responsibility to obtain licenses to export, re-export or import the
++ * Software.
++ *
++ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" AND
++ * WITH ALL FAULTS AND CAVIUM MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES,
++ * EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE
++ * SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
++ * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
++ * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
++ * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
++ * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
++ * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
++ * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
++*/
++/****************************************************************************/
++
++#include <linux/scatterlist.h>
++#include <asm/octeon/octeon.h>
++#include "octeon-asm.h"
++
++/****************************************************************************/
++
++extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *);
++extern void octeon_crypto_disable(struct octeon_cop2_state *, unsigned long);
++
++#define SG_INIT(s, p, i, l) \
++	{ \
++	    (i) = 0; \
++	    (l) = (s)[0].length; \
++	    (p) = (typeof(p)) sg_virt((s)); \
++		CVMX_PREFETCH0((p)); \
++	}
++
++#define SG_CONSUME(s, p, i, l) \
++	{ \
++		(p)++; \
++		(l) -= sizeof(*(p)); \
++		if ((l) < 0) { \
++			dprintk("%s, %d: l = %d\n", __FILE__, __LINE__, l); \
++		} else if ((l) == 0) { \
++		    (i)++; \
++		    (l) = (s)[0].length; \
++		    (p) = (typeof(p)) sg_virt(s); \
++			CVMX_PREFETCH0((p)); \
++		} \
++	}
++
++#define ESP_HEADER_LENGTH     8
++#define DES_CBC_IV_LENGTH     8
++#define AES_CBC_IV_LENGTH     16
++#define ESP_HMAC_LEN          12
++
++#define ESP_HEADER_LENGTH 8
++#define DES_CBC_IV_LENGTH 8
++
++/****************************************************************************/
++
++#define CVM_LOAD_SHA_UNIT(dat, next)  { \
++   if (next == 0) {                     \
++      next = 1;                         \
++      CVMX_MT_HSH_DAT (dat, 0);         \
++   } else if (next == 1) {              \
++      next = 2;                         \
++      CVMX_MT_HSH_DAT (dat, 1);         \
++   } else if (next == 2) {              \
++      next = 3;                    \
++      CVMX_MT_HSH_DAT (dat, 2);         \
++   } else if (next == 3) {              \
++      next = 4;                         \
++      CVMX_MT_HSH_DAT (dat, 3);         \
++   } else if (next == 4) {              \
++      next = 5;                           \
++      CVMX_MT_HSH_DAT (dat, 4);         \
++   } else if (next == 5) {              \
++      next = 6;                         \
++      CVMX_MT_HSH_DAT (dat, 5);         \
++   } else if (next == 6) {              \
++      next = 7;                         \
++      CVMX_MT_HSH_DAT (dat, 6);         \
++   } else {                             \
++     CVMX_MT_HSH_STARTSHA (dat);        \
++     next = 0;                          \
++   }                                    \
++}
++
++#define CVM_LOAD2_SHA_UNIT(dat1, dat2, next)  { \
++   if (next == 0) {                      \
++      CVMX_MT_HSH_DAT (dat1, 0);         \
++      CVMX_MT_HSH_DAT (dat2, 1);         \
++      next = 2;                          \
++   } else if (next == 1) {               \
++      CVMX_MT_HSH_DAT (dat1, 1);         \
++      CVMX_MT_HSH_DAT (dat2, 2);         \
++      next = 3;                          \
++   } else if (next == 2) {               \
++      CVMX_MT_HSH_DAT (dat1, 2);         \
++      CVMX_MT_HSH_DAT (dat2, 3);         \
++      next = 4;                          \
++   } else if (next == 3) {               \
++      CVMX_MT_HSH_DAT (dat1, 3);         \
++      CVMX_MT_HSH_DAT (dat2, 4);         \
++      next = 5;                          \
++   } else if (next == 4) {               \
++      CVMX_MT_HSH_DAT (dat1, 4);         \
++      CVMX_MT_HSH_DAT (dat2, 5);         \
++      next = 6;                          \
++   } else if (next == 5) {               \
++      CVMX_MT_HSH_DAT (dat1, 5);         \
++      CVMX_MT_HSH_DAT (dat2, 6);         \
++      next = 7;                          \
++   } else if (next == 6) {               \
++      CVMX_MT_HSH_DAT (dat1, 6);         \
++      CVMX_MT_HSH_STARTSHA (dat2);       \
++      next = 0;                          \
++   } else {                              \
++     CVMX_MT_HSH_STARTSHA (dat1);        \
++     CVMX_MT_HSH_DAT (dat2, 0);          \
++     next = 1;                           \
++   }                                     \
++}
++
++/****************************************************************************/
++
++#define CVM_LOAD_MD5_UNIT(dat, next)  { \
++   if (next == 0) {                     \
++      next = 1;                         \
++      CVMX_MT_HSH_DAT (dat, 0);         \
++   } else if (next == 1) {              \
++      next = 2;                         \
++      CVMX_MT_HSH_DAT (dat, 1);         \
++   } else if (next == 2) {              \
++      next = 3;                    \
++      CVMX_MT_HSH_DAT (dat, 2);         \
++   } else if (next == 3) {              \
++      next = 4;                         \
++      CVMX_MT_HSH_DAT (dat, 3);         \
++   } else if (next == 4) {              \
++      next = 5;                           \
++      CVMX_MT_HSH_DAT (dat, 4);         \
++   } else if (next == 5) {              \
++      next = 6;                         \
++      CVMX_MT_HSH_DAT (dat, 5);         \
++   } else if (next == 6) {              \
++      next = 7;                         \
++      CVMX_MT_HSH_DAT (dat, 6);         \
++   } else {                             \
++     CVMX_MT_HSH_STARTMD5 (dat);        \
++     next = 0;                          \
++   }                                    \
++}
++
++#define CVM_LOAD2_MD5_UNIT(dat1, dat2, next)  { \
++   if (next == 0) {                      \
++      CVMX_MT_HSH_DAT (dat1, 0);         \
++      CVMX_MT_HSH_DAT (dat2, 1);         \
++      next = 2;                          \
++   } else if (next == 1) {               \
++      CVMX_MT_HSH_DAT (dat1, 1);         \
++      CVMX_MT_HSH_DAT (dat2, 2);         \
++      next = 3;                          \
++   } else if (next == 2) {               \
++      CVMX_MT_HSH_DAT (dat1, 2);         \
++      CVMX_MT_HSH_DAT (dat2, 3);         \
++      next = 4;                          \
++   } else if (next == 3) {               \
++      CVMX_MT_HSH_DAT (dat1, 3);         \
++      CVMX_MT_HSH_DAT (dat2, 4);         \
++      next = 5;                          \
++   } else if (next == 4) {               \
++      CVMX_MT_HSH_DAT (dat1, 4);         \
++      CVMX_MT_HSH_DAT (dat2, 5);         \
++      next = 6;                          \
++   } else if (next == 5) {               \
++      CVMX_MT_HSH_DAT (dat1, 5);         \
++      CVMX_MT_HSH_DAT (dat2, 6);         \
++      next = 7;                          \
++   } else if (next == 6) {               \
++      CVMX_MT_HSH_DAT (dat1, 6);         \
++      CVMX_MT_HSH_STARTMD5 (dat2);       \
++      next = 0;                          \
++   } else {                              \
++     CVMX_MT_HSH_STARTMD5 (dat1);        \
++     CVMX_MT_HSH_DAT (dat2, 0);          \
++     next = 1;                           \
++   }                                     \
++}
++
++/****************************************************************************/
++
++static inline uint64_t
++swap64(uint64_t a)
++{
++    return ((a >> 56) |
++       (((a >> 48) & 0xfful) << 8) |
++       (((a >> 40) & 0xfful) << 16) |
++       (((a >> 32) & 0xfful) << 24) |
++       (((a >> 24) & 0xfful) << 32) |
++       (((a >> 16) & 0xfful) << 40) |
++       (((a >> 8) & 0xfful) << 48) | (((a >> 0) & 0xfful) << 56));
++}
++
++/****************************************************************************/
++
++void
++octo_calc_hash(__u8 auth, unsigned char *key, uint64_t *inner, uint64_t *outer)
++{
++    uint8_t hash_key[64];
++    uint64_t *key1;
++    register uint64_t xor1 = 0x3636363636363636ULL;
++    register uint64_t xor2 = 0x5c5c5c5c5c5c5c5cULL;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    memset(hash_key, 0, sizeof(hash_key));
++    memcpy(hash_key, (uint8_t *) key, (auth ? 20 : 16));
++    key1 = (uint64_t *) hash_key;
++    flags = octeon_crypto_enable(&state);
++    if (auth) {
++       CVMX_MT_HSH_IV(0x67452301EFCDAB89ULL, 0);
++       CVMX_MT_HSH_IV(0x98BADCFE10325476ULL, 1);
++       CVMX_MT_HSH_IV(0xC3D2E1F000000000ULL, 2);
++    } else {
++       CVMX_MT_HSH_IV(0x0123456789ABCDEFULL, 0);
++       CVMX_MT_HSH_IV(0xFEDCBA9876543210ULL, 1);
++    }
++
++    CVMX_MT_HSH_DAT((*key1 ^ xor1), 0);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor1), 1);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor1), 2);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor1), 3);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor1), 4);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor1), 5);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor1), 6);
++    key1++;
++    if (auth)
++	CVMX_MT_HSH_STARTSHA((*key1 ^ xor1));
++    else
++	CVMX_MT_HSH_STARTMD5((*key1 ^ xor1));
++
++    CVMX_MF_HSH_IV(inner[0], 0);
++    CVMX_MF_HSH_IV(inner[1], 1);
++    if (auth) {
++	inner[2] = 0;
++	CVMX_MF_HSH_IV(((uint64_t *) inner)[2], 2);
++    }
++
++    memset(hash_key, 0, sizeof(hash_key));
++    memcpy(hash_key, (uint8_t *) key, (auth ? 20 : 16));
++    key1 = (uint64_t *) hash_key;
++    if (auth) {
++      CVMX_MT_HSH_IV(0x67452301EFCDAB89ULL, 0);
++      CVMX_MT_HSH_IV(0x98BADCFE10325476ULL, 1);
++      CVMX_MT_HSH_IV(0xC3D2E1F000000000ULL, 2);
++    } else {
++      CVMX_MT_HSH_IV(0x0123456789ABCDEFULL, 0);
++      CVMX_MT_HSH_IV(0xFEDCBA9876543210ULL, 1);
++    }
++
++    CVMX_MT_HSH_DAT((*key1 ^ xor2), 0);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor2), 1);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor2), 2);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor2), 3);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor2), 4);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor2), 5);
++    key1++;
++    CVMX_MT_HSH_DAT((*key1 ^ xor2), 6);
++    key1++;
++    if (auth)
++       CVMX_MT_HSH_STARTSHA((*key1 ^ xor2));
++    else
++       CVMX_MT_HSH_STARTMD5((*key1 ^ xor2));
++
++    CVMX_MF_HSH_IV(outer[0], 0);
++    CVMX_MF_HSH_IV(outer[1], 1);
++    if (auth) {
++      outer[2] = 0;
++      CVMX_MF_HSH_IV(outer[2], 2);
++    }
++    octeon_crypto_disable(&state, flags);
++    return;
++}
++
++/****************************************************************************/
++/* DES functions */
++
++int
++octo_des_cbc_encrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    uint64_t *data;
++    int data_i, data_l;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x7) || (crypt_off + crypt_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load 3DES Key */
++    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    if (od->octo_encklen == 24) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++    } else if (od->octo_encklen == 8) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++
++    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
++
++    while (crypt_off > 0) {
++	SG_CONSUME(sg, data, data_i, data_l);
++	crypt_off -= 8;
++    }
++
++    while (crypt_len > 0) {
++	CVMX_MT_3DES_ENC_CBC(*data);
++	CVMX_MF_3DES_RESULT(*data);
++	SG_CONSUME(sg, data, data_i, data_l);
++	crypt_len -= 8;
++    }
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++
++int
++octo_des_cbc_decrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    uint64_t *data;
++    int data_i, data_l;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x7) || (crypt_off + crypt_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load 3DES Key */
++    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    if (od->octo_encklen == 24) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++    } else if (od->octo_encklen == 8) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++
++    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
++
++    while (crypt_off > 0) {
++	SG_CONSUME(sg, data, data_i, data_l);
++	crypt_off -= 8;
++    }
++
++    while (crypt_len > 0) {
++	CVMX_MT_3DES_DEC_CBC(*data);
++	CVMX_MF_3DES_RESULT(*data);
++	SG_CONSUME(sg, data, data_i, data_l);
++	crypt_len -= 8;
++    }
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++/****************************************************************************/
++/* AES functions */
++
++int
++octo_aes_cbc_encrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    uint64_t *data, *pdata;
++    int data_i, data_l;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x7) || (crypt_off + crypt_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load AES Key */
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++
++    if (od->octo_encklen == 16) {
++	CVMX_MT_AES_KEY(0x0, 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 24) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 32) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
++
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
++
++    while (crypt_off > 0) {
++	SG_CONSUME(sg, data, data_i, data_l);
++	crypt_off -= 8;
++    }
++
++    while (crypt_len > 0) {
++	pdata = data;
++	CVMX_MT_AES_ENC_CBC0(*data);
++	SG_CONSUME(sg, data, data_i, data_l);
++	CVMX_MT_AES_ENC_CBC1(*data);
++	CVMX_MF_AES_RESULT(*pdata, 0);
++	CVMX_MF_AES_RESULT(*data, 1);
++	SG_CONSUME(sg, data, data_i, data_l);
++	crypt_len -= 16;
++    }
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++
++int
++octo_aes_cbc_decrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    uint64_t *data, *pdata;
++    int data_i, data_l;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x7) || (crypt_off + crypt_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load AES Key */
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++
++    if (od->octo_encklen == 16) {
++	CVMX_MT_AES_KEY(0x0, 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 24) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 32) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
++
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
++
++    while (crypt_off > 0) {
++	SG_CONSUME(sg, data, data_i, data_l);
++	crypt_off -= 8;
++    }
++
++    while (crypt_len > 0) {
++	pdata = data;
++	CVMX_MT_AES_DEC_CBC0(*data);
++	SG_CONSUME(sg, data, data_i, data_l);
++	CVMX_MT_AES_DEC_CBC1(*data);
++	CVMX_MF_AES_RESULT(*pdata, 0);
++	CVMX_MF_AES_RESULT(*data, 1);
++	SG_CONSUME(sg, data, data_i, data_l);
++	crypt_len -= 16;
++    }
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++/****************************************************************************/
++/* MD5 */
++
++int
++octo_null_md5_encrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    uint64_t *data;
++    uint64_t tmp1, tmp2;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 ||
++	    (auth_off & 0x7) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data, data_i, data_l);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* Load MD5 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++
++    while (auth_off > 0) {
++	SG_CONSUME(sg, data, data_i, data_l);
++	auth_off -= 8;
++    }
++
++    while (auth_len > 0) {
++	CVM_LOAD_MD5_UNIT(*data, next);
++	auth_len -= 8;
++	SG_CONSUME(sg, data, data_i, data_l);
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_MD5_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
++    }
++    CVMX_ES64(tmp1, ((alen + 64) << 3));
++    CVM_LOAD_MD5_UNIT(tmp1, next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_ES64(tmp1, ((64 + 16) << 3));
++    CVMX_MT_HSH_STARTMD5(tmp1);
++
++    /* save the HMAC */
++    SG_INIT(sg, data, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data, data_i, data_l);
++	icv_off -= 8;
++    }
++    CVMX_MF_HSH_IV(*data, 0);
++    SG_CONSUME(sg, data, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *(uint32_t *)data = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++/****************************************************************************/
++/* SHA1 */
++
++int
++octo_null_sha1_encrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    uint64_t *data;
++    uint64_t tmp1, tmp2, tmp3;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 ||
++	    (auth_off & 0x7) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data, data_i, data_l);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* Load SHA1 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
++
++    while (auth_off > 0) {
++	SG_CONSUME(sg, data, data_i, data_l);
++	auth_off -= 8;
++    }
++
++    while (auth_len > 0) {
++	CVM_LOAD_SHA_UNIT(*data, next);
++	auth_len -= 8;
++	SG_CONSUME(sg, data, data_i, data_l);
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_MD5_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
++    }
++    CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++    tmp3 = 0;
++    CVMX_MF_HSH_IV(tmp3, 2);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    tmp3 |= 0x0000000080000000;
++    CVMX_MT_HSH_DAT(tmp3, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
++
++    /* save the HMAC */
++    SG_INIT(sg, data, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data, data_i, data_l);
++	icv_off -= 8;
++    }
++    CVMX_MF_HSH_IV(*data, 0);
++    SG_CONSUME(sg, data, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *(uint32_t *)data = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++/****************************************************************************/
++/* DES MD5 */
++
++int
++octo_des_cbc_md5_encrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    union {
++	uint32_t data32[2];
++	uint64_t data64[1];
++    } mydata;
++    uint64_t *data = &mydata.data64[0];
++    uint32_t *data32;
++    uint64_t tmp1, tmp2;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
++	    (crypt_len  & 0x7) ||
++	    (auth_len  & 0x7) ||
++	    (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data32, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load 3DES Key */
++    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    if (od->octo_encklen == 24) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++    } else if (od->octo_encklen == 8) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++
++    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
++
++    /* Load MD5 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++
++    while (crypt_off > 0 && auth_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	crypt_off -= 4;
++	auth_off -= 4;
++    }
++
++    while (crypt_len > 0 || auth_len > 0) {
++	uint32_t *first = data32;
++	mydata.data32[0] = *first;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata.data32[1] = *data32;
++	if (crypt_off <= 0) {
++	    if (crypt_len > 0) {
++		CVMX_MT_3DES_ENC_CBC(*data);
++		CVMX_MF_3DES_RESULT(*data);
++		crypt_len -= 8;
++	    }
++	} else
++	    crypt_off -= 8;
++	if (auth_off <= 0) {
++	    if (auth_len > 0) {
++		CVM_LOAD_MD5_UNIT(*data, next);
++		auth_len -= 8;
++	    }
++	} else
++	    auth_off -= 8;
++	*first = mydata.data32[0];
++	*data32 = mydata.data32[1];
++	SG_CONSUME(sg, data32, data_i, data_l);
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_MD5_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
++    }
++    CVMX_ES64(tmp1, ((alen + 64) << 3));
++    CVM_LOAD_MD5_UNIT(tmp1, next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_ES64(tmp1, ((64 + 16) << 3));
++    CVMX_MT_HSH_STARTMD5(tmp1);
++
++    /* save the HMAC */
++    SG_INIT(sg, data32, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	icv_off -= 4;
++    }
++    CVMX_MF_HSH_IV(tmp1, 0);
++    *data32 = (uint32_t) (tmp1 >> 32);
++    SG_CONSUME(sg, data32, data_i, data_l);
++    *data32 = (uint32_t) tmp1;
++    SG_CONSUME(sg, data32, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *data32 = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++int
++octo_des_cbc_md5_decrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    union {
++	uint32_t data32[2];
++	uint64_t data64[1];
++    } mydata;
++    uint64_t *data = &mydata.data64[0];
++    uint32_t *data32;
++    uint64_t tmp1, tmp2;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
++	    (crypt_len  & 0x7) ||
++	    (auth_len  & 0x7) ||
++	    (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data32, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load 3DES Key */
++    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    if (od->octo_encklen == 24) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++    } else if (od->octo_encklen == 8) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++
++    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
++
++    /* Load MD5 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++
++    while (crypt_off > 0 && auth_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	crypt_off -= 4;
++	auth_off -= 4;
++    }
++
++    while (crypt_len > 0 || auth_len > 0) {
++	uint32_t *first = data32;
++	mydata.data32[0] = *first;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata.data32[1] = *data32;
++	if (auth_off <= 0) {
++	    if (auth_len > 0) {
++		CVM_LOAD_MD5_UNIT(*data, next);
++		auth_len -= 8;
++	    }
++	} else
++	    auth_off -= 8;
++	if (crypt_off <= 0) {
++	    if (crypt_len > 0) {
++		CVMX_MT_3DES_DEC_CBC(*data);
++		CVMX_MF_3DES_RESULT(*data);
++		crypt_len -= 8;
++	    }
++	} else
++	    crypt_off -= 8;
++	*first = mydata.data32[0];
++	*data32 = mydata.data32[1];
++	SG_CONSUME(sg, data32, data_i, data_l);
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_MD5_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
++    }
++    CVMX_ES64(tmp1, ((alen + 64) << 3));
++    CVM_LOAD_MD5_UNIT(tmp1, next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_ES64(tmp1, ((64 + 16) << 3));
++    CVMX_MT_HSH_STARTMD5(tmp1);
++
++    /* save the HMAC */
++    SG_INIT(sg, data32, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	icv_off -= 4;
++    }
++    CVMX_MF_HSH_IV(tmp1, 0);
++    *data32 = (uint32_t) (tmp1 >> 32);
++    SG_CONSUME(sg, data32, data_i, data_l);
++    *data32 = (uint32_t) tmp1;
++    SG_CONSUME(sg, data32, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *data32 = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++/****************************************************************************/
++/* DES SHA */
++
++int
++octo_des_cbc_sha1_encrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    union {
++	uint32_t data32[2];
++	uint64_t data64[1];
++    } mydata;
++    uint64_t *data = &mydata.data64[0];
++    uint32_t *data32;
++    uint64_t tmp1, tmp2, tmp3;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
++	    (crypt_len  & 0x7) ||
++	    (auth_len  & 0x7) ||
++	    (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data32, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load 3DES Key */
++    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    if (od->octo_encklen == 24) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++    } else if (od->octo_encklen == 8) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++
++    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
++
++    /* Load SHA1 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
++
++    while (crypt_off > 0 && auth_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	crypt_off -= 4;
++	auth_off -= 4;
++    }
++
++    while (crypt_len > 0 || auth_len > 0) {
++	uint32_t *first = data32;
++	mydata.data32[0] = *first;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata.data32[1] = *data32;
++	if (crypt_off <= 0) {
++	    if (crypt_len > 0) {
++		CVMX_MT_3DES_ENC_CBC(*data);
++		CVMX_MF_3DES_RESULT(*data);
++		crypt_len -= 8;
++	    }
++	} else
++	    crypt_off -= 8;
++	if (auth_off <= 0) {
++	    if (auth_len > 0) {
++		CVM_LOAD_SHA_UNIT(*data, next);
++		auth_len -= 8;
++	    }
++	} else
++	    auth_off -= 8;
++	*first = mydata.data32[0];
++	*data32 = mydata.data32[1];
++	SG_CONSUME(sg, data32, data_i, data_l);
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_SHA_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
++    }
++	CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++    tmp3 = 0;
++    CVMX_MF_HSH_IV(tmp3, 2);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    tmp3 |= 0x0000000080000000;
++    CVMX_MT_HSH_DAT(tmp3, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
++
++    /* save the HMAC */
++    SG_INIT(sg, data32, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	icv_off -= 4;
++    }
++    CVMX_MF_HSH_IV(tmp1, 0);
++    *data32 = (uint32_t) (tmp1 >> 32);
++    SG_CONSUME(sg, data32, data_i, data_l);
++    *data32 = (uint32_t) tmp1;
++    SG_CONSUME(sg, data32, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *data32 = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++int
++octo_des_cbc_sha1_decrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    union {
++	uint32_t data32[2];
++	uint64_t data64[1];
++    } mydata;
++    uint64_t *data = &mydata.data64[0];
++    uint32_t *data32;
++    uint64_t tmp1, tmp2, tmp3;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
++	    (crypt_len  & 0x7) ||
++	    (auth_len  & 0x7) ||
++	    (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data32, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load 3DES Key */
++    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    if (od->octo_encklen == 24) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++    } else if (od->octo_encklen == 8) {
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
++	CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++
++    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
++
++    /* Load SHA1 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
++
++    while (crypt_off > 0 && auth_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	crypt_off -= 4;
++	auth_off -= 4;
++    }
++
++    while (crypt_len > 0 || auth_len > 0) {
++	uint32_t *first = data32;
++	mydata.data32[0] = *first;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata.data32[1] = *data32;
++	if (auth_off <= 0) {
++	    if (auth_len > 0) {
++		CVM_LOAD_SHA_UNIT(*data, next);
++		auth_len -= 8;
++	    }
++	} else
++	    auth_off -= 8;
++	if (crypt_off <= 0) {
++	    if (crypt_len > 0) {
++		CVMX_MT_3DES_DEC_CBC(*data);
++		CVMX_MF_3DES_RESULT(*data);
++		crypt_len -= 8;
++	    }
++	} else
++	    crypt_off -= 8;
++	*first = mydata.data32[0];
++	*data32 = mydata.data32[1];
++	SG_CONSUME(sg, data32, data_i, data_l);
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_SHA_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
++    }
++    CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++    tmp3 = 0;
++    CVMX_MF_HSH_IV(tmp3, 2);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    tmp3 |= 0x0000000080000000;
++    CVMX_MT_HSH_DAT(tmp3, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
++    /* save the HMAC */
++    SG_INIT(sg, data32, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	icv_off -= 4;
++    }
++    CVMX_MF_HSH_IV(tmp1, 0);
++    *data32 = (uint32_t) (tmp1 >> 32);
++    SG_CONSUME(sg, data32, data_i, data_l);
++    *data32 = (uint32_t) tmp1;
++    SG_CONSUME(sg, data32, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *data32 = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++/****************************************************************************/
++/* AES MD5 */
++
++int
++octo_aes_cbc_md5_encrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    union {
++	uint32_t data32[2];
++	uint64_t data64[1];
++    } mydata[2];
++    uint64_t *pdata = &mydata[0].data64[0];
++    uint64_t *data =  &mydata[1].data64[0];
++    uint32_t *data32;
++    uint64_t tmp1, tmp2;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
++	    (crypt_len  & 0x7) ||
++	    (auth_len  & 0x7) ||
++	    (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data32, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load AES Key */
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++
++    if (od->octo_encklen == 16) {
++	CVMX_MT_AES_KEY(0x0, 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 24) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 32) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
++
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
++
++    /* Load MD5 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++
++    while (crypt_off > 0 && auth_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	crypt_off -= 4;
++	auth_off -= 4;
++    }
++
++    /* align auth and crypt */
++    while (crypt_off > 0 && auth_len > 0) {
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	CVM_LOAD_MD5_UNIT(*pdata, next);
++	crypt_off -= 8;
++	auth_len -= 8;
++    }
++
++    while (crypt_len > 0) {
++	uint32_t *pdata32[3];
++
++	pdata32[0] = data32;
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++
++	pdata32[1] = data32;
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++
++	pdata32[2] = data32;
++	mydata[1].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++
++	mydata[1].data32[1] = *data32;
++
++	CVMX_MT_AES_ENC_CBC0(*pdata);
++	CVMX_MT_AES_ENC_CBC1(*data);
++	CVMX_MF_AES_RESULT(*pdata, 0);
++	CVMX_MF_AES_RESULT(*data, 1);
++	crypt_len -= 16;
++
++	if (auth_len > 0) {
++	    CVM_LOAD_MD5_UNIT(*pdata, next);
++	    auth_len -= 8;
++	}
++	if (auth_len > 0) {
++	    CVM_LOAD_MD5_UNIT(*data, next);
++	    auth_len -= 8;
++	}
++
++	*pdata32[0] = mydata[0].data32[0];
++	*pdata32[1] = mydata[0].data32[1];
++	*pdata32[2] = mydata[1].data32[0];
++	*data32     = mydata[1].data32[1];
++
++	SG_CONSUME(sg, data32, data_i, data_l);
++    }
++
++    /* finish any left over hashing */
++    while (auth_len > 0) {
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	CVM_LOAD_MD5_UNIT(*pdata, next);
++	auth_len -= 8;
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_MD5_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
++    }
++    CVMX_ES64(tmp1, ((alen + 64) << 3));
++    CVM_LOAD_MD5_UNIT(tmp1, next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_ES64(tmp1, ((64 + 16) << 3));
++    CVMX_MT_HSH_STARTMD5(tmp1);
++
++    /* save the HMAC */
++    SG_INIT(sg, data32, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	icv_off -= 4;
++    }
++    CVMX_MF_HSH_IV(tmp1, 0);
++    *data32 = (uint32_t) (tmp1 >> 32);
++    SG_CONSUME(sg, data32, data_i, data_l);
++    *data32 = (uint32_t) tmp1;
++    SG_CONSUME(sg, data32, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *data32 = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++int
++octo_aes_cbc_md5_decrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    union {
++	uint32_t data32[2];
++	uint64_t data64[1];
++    } mydata[2];
++    uint64_t *pdata = &mydata[0].data64[0];
++    uint64_t *data =  &mydata[1].data64[0];
++    uint32_t *data32;
++    uint64_t tmp1, tmp2;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s()\n", __FUNCTION__);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
++	    (crypt_len  & 0x7) ||
++	    (auth_len  & 0x7) ||
++	    (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data32, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load AES Key */
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++
++    if (od->octo_encklen == 16) {
++	CVMX_MT_AES_KEY(0x0, 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 24) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 32) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
++
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
++
++    /* Load MD5 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++
++    while (crypt_off > 0 && auth_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	crypt_off -= 4;
++	auth_off -= 4;
++    }
++
++    /* align auth and crypt */
++    while (crypt_off > 0 && auth_len > 0) {
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	CVM_LOAD_MD5_UNIT(*pdata, next);
++	crypt_off -= 8;
++	auth_len -= 8;
++    }
++
++    while (crypt_len > 0) {
++	uint32_t *pdata32[3];
++
++	pdata32[0] = data32;
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	pdata32[1] = data32;
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	pdata32[2] = data32;
++	mydata[1].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[1].data32[1] = *data32;
++
++	if (auth_len > 0) {
++	    CVM_LOAD_MD5_UNIT(*pdata, next);
++	    auth_len -= 8;
++	}
++
++	if (auth_len > 0) {
++	    CVM_LOAD_MD5_UNIT(*data, next);
++	    auth_len -= 8;
++	}
++
++	CVMX_MT_AES_DEC_CBC0(*pdata);
++	CVMX_MT_AES_DEC_CBC1(*data);
++	CVMX_MF_AES_RESULT(*pdata, 0);
++	CVMX_MF_AES_RESULT(*data, 1);
++	crypt_len -= 16;
++
++	*pdata32[0] = mydata[0].data32[0];
++	*pdata32[1] = mydata[0].data32[1];
++	*pdata32[2] = mydata[1].data32[0];
++	*data32     = mydata[1].data32[1];
++
++	SG_CONSUME(sg, data32, data_i, data_l);
++    }
++
++    /* finish left over hash if any */
++    while (auth_len > 0) {
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	CVM_LOAD_MD5_UNIT(*pdata, next);
++	auth_len -= 8;
++    }
++
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_MD5_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
++    }
++    CVMX_ES64(tmp1, ((alen + 64) << 3));
++    CVM_LOAD_MD5_UNIT(tmp1, next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_ES64(tmp1, ((64 + 16) << 3));
++    CVMX_MT_HSH_STARTMD5(tmp1);
++
++    /* save the HMAC */
++    SG_INIT(sg, data32, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	icv_off -= 4;
++    }
++    CVMX_MF_HSH_IV(tmp1, 0);
++    *data32 = (uint32_t) (tmp1 >> 32);
++    SG_CONSUME(sg, data32, data_i, data_l);
++    *data32 = (uint32_t) tmp1;
++    SG_CONSUME(sg, data32, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *data32 = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++/****************************************************************************/
++/* AES SHA1 */
++
++int
++octo_aes_cbc_sha1_encrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    union {
++	uint32_t data32[2];
++	uint64_t data64[1];
++    } mydata[2];
++    uint64_t *pdata = &mydata[0].data64[0];
++    uint64_t *data =  &mydata[1].data64[0];
++    uint32_t *data32;
++    uint64_t tmp1, tmp2, tmp3;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s(a_off=%d a_len=%d c_off=%d c_len=%d icv_off=%d)\n",
++			__FUNCTION__, auth_off, auth_len, crypt_off, crypt_len, icv_off);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
++	    (crypt_len  & 0x7) ||
++	    (auth_len  & 0x7) ||
++	    (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data32, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load AES Key */
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++
++    if (od->octo_encklen == 16) {
++	CVMX_MT_AES_KEY(0x0, 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 24) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 32) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
++
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
++
++    /* Load SHA IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
++
++    while (crypt_off > 0 && auth_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	crypt_off -= 4;
++	auth_off -= 4;
++    }
++
++    /* align auth and crypt */
++    while (crypt_off > 0 && auth_len > 0) {
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	CVM_LOAD_SHA_UNIT(*pdata, next);
++	crypt_off -= 8;
++	auth_len -= 8;
++    }
++
++    while (crypt_len > 0) {
++	uint32_t *pdata32[3];
++
++	pdata32[0] = data32;
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	pdata32[1] = data32;
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	pdata32[2] = data32;
++	mydata[1].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[1].data32[1] = *data32;
++
++	CVMX_MT_AES_ENC_CBC0(*pdata);
++	CVMX_MT_AES_ENC_CBC1(*data);
++	CVMX_MF_AES_RESULT(*pdata, 0);
++	CVMX_MF_AES_RESULT(*data, 1);
++	crypt_len -= 16;
++
++	if (auth_len > 0) {
++	    CVM_LOAD_SHA_UNIT(*pdata, next);
++	    auth_len -= 8;
++	}
++	if (auth_len > 0) {
++	    CVM_LOAD_SHA_UNIT(*data, next);
++	    auth_len -= 8;
++	}
++
++	*pdata32[0] = mydata[0].data32[0];
++	*pdata32[1] = mydata[0].data32[1];
++	*pdata32[2] = mydata[1].data32[0];
++	*data32     = mydata[1].data32[1];
++
++	SG_CONSUME(sg, data32, data_i, data_l);
++    }
++
++    /* finish and hashing */
++    while (auth_len > 0) {
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	CVM_LOAD_SHA_UNIT(*pdata, next);
++	auth_len -= 8;
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_SHA_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
++    }
++    CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++    tmp3 = 0;
++    CVMX_MF_HSH_IV(tmp3, 2);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    tmp3 |= 0x0000000080000000;
++    CVMX_MT_HSH_DAT(tmp3, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_MD5_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* save the HMAC */
++    SG_INIT(sg, data32, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	icv_off -= 4;
++    }
++    CVMX_MF_HSH_IV(tmp1, 0);
++    *data32 = (uint32_t) (tmp1 >> 32);
++    SG_CONSUME(sg, data32, data_i, data_l);
++    *data32 = (uint32_t) tmp1;
++    SG_CONSUME(sg, data32, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *data32 = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++int
++octo_aes_cbc_sha1_decrypt(
++    struct octo_sess *od,
++    struct scatterlist *sg, int sg_len,
++    int auth_off, int auth_len,
++    int crypt_off, int crypt_len,
++    int icv_off, uint8_t *ivp)
++{
++    register int next = 0;
++    union {
++	uint32_t data32[2];
++	uint64_t data64[1];
++    } mydata[2];
++    uint64_t *pdata = &mydata[0].data64[0];
++    uint64_t *data =  &mydata[1].data64[0];
++    uint32_t *data32;
++    uint64_t tmp1, tmp2, tmp3;
++    int data_i, data_l, alen = auth_len;
++    struct octeon_cop2_state state;
++    unsigned long flags;
++
++    dprintk("%s(a_off=%d a_len=%d c_off=%d c_len=%d icv_off=%d)\n",
++			__FUNCTION__, auth_off, auth_len, crypt_off, crypt_len, icv_off);
++
++    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
++	    (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
++	    (crypt_len  & 0x7) ||
++	    (auth_len  & 0x7) ||
++	    (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
++	dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
++		"auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
++		"icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
++		auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	return -EINVAL;
++    }
++
++    SG_INIT(sg, data32, data_i, data_l);
++
++    CVMX_PREFETCH0(ivp);
++    CVMX_PREFETCH0(od->octo_enckey);
++
++    flags = octeon_crypto_enable(&state);
++
++    /* load AES Key */
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
++    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
++
++    if (od->octo_encklen == 16) {
++	CVMX_MT_AES_KEY(0x0, 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 24) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(0x0, 3);
++    } else if (od->octo_encklen == 32) {
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
++	CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
++    } else {
++	octeon_crypto_disable(&state, flags);
++	dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
++	return -EINVAL;
++    }
++    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
++
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
++    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
++
++    /* Load SHA1 IV */
++    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
++
++    while (crypt_off > 0 && auth_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	crypt_off -= 4;
++	auth_off -= 4;
++    }
++
++    /* align auth and crypt */
++    while (crypt_off > 0 && auth_len > 0) {
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	CVM_LOAD_SHA_UNIT(*pdata, next);
++	crypt_off -= 8;
++	auth_len -= 8;
++    }
++
++    while (crypt_len > 0) {
++	uint32_t *pdata32[3];
++
++	pdata32[0] = data32;
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	pdata32[1] = data32;
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	pdata32[2] = data32;
++	mydata[1].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[1].data32[1] = *data32;
++
++	if (auth_len > 0) {
++	    CVM_LOAD_SHA_UNIT(*pdata, next);
++	    auth_len -= 8;
++	}
++	if (auth_len > 0) {
++	    CVM_LOAD_SHA_UNIT(*data, next);
++	    auth_len -= 8;
++	}
++
++	CVMX_MT_AES_DEC_CBC0(*pdata);
++	CVMX_MT_AES_DEC_CBC1(*data);
++	CVMX_MF_AES_RESULT(*pdata, 0);
++	CVMX_MF_AES_RESULT(*data, 1);
++	crypt_len -= 16;
++
++	*pdata32[0] = mydata[0].data32[0];
++	*pdata32[1] = mydata[0].data32[1];
++	*pdata32[2] = mydata[1].data32[0];
++	*data32     = mydata[1].data32[1];
++
++	SG_CONSUME(sg, data32, data_i, data_l);
++    }
++
++    /* finish and leftover hashing */
++    while (auth_len > 0) {
++	mydata[0].data32[0] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	mydata[0].data32[1] = *data32;
++	SG_CONSUME(sg, data32, data_i, data_l);
++	CVM_LOAD_SHA_UNIT(*pdata, next);
++	auth_len -= 8;
++    }
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_SHA_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* Finish Inner hash */
++    while (next != 7) {
++	CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
++    }
++	CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
++
++    /* Get the inner hash of HMAC */
++    CVMX_MF_HSH_IV(tmp1, 0);
++    CVMX_MF_HSH_IV(tmp2, 1);
++    tmp3 = 0;
++    CVMX_MF_HSH_IV(tmp3, 2);
++
++    /* Initialize hash unit */
++    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
++    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
++    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
++
++    CVMX_MT_HSH_DAT(tmp1, 0);
++    CVMX_MT_HSH_DAT(tmp2, 1);
++    tmp3 |= 0x0000000080000000;
++    CVMX_MT_HSH_DAT(tmp3, 2);
++    CVMX_MT_HSH_DATZ(3);
++    CVMX_MT_HSH_DATZ(4);
++    CVMX_MT_HSH_DATZ(5);
++    CVMX_MT_HSH_DATZ(6);
++    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
++
++    /* finish the hash */
++    CVMX_PREFETCH0(od->octo_hmouter);
++#if 0
++    if (unlikely(inplen)) {
++	uint64_t tmp = 0;
++	uint8_t *p = (uint8_t *) & tmp;
++	p[inplen] = 0x80;
++	do {
++	    inplen--;
++	    p[inplen] = ((uint8_t *) data)[inplen];
++	} while (inplen);
++	CVM_LOAD_MD5_UNIT(tmp, next);
++    } else {
++	CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++    }
++#else
++    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
++#endif
++
++    /* save the HMAC */
++    SG_INIT(sg, data32, data_i, data_l);
++    while (icv_off > 0) {
++	SG_CONSUME(sg, data32, data_i, data_l);
++	icv_off -= 4;
++    }
++    CVMX_MF_HSH_IV(tmp1, 0);
++    *data32 = (uint32_t) (tmp1 >> 32);
++    SG_CONSUME(sg, data32, data_i, data_l);
++    *data32 = (uint32_t) tmp1;
++    SG_CONSUME(sg, data32, data_i, data_l);
++    CVMX_MF_HSH_IV(tmp1, 1);
++    *data32 = (uint32_t) (tmp1 >> 32);
++
++    octeon_crypto_disable(&state, flags);
++    return 0;
++}
++
++/****************************************************************************/
+diff --git a/crypto/ocf/cryptocteon/cryptocteon.c b/crypto/ocf/cryptocteon/cryptocteon.c
+new file mode 100644
+index 0000000..9940f59
+--- /dev/null
++++ b/crypto/ocf/cryptocteon/cryptocteon.c
+@@ -0,0 +1,574 @@
++/*
++ * Octeon Crypto for OCF
++ *
++ * Written by David McCullough <david_mccullough@mcafee.com>
++ * Copyright (C) 2009-2010 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.
++ *
++ * 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 <linux/scatterlist.h>
++
++#include <cryptodev.h>
++#include <uio.h>
++
++struct {
++	softc_device_decl	sc_dev;
++} octo_softc;
++
++#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
++
++struct octo_sess {
++	int					 octo_encalg;
++	#define MAX_CIPHER_KEYLEN	64
++	char				 octo_enckey[MAX_CIPHER_KEYLEN];
++	int					 octo_encklen;
++
++	int					 octo_macalg;
++	#define MAX_HASH_KEYLEN	64
++	char				 octo_mackey[MAX_HASH_KEYLEN];
++	int					 octo_macklen;
++	int					 octo_mackey_set;
++
++	int					 octo_mlen;
++	int					 octo_ivsize;
++
++#if 0
++	int					(*octo_decrypt)(struct scatterlist *sg, int sg_len,
++							uint8_t *key, int key_len, uint8_t * iv,
++							uint64_t *hminner, uint64_t *hmouter);
++
++	int					(*octo_encrypt)(struct scatterlist *sg, int sg_len,
++							uint8_t *key, int key_len, uint8_t * iv,
++							uint64_t *hminner, uint64_t *hmouter);
++#else
++	int					(*octo_encrypt)(struct octo_sess *od,
++	                      struct scatterlist *sg, int sg_len,
++						  int auth_off, int auth_len,
++						  int crypt_off, int crypt_len,
++						  int icv_off, uint8_t *ivp);
++	int					(*octo_decrypt)(struct octo_sess *od,
++	                      struct scatterlist *sg, int sg_len,
++						  int auth_off, int auth_len,
++						  int crypt_off, int crypt_len,
++						  int icv_off, uint8_t *ivp);
++#endif
++
++	uint64_t			 octo_hminner[3];
++	uint64_t			 octo_hmouter[3];
++};
++
++int32_t octo_id = -1;
++module_param(octo_id, int, 0444);
++MODULE_PARM_DESC(octo_id, "Read-Only OCF ID for cryptocteon driver");
++
++static struct octo_sess **octo_sessions = NULL;
++static u_int32_t octo_sesnum = 0;
++
++static	int octo_process(device_t, struct cryptop *, int);
++static	int octo_newsession(device_t, u_int32_t *, struct cryptoini *);
++static	int octo_freesession(device_t, u_int64_t);
++
++static device_method_t octo_methods = {
++	/* crypto device methods */
++	DEVMETHOD(cryptodev_newsession,	octo_newsession),
++	DEVMETHOD(cryptodev_freesession,octo_freesession),
++	DEVMETHOD(cryptodev_process,	octo_process),
++};
++
++#define debug octo_debug
++int octo_debug = 0;
++module_param(octo_debug, int, 0644);
++MODULE_PARM_DESC(octo_debug, "Enable debug");
++
++
++#include "cavium_crypto.c"
++
++
++/*
++ * Generate a new octo session.  We artifically limit it to a single
++ * hash/cipher or hash-cipher combo just to make it easier, most callers
++ * do not expect more than this anyway.
++ */
++static int
++octo_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
++{
++	struct cryptoini *c, *encini = NULL, *macini = NULL;
++	struct octo_sess **ocd;
++	int i;
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid == NULL || cri == NULL) {
++		dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	/*
++	 * To keep it simple, we only handle hash, cipher or hash/cipher in a
++	 * session,  you cannot currently do multiple ciphers/hashes in one
++	 * session even though it would be possibel to code this driver to
++	 * handle it.
++	 */
++	for (i = 0, c = cri; c && i < 2; i++) {
++		if (c->cri_alg == CRYPTO_MD5_HMAC ||
++				c->cri_alg == CRYPTO_SHA1_HMAC ||
++				c->cri_alg == CRYPTO_NULL_HMAC) {
++			if (macini) {
++				break;
++			}
++			macini = c;
++		}
++		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) {
++				break;
++			}
++			encini = c;
++		}
++		c = c->cri_next;
++	}
++	if (!macini && !encini) {
++		dprintk("%s,%d - EINVAL bad cipher/hash or combination\n",
++				__FILE__, __LINE__);
++		return EINVAL;
++	}
++	if (c) {
++		dprintk("%s,%d - EINVAL cannot handle chained cipher/hash combos\n",
++				__FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	/*
++	 * So we have something we can do, lets setup the session
++	 */
++
++	if (octo_sessions) {
++		for (i = 1; i < octo_sesnum; i++)
++			if (octo_sessions[i] == NULL)
++				break;
++	} else
++		i = 1;		/* NB: to silence compiler warning */
++
++	if (octo_sessions == NULL || i == octo_sesnum) {
++		if (octo_sessions == NULL) {
++			i = 1; /* We leave octo_sessions[0] empty */
++			octo_sesnum = CRYPTO_SW_SESSIONS;
++		} else
++			octo_sesnum *= 2;
++
++		ocd = kmalloc(octo_sesnum * sizeof(struct octo_sess *), SLAB_ATOMIC);
++		if (ocd == NULL) {
++			/* Reset session number */
++			if (octo_sesnum == CRYPTO_SW_SESSIONS)
++				octo_sesnum = 0;
++			else
++				octo_sesnum /= 2;
++			dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
++			return ENOBUFS;
++		}
++		memset(ocd, 0, octo_sesnum * sizeof(struct octo_sess *));
++
++		/* Copy existing sessions */
++		if (octo_sessions) {
++			memcpy(ocd, octo_sessions,
++			    (octo_sesnum / 2) * sizeof(struct octo_sess *));
++			kfree(octo_sessions);
++		}
++
++		octo_sessions = ocd;
++	}
++
++	ocd = &octo_sessions[i];
++	*sid = i;
++
++
++	*ocd = (struct octo_sess *) kmalloc(sizeof(struct octo_sess), SLAB_ATOMIC);
++	if (*ocd == NULL) {
++		octo_freesession(NULL, i);
++		dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
++		return ENOBUFS;
++	}
++	memset(*ocd, 0, sizeof(struct octo_sess));
++
++	if (encini && encini->cri_key) {
++		(*ocd)->octo_encklen = (encini->cri_klen + 7) / 8;
++		memcpy((*ocd)->octo_enckey, encini->cri_key, (*ocd)->octo_encklen);
++	}
++
++	if (macini && macini->cri_key) {
++		(*ocd)->octo_macklen = (macini->cri_klen + 7) / 8;
++		memcpy((*ocd)->octo_mackey, macini->cri_key, (*ocd)->octo_macklen);
++	}
++
++	(*ocd)->octo_mlen = 0;
++	if (encini && encini->cri_mlen)
++		(*ocd)->octo_mlen = encini->cri_mlen;
++	else if (macini && macini->cri_mlen)
++		(*ocd)->octo_mlen = macini->cri_mlen;
++	else
++		(*ocd)->octo_mlen = 12;
++
++	/*
++	 * point c at the enc if it exists, otherwise the mac
++	 */
++	c = encini ? encini : macini;
++
++	switch (c->cri_alg) {
++	case CRYPTO_DES_CBC:
++	case CRYPTO_3DES_CBC:
++		(*ocd)->octo_ivsize  = 8;
++		switch (macini ? macini->cri_alg : -1) {
++		case CRYPTO_MD5_HMAC:
++			(*ocd)->octo_encrypt = octo_des_cbc_md5_encrypt;
++			(*ocd)->octo_decrypt = octo_des_cbc_md5_decrypt;
++			octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner,
++					(*ocd)->octo_hmouter);
++			break;
++		case CRYPTO_SHA1_HMAC:
++			(*ocd)->octo_encrypt = octo_des_cbc_sha1_encrypt;
++			(*ocd)->octo_decrypt = octo_des_cbc_sha1_encrypt;
++			octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner,
++					(*ocd)->octo_hmouter);
++			break;
++		case -1:
++			(*ocd)->octo_encrypt = octo_des_cbc_encrypt;
++			(*ocd)->octo_decrypt = octo_des_cbc_decrypt;
++			break;
++		default:
++			octo_freesession(NULL, i);
++			dprintk("%s,%d: EINVALn", __FILE__, __LINE__);
++			return EINVAL;
++		}
++		break;
++	case CRYPTO_AES_CBC:
++		(*ocd)->octo_ivsize  = 16;
++		switch (macini ? macini->cri_alg : -1) {
++		case CRYPTO_MD5_HMAC:
++			(*ocd)->octo_encrypt = octo_aes_cbc_md5_encrypt;
++			(*ocd)->octo_decrypt = octo_aes_cbc_md5_decrypt;
++			octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner,
++					(*ocd)->octo_hmouter);
++			break;
++		case CRYPTO_SHA1_HMAC:
++			(*ocd)->octo_encrypt = octo_aes_cbc_sha1_encrypt;
++			(*ocd)->octo_decrypt = octo_aes_cbc_sha1_decrypt;
++			octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner,
++					(*ocd)->octo_hmouter);
++			break;
++		case -1:
++			(*ocd)->octo_encrypt = octo_aes_cbc_encrypt;
++			(*ocd)->octo_decrypt = octo_aes_cbc_decrypt;
++			break;
++		default:
++			octo_freesession(NULL, i);
++			dprintk("%s,%d: EINVALn", __FILE__, __LINE__);
++			return EINVAL;
++		}
++		break;
++	case CRYPTO_MD5_HMAC:
++		(*ocd)->octo_encrypt = octo_null_md5_encrypt;
++		(*ocd)->octo_decrypt = octo_null_md5_encrypt;
++		octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner,
++				(*ocd)->octo_hmouter);
++		break;
++	case CRYPTO_SHA1_HMAC:
++		(*ocd)->octo_encrypt = octo_null_sha1_encrypt;
++		(*ocd)->octo_decrypt = octo_null_sha1_encrypt;
++		octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner,
++				(*ocd)->octo_hmouter);
++		break;
++	default:
++		octo_freesession(NULL, i);
++		dprintk("%s,%d: EINVALn", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	(*ocd)->octo_encalg = encini ? encini->cri_alg : -1;
++	(*ocd)->octo_macalg = macini ? macini->cri_alg : -1;
++
++	return 0;
++}
++
++/*
++ * Free a session.
++ */
++static int
++octo_freesession(device_t dev, u_int64_t tid)
++{
++	u_int32_t sid = CRYPTO_SESID2LID(tid);
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (sid > octo_sesnum || octo_sessions == NULL ||
++			octo_sessions[sid] == NULL) {
++		dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++		return(EINVAL);
++	}
++
++	/* Silently accept and return */
++	if (sid == 0)
++		return(0);
++
++	if (octo_sessions[sid])
++		kfree(octo_sessions[sid]);
++	octo_sessions[sid] = NULL;
++	return 0;
++}
++
++/*
++ * Process a request.
++ */
++static int
++octo_process(device_t dev, struct cryptop *crp, int hint)
++{
++	struct cryptodesc *crd;
++	struct octo_sess *od;
++	u_int32_t lid;
++#define SCATTERLIST_MAX 16
++	struct scatterlist sg[SCATTERLIST_MAX];
++	int sg_num, sg_len;
++	struct sk_buff *skb = NULL;
++	struct uio *uiop = NULL;
++	struct cryptodesc *enccrd = NULL, *maccrd = NULL;
++	unsigned char *ivp = NULL;
++	unsigned char iv_data[HASH_MAX_LEN];
++	int auth_off = 0, auth_len = 0, crypt_off = 0, crypt_len = 0, icv_off = 0;
++
++	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 >= octo_sesnum || lid == 0 || octo_sessions == NULL ||
++			octo_sessions[lid] == NULL) {
++		crp->crp_etype = ENOENT;
++		dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
++		goto done;
++	}
++	od = octo_sessions[lid];
++
++	/*
++	 * 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;
++		}
++	}
++
++	/* point our enccrd and maccrd appropriately */
++	crd = crp->crp_desc;
++	if (crd->crd_alg == od->octo_encalg) enccrd = crd;
++	if (crd->crd_alg == od->octo_macalg) maccrd = crd;
++	crd = crd->crd_next;
++	if (crd) {
++		if (crd->crd_alg == od->octo_encalg) enccrd = crd;
++		if (crd->crd_alg == od->octo_macalg) maccrd = crd;
++		crd = crd->crd_next;
++	}
++	if (crd) {
++		crp->crp_etype = EINVAL;
++		dprintk("%s,%d: ENOENT - descriptors do not match session\n",
++				__FILE__, __LINE__);
++		goto done;
++	}
++
++	if (enccrd) {
++		if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
++			ivp = enccrd->crd_iv;
++		} else {
++			ivp = iv_data;
++			crypto_copydata(crp->crp_flags, crp->crp_buf,
++					enccrd->crd_inject, od->octo_ivsize, (caddr_t) ivp);
++		}
++
++		if (maccrd) {
++			auth_off = maccrd->crd_skip;
++			auth_len = maccrd->crd_len;
++			icv_off  = maccrd->crd_inject;
++		}
++
++		crypt_off = enccrd->crd_skip;
++		crypt_len = enccrd->crd_len;
++	} else { /* if (maccrd) */
++		auth_off = maccrd->crd_skip;
++		auth_len = maccrd->crd_len;
++		icv_off  = maccrd->crd_inject;
++	}
++
++
++	/*
++	 * setup the SG list to cover the buffer
++	 */
++	memset(sg, 0, sizeof(sg));
++	if (crp->crp_flags & CRYPTO_F_SKBUF) {
++		int i, len;
++
++		sg_num = 0;
++		sg_len = 0;
++
++		len = skb_headlen(skb);
++		sg_set_page(&sg[sg_num], virt_to_page(skb->data), len,
++				offset_in_page(skb->data));
++		sg_len += len;
++		sg_num++;
++
++		for (i = 0; i < skb_shinfo(skb)->nr_frags && sg_num < SCATTERLIST_MAX;
++				i++) {
++			len = skb_shinfo(skb)->frags[i].size;
++			sg_set_page(&sg[sg_num], skb_shinfo(skb)->frags[i].page,
++					len, skb_shinfo(skb)->frags[i].page_offset);
++			sg_len += len;
++			sg_num++;
++		}
++	} else if (crp->crp_flags & CRYPTO_F_IOV) {
++		int len;
++
++		sg_len = 0;
++		for (sg_num = 0; sg_len < crp->crp_ilen &&
++				sg_num < uiop->uio_iovcnt &&
++				sg_num < SCATTERLIST_MAX; sg_num++) {
++			len = uiop->uio_iov[sg_num].iov_len;
++			sg_set_page(&sg[sg_num],
++					virt_to_page(uiop->uio_iov[sg_num].iov_base), len,
++					offset_in_page(uiop->uio_iov[sg_num].iov_base));
++			sg_len += len;
++		}
++	} else {
++		sg_len = crp->crp_ilen;
++		sg_set_page(&sg[0], virt_to_page(crp->crp_buf), sg_len,
++				offset_in_page(crp->crp_buf));
++		sg_num = 1;
++	}
++
++
++	/*
++	 * setup a new explicit key
++	 */
++	if (enccrd) {
++		if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
++			od->octo_encklen = (enccrd->crd_klen + 7) / 8;
++			memcpy(od->octo_enckey, enccrd->crd_key, od->octo_encklen);
++		}
++	}
++	if (maccrd) {
++		if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
++			od->octo_macklen = (maccrd->crd_klen + 7) / 8;
++			memcpy(od->octo_mackey, maccrd->crd_key, od->octo_macklen);
++			od->octo_mackey_set = 0;
++		}
++		if (!od->octo_mackey_set) {
++			octo_calc_hash(maccrd->crd_alg == CRYPTO_MD5_HMAC ? 0 : 1,
++				maccrd->crd_key, od->octo_hminner, od->octo_hmouter);
++			od->octo_mackey_set = 1;
++		}
++	}
++
++
++	if (!enccrd || (enccrd->crd_flags & CRD_F_ENCRYPT))
++		(*od->octo_encrypt)(od, sg, sg_len,
++				auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++	else
++		(*od->octo_decrypt)(od, sg, sg_len,
++				auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
++
++done:
++	crypto_done(crp);
++	return 0;
++}
++
++static int
++cryptocteon_init(void)
++{
++	dprintk("%s(%p)\n", __FUNCTION__, cryptocteon_init);
++
++	softc_device_init(&octo_softc, "cryptocteon", 0, octo_methods);
++
++	octo_id = crypto_get_driverid(softc_get_device(&octo_softc),
++			CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SYNC);
++	if (octo_id < 0) {
++		printk("Cryptocteon device cannot initialize!");
++		return -ENODEV;
++	}
++
++	crypto_register(octo_id, CRYPTO_MD5_HMAC, 0,0);
++	crypto_register(octo_id, CRYPTO_SHA1_HMAC, 0,0);
++	//crypto_register(octo_id, CRYPTO_MD5, 0,0);
++	//crypto_register(octo_id, CRYPTO_SHA1, 0,0);
++	crypto_register(octo_id, CRYPTO_DES_CBC, 0,0);
++	crypto_register(octo_id, CRYPTO_3DES_CBC, 0,0);
++	crypto_register(octo_id, CRYPTO_AES_CBC, 0,0);
++
++	return(0);
++}
++
++static void
++cryptocteon_exit(void)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	crypto_unregister_all(octo_id);
++	octo_id = -1;
++}
++
++module_init(cryptocteon_init);
++module_exit(cryptocteon_exit);
++
++MODULE_LICENSE("BSD");
++MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
++MODULE_DESCRIPTION("Cryptocteon (OCF module for Cavium OCTEON crypto)");
+diff --git a/crypto/ocf/cryptodev.c b/crypto/ocf/cryptodev.c
+new file mode 100644
+index 0000000..87a4c37
+--- /dev/null
++++ b/crypto/ocf/cryptodev.c
+@@ -0,0 +1,1061 @@
++/*	$OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $	*/
++
++/*-
++ * Linux port done by David McCullough <david_mccullough@mcafee.com>
++ * Copyright (C) 2006-2010 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	authkey;
++	/* 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__,
++				(int)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 && cse->info.blocksize) {
++		if (cop->op == COP_ENCRYPT) {
++			crde = crp->crp_desc;
++			crda = crde->crd_next;
++		} else {
++			crda = crp->crp_desc;
++			crde = crda->crd_next;
++		}
++	} else if (cse->info.authsize) {
++		crda = crp->crp_desc;
++	} 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) {
++		dprintk("%s error in crypto_dispatch\n", __FUNCTION__);
++		goto bail;
++	}
++
++	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 = 0;
++	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;
++			info.authkey = 16;
++			break;
++		case CRYPTO_SHA1_HMAC:
++			info.authsize = SHA1_HASH_LEN;
++			info.authkey = 20;
++			break;
++		case CRYPTO_SHA2_256_HMAC:
++			info.authsize = SHA2_256_HASH_LEN;
++			info.authkey = 32;
++			break;
++		case CRYPTO_SHA2_384_HMAC:
++			info.authsize = SHA2_384_HASH_LEN;
++			info.authkey = 48;
++			break;
++		case CRYPTO_SHA2_512_HMAC:
++			info.authsize = SHA2_512_HASH_LEN;
++			info.authkey = 64;
++			break;
++		case CRYPTO_RIPEMD160_HMAC:
++			info.authsize = RIPEMD160_HASH_LEN;
++			info.authkey = 20;
++			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.authkey && sop.mackeylen != info.authkey) {
++				dprintk("%s(%s) - mackeylen %d != %d\n", __FUNCTION__,
++						CIOCGSESSSTR, sop.mackeylen, info.authkey);
++				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@mcafee.com>");
++MODULE_DESCRIPTION("Cryptodev (user interface to OCF)");
+diff --git a/crypto/ocf/cryptodev.h b/crypto/ocf/cryptodev.h
+new file mode 100644
+index 0000000..6032317
+--- /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@mcafee.com>
++ * Copyright (C) 2006-2010 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 100644
+index 0000000..52e1570
+--- /dev/null
++++ b/crypto/ocf/cryptosoft.c
+@@ -0,0 +1,1210 @@
++/*
++ * 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@mcafee.com>
++ * Copyright (C) 2004-2010 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 <linux/version.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
++#include <linux/scatterlist.h>
++#endif
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
++#include <crypto/hash.h>
++#endif
++
++#include <cryptodev.h>
++#include <uio.h>
++
++struct {
++	softc_device_decl	sc_dev;
++} swcr_softc;
++
++#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
++
++#define SW_TYPE_CIPHER		0x01
++#define SW_TYPE_HMAC		0x02
++#define SW_TYPE_HASH		0x04
++#define SW_TYPE_COMP		0x08
++#define SW_TYPE_BLKCIPHER	0x10
++#define SW_TYPE_ALG_MASK	0x1f
++
++#define SW_TYPE_ASYNC		0x8000
++
++/* We change some of the above if we have an async interface */
++
++#define SW_TYPE_ALG_AMASK	(SW_TYPE_ALG_MASK | SW_TYPE_ASYNC)
++
++#define SW_TYPE_ABLKCIPHER	(SW_TYPE_BLKCIPHER | SW_TYPE_ASYNC)
++#define SW_TYPE_AHASH		(SW_TYPE_HASH | SW_TYPE_ASYNC)
++#define SW_TYPE_AHMAC		(SW_TYPE_HMAC | SW_TYPE_ASYNC)
++
++#define SCATTERLIST_MAX 16
++
++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;
++};
++
++struct swcr_req {
++	struct swcr_data	*sw_head;
++	struct swcr_data	*sw;
++	struct cryptop		*crp;
++	struct cryptodesc	*crd;
++	struct scatterlist	 sg[SCATTERLIST_MAX];
++	unsigned char		 iv[EALG_MAX_BLOCK_LEN];
++	char				 result[HASH_MAX_LEN];
++	void				*crypto_req;
++};
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++static kmem_cache_t *swcr_req_cache;
++#else
++static struct kmem_cache *swcr_req_cache;
++#endif
++
++#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 , CRYPTO_TFM_MODE_ECB
++	#define cbc(X)								#X , CRYPTO_TFM_MODE_CBC
++	#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))
++	#define crypto_blkcipher_set_flags(x, y)	/* nop */
++
++	/* Hash/HMAC/Digest */
++	struct hash_desc
++	{
++		struct crypto_tfm *tfm;
++	};
++	#define hmac(X)							#X , 0
++	#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)
++	#define plain(X)	#X , 0
++#else
++	#define ecb(X)	"ecb(" #X ")" , 0
++	#define cbc(X)	"cbc(" #X ")" , 0
++	#define hmac(X)	"hmac(" #X ")" , 0
++	#define plain(X)	#X , 0
++#endif /* if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
++/* no ablkcipher in older kernels */
++#define crypto_alloc_ablkcipher(a,b,c)		(NULL)
++#define crypto_ablkcipher_tfm(x)			((struct crypto_tfm *)(x))
++#define crypto_ablkcipher_set_flags(a, b)	/* nop */
++#define crypto_ablkcipher_setkey(x, y, z)	(-EINVAL)
++#define	crypto_has_ablkcipher(a,b,c)		(0)
++#else
++#define	HAVE_ABLKCIPHER
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
++/* no ahash in older kernels */
++#define crypto_ahash_tfm(x)					((struct crypto_tfm *)(x))
++#define	crypto_alloc_ahash(a,b,c)			(NULL)
++#define	crypto_ahash_digestsize(x)			0
++#else
++#define	HAVE_AHASH
++#endif
++
++struct crypto_details {
++	char *alg_name;
++	int mode;
++	int sw_type;
++};
++
++static struct crypto_details crypto_details[] = {
++	[CRYPTO_DES_CBC]         = { cbc(des),          SW_TYPE_BLKCIPHER, },
++	[CRYPTO_3DES_CBC]        = { cbc(des3_ede),     SW_TYPE_BLKCIPHER, },
++	[CRYPTO_BLF_CBC]         = { cbc(blowfish),     SW_TYPE_BLKCIPHER, },
++	[CRYPTO_CAST_CBC]        = { cbc(cast5),        SW_TYPE_BLKCIPHER, },
++	[CRYPTO_SKIPJACK_CBC]    = { cbc(skipjack),     SW_TYPE_BLKCIPHER, },
++	[CRYPTO_MD5_HMAC]        = { hmac(md5),         SW_TYPE_HMAC, },
++	[CRYPTO_SHA1_HMAC]       = { hmac(sha1),        SW_TYPE_HMAC, },
++	[CRYPTO_RIPEMD160_HMAC]  = { hmac(ripemd160),   SW_TYPE_HMAC, },
++	[CRYPTO_MD5_KPDK]        = { plain(md5-kpdk),   SW_TYPE_HASH, },
++	[CRYPTO_SHA1_KPDK]       = { plain(sha1-kpdk),  SW_TYPE_HASH, },
++	[CRYPTO_AES_CBC]         = { cbc(aes),          SW_TYPE_BLKCIPHER, },
++	[CRYPTO_ARC4]            = { ecb(arc4),         SW_TYPE_BLKCIPHER, },
++	[CRYPTO_MD5]             = { plain(md5),        SW_TYPE_HASH, },
++	[CRYPTO_SHA1]            = { plain(sha1),       SW_TYPE_HASH, },
++	[CRYPTO_NULL_HMAC]       = { hmac(digest_null), SW_TYPE_HMAC, },
++	[CRYPTO_NULL_CBC]        = { cbc(cipher_null),  SW_TYPE_BLKCIPHER, },
++	[CRYPTO_DEFLATE_COMP]    = { plain(deflate),    SW_TYPE_COMP, },
++	[CRYPTO_SHA2_256_HMAC]   = { hmac(sha256),      SW_TYPE_HMAC, },
++	[CRYPTO_SHA2_384_HMAC]   = { hmac(sha384),      SW_TYPE_HMAC, },
++	[CRYPTO_SHA2_512_HMAC]   = { hmac(sha512),      SW_TYPE_HMAC, },
++	[CRYPTO_CAMELLIA_CBC]    = { cbc(camellia),     SW_TYPE_BLKCIPHER, },
++	[CRYPTO_SHA2_256]        = { plain(sha256),     SW_TYPE_HASH, },
++	[CRYPTO_SHA2_384]        = { plain(sha384),     SW_TYPE_HASH, },
++	[CRYPTO_SHA2_512]        = { plain(sha512),     SW_TYPE_HASH, },
++	[CRYPTO_RIPEMD160]       = { plain(ripemd160),  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");
++
++int swcr_no_ahash = 0;
++module_param(swcr_no_ahash, int, 0644);
++MODULE_PARM_DESC(swcr_no_ahash,
++                "Do not use async hash/hmac even if available");
++
++int swcr_no_ablk = 0;
++module_param(swcr_no_ablk, int, 0644);
++MODULE_PARM_DESC(swcr_no_ablk,
++                "Do not use async blk ciphers even if available");
++
++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");
++
++static void swcr_process_req(struct swcr_req *req);
++
++/*
++ * 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;
++
++	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 < 0 ||
++				cri->cri_alg>=sizeof(crypto_details)/sizeof(crypto_details[0])){
++			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;
++		(*swd)->sw_type = crypto_details[cri->cri_alg].sw_type;
++		(*swd)->sw_alg = cri->cri_alg;
++
++		/* 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 ((*swd)->sw_type & SW_TYPE_BLKCIPHER) {
++			dprintk("%s crypto_alloc_*blkcipher(%s, 0x%x)\n", __FUNCTION__,
++					algo, mode);
++
++			/* try async first */
++			(*swd)->sw_tfm = swcr_no_ablk ? NULL :
++					crypto_ablkcipher_tfm(crypto_alloc_ablkcipher(algo, 0, 0));
++			if ((*swd)->sw_tfm) {
++				dprintk("%s %s cipher is async\n", __FUNCTION__, algo);
++				(*swd)->sw_type |= SW_TYPE_ASYNC;
++			} else {
++				dprintk("%s %s cipher is sync\n", __FUNCTION__, algo);
++				(*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] & 0xff);
++				dprintk("\n");
++			}
++			if ((*swd)->sw_type & SW_TYPE_ASYNC) {
++				/* OCF doesn't enforce keys */
++				crypto_ablkcipher_set_flags(
++						__crypto_ablkcipher_cast((*swd)->sw_tfm),
++							CRYPTO_TFM_REQ_WEAK_KEY);
++				error = crypto_ablkcipher_setkey(
++							__crypto_ablkcipher_cast((*swd)->sw_tfm),
++								cri->cri_key, (cri->cri_klen + 7) / 8);
++			} else {
++				/* OCF doesn't enforce keys */
++				crypto_blkcipher_set_flags(
++						crypto_blkcipher_cast((*swd)->sw_tfm),
++							CRYPTO_TFM_REQ_WEAK_KEY);
++				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 ((*swd)->sw_type & (SW_TYPE_HMAC | SW_TYPE_HASH)) {
++			dprintk("%s crypto_alloc_*hash(%s, 0x%x)\n", __FUNCTION__,
++					algo, mode);
++
++			/* try async first */
++			(*swd)->sw_tfm = swcr_no_ahash ? NULL :
++					crypto_ahash_tfm(crypto_alloc_ahash(algo, 0, 0));
++			if ((*swd)->sw_tfm) {
++				dprintk("%s %s hash is async\n", __FUNCTION__, algo);
++				(*swd)->sw_type |= SW_TYPE_ASYNC;
++			} else {
++				dprintk("%s %s hash is sync\n", __FUNCTION__, algo);
++				(*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 if ((*swd)->sw_type & SW_TYPE_ASYNC) {
++				(*swd)->u.hmac.sw_mlen = crypto_ahash_digestsize(
++						__crypto_ahash_cast((*swd)->sw_tfm));
++			} else  {
++				(*swd)->u.hmac.sw_mlen = crypto_hash_digestsize(
++						crypto_hash_cast((*swd)->sw_tfm));
++			}
++		} else if ((*swd)->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", (*swd)->sw_type);
++			swcr_freesession(NULL, i);
++			return EINVAL;
++		}
++
++		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) {
++			switch (swd->sw_type & SW_TYPE_ALG_AMASK) {
++#ifdef HAVE_AHASH
++			case SW_TYPE_AHMAC:
++			case SW_TYPE_AHASH:
++				crypto_free_ahash(__crypto_ahash_cast(swd->sw_tfm));
++				break;
++#endif
++#ifdef HAVE_ABLKCIPHER
++			case SW_TYPE_ABLKCIPHER:
++				crypto_free_ablkcipher(__crypto_ablkcipher_cast(swd->sw_tfm));
++				break;
++#endif
++			case SW_TYPE_BLKCIPHER:
++				crypto_free_blkcipher(crypto_blkcipher_cast(swd->sw_tfm));
++				break;
++			case SW_TYPE_HMAC:
++			case SW_TYPE_HASH:
++				crypto_free_hash(crypto_hash_cast(swd->sw_tfm));
++				break;
++			case SW_TYPE_COMP:
++				crypto_free_comp(crypto_comp_cast(swd->sw_tfm));
++			default:
++				crypto_free_tfm(swd->sw_tfm);
++				break;
++			}
++			swd->sw_tfm = NULL;
++		}
++		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;
++}
++
++#if defined(HAVE_ABLKCIPHER) || defined(HAVE_AHASH)
++/* older kernels had no async interface */
++
++static void swcr_process_callback(struct crypto_async_request *creq, int err)
++{
++	struct swcr_req *req = creq->data;
++
++	dprintk("%s()\n", __FUNCTION__);
++	if (err) {
++		if (err == -EINPROGRESS)
++			return;
++		dprintk("%s() fail %d\n", __FUNCTION__, -err);
++		req->crp->crp_etype = -err;
++		goto done;
++	}
++
++	switch (req->sw->sw_type & SW_TYPE_ALG_AMASK) {
++	case SW_TYPE_AHMAC:
++	case SW_TYPE_AHASH:
++		crypto_copyback(req->crp->crp_flags, req->crp->crp_buf,
++				req->crd->crd_inject, req->sw->u.hmac.sw_mlen, req->result);
++		ahash_request_free(req->crypto_req);
++		break;
++	case SW_TYPE_ABLKCIPHER:
++		ablkcipher_request_free(req->crypto_req);
++		break;
++	default:
++		req->crp->crp_etype = EINVAL;
++		goto done;
++	}
++
++	req->crd = req->crd->crd_next;
++	if (req->crd) {
++		swcr_process_req(req);
++		return;
++	}
++
++done:
++	dprintk("%s crypto_done %p\n", __FUNCTION__, req);
++	crypto_done(req->crp);
++	kmem_cache_free(swcr_req_cache, req);
++}
++#endif /* defined(HAVE_ABLKCIPHER) || defined(HAVE_AHASH) */
++
++
++static void swcr_process_req(struct swcr_req *req)
++{
++	struct swcr_data *sw;
++	struct cryptop *crp = req->crp;
++	struct cryptodesc *crd = req->crd;
++	struct sk_buff *skb = (struct sk_buff *) crp->crp_buf;
++	struct uio *uiop = (struct uio *) crp->crp_buf;
++	int sg_num, sg_len, skip;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	/*
++	 * 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 = req->sw_head; 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;
++	}
++
++	req->sw = sw;
++	skip = crd->crd_skip;
++
++	/*
++	 * setup the SG list skip from the start of the buffer
++	 */
++	memset(req->sg, 0, sizeof(req->sg));
++	sg_init_table(req->sg, SCATTERLIST_MAX);
++	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(&req->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(&req->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(&req->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(&req->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 & SW_TYPE_ALG_AMASK) {
++
++#ifdef HAVE_AHASH
++	case SW_TYPE_AHMAC:
++	case SW_TYPE_AHASH:
++		{
++		int ret;
++
++		/* 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;
++		}
++
++		req->crypto_req =
++				ahash_request_alloc(__crypto_ahash_cast(sw->sw_tfm),GFP_KERNEL);
++		if (!req->crypto_req) {
++			crp->crp_etype = ENOMEM;
++			dprintk("%s,%d: ENOMEM ahash_request_alloc", __FILE__, __LINE__);
++			goto done;
++		}
++
++		ahash_request_set_callback(req->crypto_req,
++				CRYPTO_TFM_REQ_MAY_BACKLOG, swcr_process_callback, req);
++
++		memset(req->result, 0, sizeof(req->result));
++
++		if (sw->sw_type & SW_TYPE_AHMAC)
++			crypto_ahash_setkey(__crypto_ahash_cast(sw->sw_tfm),
++					sw->u.hmac.sw_key, sw->u.hmac.sw_klen);
++		ahash_request_set_crypt(req->crypto_req, req->sg, req->result, sg_len);
++		ret = crypto_ahash_digest(req->crypto_req);
++		switch (ret) {
++		case -EINPROGRESS:
++		case -EBUSY:
++			return;
++		default:
++		case 0:
++			dprintk("hash OP %s %d\n", ret ? "failed" : "success", ret);
++			crp->crp_etype = ret;
++			ahash_request_free(req->crypto_req);
++			goto done;
++		}
++		} break;
++#endif /* HAVE_AHASH */
++
++#ifdef HAVE_ABLKCIPHER
++	case SW_TYPE_ABLKCIPHER: {
++		int ret;
++		unsigned char *ivp = req->iv;
++		int ivsize =
++			crypto_ablkcipher_ivsize(__crypto_ablkcipher_cast(sw->sw_tfm));
++
++		if (sg_len < crypto_ablkcipher_blocksize(
++				__crypto_ablkcipher_cast(sw->sw_tfm))) {
++			crp->crp_etype = EINVAL;
++			dprintk("%s,%d: EINVAL len %d < %d\n", __FILE__, __LINE__,
++					sg_len, crypto_ablkcipher_blocksize(
++						__crypto_ablkcipher_cast(sw->sw_tfm)));
++			goto done;
++		}
++
++		if (ivsize > sizeof(req->iv)) {
++			crp->crp_etype = EINVAL;
++			dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++			goto done;
++		}
++
++		req->crypto_req = ablkcipher_request_alloc(
++				__crypto_ablkcipher_cast(sw->sw_tfm), GFP_KERNEL);
++		if (!req->crypto_req) {
++			crp->crp_etype = ENOMEM;
++			dprintk("%s,%d: ENOMEM ablkcipher_request_alloc",
++					__FILE__, __LINE__);
++			goto done;
++		}
++
++		ablkcipher_request_set_callback(req->crypto_req,
++				CRYPTO_TFM_REQ_MAY_BACKLOG, swcr_process_callback, req);
++
++		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] & 0xff);
++				dprintk("\n");
++			}
++			/* OCF doesn't enforce keys */
++			crypto_ablkcipher_set_flags(__crypto_ablkcipher_cast(sw->sw_tfm),
++					CRYPTO_TFM_REQ_WEAK_KEY);
++			error = crypto_ablkcipher_setkey(
++						__crypto_ablkcipher_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;
++			}
++		}
++
++		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);
++			}
++			ablkcipher_request_set_crypt(req->crypto_req, req->sg, req->sg,
++					sg_len, ivp);
++			ret = crypto_ablkcipher_encrypt(req->crypto_req);
++
++		} 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);
++			ablkcipher_request_set_crypt(req->crypto_req, req->sg, req->sg,
++					sg_len, ivp);
++			ret = crypto_ablkcipher_decrypt(req->crypto_req);
++		}
++
++		switch (ret) {
++		case -EINPROGRESS:
++		case -EBUSY:
++			return;
++		default:
++		case 0:
++			dprintk("crypto OP %s %d\n", ret ? "failed" : "success", ret);
++			crp->crp_etype = ret;
++			goto done;
++		}
++		} break;
++#endif /* HAVE_ABLKCIPHER */
++
++	case SW_TYPE_BLKCIPHER: {
++		unsigned char iv[EALG_MAX_BLOCK_LEN];
++		unsigned char *ivp = iv;
++		struct blkcipher_desc desc;
++		int ivsize = crypto_blkcipher_ivsize(crypto_blkcipher_cast(sw->sw_tfm));
++
++		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] & 0xff);
++				dprintk("\n");
++			}
++			/* OCF doesn't enforce keys */
++			crypto_blkcipher_set_flags(crypto_blkcipher_cast(sw->sw_tfm),
++					CRYPTO_TFM_REQ_WEAK_KEY);
++			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, req->sg, req->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, req->sg, req->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,
++					req->sg, sg_num, result);
++#else
++			crypto_hash_setkey(desc.tfm, sw->u.hmac.sw_key,
++					sw->u.hmac.sw_klen);
++			crypto_hash_digest(&desc, req->sg, sg_len, result);
++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
++
++		} else { /* SW_TYPE_HASH */
++			crypto_hash_digest(&desc, req->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(&req->sg[blk]),
++						req->sg[blk].length);
++				obuf += req->sg[blk].length;
++			}
++			olen -= sg_len;
++		} else
++			ibuf = sg_virt(&req->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);
++	kmem_cache_free(swcr_req_cache, req);
++}
++
++
++/*
++ * Process a crypto request.
++ */
++static int
++swcr_process(device_t dev, struct cryptop *crp, int hint)
++{
++	struct swcr_req *req = NULL;
++	u_int32_t 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;
++	}
++
++	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) {
++		struct sk_buff *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) {
++		struct uio *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;
++		}
++	}
++
++	/*
++	 * setup a new request ready for queuing
++	 */
++	req = kmem_cache_alloc(swcr_req_cache, SLAB_ATOMIC);
++	if (req == NULL) {
++		dprintk("%s,%d: ENOMEM\n", __FILE__, __LINE__);
++		crp->crp_etype = ENOMEM;
++		goto done;
++	}
++	memset(req, 0, sizeof(*req));
++
++	req->sw_head = swcr_sessions[lid];
++	req->crp = crp;
++	req->crd = crp->crp_desc;
++
++	swcr_process_req(req);
++	return 0;
++
++done:
++	crypto_done(crp);
++	if (req)
++		kmem_cache_free(swcr_req_cache, req);
++	return 0;
++}
++
++
++static int
++cryptosoft_init(void)
++{
++	int i, sw_type, mode;
++	char *algo;
++
++	dprintk("%s(%p)\n", __FUNCTION__, cryptosoft_init);
++
++	swcr_req_cache = kmem_cache_create("cryptosoft_req",
++				sizeof(struct swcr_req), 0, SLAB_HWCACHE_ALIGN, NULL
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
++				, NULL
++#endif
++				);
++	if (!swcr_req_cache) {
++		printk("cryptosoft: failed to create request cache\n");
++		return -ENOENT;
++	}
++
++	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("cryptosoft: Software crypto device cannot initialize!");
++		return -ENODEV;
++	}
++
++#define	REGISTER(alg) \
++		crypto_register(swcr_id, alg, 0,0)
++
++	for (i = 0; i < sizeof(crypto_details)/sizeof(crypto_details[0]); i++) {
++		int found;
++
++		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;
++
++		found = 0;
++		switch (sw_type & SW_TYPE_ALG_MASK) {
++		case SW_TYPE_CIPHER:
++			found = crypto_has_cipher(algo, 0, CRYPTO_ALG_ASYNC);
++			break;
++		case SW_TYPE_HMAC:
++			found = crypto_has_hash(algo, 0, swcr_no_ahash?CRYPTO_ALG_ASYNC:0);
++			break;
++		case SW_TYPE_HASH:
++			found = crypto_has_hash(algo, 0, swcr_no_ahash?CRYPTO_ALG_ASYNC:0);
++			break;
++		case SW_TYPE_COMP:
++			found = crypto_has_comp(algo, 0, CRYPTO_ALG_ASYNC);
++			break;
++		case SW_TYPE_BLKCIPHER:
++			found = crypto_has_blkcipher(algo, 0, CRYPTO_ALG_ASYNC);
++			if (!found && !swcr_no_ablk)
++				found = crypto_has_ablkcipher(algo, 0, 0);
++			break;
++		}
++		if (found) {
++			REGISTER(i);
++		} else {
++			dprintk("%s:Algorithm Type %d not supported (algorithm %d:'%s')\n",
++					__FUNCTION__, sw_type, i, algo);
++		}
++	}
++	return 0;
++}
++
++static void
++cryptosoft_exit(void)
++{
++	dprintk("%s()\n", __FUNCTION__);
++	crypto_unregister_all(swcr_id);
++	swcr_id = -1;
++	kmem_cache_destroy(swcr_req_cache);
++}
++
++late_initcall(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 100644
+index 0000000..9aab295
+--- /dev/null
++++ b/crypto/ocf/ep80579/Makefile
+@@ -0,0 +1,119 @@
++#########################################################################
++#
++#  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,2009 Intel Corporation. All rights reserved.
++#
++#   This program is free software; you can redistribute it and/or modify
++#   it under the terms of version 2 of the GNU General Public License as
++#   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,2009 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.2-229
++############################################################################
++
++
++####################Common variables and definitions########################
++
++ifndef ICP_ROOT
++$(warning ICP_ROOT is undefined. Please set the path to EP80579 release package directory \
++        "-> setenv ICP_ROOT <path>")
++all fastdep:
++	:
++else
++
++ifndef KERNEL_SOURCE_ROOT
++$(error KERNEL_SOURCE_ROOT is undefined. Please set the path to the kernel source directory \
++        "-> setenv KERNEL_SOURCE_ROOT <path>")
++endif
++
++# Ensure The ENV_DIR environmental var is defined.
++ifndef ICP_ENV_DIR
++$(error ICP_ENV_DIR is undefined. Please set the path to EP80579 driver environment.mk file \
++        "-> 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 icp_ocf_linux.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 shown below
++install: module
++
++###################Include rules makefiles########################
++include ${ICP_BUILDSYSTEM_PATH}/build_files/rules.mk
++###################End of Rules inclusion#########################
++
++endif
+diff --git a/crypto/ocf/ep80579/icp_asym.c b/crypto/ocf/ep80579/icp_asym.c
+new file mode 100644
+index 0000000..d2641c5
+--- /dev/null
++++ b/crypto/ocf/ep80579/icp_asym.c
+@@ -0,0 +1,1334 @@
++/***************************************************************************
++ *
++ * 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,2009 Intel Corporation. All rights reserved.
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of version 2 of the GNU General Public License as
++ *   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,2009 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.2-229
++ *
++ ***************************************************************************/
++
++#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)
++
++/*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)
++
++/*Function to compute Diffie Hellman (DH) phase 1 or phase 2 key values*/
++static int icp_ocfDrvDHComputeKey(struct cryptkop *krp);
++
++/*Function to compute a Modular Exponentiation (Mod Exp)*/
++static int icp_ocfDrvModExp(struct cryptkop *krp);
++
++/*Function to compute a Mod Exp using the Chinease Remainder Theorem*/
++static int icp_ocfDrvModExpCRT(struct cryptkop *krp);
++
++/*Helper function to compute whether the first big number argument is less than
++ the second big number argument */
++static int
++icp_ocfDrvCheckALessThanB(CpaFlatBuffer * pK, CpaFlatBuffer * pQ, int *doCheck);
++
++/*Function to sign an input with DSA R and S keys*/
++static int icp_ocfDrvDsaSign(struct cryptkop *krp);
++
++/*Function to Verify a DSA buffer signature*/
++static int icp_ocfDrvDsaVerify(struct cryptkop *krp);
++
++/*Callback function for DH operation*/
++static void
++icp_ocfDrvDhP1CallBack(void *callbackTag,
++		       CpaStatus status,
++		       void *pOpData, CpaFlatBuffer * pLocalOctetStringPV);
++
++/*Callback function for ME operation*/
++static void
++icp_ocfDrvModExpCallBack(void *callbackTag,
++			 CpaStatus status,
++			 void *pOpData, CpaFlatBuffer * pResult);
++
++/*Callback function for ME CRT operation*/
++static void
++icp_ocfDrvModExpCRTCallBack(void *callbackTag,
++			    CpaStatus status,
++			    void *pOpData, CpaFlatBuffer * pOutputData);
++
++/*Callback function for DSA sign operation*/
++static void
++icp_ocfDrvDsaRSSignCallBack(void *callbackTag,
++			    CpaStatus status,
++			    void *pOpData,
++			    CpaBoolean protocolStatus,
++			    CpaFlatBuffer * pR, CpaFlatBuffer * pS);
++
++/*Callback function for DSA Verify operation*/
++static void
++icp_ocfDrvDsaVerifyCallBack(void *callbackTag,
++			    CpaStatus status,
++			    void *pOpData, CpaBoolean verifyStatus);
++
++/* Name        : icp_ocfDrvPkeProcess
++ *
++ * Description : This function will choose which PKE process to follow
++ * based on the input arguments
++ */
++int icp_ocfDrvPkeProcess(icp_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 == icp_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;
++
++/*All allocations are set to ICP_M_NOWAIT due to the possibility of getting
++called in interrupt context*/
++	pPhase1OpData = icp_kmem_cache_zalloc(drvDH_zone, ICP_M_NOWAIT);
++	if (NULL == pPhase1OpData) {
++		APRINTK("%s():Failed to get memory for key gen data\n",
++			__FUNCTION__);
++		krp->krp_status = ENOMEM;
++		return ENOMEM;
++	}
++
++	pLocalOctetStringPV =
++	    icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
++	if (NULL == pLocalOctetStringPV) {
++		APRINTK("%s():Failed to get memory for pLocalOctetStringPV\n",
++			__FUNCTION__);
++		ICP_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);
++		ICP_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 = icp_kmem_cache_zalloc(drvLnModExp_zone, ICP_M_NOWAIT);
++	if (NULL == pModExpOpData) {
++		APRINTK("%s():Failed to get memory for key gen data\n",
++			__FUNCTION__);
++		krp->krp_status = ENOMEM;
++		return ENOMEM;
++	}
++
++	pResult = icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
++	if (NULL == pResult) {
++		APRINTK("%s():Failed to get memory for ModExp result\n",
++			__FUNCTION__);
++		ICP_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);
++
++	DPRINTK("%s : base (%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);
++		ICP_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 =
++	    icp_kmem_cache_zalloc(drvRSADecrypt_zone, ICP_M_NOWAIT);
++	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
++	    = icp_kmem_cache_zalloc(drvRSAPrivateKey_zone, ICP_M_NOWAIT);
++	if (NULL == rsaDecryptOpData->pRecipientPrivateKey) {
++		APRINTK("%s():Failed to get memory for MOD EXP CRT"
++			" private key values struct\n", __FUNCTION__);
++		ICP_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 = icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
++	if (NULL == pOutputData) {
++		APRINTK("%s():Failed to get memory"
++			" for MOD EXP CRT output data\n", __FUNCTION__);
++		ICP_CACHE_FREE(drvRSAPrivateKey_zone,
++			       rsaDecryptOpData->pRecipientPrivateKey);
++		ICP_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);
++		ICP_CACHE_FREE(drvRSAPrivateKey_zone,
++			       rsaDecryptOpData->pRecipientPrivateKey);
++		ICP_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 =
++	    icp_kmem_cache_zalloc(drvDSARSSign_zone, ICP_M_NOWAIT);
++	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 =
++	    icp_kmem_cache_alloc(drvDSARSSignKValue_zone, ICP_M_NOWAIT);
++
++	if (NULL == dsaRsSignOpData->K.pData) {
++		APRINTK("%s():Failed to get memory"
++			" for DSA RS Sign Op Random value\n", __FUNCTION__);
++		ICP_CACHE_FREE(drvDSARSSign_zone, dsaRsSignOpData);
++		krp->krp_status = ENOMEM;
++		return ENOMEM;
++	}
++
++	pR = icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
++	if (NULL == pR) {
++		APRINTK("%s():Failed to get memory"
++			" for DSA signature R\n", __FUNCTION__);
++		ICP_CACHE_FREE(drvDSARSSignKValue_zone,
++			       dsaRsSignOpData->K.pData);
++		ICP_CACHE_FREE(drvDSARSSign_zone, dsaRsSignOpData);
++		krp->krp_status = ENOMEM;
++		return ENOMEM;
++	}
++
++	pS = icp_kmem_cache_zalloc(drvFlatBuffer_zone, ICP_M_NOWAIT);
++	if (NULL == pS) {
++		APRINTK("%s():Failed to get memory"
++			" for DSA signature S\n", __FUNCTION__);
++		icp_ocfDrvFreeFlatBuffer(pR);
++		ICP_CACHE_FREE(drvDSARSSignKValue_zone,
++			       dsaRsSignOpData->K.pData);
++		ICP_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);
++			ICP_CACHE_FREE(drvDSARSSignKValue_zone,
++				       dsaRsSignOpData->K.pData);
++			ICP_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);
++			ICP_CACHE_FREE(drvDSARSSignKValue_zone,
++				       dsaRsSignOpData->K.pData);
++			ICP_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);
++
++	/*OpenSSL dgst parameter is left in big endian byte order,
++	   therefore no byte swap is required */
++	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);
++
++	/* 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);
++		ICP_CACHE_FREE(drvDSARSSignKValue_zone,
++			       dsaRsSignOpData->K.pData);
++		ICP_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 =
++	    icp_kmem_cache_zalloc(drvDSAVerify_zone, ICP_M_NOWAIT);
++	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);
++
++	/*OpenSSL dgst parameter is left in big endian byte order,
++	   therefore no byte swap is required */
++	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);
++
++	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);
++		ICP_CACHE_FREE(drvDSAVerify_zone, dsaVerifyOpData);
++		krp->krp_status = ECANCELED;
++	}
++
++	return lacStatus;
++}
++
++/* 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));
++		ICP_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));
++	ICP_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));
++		ICP_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));
++	ICP_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));
++		ICP_CACHE_FREE(drvRSAPrivateKey_zone,
++			       pDecryptData->pRecipientPrivateKey);
++		memset(pDecryptData, 0, sizeof(CpaCyRsaDecryptOpData));
++		ICP_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));
++	ICP_CACHE_FREE(drvRSAPrivateKey_zone,
++		       pDecryptData->pRecipientPrivateKey);
++	memset(pDecryptData, 0, sizeof(CpaCyRsaDecryptOpData));
++	ICP_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);
++		ICP_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);
++		ICP_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);
++	ICP_CACHE_FREE(drvDSARSSignKValue_zone, pSignData->K.pData);
++	memset(pSignData, 0, sizeof(CpaCyDsaRSSignOpData));
++	ICP_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));
++	ICP_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 100644
+index 0000000..5d46c0a
+--- /dev/null
++++ b/crypto/ocf/ep80579/icp_common.c
+@@ -0,0 +1,773 @@
++/*************************************************************************
++ *
++ * 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,2009 Intel Corporation. All rights reserved.
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of version 2 of the GNU General Public License as
++ *   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,2009 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.2-229
++ *
++ ***************************************************************************/
++
++/*
++ * 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                         (1)
++#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 EP80579 Driver. If set to zero, there is no limit. */
++#define DEFAULT_OCF_TO_DRV_MAX_SESSION_COUNT    (0)
++#define NUM_SUPPORTED_CAPABILITIES              (21)
++
++/*Slab zone names*/
++#define ICP_SESSION_DATA_NAME   "icp_ocf.SesDat"
++#define ICP_OP_DATA_NAME        "icp_ocf.OpDat"
++#define ICP_DH_NAME             "icp_ocf.DH"
++#define ICP_MODEXP_NAME         "icp_ocf.ModExp"
++#define ICP_RSA_DECRYPT_NAME    "icp_ocf.RSAdec"
++#define ICP_RSA_PKEY_NAME       "icp_ocf.RSApk"
++#define ICP_DSA_SIGN_NAME       "icp_ocf.DSAsg"
++#define ICP_DSA_VER_NAME        "icp_ocf.DSAver"
++#define ICP_RAND_VAL_NAME       "icp_ocf.DSArnd"
++#define ICP_FLAT_BUFF_NAME      "icp_ocf.FB"
++
++/*Slabs zones*/
++icp_kmem_cache drvSessionData_zone = NULL;
++icp_kmem_cache drvOpData_zone = NULL;
++icp_kmem_cache drvDH_zone = NULL;
++icp_kmem_cache drvLnModExp_zone = NULL;
++icp_kmem_cache drvRSADecrypt_zone = NULL;
++icp_kmem_cache drvRSAPrivateKey_zone = NULL;
++icp_kmem_cache drvDSARSSign_zone = NULL;
++icp_kmem_cache drvDSARSSignKValue_zone = NULL;
++icp_kmem_cache drvDSAVerify_zone = NULL;
++
++/*Slab zones for flatbuffers and bufferlist*/
++icp_kmem_cache drvFlatBuffer_zone = NULL;
++
++static inline int icp_cache_null_check(void)
++{
++	return (drvSessionData_zone && drvOpData_zone
++		&& drvDH_zone && drvLnModExp_zone && drvRSADecrypt_zone
++		&& drvRSAPrivateKey_zone && drvDSARSSign_zone
++		&& drvDSARSSign_zone && drvDSARSSignKValue_zone
++		&& drvDSAVerify_zone && drvFlatBuffer_zone);
++}
++
++/*Function to free all allocated slab caches before exiting the module*/
++static void icp_ocfDrvFreeCaches(void);
++
++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 EP80579 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 */
++icp_atomic_t icp_ocfDrvIsExiting = ICP_ATOMIC_INIT(0);
++
++/* This is used to show how many lac sessions were not deregistered*/
++icp_atomic_t lac_session_failed_dereg_count = ICP_ATOMIC_INIT(0);
++
++/* This is used to track the number of registered sessions between OCF and
++ * and the OCF EP80579 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 */
++icp_atomic_t num_ocf_to_drv_registered_sessions = ICP_ATOMIC_INIT(0);
++
++/* Head of linked list used to store session data */
++icp_drvSessionListHead_t icp_ocfDrvGlobalSymListHead;
++icp_drvSessionListHead_t icp_ocfDrvGlobalSymListHead_FreeMemList;
++
++icp_spinlock_t icp_ocfDrvSymSessInfoListSpinlock;
++
++/*Below pointer is only used in linux, FreeBSD uses the name to
++create its own variable name*/
++icp_workqueue *icp_ocfDrvFreeLacSessionWorkQ = NULL;
++ICP_WORKQUEUE_DEFINE_THREAD(icp_ocfDrvFreeLacSessionWorkQ);
++
++struct icp_drvBuffListInfo defBuffListInfo;
++
++/* 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
++ */
++ICP_MODULE_INIT_FUNC(icp_ocfDrvInit)
++{
++	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);
++		icp_module_return_code(EINVAL);
++	}
++
++	/* 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 icp_module_return_code(EINVAL);
++	}
++
++	icp_spin_lock_init(&icp_ocfDrvSymSessInfoListSpinlock);
++
++	/* 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 icp_module_return_code(ENOMEM);
++	}
++
++	/*Register OCF EP80579 Driver with OCF */
++	icp_ocfDrvDriverId = ICP_CRYPTO_GET_DRIVERID();
++
++	if (icp_ocfDrvDriverId < 0) {
++		EPRINTK("%s : ICP driver failed to register with OCF!\n",
++			__FUNCTION__);
++		return icp_module_return_code(ENODEV);
++	}
++
++	/*Create all the slab caches used by the OCF EP80579 Driver */
++	drvSessionData_zone =
++	    ICP_CACHE_CREATE(ICP_SESSION_DATA_NAME, struct icp_drvSessionData);
++
++	/*
++	 * 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 =
++	    icp_kmem_cache_create(ICP_OP_DATA_NAME,
++				  sizeof(struct icp_drvOpData) +
++				  defBuffListInfo.metaSize,
++				  ICP_KERNEL_CACHE_ALIGN,
++				  ICP_KERNEL_CACHE_NOINIT);
++
++	drvDH_zone = ICP_CACHE_CREATE(ICP_DH_NAME, CpaCyDhPhase1KeyGenOpData);
++
++	drvLnModExp_zone =
++	    ICP_CACHE_CREATE(ICP_MODEXP_NAME, CpaCyLnModExpOpData);
++
++	drvRSADecrypt_zone =
++	    ICP_CACHE_CREATE(ICP_RSA_DECRYPT_NAME, CpaCyRsaDecryptOpData);
++
++	drvRSAPrivateKey_zone =
++	    ICP_CACHE_CREATE(ICP_RSA_PKEY_NAME, CpaCyRsaPrivateKey);
++
++	drvDSARSSign_zone =
++	    ICP_CACHE_CREATE(ICP_DSA_SIGN_NAME, CpaCyDsaRSSignOpData);
++
++	/*too awkward to use a macro here */
++	drvDSARSSignKValue_zone =
++	    ICP_CACHE_CREATE(ICP_RAND_VAL_NAME,
++			     DSA_RS_SIGN_PRIMEQ_SIZE_IN_BYTES);
++
++	drvDSAVerify_zone =
++	    ICP_CACHE_CREATE(ICP_DSA_VER_NAME, CpaCyDsaVerifyOpData);
++
++	drvFlatBuffer_zone =
++	    ICP_CACHE_CREATE(ICP_FLAT_BUFF_NAME, CpaFlatBuffer);
++
++	if (0 == icp_cache_null_check()) {
++		icp_ocfDrvFreeCaches();
++		EPRINTK("%s() line %d: Not enough memory!\n",
++			__FUNCTION__, __LINE__);
++		return ENOMEM;
++	}
++
++	/* Register the ICP symmetric crypto support. */
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_NULL_CBC, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_DES_CBC, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_3DES_CBC, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_AES_CBC, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_ARC4, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_MD5, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_MD5_HMAC, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA1, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA1_HMAC, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_256, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_256_HMAC,
++			     ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_384, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_384_HMAC,
++			     ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_512, ocfStatus);
++	ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_512_HMAC,
++			     ocfStatus);
++
++	/* Register the ICP asymmetric algorithm support */
++	ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId, CRK_DH_COMPUTE_KEY,
++			      ocfStatus);
++	ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId, CRK_MOD_EXP, ocfStatus);
++	ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId, CRK_MOD_EXP_CRT, ocfStatus);
++	ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId, CRK_DSA_SIGN, ocfStatus);
++	ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId, CRK_DSA_VERIFY, ocfStatus);
++
++	/* Register the ICP random number generator support */
++	ICP_REG_RAND_WITH_OCF(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 icp_module_return_code(ECANCELED);
++	}
++
++	DPRINTK("%s: Registered %d of %d device capabilities\n",
++		__FUNCTION__, ocfStatus, NUM_SUPPORTED_CAPABILITIES);
++
++	/*Session data linked list used during module exit */
++	ICP_INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead);
++	ICP_INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead_FreeMemList);
++
++	ICP_WORKQUEUE_CREATE(icp_ocfDrvFreeLacSessionWorkQ, "icpwq");
++	if (ICP_WORKQUEUE_NULL_CHECK(icp_ocfDrvFreeLacSessionWorkQ)) {
++		EPRINTK("%s: Failed to create single "
++			"thread workqueue\n", __FUNCTION__);
++		icp_ocfDrvFreeCaches();
++		icp_ocfDrvDriverId = INVALID_DRIVER_ID;
++		return icp_module_return_code(ENOMEM);
++	}
++
++	return icp_module_return_code(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.
++ */
++ICP_MODULE_EXIT_FUNC(icp_ocfDrvExit)
++{
++	CpaStatus lacStatus = CPA_STATUS_SUCCESS;
++	struct icp_drvSessionData *sessionData = NULL;
++	struct icp_drvSessionData *tempSessionData = NULL;
++	int i, remaining_delay_time_in_jiffies = 0;
++
++	/* For FreeBSD the invariant macro below makes function to return     */
++	/* with EBUSY value in the case of any session which has been regi-   */
++	/* stered with LAC not being deregistered.                            */
++	/* The Linux implementation is empty since it is purely to compensate */
++	/* for a limitation of the FreeBSD 7.1 Opencrypto framework.          */
++
++    ICP_MODULE_EXIT_INV();
++
++	/* 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.                             */
++	icp_atomic_set(&icp_ocfDrvIsExiting, 1);
++
++	/*Existing sessions will be routed to another driver after these calls */
++	crypto_unregister_all(icp_ocfDrvDriverId);
++	crypto_runregister_all(icp_ocfDrvDriverId);
++
++	if (ICP_WORKQUEUE_NULL_CHECK(icp_ocfDrvFreeLacSessionWorkQ)) {
++		DPRINTK("%s: workqueue already "
++			"destroyed, therefore module exit "
++			" function already called. Exiting.\n", __FUNCTION__);
++		return ICP_MODULE_EXIT_FUNC_RETURN_VAL;
++	}
++	/*If any sessions are waiting to be deregistered, do that. This also
++	   flushes the work queue */
++	ICP_WORKQUEUE_DESTROY(icp_ocfDrvFreeLacSessionWorkQ);
++
++	/*ENTER CRITICAL SECTION */
++	icp_spin_lockbh_lock(&icp_ocfDrvSymSessInfoListSpinlock);
++
++	ICP_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) {
++					icp_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 =
++					    icp_schedule_timeout
++					    (&icp_ocfDrvSymSessInfoListSpinlock,
++					     remaining_delay_time_in_jiffies);
++				}
++
++				DPRINTK
++				    ("%s(): Retry %d to deregistrate the session\n",
++				     __FUNCTION__, i);
++			}
++		}
++
++		/*remove from current list */
++		ICP_LIST_DEL(tempSessionData, listNode);
++		/*add to free mem linked list */
++		ICP_LIST_ADD(tempSessionData,
++			     &icp_ocfDrvGlobalSymListHead_FreeMemList,
++			     listNode);
++
++	}
++
++	/*EXIT CRITICAL SECTION */
++	icp_spin_lockbh_unlock(&icp_ocfDrvSymSessInfoListSpinlock);
++
++	/*set back to initial values */
++	sessionData = NULL;
++	/*still have a reference in our list! */
++	tempSessionData = NULL;
++	/*free memory */
++
++	ICP_LIST_FOR_EACH_ENTRY_SAFE(tempSessionData, sessionData,
++				     &icp_ocfDrvGlobalSymListHead_FreeMemList,
++				     listNode) {
++
++		ICP_LIST_DEL(tempSessionData, listNode);
++		/* Free allocated CpaCySymSessionCtx */
++		if (NULL != tempSessionData->sessHandle) {
++			icp_kfree(tempSessionData->sessHandle);
++		}
++		memset(tempSessionData, 0, sizeof(struct icp_drvSessionData));
++		ICP_CACHE_FREE(drvSessionData_zone, tempSessionData);
++	}
++
++	if (0 != icp_atomic_read(&lac_session_failed_dereg_count)) {
++		DPRINTK("%s(): %d LAC sessions were not deregistered "
++			"correctly. This is not a clean exit! \n",
++			__FUNCTION__,
++			icp_atomic_read(&lac_session_failed_dereg_count));
++	}
++
++	icp_ocfDrvFreeCaches();
++	icp_ocfDrvDriverId = INVALID_DRIVER_ID;
++
++	icp_spin_lock_destroy(&icp_ocfDrvSymSessInfoListSpinlock);
++
++	/* 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);
++	}
++
++	return ICP_MODULE_EXIT_FUNC_RETURN_VAL;
++}
++
++/* Name        : icp_ocfDrvFreeCaches
++ *
++ * Description : This function deregisters all slab caches
++ */
++static void icp_ocfDrvFreeCaches(void)
++{
++	icp_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 */
++	icp_atomic_inc(&lac_session_failed_dereg_count);
++
++	/*Farm off to work queue */
++	workstore =
++	    icp_kmalloc(sizeof(struct icp_ocfDrvFreeLacSession), ICP_M_NOWAIT);
++	if (NULL == workstore) {
++		DPRINTK("%s(): unable to free session - no memory available "
++			"for work queue\n", __FUNCTION__);
++		return ENOMEM;
++	}
++
++	workstore->sessionToDeregister = sessionToDeregister;
++
++	icp_init_work(&(workstore->work),
++		      icp_ocfDrvDeferedFreeLacSessionTaskFn, workstore);
++
++	ICP_WORKQUEUE_ENQUEUE(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
++ */
++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;
++	icp_kfree(workstore);
++
++	/*if exiting, give deregistration one more blast only */
++	if (icp_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;
++		}
++
++		icp_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) {
++			icp_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 =
++			    icp_schedule_timeout(NULL,
++						 remaining_delay_time_in_jiffies);
++		}
++
++	}
++
++	DPRINTK("%s(): Unable to deregister session\n", __FUNCTION__);
++	DPRINTK("%s(): Number of unavailable LAC sessions = %d\n", __FUNCTION__,
++		icp_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_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_ocfDrvFreeFlatBuffer
++ *
++ * Description : This function will deallocate flat buffer.
++ */
++inline void icp_ocfDrvFreeFlatBuffer(CpaFlatBuffer * pFlatBuffer)
++{
++	if (pFlatBuffer != NULL) {
++		memset(pFlatBuffer, 0, sizeof(CpaFlatBuffer));
++		ICP_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,
++			struct icp_drvOpData *pOpData)
++{
++	Cpa32U metaSize = 0;
++
++	if (pBufferList->numBuffers <= ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) {
++		uint8_t *pOpDataStartAddr = (uint8_t *) 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 = (void *)(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 =
++		    icp_kmalloc(metaSize, ICP_M_NOWAIT);
++	}
++	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) {
++		icp_kfree(pBufferList->pPrivateMetaData);
++	}
++}
++
++/* Module declaration, init and exit functions */
++ICP_DECLARE_MODULE(icp_ocf, icp_ocfDrvInit, icp_ocfDrvExit);
++ICP_MODULE_DESCRIPTION("OCF Driver for Intel Quick Assist crypto acceleration");
++ICP_MODULE_VERSION(icp_ocf, ICP_OCF_VER_MJR);
++ICP_MODULE_LICENSE("Dual BSD/GPL");
++ICP_MODULE_AUTHOR("Intel");
++
++/* Module parameters */
++ICP_MODULE_PARAM_INT(icp_ocf, num_dereg_retries,
++		     "Number of times to retry LAC Sym Session Deregistration. "
++		     "Default 10, Max 100");
++ICP_MODULE_PARAM_INT(icp_ocf, dereg_retry_delay_in_jiffies, "Delay in jiffies "
++		     "(added to a schedule() function call) before a LAC Sym "
++		     "Session Dereg is retried. Default 10");
++ICP_MODULE_PARAM_INT(icp_ocf, 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)");
++
++/* Module dependencies */
++#define MODULE_MIN_VER	1
++#define CRYPTO_MAX_VER	3
++#define LAC_MAX_VER	2
++
++ICP_MODULE_DEPEND(icp_ocf, crypto, MODULE_MIN_VER, MODULE_MIN_VER,
++		  CRYPTO_MAX_VER);
++ICP_MODULE_DEPEND(icp_ocf, cryptodev, MODULE_MIN_VER, MODULE_MIN_VER,
++		  CRYPTO_MAX_VER);
++ICP_MODULE_DEPEND(icp_ocf, icp_crypto, MODULE_MIN_VER, MODULE_MIN_VER,
++		  LAC_MAX_VER);
+diff --git a/crypto/ocf/ep80579/icp_ocf.h b/crypto/ocf/ep80579/icp_ocf.h
+new file mode 100644
+index 0000000..d9dde87
+--- /dev/null
++++ b/crypto/ocf/ep80579/icp_ocf.h
+@@ -0,0 +1,376 @@
++/***************************************************************************
++ *
++ * 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,2009 Intel Corporation. All rights reserved.
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of version 2 of the GNU General Public License as
++ *   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,2009 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.2-229
++ *
++ ***************************************************************************/
++
++/*
++ * OCF driver header file for the Intel ICP processor.
++ */
++
++#ifndef ICP_OCF_H_
++#define ICP_OCF_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>
++
++#include "icp_os.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 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)
++
++#if ICP_OCF_PRINT_DEBUG_MESSAGES == 1
++#define DPRINTK(args...)      \
++{			      \
++                ICP_IPRINTK(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...)						\
++{									\
++       ICP_APRINTK(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...)      \
++{			      \
++       ICP_EPRINTK(args); \
++}
++
++#else				//ICP_OCF_PRINT_KERN_ERRS == 1
++
++#define EPRINTK(args...)
++
++#endif				//ICP_OCF_PRINT_KERN_ERRS == 1
++
++#define IPRINTK(args...)      \
++{			      \
++      ICP_IPRINTK(args); \
++}
++
++/*DSA Prime Q size in bytes (as defined in the standard) */
++#define DSA_RS_SIGN_PRIMEQ_SIZE_IN_BYTES	(20)
++
++#define BITS_TO_BYTES(bytes, bits)					\
++	bytes = (bits + NUM_BITS_IN_BYTE_MINUS_ONE) / NUM_BITS_IN_BYTE
++
++typedef enum {
++	ICP_OCF_DRV_ALG_CIPHER = 0,
++	ICP_OCF_DRV_ALG_HASH
++} icp_ocf_drv_alg_type_t;
++
++typedef ICP_LIST_HEAD(icp_drvSessionListHead_s,
++		      icp_drvSessionData) icp_drvSessionListHead_t;
++
++/*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 struct is required for deferred session
++ deregistration as a work queue function can
++ only have one argument*/
++struct icp_ocfDrvFreeLacSession {
++	CpaCySymSessionCtx sessionToDeregister;
++	icp_workstruct work;
++};
++
++/*
++This is the OCF<->OCF_DRV session object:
++
++1.listNode
++  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.inUse
++  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.sessHandle
++  The third member is a LAC<->OCF_DRV session handle (initialised with the first
++  perform request for that session).
++
++4.lacSessCtx
++  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 EP80579 Driver only registers a new LAC session at perform time
++*/
++struct icp_drvSessionData {
++	ICP_LIST_ENTRY(icp_drvSessionData) listNode;
++	usage_derisk inUse;
++	CpaCySymSessionCtx sessHandle;
++	CpaCySymSessionSetupData lacSessCtx;
++};
++
++/* These are all defined in icp_common.c */
++extern icp_atomic_t lac_session_failed_dereg_count;
++extern icp_atomic_t icp_ocfDrvIsExiting;
++extern icp_atomic_t num_ocf_to_drv_registered_sessions;
++
++extern int32_t icp_ocfDrvDriverId;
++
++extern icp_drvSessionListHead_t icp_ocfDrvGlobalSymListHead;
++extern icp_drvSessionListHead_t icp_ocfDrvGlobalSymListHead_FreeMemList;
++extern icp_workqueue *icp_ocfDrvFreeLacSessionWorkQ;
++extern icp_spinlock_t icp_ocfDrvSymSessInfoListSpinlock;
++
++/*Slab zones for symettric functionality, instantiated in icp_common.c*/
++extern icp_kmem_cache drvSessionData_zone;
++extern icp_kmem_cache drvOpData_zone;
++
++/*Slabs zones for asymettric functionality, instantiated in icp_common.c*/
++extern icp_kmem_cache drvDH_zone;
++extern icp_kmem_cache drvLnModExp_zone;
++extern icp_kmem_cache drvRSADecrypt_zone;
++extern icp_kmem_cache drvRSAPrivateKey_zone;
++extern icp_kmem_cache drvDSARSSign_zone;
++extern icp_kmem_cache drvDSARSSignKValue_zone;
++extern icp_kmem_cache drvDSAVerify_zone;
++
++/* Module parameters defined in icp_cpmmon.c*/
++
++/* Module parameters - gives the number of times LAC deregistration shall be
++   re-tried */
++extern int num_dereg_retries;
++
++/* Module parameter - gives the delay time in jiffies before a LAC session
++   shall be attempted to be deregistered again */
++extern int dereg_retry_delay_in_jiffies;
++
++/* Module parameter - gives the maximum number of sessions possible between
++   OCF and the OCF EP80579 Driver. If set to zero, there is no limit.*/
++extern int max_sessions;
++
++/*Slab zones for flatbuffers and bufferlist*/
++extern icp_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.*/
++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;
++};
++
++/* Create a new session between OCF and this driver*/
++int icp_ocfDrvNewSession(icp_device_t dev, uint32_t * sild,
++			 struct cryptoini *cri);
++
++/* Free a session between this driver and the Quick Assist Framework*/
++int icp_ocfDrvFreeLACSession(icp_device_t dev, uint64_t sid);
++
++/* Defer freeing a Quick Assist session*/
++void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg);
++
++/* Process OCF cryptographic request for a symmetric algorithm*/
++int icp_ocfDrvSymProcess(icp_device_t dev, struct cryptop *crp, int hint);
++
++/* Process OCF cryptographic request for an asymmetric algorithm*/
++int icp_ocfDrvPkeProcess(icp_device_t dev, struct cryptkop *krp, int hint);
++
++/* Populate a buffer with random data*/
++int icp_ocfDrvReadRandom(void *arg, uint32_t * buf, int maxwords);
++
++/* Retry Quick Assist session deregistration*/
++int icp_ocfDrvDeregRetry(CpaCySymSessionCtx sessionToDeregister);
++
++/* Convert an OS scatter gather list to a CPA buffer list*/
++int icp_ocfDrvPacketBuffToBufferList(icp_packet_buffer_t * pPacketBuffer,
++				     CpaBufferList * bufferList);
++
++/* Convert a CPA buffer list to an OS scatter gather list*/
++int icp_ocfDrvBufferListToPacketBuff(CpaBufferList * bufferList,
++				     icp_packet_buffer_t ** pPacketBuffer);
++
++/* Get the number of buffers in an OS scatter gather list*/
++uint16_t icp_ocfDrvGetPacketBuffFrags(icp_packet_buffer_t * pPacketBuffer);
++
++/* Convert a single OS buffer to a CPA Flat Buffer*/
++void icp_ocfDrvSinglePacketBuffToFlatBuffer(icp_packet_buffer_t * pPacketBuffer,
++					    CpaFlatBuffer * pFlatBuffer);
++
++/* Add pointer and length to a CPA Flat Buffer structure*/
++void icp_ocfDrvPtrAndLenToFlatBuffer(void *pData, uint32_t len,
++				     CpaFlatBuffer * pFlatBuffer);
++
++/* Convert pointer and length values to a CPA buffer list*/
++void icp_ocfDrvPtrAndLenToBufferList(void *pDataIn, uint32_t length,
++				     CpaBufferList * pBufferList);
++
++/* Convert a CPA buffer list to pointer and length values*/
++void icp_ocfDrvBufferListToPtrAndLen(CpaBufferList * pBufferList,
++				     void **ppDataOut, uint32_t * pLength);
++
++/* Set the number of flat buffers in bufferlist and the size of memory
++   to allocate for the pPrivateMetaData member of the CpaBufferList.*/
++int icp_ocfDrvBufferListMemInfo(uint16_t numBuffers,
++				struct icp_drvBuffListInfo *buffListInfo);
++
++/* Find pointer position of the digest within an OS scatter gather list*/
++uint8_t *icp_ocfDrvPacketBufferDigestPointerFind(struct icp_drvOpData
++						 *drvOpData,
++						 int offsetInBytes,
++						 uint32_t digestSizeInBytes);
++
++/*This top level function is used to find a pointer to where a digest is
++  stored/needs to be inserted. */
++uint8_t *icp_ocfDrvDigestPointerFind(struct icp_drvOpData *drvOpData,
++				     struct cryptodesc *crp_desc);
++
++/* Free a CPA flat buffer*/
++void icp_ocfDrvFreeFlatBuffer(CpaFlatBuffer * pFlatBuffer);
++
++/* This function will allocate memory for the pPrivateMetaData
++   member of CpaBufferList. */
++int icp_ocfDrvAllocMetaData(CpaBufferList * pBufferList,
++			    struct icp_drvOpData *pOpData);
++
++/* Free data allocated for the pPrivateMetaData
++   member of CpaBufferList.*/
++void icp_ocfDrvFreeMetaData(CpaBufferList * pBufferList);
++
++#define ICP_CACHE_CREATE(cache_ID, cache_name) \
++	icp_kmem_cache_create(cache_ID, sizeof(cache_name),ICP_KERNEL_CACHE_ALIGN,\
++	ICP_KERNEL_CACHE_NOINIT)
++
++#define ICP_CACHE_FREE(args...) \
++	icp_kmem_cache_free (args)
++
++#define ICP_CACHE_DESTROY(slab_zone)\
++{\
++        if(NULL != slab_zone){\
++                icp_kmem_cache_destroy(slab_zone);\
++                slab_zone = NULL;\
++        }\
++}
++
++#endif
++/* ICP_OCF_H_ */
+diff --git a/crypto/ocf/ep80579/icp_sym.c b/crypto/ocf/ep80579/icp_sym.c
+new file mode 100644
+index 0000000..e1c7148
+--- /dev/null
++++ b/crypto/ocf/ep80579/icp_sym.c
+@@ -0,0 +1,1153 @@
++/***************************************************************************
++ *
++ * 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,2009 Intel Corporation. All rights reserved.
++ *
++ *   This program is free software; you can redistribute it and/or modify
++ *   it under the terms of version 2 of the GNU General Public License as
++ *   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,2009 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.2-229
++ *
++ ***************************************************************************/
++/*
++ * 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 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 EP80579 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 == ICP_CRYPTO_F_PACKET_BUF) {
++			if (ICP_OCF_DRV_STATUS_SUCCESS !=
++			    icp_ocfDrvBufferListToPacketBuff(pDstBuffer,
++							     (icp_packet_buffer_t
++							      **)
++							     & (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) {
++		icp_kfree(pDstBuffer->pBuffers);
++	}
++	icp_ocfDrvFreeMetaData(pDstBuffer);
++	ICP_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(icp_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 = icp_kmem_cache_zalloc(drvSessionData_zone, ICP_M_NOWAIT);
++	if (NULL == sessionData) {
++		DPRINTK("%s():No memory for Session Data\n", __FUNCTION__);
++		return ENOMEM;
++	}
++
++	/*ENTER CRITICAL SECTION */
++	icp_spin_lockbh_lock(&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 == icp_atomic_read(&icp_ocfDrvIsExiting)) {
++		delete_session++;
++
++	} else if (NO_OCF_TO_DRV_MAX_SESSIONS != max_sessions) {
++		if (icp_atomic_read(&num_ocf_to_drv_registered_sessions) >=
++		    (max_sessions -
++		     icp_atomic_read(&lac_session_failed_dereg_count))) {
++			delete_session++;
++		} else {
++			icp_atomic_inc(&num_ocf_to_drv_registered_sessions);
++			/* Add to session data linked list */
++			ICP_LIST_ADD(sessionData, &icp_ocfDrvGlobalSymListHead,
++				     listNode);
++		}
++
++	} else if (NO_OCF_TO_DRV_MAX_SESSIONS == max_sessions) {
++		ICP_LIST_ADD(sessionData, &icp_ocfDrvGlobalSymListHead,
++			     listNode);
++	}
++
++	sessionData->inUse = ICP_SESSION_INITIALISED;
++
++	/*EXIT CRITICAL SECTION */
++	icp_spin_lockbh_unlock(&icp_ocfDrvSymSessInfoListSpinlock);
++
++	if (delete_session) {
++		DPRINTK("%s():No Session handles available\n", __FUNCTION__);
++		ICP_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 */
++	icp_spin_lockbh_lock(&icp_ocfDrvSymSessInfoListSpinlock);
++
++	if (CPA_TRUE == icp_atomic_read(&icp_ocfDrvIsExiting)) {
++		/*If the Driver is exiting, allow that process to
++		   handle any deletions */
++		/*EXIT CRITICAL SECTION */
++		icp_spin_lockbh_unlock(&icp_ocfDrvSymSessInfoListSpinlock);
++		return;
++	}
++
++	icp_atomic_dec(&num_ocf_to_drv_registered_sessions);
++
++	ICP_LIST_DEL(sessionData, listNode);
++
++	/*EXIT CRITICAL SECTION */
++	icp_spin_lockbh_unlock(&icp_ocfDrvSymSessInfoListSpinlock);
++
++	if (NULL != sessionData->sessHandle) {
++		icp_kfree(sessionData->sessHandle);
++	}
++	ICP_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(icp_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) &&
++	    (ICP_SESSION_RUNNING != sessionData->inUse) &&
++	    (ICP_SESSION_DEREGISTERED != sessionData->inUse)) {
++		DPRINTK("%s() Session not initialised.\n", __FUNCTION__);
++		return EINVAL;
++	}
++
++	if (ICP_SESSION_RUNNING == sessionData->inUse) {
++		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);
++			icp_atomic_inc(&lac_session_failed_dereg_count);
++			retval = EPERM;
++		}
++	} else {
++		DPRINTK("%s() Session not registered with LAC.\n",
++			__FUNCTION__);
++	}
++
++	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(icp_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;
++
++	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 == icp_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);
++			crp->crp_etype = EINVAL;
++			return EINVAL;
++		}
++		sessionData->sessHandle =
++		    icp_kmalloc(sessionCtxSizeInBytes, ICP_M_NOWAIT);
++		if (NULL == sessionData->sessHandle) {
++			EPRINTK
++			    ("%s(): Failed to get memory for SymSessionCtx\n",
++			     __FUNCTION__);
++			crp->crp_etype = ENOMEM;
++			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);
++			crp->crp_etype = EFAULT;
++			return EFAULT;
++		}
++
++		sessionData->inUse = ICP_SESSION_RUNNING;
++	}
++
++	drvOpData = icp_kmem_cache_zalloc(drvOpData_zone, ICP_M_NOWAIT);
++	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;
++
++	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 buffer list array memory if the data fragment is more than
++	 * the default number (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) and not
++	 * calculated already
++	 */
++	if (crp->crp_flags & ICP_CRYPTO_F_PACKET_BUF) {
++		if (NULL == drvOpData->lacOpData.pDigestResult) {
++			drvOpData->numBufferListArray =
++			    icp_ocfDrvGetPacketBuffFrags((icp_packet_buffer_t *)
++							 crp->crp_buf);
++		}
++
++		if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS <
++		    drvOpData->numBufferListArray) {
++			DPRINTK("%s() numBufferListArray more than default\n",
++				__FUNCTION__);
++			drvOpData->srcBuffer.pBuffers = NULL;
++			drvOpData->srcBuffer.pBuffers =
++			    icp_kmalloc(drvOpData->numBufferListArray *
++					sizeof(CpaFlatBuffer), ICP_M_NOWAIT);
++			if (NULL == drvOpData->srcBuffer.pBuffers) {
++				EPRINTK("%s() Failed to get memory for "
++					"pBuffers\n", __FUNCTION__);
++				ICP_CACHE_FREE(drvOpData_zone, drvOpData);
++				crp->crp_etype = ENOMEM;
++				return ENOMEM;
++			}
++		}
++	}
++
++	/*
++	 * Check the type of buffer structure we got and convert it into
++	 * CpaBufferList format.
++	 */
++	if (crp->crp_flags & ICP_CRYPTO_F_PACKET_BUF) {
++		if (ICP_OCF_DRV_STATUS_SUCCESS !=
++		    icp_ocfDrvPacketBuffToBufferList((icp_packet_buffer_t *)
++						     crp->crp_buf,
++						     &(drvOpData->srcBuffer))) {
++			EPRINTK("%s():Failed to translate from packet buffer "
++				"to bufferlist\n", __FUNCTION__);
++			crp->crp_etype = EINVAL;
++			goto err;
++		}
++
++		drvOpData->bufferType = ICP_CRYPTO_F_PACKET_BUF;
++	} 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;
++	}
++
++	/* 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 = ERESTART;
++		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) {
++		icp_kfree(drvOpData->srcBuffer.pBuffers);
++	}
++	icp_ocfDrvFreeMetaData(&(drvOpData->srcBuffer));
++	ICP_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.
++ */
++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;
++
++	if (drvOpData->crp->crp_flags & ICP_CRYPTO_F_PACKET_BUF) {
++
++		return icp_ocfDrvPacketBufferDigestPointerFind(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;
++}
+diff --git a/crypto/ocf/hifn/Makefile b/crypto/ocf/hifn/Makefile
+new file mode 100644
+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 100644
+index 0000000..6136e84
+--- /dev/null
++++ b/crypto/ocf/hifn/hifn7751.c
+@@ -0,0 +1,2976 @@
++/*	$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");
++
++int hifn_cache_linesize = 0x10;
++module_param(hifn_cache_linesize, int, 0444);
++MODULE_PARM_DESC(hifn_cache_linesize, "PCI config cache line size");
++
++#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);
++	/* piggy back the cache line setting here */
++	pci_write_config_byte(sc->sc_pcidev, PCI_CACHE_LINE_SIZE, hifn_cache_linesize);
++}
++
++/*
++ * 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@mcafee.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 100644
+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 100644
+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 100644
+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 100644
+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 100644
+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 100644
+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 100644
+index 0000000..d5414a4
+--- /dev/null
++++ b/crypto/ocf/ixp4xx/ixp4xx.c
+@@ -0,0 +1,1324 @@
++/*
++ * 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@mcafee.com>
++ * Copyright (C) 2006-2010 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;
++		}
++		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/kirkwood/Makefile b/crypto/ocf/kirkwood/Makefile
+new file mode 100644
+index 0000000..6dafd00
+--- /dev/null
++++ b/crypto/ocf/kirkwood/Makefile
+@@ -0,0 +1,19 @@
++# for SGlinux builds
++-include $(ROOTDIR)/modules/.config
++
++obj-$(CONFIG_OCF_KIRKWOOD) += mv_cesa.o
++
++mv_cesa-y := cesa/mvCesa.o cesa/mvLru.o cesa/mvMD5.o cesa/mvSHA1.o cesa/AES/mvAesAlg.o cesa/AES/mvAesApi.o cesa/mvCesaDebug.o cesa_ocf_drv.o
++
++# Extra objects required by the CESA driver
++mv_cesa-y += mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.o mvHal/kw_family/boardEnv/mvBoardEnvLib.o mvHal/mv_hal/twsi/mvTwsi.o mvHal/kw_family/ctrlEnv/sys/mvCpuIf.o mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.o mvHal/kw_family/ctrlEnv/sys/mvSysDram.o mvHal/linux_oss/mvOs.o mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.o mvHal/mv_hal/gpp/mvGpp.o mvHal/kw_family/ctrlEnv/sys/mvSysPex.o mvHal/mv_hal/pex/mvPex.o mvHal/kw_family/boardEnv/mvBoardEnvSpec.o mvHal/common/mvCommon.o mvHal/common/mvDebug.o mvHal/kw_family/ctrlEnv/sys/mvSysCesa.o
++
++ifdef src
++EXTRA_CFLAGS += -I$(src)/.. -I$(src)/cesa -I$(src)/mvHal -I$(src)/mvHal/common -I$(src)/mvHal/kw_family -I$(src)/mvHal/mv_hal -I$(src)/mvHal/linux_oss -I$(src)
++endif
++
++EXTRA_CFLAGS += -DMV_LINUX -DMV_CPU_LE -DMV_ARM -DMV_INCLUDE_CESA -DMV_INCLUDE_PEX -DMV_CACHE_COHERENCY=3
++ifdef TOPDIR
++-include $(TOPDIR)/Rules.make
++endif
++
+diff --git a/crypto/ocf/kirkwood/cesa/AES/mvAes.h b/crypto/ocf/kirkwood/cesa/AES/mvAes.h
+new file mode 100644
+index 0000000..07a8601
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/AES/mvAes.h
+@@ -0,0 +1,62 @@
++/* 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
++*/
++
++#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);
++
++
+diff --git a/crypto/ocf/kirkwood/cesa/AES/mvAesAlg.c b/crypto/ocf/kirkwood/cesa/AES/mvAesAlg.c
+new file mode 100644
+index 0000000..a65dc28
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/AES/mvAesAlg.c
+@@ -0,0 +1,317 @@
++/* 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 "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/crypto/ocf/kirkwood/cesa/AES/mvAesAlg.h b/crypto/ocf/kirkwood/cesa/AES/mvAesAlg.h
+new file mode 100644
+index 0000000..ec81e40
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/AES/mvAesAlg.h
+@@ -0,0 +1,19 @@
++/* 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
++
++#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);
++
++#endif /* __RIJNDAEL_ALG_H */
+diff --git a/crypto/ocf/kirkwood/cesa/AES/mvAesApi.c b/crypto/ocf/kirkwood/cesa/AES/mvAesApi.c
+new file mode 100644
+index 0000000..b432dc6
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/AES/mvAesApi.c
+@@ -0,0 +1,312 @@
++/* 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 "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/crypto/ocf/kirkwood/cesa/mvCesa.c b/crypto/ocf/kirkwood/cesa/mvCesa.c
+new file mode 100644
+index 0000000..17ab086
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvCesa.c
+@@ -0,0 +1,3126 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++        this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "cesa/mvCesa.h"
++
++#include "ctrlEnv/mvCtrlEnvLib.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_BUF_INFO             cesaSramSaBuf;
++short                   cesaLastSid = -1;
++MV_CESA_SA*             pCesaSAD = NULL;
++MV_U16                  cesaMaxSA = 0;
++
++MV_CESA_REQ*            pCesaReqFirst = NULL;
++MV_CESA_REQ*            pCesaReqLast = NULL;
++MV_CESA_REQ*            pCesaReqEmpty = NULL;
++MV_CESA_REQ*            pCesaReqProcess = NULL;
++int                     cesaQueueDepth = 0;
++int                     cesaReqResources = 0;
++
++MV_CESA_SRAM_MAP*       cesaSramVirtPtr = NULL;
++MV_U32                  cesaCryptEngBase = 0;
++void			*cesaOsHandle = NULL;
++#if (MV_CESA_VERSION >= 3)
++MV_U32			cesaChainLength = 0;
++int                     chainReqNum = 0;
++MV_U32			chainIndex = 0;
++MV_CESA_REQ*		pNextActiveChain = 0;
++MV_CESA_REQ*		pEndCurrChain = 0;
++MV_BOOL			isFirstReq = MV_TRUE;
++#endif
++
++static INLINE MV_U8*  mvCesaSramAddrGet(void)
++{
++#ifdef MV_CESA_NO_SRAM
++    return (MV_U8*)cesaSramVirtPtr;
++#else
++    return (MV_U8*)cesaCryptEngBase;
++#endif /* MV_CESA_NO_SRAM */
++}
++
++static INLINE MV_ULONG    mvCesaSramVirtToPhys(void* pDev, MV_U8* pSramVirt)
++{
++#ifdef MV_CESA_NO_SRAM
++    return (MV_ULONG)mvOsIoVirtToPhy(NULL, pSramVirt);
++#else
++    return (MV_ULONG)pSramVirt;
++#endif /* MV_CESA_NO_SRAM */
++}
++
++/* Internal Function prototypes */
++
++static INLINE void      mvCesaSramDescrBuild(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(short sid, MV_DMA_DESC *pDmaDesc);
++
++static INLINE int       mvCesaDmaCopyPrepare(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_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_CESA_REQ* pReq);
++static MV_STATUS   mvCesaFragReqProcess(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_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);
++
++
++/* Go to the next request in the request queue */
++static INLINE MV_CESA_REQ* MV_CESA_REQ_NEXT_PTR(MV_CESA_REQ* pReq)
++{
++    if(pReq == pCesaReqLast)
++        return pCesaReqFirst;
++
++    return pReq+1;
++}
++
++#if (MV_CESA_VERSION >= 3)
++/* Go to the previous request in the request queue */
++static INLINE MV_CESA_REQ* MV_CESA_REQ_PREV_PTR(MV_CESA_REQ* pReq)
++{
++    if(pReq == pCesaReqFirst)
++        return pCesaReqLast;
++
++    return pReq-1;
++}
++
++#endif
++
++
++static INLINE void mvCesaReqProcessStart(MV_CESA_REQ* pReq)
++{
++    int frag;
++
++#if (MV_CESA_VERSION >= 3)
++    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++;
++    }
++#if (MV_CESA_VERSION >= 2)
++    /* Enable TDMA engine */
++    MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0);
++    MV_REG_WRITE(MV_CESA_TDMA_NEXT_DESC_PTR_REG,
++            (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
++#else
++    /* Enable IDMA engine */
++    MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0);
++    MV_REG_WRITE(IDMA_NEXT_DESC_PTR_REG(0),
++            (MV_U32)mvCesaVirtToPhys(&pReq->dmaDescBuf, pReq->dma[frag].pDmaFirst));
++#endif /* MV_CESA_VERSION >= 2 */
++
++#if defined(MV_BRIDGE_SYNC_REORDER)
++    mvOsBridgeReorderWA();
++#endif
++
++    /* Start Accelerator */
++    MV_REG_WRITE(MV_CESA_CMD_REG, MV_CESA_CMD_CHAN_ENABLE_MASK);
++}
++
++
++/*******************************************************************************
++* 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.
++*       pSramBase       - virtual address of Sram
++*	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, char* pSramBase, MV_U32 cryptEngBase,
++			 void *osHandle)
++{
++    int     i, req;
++    MV_U32  descOffsetReg, configReg;
++    MV_CESA_SRAM_SA *pSramSA;
++
++
++    mvOsPrintf("mvCesaInit: sessions=%d, queue=%d, pSram=%p\n",
++                numOfSession, queueDepth, pSramBase);
++
++    cesaOsHandle = osHandle;
++    /* Create 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;
++
++    /* Allocate imag of sramSA in the DRAM */
++    cesaSramSaBuf.bufSize = sizeof(MV_CESA_SRAM_SA)*numOfSession +
++                                    CPU_D_CACHE_LINE_SIZE;
++
++    cesaSramSaBuf.bufVirtPtr = mvOsIoCachedMalloc(osHandle,cesaSramSaBuf.bufSize,
++						  &cesaSramSaBuf.bufPhysAddr,
++						  &cesaSramSaBuf.memHandle);
++
++    if(cesaSramSaBuf.bufVirtPtr == NULL)
++    {
++        mvOsPrintf("mvCesaInit: Can't allocate %d bytes for sramSA structures\n",
++                    cesaSramSaBuf.bufSize);
++        mvCesaFinish();
++        return MV_NO_RESOURCE;
++    }
++    memset(cesaSramSaBuf.bufVirtPtr, 0, cesaSramSaBuf.bufSize);
++    pSramSA = (MV_CESA_SRAM_SA*)MV_ALIGN_UP((MV_ULONG)cesaSramSaBuf.bufVirtPtr,
++                                                       CPU_D_CACHE_LINE_SIZE);
++    for(i=0; i<numOfSession; i++)
++    {
++        pCesaSAD[i].pSramSA = &pSramSA[i];
++    }
++
++    /* Create request queue */
++    pCesaReqFirst = mvOsMalloc(sizeof(MV_CESA_REQ)*queueDepth);
++    if(pCesaReqFirst == 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, 0, sizeof(MV_CESA_REQ)*queueDepth);
++    pCesaReqEmpty = pCesaReqFirst;
++    pCesaReqLast = pCesaReqFirst + (queueDepth-1);
++    pCesaReqProcess = pCesaReqEmpty;
++    cesaQueueDepth = queueDepth;
++    cesaReqResources = queueDepth;
++#if (MV_CESA_VERSION >= 3)
++    cesaChainLength = MAX_CESA_CHAIN_LENGTH;
++#endif
++    /* pSramBase must be 8 byte aligned */
++    if( MV_IS_NOT_ALIGN((MV_ULONG)pSramBase, 8) )
++    {
++        mvOsPrintf("mvCesaInit: pSramBase (%p) must be 8 byte aligned\n",
++                pSramBase);
++        mvCesaFinish();
++        return MV_NOT_ALIGNED;
++    }
++    cesaSramVirtPtr = (MV_CESA_SRAM_MAP*)pSramBase;
++
++    cesaCryptEngBase = cryptEngBase;
++
++    /*memset(cesaSramVirtPtr, 0, sizeof(MV_CESA_SRAM_MAP));*/
++
++    /* Clear registers */
++    MV_REG_WRITE( MV_CESA_CFG_REG, 0);
++    MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
++    MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 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[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->desc - mvCesaSramAddrGet());
++    MV_REG_WRITE(MV_CESA_CHAN_DESC_OFFSET_REG, descOffsetReg);
++
++    configReg |= (MV_CESA_CFG_WAIT_DMA_MASK | MV_CESA_CFG_ACT_DMA_MASK);
++#if (MV_CESA_VERSION >= 3)
++    configReg |= MV_CESA_CFG_CHAIN_MODE_MASK;
++#endif
++
++#if (MV_CESA_VERSION >= 2)
++    /* Initialize TDMA engine */
++    MV_REG_WRITE(MV_CESA_TDMA_CTRL_REG, MV_CESA_TDMA_CTRL_VALUE);
++    MV_REG_WRITE(MV_CESA_TDMA_BYTE_COUNT_REG, 0);
++    MV_REG_WRITE(MV_CESA_TDMA_CURR_DESC_PTR_REG, 0);
++#else
++    /* Initialize IDMA #0 engine */
++    MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0);
++    MV_REG_WRITE(IDMA_BYTE_COUNT_REG(0), 0);
++    MV_REG_WRITE(IDMA_CURR_DESC_PTR_REG(0), 0);
++    MV_REG_WRITE(IDMA_CTRL_HIGH_REG(0), ICCHR_ENDIAN_LITTLE
++#ifdef MV_CPU_LE
++		| ICCHR_DESC_BYTE_SWAP_EN
++#endif
++		 );
++    /* Clear Cause Byte of IDMA channel to be used */
++    MV_REG_WRITE( IDMA_CAUSE_REG, ~ICICR_CAUSE_MASK_ALL(0));
++    MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), MV_CESA_IDMA_CTRL_LOW_VALUE);
++#endif /* (MV_CESA_VERSION >= 2) */
++
++    /* Set CESA configuration registers */
++    MV_REG_WRITE( MV_CESA_CFG_REG, configReg);
++    mvCesaDebugStatsClear();
++
++    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;
++    MV_CESA_REQ*    pReq;
++
++    mvOsPrintf("mvCesaFinish: \n");
++
++    cesaSramVirtPtr = NULL;
++
++    /* Free all resources: DMA list, etc. */
++    for(req=0; req<cesaQueueDepth; req++)
++    {
++	pReq = &pCesaReqFirst[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);
++        }
++    }
++#if (MV_CESA_VERSION < 2)
++    MV_REG_WRITE(IDMA_CTRL_LOW_REG(0), 0);
++#endif /* (MV_CESA_VERSION < 2) */
++
++    /* Free request queue */
++    if(pCesaReqFirst != NULL)
++    {
++        mvOsFree(pCesaReqFirst);
++        pCesaReqFirst = pCesaReqLast = NULL;
++        pCesaReqEmpty = pCesaReqProcess = NULL;
++        cesaQueueDepth = cesaReqResources = 0;
++    }
++    /* Free SA database */
++    if(pCesaSAD != NULL)
++    {
++        mvOsFree(pCesaSAD);
++        pCesaSAD = NULL;
++        cesaMaxSA = 0;
++    }
++    MV_REG_WRITE( MV_CESA_CFG_REG, 0);
++    MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
++    MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 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* pIV, int ivSize)
++{
++    MV_U8*  pSramIV;
++#if defined(MV646xx)
++    mvOsPrintf("mvCesaCryptoIvSet: ERR. shouldn't use this call on MV64660\n");
++#endif
++    pSramIV = cesaSramVirtPtr->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->cryptoIV,
++                                MV_CESA_MAX_IV_LENGTH);
++    mvOsCacheInvalidate(NULL, cesaSramVirtPtr->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;
++
++    cesaStats.openedCount++;
++
++    /* Find free entry in SAD */
++    for(sid=0; sid<cesaMaxSA; sid++)
++    {
++        if(pCesaSAD[sid].valid == 0)
++        {
++            break;
++        }
++    }
++    if(sid == cesaMaxSA)
++    {
++        mvOsPrintf("mvCesaSessionOpen: SA Database is FULL\n");
++        return MV_FULL;
++    }
++
++    /* 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 and SHA1) - Maximum Key size is 64 bytes */
++        if( (pSession->macMode == MV_CESA_MAC_HMAC_MD5) ||
++            (pSession->macMode == MV_CESA_MAC_HMAC_SHA1) )
++        {
++            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;
++
++            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) or 12 bytes (96 bits) for both */
++        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, Both-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;
++
++    pCesaSAD[sid].valid = 1;
++    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)
++{
++    cesaStats.closedCount++;
++
++    if(sid >= cesaMaxSA)
++    {
++        mvOsPrintf("CESA Error: sid (%d) is too big\n", sid);
++        return MV_BAD_PARAM;
++    }
++    if(pCesaSAD[sid].valid == 0)
++    {
++        mvOsPrintf("CESA Warning: Session (sid=%d) is invalid\n", sid);
++        return MV_NOT_FOUND;
++    }
++    if(cesaLastSid == sid)
++        cesaLastSid = -1;
++
++    pCesaSAD[sid].valid = 0;
++    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_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_CESA_COMMAND *pCmd)
++{
++    MV_STATUS       status;
++    MV_CESA_REQ*    pReq = pCesaReqEmpty;
++    int             sid = pCmd->sessionId;
++    MV_CESA_SA*     pSA = &pCesaSAD[sid];
++#if (MV_CESA_VERSION >= 3)
++     MV_CESA_REQ*   pFromReq;
++     MV_CESA_REQ*   pToReq;
++#endif
++    cesaStats.reqCount++;
++
++    /* Check that the request queue is not FULL */
++    if(cesaReqResources == 0)
++        return MV_NO_RESOURCE;
++
++    if( (sid >= cesaMaxSA) || (!pSA->valid) )
++    {
++        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->buf) )
++    {
++        /* request size is smaller than single buffer size */
++        pReq->fragMode = MV_CESA_FRAG_NONE;
++
++        /* Prepare NOT fragmented packets */
++        status = mvCesaReqProcess(pReq);
++        if(status != MV_OK)
++        {
++            mvOsPrintf("CesaReady: ReqProcess error: pReq=%p, status=0x%x\n",
++                        pReq, status);
++        }
++#if (MV_CESA_VERSION >= 3)
++	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(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(pReq, frag);
++            if(status == MV_OK) {
++#if (MV_CESA_VERSION >= 3)
++		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
++                frag++;
++        }
++        }
++        pReq->frags.numFrag = frag;
++#if (MV_CESA_VERSION >= 3)
++	if(chainReqNum) {
++		chainReqNum += pReq->frags.numFrag;
++		if(chainReqNum >= MAX_CESA_CHAIN_LENGTH)
++			chainReqNum = MAX_CESA_CHAIN_LENGTH;
++	}
++#endif
++    }
++
++    pReq->state = MV_CESA_PENDING;
++
++    pCesaReqEmpty = MV_CESA_REQ_NEXT_PTR(pReq);
++    cesaReqResources -= 1;
++
++/* #ifdef CESA_DEBUG */
++    if( (cesaQueueDepth - cesaReqResources) > cesaStats.maxReqCount)
++        cesaStats.maxReqCount = (cesaQueueDepth - cesaReqResources);
++/* #endif CESA_DEBUG */
++
++    cesaLastSid = sid;
++
++#if (MV_CESA_VERSION >= 3)
++    /* Are we within chain bounderies and follows the first request ? */
++    if((chainReqNum > 0) && (chainReqNum < MAX_CESA_CHAIN_LENGTH)) {
++	if(chainIndex) {
++		pFromReq = MV_CESA_REQ_PREV_PTR(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->state != MV_CESA_PENDING)
++			pEndCurrChain = pNextActiveChain = MV_CESA_REQ_NEXT_PTR(pReq);
++	}
++	else { /* we have only one chain, start new one */
++		chainReqNum = 0;
++		chainIndex++;
++		/* align active & next pointers  */
++		if(pNextActiveChain->state != MV_CESA_PENDING)
++			pEndCurrChain = pNextActiveChain = pReq;
++	}
++    }
++    else {
++		/* In case we concatenate full chain */
++		if(chainReqNum == MAX_CESA_CHAIN_LENGTH) {
++			chainIndex++;
++			if(pNextActiveChain->state != MV_CESA_PENDING)
++				pEndCurrChain = pNextActiveChain = pReq;
++			chainReqNum = 0;
++		}
++
++		pReq = pCesaReqProcess;
++		if(pReq->state == MV_CESA_PENDING) {
++			pNextActiveChain = pReq;
++			pEndCurrChain = MV_CESA_REQ_NEXT_PTR(pReq);
++			/* Start Process new request */
++			mvCesaReqProcessStart(pReq);
++		}
++    }
++
++    chainReqNum++;
++
++    if((chainIndex < MAX_CESA_CHAIN_LENGTH) && (chainReqNum > cesaStats.maxChainUsage))
++	cesaStats.maxChainUsage = chainReqNum;
++
++#else
++
++    /* Check status of CESA channels and process requests if possible */
++    pReq = pCesaReqProcess;
++    if(pReq->state == MV_CESA_PENDING)
++    {
++        /* Start Process new request */
++        mvCesaReqProcessStart(pReq);
++    }
++#endif
++    /* If request queue became FULL - return MV_NO_MORE */
++    if(cesaReqResources == 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_CESA_RESULT* pResult)
++{
++    MV_STATUS       status, readyStatus = MV_NOT_READY;
++    MV_U32          statusReg;
++    MV_CESA_REQ*    pReq;
++    MV_CESA_SA*     pSA;
++
++#if (MV_CESA_VERSION >= 3)
++    if(isFirstReq == MV_TRUE) {
++	if(chainIndex == 0)
++		chainReqNum = 0;
++
++	isFirstReq = MV_FALSE;
++
++	if(pNextActiveChain->state == MV_CESA_PENDING) {
++		/* Start request Process */
++		mvCesaReqProcessStart(pNextActiveChain);
++		pEndCurrChain = pNextActiveChain;
++		if(chainIndex > 0)
++			chainIndex--;
++		/* Update pNextActiveChain to next chain head */
++		   while(pNextActiveChain->state == MV_CESA_CHAIN)
++			pNextActiveChain = MV_CESA_REQ_NEXT_PTR(pNextActiveChain);
++	}
++    }
++
++    /* Check if there are more processed requests - can we remove pEndCurrChain ??? */
++    if(pCesaReqProcess == pEndCurrChain) {
++		isFirstReq = MV_TRUE;
++		pEndCurrChain = pNextActiveChain;
++#else
++    if(pCesaReqProcess->state != MV_CESA_PROCESS) {
++#endif
++        return MV_EMPTY;
++    }
++
++#ifdef CESA_DEBUG
++    statusReg = MV_REG_READ(MV_CESA_STATUS_REG);
++    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;
++    pSA = &pCesaSAD[pReq->pCmd->sessionId];
++
++    pResult->retCode = MV_OK;
++    if(pReq->fragMode != MV_CESA_FRAG_NONE)
++    {
++        MV_U8*          pNewDigest;
++      int             frag;
++#if (MV_CESA_VERSION >= 3)
++      pReq->frags.nextFrag = 1;
++      while(pReq->frags.nextFrag <= pReq->frags.numFrag) {
++#endif
++	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(pReq, pSA, macDataSize);
++                }
++
++                /* Copy new digest from SRAM to the Destination buffer */
++                pNewDigest = cesaSramVirtPtr->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;
++        }
++#if (MV_CESA_VERSION >= 3)
++	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);
++            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;
++
++        pReq->state = MV_CESA_IDLE;
++        pCesaReqProcess = MV_CESA_REQ_NEXT_PTR(pReq);
++        cesaReqResources++;
++
++        if(pSA->ctrMode)
++        {
++            /* For AES CTR mode - complete processing and free allocated resources */
++            mvCesaCtrModeComplete(pReq->pOrgCmd, pReq->pCmd);
++            mvCesaCtrModeFinish(pReq->pCmd);
++            pReq->pOrgCmd = NULL;
++        }
++    }
++
++#if (MV_CESA_VERSION < 3)
++    if(pCesaReqProcess->state == MV_CESA_PROCESS)
++    {
++        /* Start request Process */
++        mvCesaReqProcessStart(pCesaReqProcess);
++        if(readyStatus == MV_NOT_READY)
++            readyStatus = MV_BUSY;
++    }
++    else if(pCesaReqProcess != pCesaReqEmpty)
++    {
++        /* Start process new request from the queue */
++        mvCesaReqProcessStart(pCesaReqProcess);
++    }
++#endif
++    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;
++}
++
++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",
++                __FUNCTION__, 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_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->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->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(pCmd->pSrc, cesaSramVirtPtr->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->tempCryptoIV - mvCesaSramAddrGet();
++
++                    /* 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(pCmd->pSrc, cesaSramVirtPtr->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(pCmd->pSrc, cesaSramVirtPtr->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->tempDigest - mvCesaSramAddrGet();
++                }
++                else
++                {
++                    digestOffset = pCmd->digestOffset;
++                }
++            }
++        }
++        /* Update SA in SRAM */
++        if(cesaLastSid != sid)
++        {
++            mvCesaSramSaUpdate(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->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->tempDigest - mvCesaSramAddrGet();
++                }
++                else
++                {
++                    digestOffset = pCmd->digestOffset - pReq->frags.bufOffset;
++                }
++                pReq->frags.newDigestOffset = digestOffset;
++                macTotalLen = pCmd->macLength;
++
++                /* HW can't calculate the Digest correctly for fragmented packets
++                 * in the following cases:
++                 *  - MV88F5182                                           ||
++                 *  - MV88F5181L when total macLength more that 16 Kbytes ||
++                 *  - total macLength more that 64 Kbytes
++                 */
++                if( (mvCtrlModelGet() == MV_5182_DEV_ID) ||
++                    ( (mvCtrlModelGet() == MV_5181_DEV_ID) &&
++                      (mvCtrlRevGet() >= MV_5181L_A0_REV)  &&
++                      (pCmd->macLength >= (1 << 14)) ) )
++                {
++                    return MV_TERMINATE;
++                }
++            }
++            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
++        {
++            /* WA for MV88F5182 SHA1 and MD5 fragmentation mode */
++            if( (mvCtrlModelGet() == MV_5182_DEV_ID) &&
++                (((pSA->config & MV_CESA_MAC_MODE_MASK) ==
++                    (MV_CESA_MAC_MD5 << MV_CESA_MAC_MODE_OFFSET)) ||
++                ((pSA->config & MV_CESA_MAC_MODE_MASK) ==
++                    (MV_CESA_MAC_SHA1 << MV_CESA_MAC_MODE_OFFSET))) )
++            {
++                pReq->frags.newDigestOffset = cesaSramVirtPtr->tempDigest - mvCesaSramAddrGet();
++                pReq->fragMode = MV_CESA_FRAG_LAST;
++
++                return MV_TERMINATE;
++            }
++            /* Middle fragment */
++            config = pSA->config | (MV_CESA_FRAG_MIDDLE << MV_CESA_FRAG_MODE_OFFSET);
++            copySize = sizeof(cesaSramVirtPtr->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(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(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(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->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_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->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(pCmd->pSrc, cesaSramVirtPtr->cryptoIV, &pDmaDesc[i],
++                                    MV_FALSE, pCmd->ivOffset, pSA->cryptoIvSize, pCmd->skipFlush);
++    }
++
++    /* Update SA in SRAM */
++    if(cesaLastSid != sid)
++    {
++        mvCesaSramSaUpdate(sid, &pDmaDesc[i]);
++        i++;
++    }
++
++    /********* Prepare DMA descriptors to copy from pSrc to SRAM *********/
++    pMbuf = pCmd->pSrc;
++    i += mvCesaDmaCopyPrepare(pMbuf, pSramBuf + fixOffset, &pDmaDesc[i],
++                                MV_FALSE, 0, pMbuf->mbufSize, pCmd->skipFlush);
++
++    /* Prepare Security Accelerator descriptor to SRAM words 0 - 7 */
++    mvCesaSramDescrBuild(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(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_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 = pSramDesc = &cesaSramVirtPtr->desc;
++    MV_U16          sramBufOffset = (MV_U16)((MV_U8*)cesaSramVirtPtr->buf - mvCesaSramAddrGet());
++
++    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->sramSA.cryptoKey -
++                                                            mvCesaSramAddrGet()));
++        /* word 4 */
++        pCesaDesc->cryptoIvOffset  = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->cryptoIV -
++                                                            mvCesaSramAddrGet()));
++        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->sramSA.macInnerIV -
++                                 mvCesaSramAddrGet()));
++        pCesaDesc->macOuterIvOffset = MV_16BIT_LE((MV_U16)(cesaSramVirtPtr->sramSA.macOuterIV -
++                                 mvCesaSramAddrGet()));
++    }
++    /* 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(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(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 = MV_32BIT_LE(mvCesaVirtToPhys(&cesaSramSaBuf, pSA->pSramSA));
++     pDmaDesc->phyDestAdd =
++          MV_32BIT_LE(mvCesaSramVirtToPhys(NULL, (MV_U8*)&cesaSramVirtPtr->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_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(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(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_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(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 or HMAC_SHA1.
++*       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
++    {
++        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_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(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_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(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);
++    }
++}
++
++/*******************************************************************************
++* mvCesaFragAuthComplete -
++*
++* DESCRIPTION:
++*
++*
++* INPUT:
++*       MV_CESA_REQ*    pReq,
++*       MV_CESA_SA*     pSA,
++*       int             macDataSize
++*
++* RETURN:
++*       MV_STATUS
++*
++*******************************************************************************/
++static MV_STATUS   mvCesaFragAuthComplete(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->buf[0], pCmd->pSrc, pReq->frags.bufOffset, macDataSize);
++    mvCesaCopyToMbuf(cesaSramVirtPtr->buf[0], pCmd->pDst, pReq->frags.bufOffset, macDataSize);
++*/
++    pDigest = (mvCesaSramAddrGet() + 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;
++
++        case MV_CESA_MAC_MD5:
++            mvCesaFragMd5Complete(pCmd->pDst, pReq->frags.bufOffset, pOuterIV,
++                               macDataSize, pCmd->macLength, pDigest);
++        break;
++
++        case MV_CESA_MAC_HMAC_SHA1:
++            pOuterIV = pSA->pSramSA->macOuterIV;
++
++        case MV_CESA_MAC_SHA1:
++            mvCesaFragSha1Complete(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("mvCesaSessionOpen: 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;
++
++    /* 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_CESA_SA* pSA, MV_CESA_COMMAND *pCmd
++*
++* RETURN:
++*       MV_STATUS
++*
++*******************************************************************************/
++static MV_STATUS   mvCesaFragParamCheck(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->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->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->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->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)) )
++    {
++        if( (mvCtrlModelGet() == MV_5182_DEV_ID) ||
++            ( (mvCtrlModelGet() == MV_5181_DEV_ID) &&
++              (mvCtrlRevGet() >= MV_5181L_A0_REV)  &&
++              (pCmd->macLength >= (1 << 14)) ) )
++        {
++            return MV_NOT_ALLOWED;
++        }
++
++        /* 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/crypto/ocf/kirkwood/cesa/mvCesa.h b/crypto/ocf/kirkwood/cesa/mvCesa.h
+new file mode 100644
+index 0000000..c0abc9b
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvCesa.h
+@@ -0,0 +1,412 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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__
++
++#include "mvOs.h"
++#include "mvCommon.h"
++#include "mvDebug.h"
++
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++
++#include "cesa/mvMD5.h"
++#include "cesa/mvSHA1.h"
++
++#include "cesa/mvCesa.h"
++#include "cesa/AES/mvAes.h"
++#include "mvSysHwConfig.h"
++
++#ifdef MV_INCLUDE_IDMA
++#include "idma/mvIdma.h"
++#include "idma/mvIdmaRegs.h"
++#else
++/* 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;
++#endif /* MV_INCLUDE_IDMA */
++
++#include "cesa/mvCesaRegs.h"
++
++#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_MAX_DIGEST_SIZE         MV_CESA_SHA1_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_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_COMMAND;
++
++
++
++MV_STATUS   mvCesaHalInit (int numOfSession, int queueDepth, char* pSramBase, MV_U32 cryptEngBase, void *osHandle);
++MV_STATUS   mvCesaFinish (void);
++MV_STATUS   mvCesaSessionOpen(MV_CESA_OPEN_SESSION *pSession, short* pSid);
++MV_STATUS   mvCesaSessionClose(short sid);
++MV_STATUS   mvCesaCryptoIvSet(MV_U8* pIV, int ivSize);
++
++MV_STATUS   mvCesaAction (MV_CESA_COMMAND* pCmd);
++
++MV_U32      mvCesaInProcessGet(void);
++MV_STATUS   mvCesaReadyDispatch(void);
++MV_STATUS   mvCesaReadyGet(MV_CESA_RESULT* pResult);
++MV_BOOL     mvCesaIsReady(void);
++
++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 ********/
++#if (MV_CESA_VERSION >= 2)
++#if (MV_CACHE_COHERENCY  == MV_CACHE_COHER_SW)
++#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
++#else
++#define MV_CESA_TDMA_CTRL_VALUE       MV_CESA_TDMA_DST_BURST_MASK(MV_CESA_TDMA_BURST_32B)  \
++                                    | MV_CESA_TDMA_SRC_BURST_MASK(MV_CESA_TDMA_BURST_128B) \
++                                    /*| MV_CESA_TDMA_OUTSTAND_READ_EN_MASK                   */\
++                                    | MV_CESA_TDMA_ENABLE_MASK
++
++#endif
++#else
++#define MV_CESA_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
++#endif /* MV_CESA_VERSION >= 2 */
++
++#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,
++#if (MV_CESA_VERSION >= 3)
++    MV_CESA_CHAIN,
++#endif
++} 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_U32              config;
++    MV_U8               cryptoKeyLength;
++    MV_U8               cryptoIvSize;
++    MV_U8               cryptoBlockSize;
++    MV_U8               digestSize;
++    MV_U8               macKeyLength;
++    MV_U8               valid;
++    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;
++#if (MV_CESA_VERSION >= 3)
++    MV_U32  maxChainUsage;
++#endif
++
++} MV_CESA_STATS;
++
++
++/* External variables */
++
++extern MV_CESA_STATS    cesaStats;
++extern MV_CESA_FRAGS    cesaFrags;
++
++extern MV_BUF_INFO      cesaSramSaBuf;
++
++extern MV_CESA_SA*       pCesaSAD;
++extern MV_U16            cesaMaxSA;
++
++extern MV_CESA_REQ*      pCesaReqFirst;
++extern MV_CESA_REQ*      pCesaReqLast;
++extern MV_CESA_REQ*      pCesaReqEmpty;
++extern MV_CESA_REQ*      pCesaReqProcess;
++extern int               cesaQueueDepth;
++extern int               cesaReqResources;
++#if (MV_CESA_VERSION>= 3)
++extern MV_U32		cesaChainLength;
++#endif
++
++extern MV_CESA_SRAM_MAP*  cesaSramVirtPtr;
++extern MV_U32           cesaSramPhysAddr;
++
++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);
++
++
++
++#endif /* __mvCesa_h__ */
+diff --git a/crypto/ocf/kirkwood/cesa/mvCesaDebug.c b/crypto/ocf/kirkwood/cesa/mvCesaDebug.c
+new file mode 100644
+index 0000000..31b78a8
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvCesaDebug.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 "mvOs.h"
++#include "mvDebug.h"
++
++#include "cesa/mvMD5.h"
++#include "cesa/mvSHA1.h"
++
++#include "cesa/mvCesa.h"
++#include "cesa/mvCesaRegs.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_HMAC_MD5:
++            return "HMAC-MD5";
++
++        case MV_CESA_MAC_HMAC_SHA1:
++            return "HMAC_SHA1";
++
++        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)
++{
++    mvOsPrintf("\t CESA Registers:\n");
++
++    mvOsPrintf("MV_CESA_CMD_REG                     : 0x%X = 0x%08x\n",
++                MV_CESA_CMD_REG,
++                MV_REG_READ( MV_CESA_CMD_REG ) );
++
++    mvOsPrintf("MV_CESA_CHAN_DESC_OFFSET_REG        : 0x%X = 0x%08x\n",
++                MV_CESA_CHAN_DESC_OFFSET_REG,
++                MV_REG_READ(MV_CESA_CHAN_DESC_OFFSET_REG) );
++
++    mvOsPrintf("MV_CESA_CFG_REG                     : 0x%X = 0x%08x\n",
++                MV_CESA_CFG_REG,
++                MV_REG_READ( MV_CESA_CFG_REG ) );
++
++    mvOsPrintf("MV_CESA_STATUS_REG                  : 0x%X = 0x%08x\n",
++                MV_CESA_STATUS_REG,
++                MV_REG_READ( MV_CESA_STATUS_REG ) );
++
++    mvOsPrintf("MV_CESA_ISR_CAUSE_REG               : 0x%X = 0x%08x\n",
++                MV_CESA_ISR_CAUSE_REG,
++                MV_REG_READ( MV_CESA_ISR_CAUSE_REG ) );
++
++    mvOsPrintf("MV_CESA_ISR_MASK_REG                : 0x%X = 0x%08x\n",
++                MV_CESA_ISR_MASK_REG,
++                MV_REG_READ( MV_CESA_ISR_MASK_REG ) );
++#if (MV_CESA_VERSION >= 2)
++    mvOsPrintf("MV_CESA_TDMA_CTRL_REG               : 0x%X = 0x%08x\n",
++                MV_CESA_TDMA_CTRL_REG,
++                MV_REG_READ( MV_CESA_TDMA_CTRL_REG ) );
++
++    mvOsPrintf("MV_CESA_TDMA_BYTE_COUNT_REG         : 0x%X = 0x%08x\n",
++                MV_CESA_TDMA_BYTE_COUNT_REG,
++                MV_REG_READ( MV_CESA_TDMA_BYTE_COUNT_REG ) );
++
++    mvOsPrintf("MV_CESA_TDMA_SRC_ADDR_REG           : 0x%X = 0x%08x\n",
++                MV_CESA_TDMA_SRC_ADDR_REG,
++                MV_REG_READ( MV_CESA_TDMA_SRC_ADDR_REG ) );
++
++    mvOsPrintf("MV_CESA_TDMA_DST_ADDR_REG           : 0x%X = 0x%08x\n",
++                MV_CESA_TDMA_DST_ADDR_REG,
++                MV_REG_READ( MV_CESA_TDMA_DST_ADDR_REG ) );
++
++    mvOsPrintf("MV_CESA_TDMA_NEXT_DESC_PTR_REG      : 0x%X = 0x%08x\n",
++                MV_CESA_TDMA_NEXT_DESC_PTR_REG,
++                MV_REG_READ( MV_CESA_TDMA_NEXT_DESC_PTR_REG ) );
++
++    mvOsPrintf("MV_CESA_TDMA_CURR_DESC_PTR_REG      : 0x%X = 0x%08x\n",
++                MV_CESA_TDMA_CURR_DESC_PTR_REG,
++                MV_REG_READ( MV_CESA_TDMA_CURR_DESC_PTR_REG ) );
++
++    mvOsPrintf("MV_CESA_TDMA_ERROR_CAUSE_REG        : 0x%X = 0x%08x\n",
++                MV_CESA_TDMA_ERROR_CAUSE_REG,
++                MV_REG_READ( MV_CESA_TDMA_ERROR_CAUSE_REG ) );
++
++    mvOsPrintf("MV_CESA_TDMA_ERROR_MASK_REG         : 0x%X = 0x%08x\n",
++                MV_CESA_TDMA_ERROR_MASK_REG,
++                MV_REG_READ( MV_CESA_TDMA_ERROR_CAUSE_REG ) );
++
++#endif
++}
++
++void    mvCesaDebugStatus(void)
++{
++    mvOsPrintf("\n\t CESA Status\n\n");
++
++    mvOsPrintf("pReqQ=%p, qDepth=%d, reqSize=%ld bytes, qRes=%d, ",
++                pCesaReqFirst, cesaQueueDepth, sizeof(MV_CESA_REQ),
++                cesaReqResources);
++#if (MV_CESA_VERSION >= 3)
++    mvOsPrintf("chainLength=%u\n",cesaChainLength);
++#else
++   mvOsPrintf("\n");
++#endif
++
++    mvOsPrintf("pSAD=%p, maxSA=%d, sizeSA=%ld bytes\n",
++                pCesaSAD, cesaMaxSA, 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)
++{
++    mvOsPrintf("\n\t CESA Request Queue:\n\n");
++
++    mvOsPrintf("pFirstReq=%p, pLastReq=%p, qDepth=%d, reqSize=%ld bytes\n",
++                pCesaReqFirst, pCesaReqLast, cesaQueueDepth, sizeof(MV_CESA_REQ));
++
++    mvOsPrintf("pEmpty=%p, pProcess=%p, qResources=%d\n",
++                pCesaReqEmpty, pCesaReqProcess,
++                cesaReqResources);
++
++    if(mode != 0)
++    {
++        int             count = 0;
++        MV_CESA_REQ*    pReq = pCesaReqFirst;
++
++        for(count=0; count<cesaQueueDepth; 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=%ld bytes\n",
++                pSramSA, 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->valid) || ((pSA->count != 0) && (mode > 0)) || (mode >= 2) )
++    {
++        mvOsPrintf("\n\nCESA SA Entry #%d (%p) - %s (count=%d)\n",
++                    sid, pSA,
++                    pSA->valid ? "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)
++{
++    mvOsPrintf("\n\t SRAM contents: size=%ld, pVirt=%p\n\n",
++            sizeof(MV_CESA_SRAM_MAP), cesaSramVirtPtr);
++
++    mvOsPrintf("\n\t Sram buffer: size=%d, pVirt=%p\n",
++                    MV_CESA_MAX_BUF_SIZE, cesaSramVirtPtr->buf);
++        if(mode != 0)
++            mvDebugMemDump(cesaSramVirtPtr->buf, 64, 1);
++
++    mvOsPrintf("\n");
++    mvOsPrintf("\n\t Sram descriptor: size=%ld, pVirt=%p\n",
++                    sizeof(MV_CESA_DESC), &cesaSramVirtPtr->desc);
++    if(mode != 0)
++    {
++        mvOsPrintf("\n");
++        mvCesaDebugDescriptor(&cesaSramVirtPtr->desc);
++    }
++    mvOsPrintf("\n\t Sram IV: size=%d, pVirt=%p\n",
++                    MV_CESA_MAX_IV_LENGTH, &cesaSramVirtPtr->cryptoIV);
++    if(mode != 0)
++    {
++        mvOsPrintf("\n");
++        mvDebugMemDump(cesaSramVirtPtr->cryptoIV, MV_CESA_MAX_IV_LENGTH, 1);
++    }
++    mvOsPrintf("\n");
++    mvCesaDebugSramSA(&cesaSramVirtPtr->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);
++#if (MV_CESA_VERSION >= 3)
++    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/crypto/ocf/kirkwood/cesa/mvCesaRegs.h b/crypto/ocf/kirkwood/cesa/mvCesaRegs.h
+new file mode 100644
+index 0000000..6b7ce12
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvCesaRegs.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.
++
++*******************************************************************************/
++
++#ifndef __mvCesaRegs_h__
++#define __mvCesaRegs_h__
++
++#include "mvTypes.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_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                     (MV_CESA_REG_BASE + 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        (MV_CESA_REG_BASE + 0xE04)
++
++/********** Security Accelerator Configuration Register **********/
++#define MV_CESA_CFG_REG                     (MV_CESA_REG_BASE + 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)
++
++/********** Security Accelerator Status Register ***********/
++#define MV_CESA_STATUS_REG                  (MV_CESA_REG_BASE + 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               (MV_CESA_REG_BASE + 0xE20)
++
++/* Cryptographic Engines and Security Accelerator Interrupt Mask Register */
++#define MV_CESA_ISR_MASK_REG                (MV_CESA_REG_BASE + 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            (MV_CESA_REG_BASE + 0xd38)
++#define MV_CESA_AUTH_BIT_COUNT_LOW_REG      (MV_CESA_REG_BASE + 0xd20)
++#define MV_CESA_AUTH_BIT_COUNT_HIGH_REG     (MV_CESA_REG_BASE + 0xd24)
++
++#define MV_CESA_AUTH_INIT_VAL_DIGEST_REG(i) (MV_CESA_REG_BASE + 0xd00 + (i<<2))
++
++#define MV_CESA_AUTH_INIT_VAL_DIGEST_A_REG  (MV_CESA_REG_BASE + 0xd00)
++#define MV_CESA_AUTH_INIT_VAL_DIGEST_B_REG  (MV_CESA_REG_BASE + 0xd04)
++#define MV_CESA_AUTH_INIT_VAL_DIGEST_C_REG  (MV_CESA_REG_BASE + 0xd08)
++#define MV_CESA_AUTH_INIT_VAL_DIGEST_D_REG  (MV_CESA_REG_BASE + 0xd0c)
++#define MV_CESA_AUTH_INIT_VAL_DIGEST_E_REG  (MV_CESA_REG_BASE + 0xd10)
++#define MV_CESA_AUTH_COMMAND_REG            (MV_CESA_REG_BASE + 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               (MV_CESA_TDMA_REG_BASE + 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         (MV_CESA_TDMA_REG_BASE + 0x800)
++#define MV_CESA_TDMA_SRC_ADDR_REG           (MV_CESA_TDMA_REG_BASE + 0x810)
++#define MV_CESA_TDMA_DST_ADDR_REG           (MV_CESA_TDMA_REG_BASE + 0x820)
++#define MV_CESA_TDMA_NEXT_DESC_PTR_REG      (MV_CESA_TDMA_REG_BASE + 0x830)
++#define MV_CESA_TDMA_CURR_DESC_PTR_REG      (MV_CESA_TDMA_REG_BASE + 0x870)
++
++#define MV_CESA_TDMA_ERROR_CAUSE_REG        (MV_CESA_TDMA_REG_BASE + 0x8C0)
++#define MV_CESA_TDMA_ERROR_MASK_REG         (MV_CESA_TDMA_REG_BASE + 0x8C4)
++
++
++#endif /* __mvCesaRegs_h__ */
++
+diff --git a/crypto/ocf/kirkwood/cesa/mvCesaTest.c b/crypto/ocf/kirkwood/cesa/mvCesaTest.c
+new file mode 100644
+index 0000000..7463293
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvCesaTest.c
+@@ -0,0 +1,3096 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++        this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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/wait.h>
++wait_queue_head_t   cesaTest_waitq;
++spinlock_t          cesaLock;
++
++#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))
++
++#define CESA_TEST_TICK_GET()        jiffies
++#define CESA_TEST_TICK_TO_MS(tick)  jiffies_to_msecs(tick)
++
++#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 "mvSysHwConfig.h"
++#include "boardEnv/mvBoardEnvLib.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++#include "cntmr/mvCntmr.h"
++#include "cesa/mvCesa.h"
++#include "cesa/mvCesaRegs.h"
++#include "cesa/mvMD5.h"
++#include "cesa/mvSHA1.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          dmaCause;
++    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 = 0;
++static MV_CESA_TEST_TRACE    cesaTestTrace[MV_CESA_TEST_TRACE_SIZE];
++
++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].dmaCause = MV_REG_READ(IDMA_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;
++}
++
++#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,
++    SHA_TEST_TYPE         = 4,
++    COMBINED_TEST_TYPE    = 5,
++
++    MAX_TEST_TYPE
++};
++
++/* Tests data base */
++typedef struct
++{
++    short           sid;
++    char            cryptoAlgorithm;    /* DES/3DES/AES */
++    char            cryptoMode;         /* ECB or CBC */
++    char            macAlgorithm;       /* MD5 / SHA1 */
++    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 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   shaTestSessions[] =
++{
++/*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   combinedTestSessions[] =
++{
++/*500*/ {-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"
++        },
++/*501*/ {-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"
++        },
++/*502*/ {-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"
++        },
++/*503*/ {-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"
++        },
++/*504*/ {-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"
++        },
++/*505*/ {-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"
++        },
++/*506*/ {-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"
++        },
++/*507*/ {-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"
++        },
++/*508*/ {-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"
++        },
++};
++
++
++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]) },
++    { shaTestSessions,       sizeof(shaTestSessions)/sizeof(shaTestSessions[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  cesaDataAndMd5digest1[]  = "48692054686572659294727a3638bb1c13f48ef8158bfc9d";
++char  cesaDataAndSha1digest1[] = "4869205468657265b617318655057264e28bc0b6fb378c8ef146be00";
++
++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] = "";
++
++/* Ascii string is "abc" */
++char hashHexStr3[] = "616263";
++char hashMd5digest3[] = "900150983cd24fb0d6963f7d28e17f72";
++char hashSha1digest3[] = "a9993e364706816aba3e25717850c26c9cd0d89d";
++
++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";
++
++
++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  },
++};
++
++
++/* 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     shaMultiSizeTest402[] =
++{
++    { 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     shaMultiSizeTest404[] =
++{
++    { 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     shaMultiSizeTest405[] =
++{
++    { 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     tripleDesMdMultiSizeTest502[] =
++{
++    {   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     tripleDesShaMultiSizeTest503[] =
++{
++    {   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     cbc3desMdMultiSizeTest504[] =
++{
++    {   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     cbc3desShaMultiSizeTest505[] =
++{
++    {   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     cbcAes128md5multiSizeTest506[] =
++{
++    {   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     cbcAes128sha1multiSizeTest507[] =
++{
++    {   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 shaTest(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     kBits, milliSec, rate;
++
++    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;
++
++    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;
++    mvCesaDebugMbuf("src", pMbuf, offset,size);
++    pMbuf = cesaCmdRing[req].pDst;
++    mvCesaDebugMbuf("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( mvCesaDebugMbuf("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;
++
++        cesaEndTicks = CESA_TEST_TICK_GET();
++        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;
++
++    cesaTestIsrCount++;
++    /* Clear cause register */
++    cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
++    if( (cause & MV_CESA_CAUSE_ACC_DMA_ALL_MASK) == 0)
++    {
++        mvOsPrintf("cesaTestReadyIsr: cause=0x%x\n", cause);
++#ifdef MV_NETBSD
++        return 0;
++#else
++#ifdef __KERNEL__
++        return 1;
++#else
++        return;
++#endif
++#endif
++    }
++
++    MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
++
++    while(MV_TRUE)
++    {
++        /* Get Ready requests */
++        status = mvCesaReadyGet(&result);
++        if(status == MV_OK)
++            cesaCheckReady(&result);
++
++        break;
++    }
++    if( (cesaTestFull == 1) && (status != MV_BUSY) )
++    {
++        cesaTestFull = 0;
++        CESA_TEST_WAKE_UP();
++    }
++
++#ifdef __KERNEL__
++    return 1;
++#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 = mvCesaSessionOpen(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 = mvCesaSessionClose(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_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";
++
++    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;
++        }
++    }
++
++    cesaBeginTicks = CESA_TEST_TICK_GET();
++    CESA_TEST_DEBUG_CODE( memset(cesaTestTrace, 0, sizeof(cesaTestTrace));
++                     cesaTestTraceIdx = 0;
++    );
++
++    if(cesaCheckMode == CESA_SW_NULL_CHECK_MODE)
++    {
++        volatile 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);
++            }
++        }
++        cesaEndTicks = CESA_TEST_TICK_GET();
++        cesaRate = getRate(&cesaRateAfterDot);
++        cesaIsReady = MV_TRUE;
++
++        return MV_OK;
++    }
++
++    /*cesaTestIsrCount = 0;*/
++    /*mvCesaDebugStatsClear();*/
++
++#ifndef MV_NETBSD
++    MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
++#endif
++
++    for(i=0; i<iter; i++)
++    {
++        unsigned long flags;
++
++        pCmd = &cesaCmdRing[cmdReqId];
++        pCmd->pReqPrv = (void*)cmdReqId;
++
++        CESA_TEST_LOCK(flags);
++
++        rc = mvCesaAction(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 = mvCesaAction(pCmd);
++
++            CESA_TEST_UNLOCK(flags);
++        }
++        if( (rc != MV_OK) && (rc != MV_NO_MORE) )
++        {
++            mvOsPrintf("mvCesaAction 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;
++}
++
++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;
++    char            *pSram;
++    MV_STATUS       status;
++    MV_CPU_DEC_WIN  addrDecWin;
++#endif
++
++    cesaCmdRing = mvOsMalloc(sizeof(MV_CESA_COMMAND) * CESA_DEF_REQ_SIZE);
++    if(cesaCmdRing == NULL)
++    {
++        mvOsPrintf("testStart: Can't allocate %ld bytes of memory\n",
++                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
++    if (mvCpuIfTargetWinGet(CRYPT_ENG, &addrDecWin) == MV_OK)
++        pSram = (char*)addrDecWin.addrWin.baseLow;
++    else
++    {
++        mvOsPrintf("mvCesaInit: ERR. mvCpuIfTargetWinGet failed\n");
++        return;
++    }
++
++#ifdef MV_CESA_NO_SRAM
++    pSram = mvOsMalloc(4*1024+8);
++    if(pSram == NULL)
++    {
++        mvOsPrintf("CesaTest: can't allocate %d bytes for SRAM simulation\n",
++                4*1024+8);
++        /* !!!! Dima cesaTestCleanup();*/
++        return;
++    }
++    pSram = (MV_U8*)MV_ALIGN_UP((MV_U32)pSram, 8);
++#endif /* MV_CESA_NO_SRAM */
++
++    numOfSessions = CESA_DEF_SESSION_NUM;
++    queueDepth = CESA_DEF_REQ_SIZE - MV_CESA_MAX_CHAN;
++
++    status = mvCesaInit(numOfSessions, queueDepth, pSram, 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);
++
++#ifndef MV_NETBSD
++    MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
++    MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 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__)
++        if( request_irq(CESA_IRQ, cesaTestReadyIsr, (SA_INTERRUPT) , "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;
++
++    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;
++        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;
++                mvCesaCryptoIvSet(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';
++}
++
++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 defined(MV_LINUX)
++/* 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    shaTest(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    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(500);
++    testOpen(501);
++    testOpen(502);
++    testOpen(503);
++    testOpen(504);
++    testOpen(505);
++    testOpen(506);
++    testOpen(507);
++
++/* DES ECB + MD5 encode test */
++    status = testRun(500, 17, iter, reqSize, mode);
++    printTestResults(500, status, mode);
++
++/* DES ECB + SHA1 encode test */
++    status = testRun(501, 18, iter, reqSize, mode);
++    printTestResults(501, status, mode);
++
++/* 3DES ECB + MD5 encode test */
++    status = testRun(502, 17, iter, reqSize, mode);
++    printTestResults(502, status, mode);
++
++/* 3DES ECB + SHA1 encode test */
++    status = testRun(503, 18, iter, reqSize, mode);
++    printTestResults(503, status, mode);
++
++/* 3DES CBC + MD5 encode test */
++    status = testRun(504, 19, i, reqSize, mode);
++    printTestResults(504, status, mode);
++
++/* 3DES CBC + SHA1 encode test */
++    status = testRun(505, 20, i, reqSize, mode);
++    printTestResults(505, status, mode);
++
++/* AES-128 CBC + MD5 encode test */
++    status = testRun(506, 21, i, reqSize, mode);
++    printTestResults(506, status, mode);
++
++/* AES-128 CBC + SHA1 encode test */
++    status = testRun(507, 22, i, reqSize, mode);
++    printTestResults(507, status, mode);
++
++    testClose(500);
++    testClose(501);
++    testClose(502);
++    testClose(503);
++    testClose(504);
++    testClose(505);
++    testClose(506);
++    testClose(507);
++}
++
++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 */
++    shaTest(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 = shaMultiSizeTest402;
++            if(inputData == NULL)
++                cesaTestCases[0].plainHexStr = hashHexStr80;
++            break;
++
++        case 404:
++            pMultiTest = shaMultiSizeTest404;
++            if(inputData == NULL)
++                cesaTestCases[0].plainHexStr = hashHexStr80;
++            break;
++
++        case 405:
++            pMultiTest = shaMultiSizeTest405;
++            if(inputData == NULL)
++                cesaTestCases[0].plainHexStr = hashHexStr80;
++            break;
++
++        case 502:
++            pMultiTest = tripleDesMdMultiSizeTest502;
++            if(inputData == NULL)
++                cesaTestCases[0].plainHexStr = hashHexStr80;
++            break;
++
++        case 503:
++            pMultiTest = tripleDesShaMultiSizeTest503;
++            if(inputData == NULL)
++                cesaTestCases[0].plainHexStr = hashHexStr80;
++            break;
++
++        case 504:
++            iter = 1;
++            pMultiTest = cbc3desMdMultiSizeTest504;
++            cesaTestCases[0].pCryptoIV = iv1;
++            if(inputData == NULL)
++                cesaTestCases[0].plainHexStr = hashHexStr80;
++            break;
++
++        case 505:
++            iter = 1;
++            pMultiTest = cbc3desShaMultiSizeTest505;
++            cesaTestCases[0].pCryptoIV = iv1;
++            if(inputData == NULL)
++                cesaTestCases[0].plainHexStr = hashHexStr80;
++            break;
++
++        case 506:
++            iter = 1;
++            pMultiTest = cbcAes128md5multiSizeTest506;
++            cesaTestCases[0].pCryptoIV = iv5;
++            if(inputData == NULL)
++                cesaTestCases[0].plainHexStr = hashHexStr80;
++            break;
++
++        case 507:
++            iter = 1;
++            pMultiTest = cbcAes128sha1multiSizeTest507;
++            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 = %ld\n", 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 = %ld\n", 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 = %ld\n", 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   iCause   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].dmaCause, 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/crypto/ocf/kirkwood/cesa/mvLru.c b/crypto/ocf/kirkwood/cesa/mvLru.c
+new file mode 100644
+index 0000000..9ab29a8
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvLru.c
+@@ -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.
++
++*******************************************************************************/
++
++#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/crypto/ocf/kirkwood/cesa/mvLru.h b/crypto/ocf/kirkwood/cesa/mvLru.h
+new file mode 100644
+index 0000000..896e7f8
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvLru.h
+@@ -0,0 +1,112 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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__
++
++
++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);
++
++
++#endif /* __mvLru_h__ */
+diff --git a/crypto/ocf/kirkwood/cesa/mvMD5.c b/crypto/ocf/kirkwood/cesa/mvMD5.c
+new file mode 100644
+index 0000000..189f629
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvMD5.c
+@@ -0,0 +1,349 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "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];
++    if ((ctx->bits[0] = t + ((MV_U32) len << 3)) < 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/crypto/ocf/kirkwood/cesa/mvMD5.h b/crypto/ocf/kirkwood/cesa/mvMD5.h
+new file mode 100644
+index 0000000..d05c6b6
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvMD5.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 __mvMD5_h__
++#define __mvMD5_h__
++
++#include "mvMD5.h"
++
++#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);
++
++
++#endif /* __mvMD5_h__ */
+diff --git a/crypto/ocf/kirkwood/cesa/mvSHA1.c b/crypto/ocf/kirkwood/cesa/mvSHA1.c
+new file mode 100644
+index 0000000..0e0786b
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvSHA1.c
+@@ -0,0 +1,239 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "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;
++    if ((context->count[0] += len << 3) < (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/crypto/ocf/kirkwood/cesa/mvSHA1.h b/crypto/ocf/kirkwood/cesa/mvSHA1.h
+new file mode 100644
+index 0000000..17df9fc
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa/mvSHA1.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.
++
++*******************************************************************************/
++
++#ifndef __mvSHA1_h__
++#define __mvSHA1_h__
++
++#include "mvSHA1.h"
++
++#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);
++
++
++#endif /* __mvSHA1_h__ */
+diff --git a/crypto/ocf/kirkwood/cesa_ocf_drv.c b/crypto/ocf/kirkwood/cesa_ocf_drv.c
+new file mode 100644
+index 0000000..ccf9227
+--- /dev/null
++++ b/crypto/ocf/kirkwood/cesa_ocf_drv.c
+@@ -0,0 +1,1296 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding 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 <linux/platform_device.h>
++#include <asm/scatterlist.h>
++#include <linux/spinlock.h>
++#include "ctrlEnv/sys/mvSysCesa.h"
++#include "cesa/mvCesa.h" /* moved here before cryptodev.h due to include dependencies */
++#include <cryptodev.h>
++#include <uio.h>
++#include <plat/mv_cesa.h>
++#include <linux/mbus.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
++
++
++/* TDMA Regs */
++#define WINDOW_BASE(i) 0xA00 + (i << 3)
++#define WINDOW_CTRL(i) 0xA04 + (i << 3)
++
++/* interrupt handling */
++#undef CESA_OCF_POLLING
++#undef CESA_OCF_TASKLET
++
++#if defined(CESA_OCF_POLLING) && defined(CESA_OCF_TASKLET)
++#error "don't use both tasklet and polling mode"
++#endif
++
++extern int cesaReqResources;
++/* support for spliting action into 2 actions */
++#define CESA_OCF_SPLIT
++
++/* general defines */
++#define CESA_OCF_MAX_SES 128
++#define CESA_Q_SIZE	 64
++
++
++/* 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;
++};
++
++/* CESA device data */
++struct cesa_dev {
++	void __iomem *sram;
++	void __iomem *reg;
++        struct mv_cesa_platform_data *plat_data;
++	int irq;
++};
++
++#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;
++};
++
++/* global variables */
++static int32_t			cesa_ocf_id		= -1;
++static struct cesa_ocf_data	*cesa_ocf_sessions[CESA_OCF_MAX_SES];
++static spinlock_t		cesa_lock;
++static struct cesa_dev cesa_device;
++
++/* 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 void		cesa_callback		(unsigned long);
++static irqreturn_t	cesa_interrupt_handler	(int, void *);
++#ifdef CESA_OCF_POLLING
++static void cesa_interrupt_polling(void);
++#endif
++#ifdef CESA_OCF_TASKLET
++static struct tasklet_struct cesa_ocf_tasklet;
++#endif
++
++static struct timeval          tt_start;
++static struct timeval          tt_end;
++
++/*
++ * 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),
++};
++
++
++
++/* Add debug Trace */
++#undef CESA_OCF_TRACE_DEBUG
++#ifdef CESA_OCF_TRACE_DEBUG
++
++#define MV_CESA_USE_TIMER_ID    0
++
++typedef struct
++{
++    int             type;       /* 0 - isrEmpty, 1 - cesaReadyGet, 2 - cesaAction */
++    MV_U32          timeStamp;
++    MV_U32          cause;
++    MV_U32          realCause;
++    MV_U32          dmaCause;
++    int             resources;
++    MV_CESA_REQ*    pReqReady;
++    MV_CESA_REQ*    pReqEmpty;
++    MV_CESA_REQ*    pReqProcess;
++} MV_CESA_TEST_TRACE;
++
++#define MV_CESA_TEST_TRACE_SIZE      50
++
++static int cesaTestTraceIdx = 0;
++static MV_CESA_TEST_TRACE    cesaTestTrace[MV_CESA_TEST_TRACE_SIZE];
++
++static void cesaTestTraceAdd(int type)
++{
++    cesaTestTrace[cesaTestTraceIdx].type = type;
++    cesaTestTrace[cesaTestTraceIdx].realCause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
++    //cesaTestTrace[cesaTestTraceIdx].idmaCause = MV_REG_READ(IDMA_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;
++}
++
++#else /* CESA_OCF_TRACE_DEBUG */
++
++#define cesaTestTraceAdd(x)
++
++#endif /* CESA_OCF_TRACE_DEBUG */
++
++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);
++}
++
++#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
++
++/*
++ * 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;
++	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;
++
++        dprintk("%s()\n", __FUNCTION__);
++
++	if( cesaReqResources <= 1 ) {
++                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_MAX_SES) || (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
++
++	/* malloc a new  cesa process */
++	cesa_ocf_cmd = kmalloc(sizeof(struct cesa_ocf_process), GFP_ATOMIC);
++
++        if (cesa_ocf_cmd == NULL) {
++		printk("%s,%d: ENOBUFS \n", __FILE__, __LINE__);
++		goto p_error;
++	}
++	memset(cesa_ocf_cmd, 0, sizeof(struct cesa_ocf_process));
++
++	/* 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;
++						crypto_copy_bits_back(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) {
++		mvCesaDebugMbuf("SRC BUFFER", cesa_cmd->pSrc, 0, cesa_cmd->pSrc->mbufSize);
++	}
++
++
++	/* send action to HAL */
++	spin_lock_irqsave(&cesa_lock, flags);
++	status = mvCesaAction(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;
++
++			/* malloc a new cesa process and init it */
++			cesa_ocf_cmd_wa = kmalloc(sizeof(struct cesa_ocf_process), GFP_ATOMIC);
++
++			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;
++
++			/* 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 = mvCesaAction(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 = mvCesaAction(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)
++			kfree(cesa_ocf_cmd);
++		if(cesa_ocf_cmd_wa)
++			kfree(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;
++        }
++
++
++#ifdef CESA_OCF_POLLING
++	cesa_interrupt_polling();
++#endif
++	cesaTestTraceAdd(5);
++
++	return 0;
++p_error:
++	crp->crp_etype = EINVAL;
++	if(cesa_ocf_cmd)
++		kfree(cesa_ocf_cmd);
++	if(cesa_ocf_cmd_wa)
++		kfree(cesa_ocf_cmd_wa);
++		return EINVAL;
++}
++
++/*
++ * cesa callback.
++ */
++static void
++cesa_callback(unsigned long dummy)
++{
++	struct cesa_ocf_process *cesa_ocf_cmd = NULL;
++	struct cryptop		*crp = NULL;
++	MV_CESA_RESULT		result[MV_CESA_MAX_CHAN];
++	int			res_idx = 0,i;
++	MV_STATUS               status;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++#ifdef CESA_OCF_TASKLET
++	disable_irq(cesa_device.irq);
++#endif
++    while(MV_TRUE) {
++
++		 /* Get Ready requests */
++		spin_lock(&cesa_lock);
++		status = mvCesaReadyGet(&result[res_idx]);
++		spin_unlock(&cesa_lock);
++
++	        cesaTestTraceAdd(2);
++
++		    if(status != MV_OK) {
++#ifdef CESA_OCF_POLLING
++		        if(status == MV_BUSY) { /* Fragment */
++			        cesa_interrupt_polling();
++			        return;
++		        }
++#endif
++		    break;
++	    }
++	        res_idx++;
++		    break;
++	    }
++
++	for(i = 0; i < res_idx; i++) {
++
++		if(!result[i].pReqPrv) {
++			printk("%s,%d: warning private is NULL\n", __FILE__, __LINE__);
++			break;
++		}
++
++		cesa_ocf_cmd = result[i].pReqPrv;
++		crp = cesa_ocf_cmd->crp;
++
++		// ignore HMAC error.
++		//if(result->retCode)
++		//	crp->crp_etype = EIO;
++
++#if  defined(CESA_OCF_POLLING)
++		if(!cesa_ocf_cmd->need_cb){
++			cesa_interrupt_polling();
++		}
++#endif
++		if(cesa_ocf_cmd->need_cb) {
++			if(debug) {
++				mvCesaDebugMbuf("DST BUFFER", cesa_ocf_cmd->cesa_cmd.pDst, 0, cesa_ocf_cmd->cesa_cmd.pDst->mbufSize);
++			}
++			crypto_done(crp);
++		}
++		kfree(cesa_ocf_cmd);
++	}
++#ifdef CESA_OCF_TASKLET
++	enable_irq(cesa_device.irq);
++#endif
++
++	cesaTestTraceAdd(3);
++
++	return;
++}
++
++#ifdef CESA_OCF_POLLING
++static void
++cesa_interrupt_polling(void)
++{
++        u32			cause;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	/* Read cause register */
++	do {
++		cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
++		cause &= MV_CESA_CAUSE_ACC_DMA_ALL_MASK;
++
++	} while (cause == 0);
++
++	/* clear interrupts */
++	MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
++
++	cesa_callback(0);
++
++	return;
++}
++
++#endif
++
++/*
++ * cesa Interrupt polling routine.
++ */
++static irqreturn_t
++cesa_interrupt_handler(int irq, void *arg)
++{
++        u32			cause;
++
++	dprintk("%s()\n", __FUNCTION__);
++
++	cesaTestTraceAdd(0);
++
++	/* Read cause register */
++	cause = MV_REG_READ(MV_CESA_ISR_CAUSE_REG);
++
++	if( (cause & MV_CESA_CAUSE_ACC_DMA_ALL_MASK) == 0)
++	{
++        /* Empty interrupt */
++		dprintk("%s,%d: cesaTestReadyIsr: cause=0x%x\n", __FILE__, __LINE__, cause);
++		return IRQ_HANDLED;
++	}
++
++	/* clear interrupts */
++	MV_REG_WRITE(MV_CESA_ISR_CAUSE_REG, 0);
++
++	cesaTestTraceAdd(1);
++#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;
++	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", __FUNCTION__);
++        if (sid == NULL || cri == NULL) {
++                printk("%s,%d: EINVAL\n", __FILE__, __LINE__);
++                return EINVAL;
++        }
++
++	/* leave first empty like in other implementations */
++        for (i = 1; i < CESA_OCF_MAX_SES; i++) {
++			if (cesa_ocf_sessions[i] == NULL)
++				break;
++	}
++
++	if(i >= CESA_OCF_MAX_SES) {
++		printk("%s,%d: no more sessions \n", __FILE__, __LINE__);
++                return EINVAL;
++	}
++
++        cesa_ocf_sessions[i] = (struct cesa_ocf_data *) kmalloc(sizeof(struct cesa_ocf_data), GFP_ATOMIC);
++        if (cesa_ocf_sessions[i] == NULL) {
++                cesa_ocf_freesession(NULL, i);
++                printk("%s,%d: ENOBUFS \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;
++		status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_encrypt);
++		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;
++		status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_decrypt);
++		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;
++			status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_encrypt);
++			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;
++			status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_decrypt);
++			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;
++			status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->frag_wa_auth);
++			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;
++		status = mvCesaSessionOpen(cesa_ses, &cesa_ocf_cur_ses->sid_encrypt);
++		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;
++
++        dprintk("%s() %d \n", __FUNCTION__, sid);
++        if ( (sid >= CESA_OCF_MAX_SES) || (cesa_ocf_sessions[sid] == NULL) ) {
++                printk("%s,%d: EINVAL can't free session %d \n", __FILE__, __LINE__, sid);
++                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) {
++		mvCesaSessionClose(cesa_ocf_cur_ses->sid_encrypt);
++	}
++	if (cesa_ocf_cur_ses->sid_decrypt != -1) {
++		mvCesaSessionClose(cesa_ocf_cur_ses->sid_decrypt);
++	}
++	if (cesa_ocf_cur_ses->frag_wa_encrypt != -1) {
++		mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_encrypt);
++	}
++	if (cesa_ocf_cur_ses->frag_wa_decrypt != -1) {
++		mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_decrypt);
++	}
++	if (cesa_ocf_cur_ses->frag_wa_auth != -1) {
++		mvCesaSessionClose(cesa_ocf_cur_ses->frag_wa_auth);
++	}
++
++	kfree(cesa_ocf_cur_ses);
++	cesa_ocf_sessions[sid] = NULL;
++
++        return 0;
++}
++
++
++/* TDMA Window setup */
++
++static void __init
++setup_tdma_mbus_windows(struct cesa_dev *dev)
++{
++    int i;
++
++    for (i = 0; i < 4; i++) {
++        writel(0, dev->reg + WINDOW_BASE(i));
++        writel(0, dev->reg + WINDOW_CTRL(i));
++    }
++
++    for (i = 0; i < dev->plat_data->dram->num_cs; i++) {
++        struct mbus_dram_window *cs = dev->plat_data->dram->cs + i;
++        writel(
++            ((cs->size - 1) & 0xffff0000) |
++            (cs->mbus_attr << 8) |
++            (dev->plat_data->dram->mbus_dram_target_id << 4) | 1,
++            dev->reg + WINDOW_CTRL(i)
++        );
++        writel(cs->base, dev->reg + WINDOW_BASE(i));
++    }
++}
++
++/*
++ * our driver startup and shutdown routines
++ */
++static int
++mv_cesa_ocf_init(struct platform_device *pdev)
++{
++#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", __FUNCTION__);
++	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
++
++	memset(&cesa_device, 0, sizeof(struct cesa_dev));
++	/* Get the IRQ, and crypto memory regions */
++	{
++		struct resource *res;
++		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sram");
++
++		if (!res)
++			return -ENXIO;
++
++		cesa_device.sram = ioremap(res->start, res->end - res->start + 1);
++		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
++
++		if (!res) {
++		        iounmap(cesa_device.sram);
++			return -ENXIO;
++                }
++                cesa_device.reg = ioremap(res->start, res->end - res->start + 1);
++		cesa_device.irq = platform_get_irq(pdev, 0);
++		cesa_device.plat_data = pdev->dev.platform_data;
++	        setup_tdma_mbus_windows(&cesa_device);
++
++	}
++
++
++	if( MV_OK != mvCesaInit(CESA_OCF_MAX_SES*5, CESA_Q_SIZE, cesa_device.reg,
++				NULL) ) {
++		printk("%s,%d: mvCesaInit Failed. \n", __FILE__, __LINE__);
++		return EINVAL;
++	}
++
++	/* clear and unmask Int */
++	MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
++#ifndef CESA_OCF_POLLING
++    MV_REG_WRITE( MV_CESA_ISR_MASK_REG, MV_CESA_CAUSE_ACC_DMA_MASK);
++#endif
++#ifdef CESA_OCF_TASKLET
++	tasklet_init(&cesa_ocf_tasklet, cesa_callback, (unsigned int) 0);
++#endif
++	/* register interrupt */
++	if( request_irq( cesa_device.irq, cesa_interrupt_handler,
++                             (IRQF_DISABLED) , "cesa", &cesa_ocf_id) < 0) {
++		printk("%s,%d: cannot assign irq %x\n", __FILE__, __LINE__, cesa_device.reg);
++		return EINVAL;
++        }
++
++
++	memset(cesa_ocf_sessions, 0, sizeof(struct cesa_ocf_data *) * CESA_OCF_MAX_SES);
++
++#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
++mv_cesa_ocf_exit(struct platform_device *pdev)
++{
++	dprintk("%s()\n", __FUNCTION__);
++
++	crypto_unregister_all(cesa_ocf_id);
++	cesa_ocf_id = -1;
++	iounmap(cesa_device.reg);
++	iounmap(cesa_device.sram);
++	free_irq(cesa_device.irq, NULL);
++
++	/* mask and clear Int */
++	MV_REG_WRITE( MV_CESA_ISR_MASK_REG, 0);
++	MV_REG_WRITE( MV_CESA_ISR_CAUSE_REG, 0);
++
++
++	if( MV_OK != mvCesaFinish() ) {
++		printk("%s,%d: mvCesaFinish Failed. \n", __FILE__, __LINE__);
++		return;
++	}
++}
++
++
++void cesa_ocf_debug(void)
++{
++
++#ifdef CESA_OCF_TRACE_DEBUG
++    {
++        int i, j;
++        j = cesaTestTraceIdx;
++        mvOsPrintf("No  Type   rCause   iCause   Proc   Isr   Res     Time     pReady    pProc    pEmpty\n");
++        for(i=0; i<MV_CESA_TEST_TRACE_SIZE; i++)
++        {
++            mvOsPrintf("%02d.  %d   0x%04x   0x%04x   0x%02x   0x%02x   %02d   0x%06x  %p  %p  %p\n",
++                j, cesaTestTrace[j].type, cesaTestTrace[j].realCause,
++                cesaTestTrace[j].idmaCause,
++                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
++
++}
++
++static struct platform_driver marvell_cesa = {
++	.probe		= mv_cesa_ocf_init,
++	.remove		= mv_cesa_ocf_exit,
++	.driver		= {
++		.owner	= THIS_MODULE,
++		.name	= "mv_crypto",
++	},
++};
++
++MODULE_ALIAS("platform:mv_crypto");
++
++static int __init mv_cesa_init(void)
++{
++	return platform_driver_register(&marvell_cesa);
++}
++
++module_init(mv_cesa_init);
++
++static void __exit mv_cesa_exit(void)
++{
++	platform_driver_unregister(&marvell_cesa);
++}
++
++module_exit(mv_cesa_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Ronen Shitrit");
++MODULE_DESCRIPTION("OCF module for Orion CESA crypto");
+diff --git a/crypto/ocf/kirkwood/mvHal/common/mv802_3.h b/crypto/ocf/kirkwood/mvHal/common/mv802_3.h
+new file mode 100644
+index 0000000..3769dde
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mv802_3.h
+@@ -0,0 +1,213 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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_APPLE_TALK_ARP_TYPE      0x80F3
++#define MV_NOVELL_IPX_TYPE          0x8137
++#define MV_EAPOL_TYPE				0x888e
++
++
++
++/* 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_VLAN_HLEN		(4)
++
++/* This macro checks for a multicast mac address    */
++#define MV_IS_MULTICAST_MAC(mac)  (((mac)[0] & 0x1) == 1)
++
++
++/* 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;
++
++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
++};
++
++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 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;
++
++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/crypto/ocf/kirkwood/mvHal/common/mvCommon.c b/crypto/ocf/kirkwood/mvHal/common/mvCommon.c
+new file mode 100644
+index 0000000..dc0e0cf
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvCommon.c
+@@ -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.
++
++*******************************************************************************/
++
++#include "mvOs.h"
++#include "mv802_3.h"
++#include "mvCommon.h"
++
++
++/*******************************************************************************
++* 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;
++}
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/common/mvCommon.h b/crypto/ocf/kirkwood/mvHal/common/mvCommon.h
+new file mode 100644
+index 0000000..c8e9ce1
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvCommon.h
+@@ -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.
++
++*******************************************************************************/
++
++
++
++#ifndef __INCmvCommonh
++#define __INCmvCommonh
++
++#include "mvTypes.h"
++
++/* 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 0x1122 -> 0x2211                            */
++#define MV_BYTE_SWAP_16BIT(X) ((((X)&0xff)<<8) | (((X)&0xff00)>>8))
++
++/* 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))
++
++/* 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
++#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
++
++/* 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
++
++/* 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))
++
++/* Temporary */
++#define mvOsDivide(num, div)        \
++({                                  \
++    int i=0, rem=(num);             \
++                                    \
++    while(rem >= (div))             \
++    {                               \
++        rem -= (div);               \
++        i++;                        \
++    }                               \
++    (i);                            \
++})
++
++/* Temporary */
++#define mvOsReminder(num, div)      \
++({                                  \
++    int rem = (num);                \
++                                    \
++    while(rem >= (div))             \
++        rem -= (div);               \
++    (rem);                          \
++})
++
++#define MV_IP_QUAD(ipAddr)    ((ipAddr >> 24) & 0xFF), ((ipAddr >> 16) & 0xFF), \
++                              ((ipAddr >> 8) & 0xFF), ((ipAddr >> 0) & 0xFF)
++
++#define MV_IS_POWER_OF_2(num) ((num != 0) && ((num & (num - 1)) == 0))
++
++#ifndef MV_ASMLANGUAGE
++/* mvCommon API list */
++
++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);
++
++#endif /* MV_ASMLANGUAGE */
++
++
++#endif	/* __INCmvCommonh */
+diff --git a/crypto/ocf/kirkwood/mvHal/common/mvDebug.c b/crypto/ocf/kirkwood/mvHal/common/mvDebug.c
+new file mode 100644
+index 0000000..087f36d
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvDebug.c
+@@ -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.
++
++*******************************************************************************/
++
++
++
++/* includes */
++#include "mvOs.h"
++#include "mv802_3.h"
++#include "mvCommon.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:
++                        if( memAddr == CPU_PHY_MEM(memAddr) )
++                        {
++                            mvOsPrintf("%02x ", MV_MEMIO8_READ(memAddr));
++                        }
++                        else
++                        {
++                            mvOsPrintf("%02x ", *((MV_U8*)memAddr));
++                        }
++                        break;
++
++                    case 2:
++                        if( memAddr == CPU_PHY_MEM(memAddr) )
++                        {
++                            mvOsPrintf("%04x ", MV_MEMIO16_READ(memAddr));
++                        }
++                        else
++                        {
++                            mvOsPrintf("%04x ", *((MV_U16*)memAddr));
++                        }
++                        break;
++
++                    case 4:
++                        if( memAddr == CPU_PHY_MEM(memAddr) )
++                        {
++                            mvOsPrintf("%08x ", MV_MEMIO32_READ(memAddr));
++                        }
++                        else
++                        {
++                            mvOsPrintf("%08x ", *((MV_U32*)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/crypto/ocf/kirkwood/mvHal/common/mvDebug.h b/crypto/ocf/kirkwood/mvHal/common/mvDebug.h
+new file mode 100644
+index 0000000..e4975be
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvDebug.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 __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/crypto/ocf/kirkwood/mvHal/common/mvDeviceId.h b/crypto/ocf/kirkwood/mvHal/common/mvDeviceId.h
+new file mode 100644
+index 0000000..4782094
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvDeviceId.h
+@@ -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.
++
++*******************************************************************************/
++
++#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_6192_DEV_ID			0x6192
++#define MV_6190_DEV_ID			0x6190
++#define MV_6180_DEV_ID			0x6180
++
++#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_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"
++
++
++#endif /* __INCmvDeviceIdh */
+diff --git a/crypto/ocf/kirkwood/mvHal/common/mvHalVer.h b/crypto/ocf/kirkwood/mvHal/common/mvHalVer.h
+new file mode 100644
+index 0000000..3bfcfe1
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvHalVer.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 __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 */
+\ No newline at end of file
+diff --git a/crypto/ocf/kirkwood/mvHal/common/mvStack.c b/crypto/ocf/kirkwood/mvHal/common/mvStack.c
+new file mode 100644
+index 0000000..41ca7ce
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvStack.c
+@@ -0,0 +1,100 @@
++/*******************************************************************************
++*                   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 $
++* REVISION:    $Revision: 1.1 $
++* LAST UPDATE: $Modtime:  $
++*
++* DESCRIPTION:
++*     This file implements simple Stack LIFO functionality.
++*******************************************************************************/
++
++/* includes */
++#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");
++        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/crypto/ocf/kirkwood/mvHal/common/mvStack.h b/crypto/ocf/kirkwood/mvHal/common/mvStack.h
+new file mode 100644
+index 0000000..e247e61
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvStack.h
+@@ -0,0 +1,140 @@
++/*******************************************************************************
++*                   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 $
++* REVISION:    $Revision: 1.1 $
++* 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/crypto/ocf/kirkwood/mvHal/common/mvTypes.h b/crypto/ocf/kirkwood/mvHal/common/mvTypes.h
+new file mode 100644
+index 0000000..de212a1
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/common/mvTypes.h
+@@ -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.
++
++*******************************************************************************/
++
++
++#ifndef __INCmvTypesh
++#define __INCmvTypesh
++
++/* Defines */
++
++/* The following is a list of Marvell status    */
++#define MV_ERROR		    (-1)
++#define MV_OK			    (0x00)  /* Operation succeeded                   */
++#define MV_FAIL			    (0x01)	/* Operation failed                      */
++#define MV_BAD_VALUE        (0x02)  /* Illegal value (general)               */
++#define MV_OUT_OF_RANGE     (0x03)  /* The value is out of range             */
++#define MV_BAD_PARAM        (0x04)  /* Illegal parameter in function called  */
++#define MV_BAD_PTR          (0x05)  /* Illegal pointer value                 */
++#define MV_BAD_SIZE         (0x06)  /* Illegal size                          */
++#define MV_BAD_STATE        (0x07)  /* Illegal state of state machine        */
++#define MV_SET_ERROR        (0x08)  /* Set operation failed                  */
++#define MV_GET_ERROR        (0x09)  /* Get operation failed                  */
++#define MV_CREATE_ERROR     (0x0A)  /* Fail while creating an item           */
++#define MV_NOT_FOUND        (0x0B)  /* Item not found                        */
++#define MV_NO_MORE          (0x0C)  /* No more items found                   */
++#define MV_NO_SUCH          (0x0D)  /* No such item                          */
++#define MV_TIMEOUT          (0x0E)  /* Time Out                              */
++#define MV_NO_CHANGE        (0x0F)  /* Parameter(s) is already in this value */
++#define MV_NOT_SUPPORTED    (0x10)  /* This request is not support           */
++#define MV_NOT_IMPLEMENTED  (0x11)  /* Request supported but not implemented */
++#define MV_NOT_INITIALIZED  (0x12)  /* The item is not initialized           */
++#define MV_NO_RESOURCE      (0x13)  /* Resource not available (memory ...)   */
++#define MV_FULL             (0x14)  /* Item is full (Queue or table etc...)  */
++#define MV_EMPTY            (0x15)  /* Item is empty (Queue or table etc...) */
++#define MV_INIT_ERROR       (0x16)  /* Error occured while INIT process      */
++#define MV_HW_ERROR         (0x17)  /* Hardware error                        */
++#define MV_TX_ERROR         (0x18)  /* Transmit operation not succeeded      */
++#define MV_RX_ERROR         (0x19)  /* Recieve operation not succeeded       */
++#define MV_NOT_READY	    (0x1A)	/* The other side is not ready yet       */
++#define MV_ALREADY_EXIST    (0x1B)  /* Tried to create existing item         */
++#define MV_OUT_OF_CPU_MEM   (0x1C)  /* Cpu memory allocation failed.         */
++#define MV_NOT_STARTED      (0x1D)  /* Not started yet         */
++#define MV_BUSY             (0x1E)  /* Item is busy.                         */
++#define MV_TERMINATE        (0x1F)  /* Item terminates it's work.            */
++#define MV_NOT_ALIGNED      (0x20)  /* Wrong alignment                       */
++#define MV_NOT_ALLOWED      (0x21)  /* Operation NOT allowed                 */
++#define MV_WRITE_PROTECT    (0x22)  /* Write protected                       */
++
++
++#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;
++
++
++/* 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_PKT_INFO;
++
++#endif /* MV_ASMLANGUAGE */
++
++#endif /* __INCmvTypesh */
++
+diff --git a/crypto/ocf/kirkwood/mvHal/dbg-trace.c b/crypto/ocf/kirkwood/mvHal/dbg-trace.c
+new file mode 100644
+index 0000000..644fd02
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/dbg-trace.c
+@@ -0,0 +1,110 @@
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/time.h>
++#include "dbg-trace.h"
++
++#define TRACE_ARR_LEN   800
++#define STR_LEN         128
++struct trace {
++    struct timeval tv;
++        char str[STR_LEN];
++    unsigned int callback_val1;
++    unsigned int callback_val2;
++        char valid;
++};
++static unsigned int (*trc_callback1) (unsigned char) = NULL;
++static unsigned int (*trc_callback2) (unsigned char) = NULL;
++static unsigned char trc_param1 = 0;
++static unsigned char trc_param2 = 0;
++struct trace *trc_arr;
++static int trc_index;
++static int trc_active = 0;
++
++void TRC_START()
++{
++    trc_active = 1;
++}
++
++void TRC_STOP()
++{
++    trc_active = 0;
++}
++
++void TRC_INIT(void *callback1, void *callback2, unsigned char callback1_param, unsigned char callback2_param)
++{
++    printk("Marvell debug tracing is on\n");
++        trc_arr = (struct trace *)kmalloc(TRACE_ARR_LEN*sizeof(struct trace),GFP_KERNEL);
++    if(trc_arr == NULL)
++    {
++        printk("Can't allocate Debug Trace buffer\n");
++        return;
++    }
++        memset(trc_arr,0,TRACE_ARR_LEN*sizeof(struct trace));
++        trc_index = 0;
++    trc_callback1 = callback1;
++    trc_callback2 = callback2;
++    trc_param1 = callback1_param;
++    trc_param2 = callback2_param;
++}
++void TRC_REC(char *fmt,...)
++{
++    va_list args;
++        struct trace *trc = &trc_arr[trc_index];
++
++    if(trc_active == 0)
++        return;
++
++    do_gettimeofday(&trc->tv);
++    if(trc_callback1)
++        trc->callback_val1 = trc_callback1(trc_param1);
++    if(trc_callback2)
++        trc->callback_val2 = trc_callback2(trc_param2);
++    va_start(args, fmt);
++    vsprintf(trc->str,fmt,args);
++    va_end(args);
++        trc->valid = 1;
++        if((++trc_index) == TRACE_ARR_LEN) {
++                trc_index = 0;
++    }
++}
++void TRC_OUTPUT(void)
++{
++        int i,j;
++        struct trace *p;
++        printk("\n\nTrace %d items\n",TRACE_ARR_LEN);
++        for(i=0,j=trc_index; i<TRACE_ARR_LEN; i++,j++) {
++                if(j == TRACE_ARR_LEN)
++                        j = 0;
++                p = &trc_arr[j];
++                if(p->valid) {
++            unsigned long uoffs;
++            struct trace *plast;
++            if(p == &trc_arr[0])
++                plast = &trc_arr[TRACE_ARR_LEN-1];
++            else
++                plast = p-1;
++            if(p->tv.tv_sec == ((plast)->tv.tv_sec))
++                uoffs = (p->tv.tv_usec - ((plast)->tv.tv_usec));
++            else
++                uoffs = (1000000 - ((plast)->tv.tv_usec)) +
++                    ((p->tv.tv_sec - ((plast)->tv.tv_sec) - 1) * 1000000) +
++                    p->tv.tv_usec;
++                        printk("%03d: [+%ld usec]", j, (unsigned long)uoffs);
++            if(trc_callback1)
++                printk("[%u]",p->callback_val1);
++            if(trc_callback2)
++                printk("[%u]",p->callback_val2);
++            printk(": %s",p->str);
++        }
++                p->valid = 0;
++        }
++        memset(trc_arr,0,TRACE_ARR_LEN*sizeof(struct trace));
++        trc_index = 0;
++}
++void TRC_RELEASE(void)
++{
++        kfree(trc_arr);
++        trc_index = 0;
++}
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/dbg-trace.h b/crypto/ocf/kirkwood/mvHal/dbg-trace.h
+new file mode 100644
+index 0000000..a5aac26
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/dbg-trace.h
+@@ -0,0 +1,24 @@
++
++#ifndef _MV_DBG_TRCE_H_
++#define _MV_DBG_TRCE_H_
++
++#ifdef CONFIG_MV_DBG_TRACE
++void TRC_INIT(void *callback1, void *callback2,
++    unsigned char callback1_param, unsigned char callback2_param);
++void TRC_REC(char *fmt,...);
++void TRC_OUTPUT(void);
++void TRC_RELEASE(void);
++void TRC_START(void);
++void TRC_STOP(void);
++
++#else
++#define TRC_INIT(x1,x2,x3,x4)
++#define TRC_REC(X...)
++#define TRC_OUTPUT()
++#define TRC_RELEASE()
++#define TRC_START()
++#define TRC_STOP()
++#endif
++
++
++#endif
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.c b/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.c
+new file mode 100644
+index 0000000..5f62784
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.c
+@@ -0,0 +1,2513 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "boardEnv/mvBoardEnvLib.h"
++#include "ctrlEnv/mvCtrlEnvLib.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 "eth/gbe/mvEthRegs.h"
++
++/* defines  */
++/* #define MV_DEBUG */
++#ifdef MV_DEBUG
++	#define DB(x)	x
++#else
++	#define DB(x)
++#endif
++
++extern MV_CPU_ARM_CLK _cpuARMDDRCLK[];
++
++#define CODE_IN_ROM		MV_FALSE
++#define CODE_IN_RAM		MV_TRUE
++
++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;
++
++
++/*******************************************************************************
++* 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();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardEnvInit:Board unknown.\n");
++		return;
++
++	}
++
++	/* 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)->gppOutValHigh);
++
++	/* set GPP polarity */
++	mvGppPolaritySet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValLow);
++	mvGppPolaritySet(1, 0xFFFFFFFF, BOARD_INFO(boardId)->gppPolarityValHigh);
++
++    /* Workaround for Erratum FE-MISC-70*/
++    if(mvCtrlRevGet()==MV_88F6XXX_A0_REV)
++    {
++        BOARD_INFO(boardId)->gppOutEnValLow &= 0xfffffffd;
++        BOARD_INFO(boardId)->gppOutEnValLow |= (BOARD_INFO(boardId)->gppOutEnValHigh) & 0x00000002;
++    } /*End of WA*/
++
++	/* Set GPP Out Enable*/
++	mvGppTypeSet(0, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValLow);
++	mvGppTypeSet(1, 0xFFFFFFFF, BOARD_INFO(boardId)->gppOutEnValHigh);
++
++	/* Nand CE */
++	MV_REG_BIT_SET(NAND_CTRL_REG, NAND_ACTCEBOOT_BIT);
++}
++
++/*******************************************************************************
++* 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;
++}
++
++/*******************************************************************************
++* 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_BOOL ethPortSgmiiSupport[BOARD_ETH_PORT_NUM] = MV_ETH_PORT_SGMII;
++
++    if(ethPortNum >= BOARD_ETH_PORT_NUM)
++    {
++	    mvOsPrintf ("Invalid portNo=%d\n", ethPortNum);
++		return MV_FALSE;
++    }
++    return ethPortSgmiiSupport[ethPortNum];
++}
++
++/*******************************************************************************
++* 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;
++}
++/*******************************************************************************
++* 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;
++}
++
++/*******************************************************************************
++* 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;
++	}
++
++	return BOARD_INFO(boardId)->pBoardMacInfo[ethPortNum].boardMacSpeed;
++}
++
++/*******************************************************************************
++* mvBoardLinkStatusIrqGet - 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	mvBoardLinkStatusIrqGet(MV_U32 ethPortNum)
++{
++	MV_U32 boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardLinkStatusIrqGet: Board unknown.\n");
++		return MV_ERROR;
++	}
++
++	return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].linkStatusIrq;
++}
++
++/*******************************************************************************
++* mvBoardSwitchPortGet - Get the mapping between the board connector and the
++* Ethernet Switch port
++*
++* DESCRIPTION:
++*       This routine returns the matching Switch port.
++*
++* INPUT:
++*       ethPortNum - Ethernet port number.
++*	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 ethPortNum, MV_U8 boardPortNum)
++{
++	MV_U32 boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardSwitchPortGet: Board unknown.\n");
++		return MV_ERROR;
++	}
++	if (boardPortNum >= BOARD_ETH_SWITCH_PORT_NUM)
++	{
++		mvOsPrintf("mvBoardSwitchPortGet: Illegal board port number.\n");
++		return MV_ERROR;
++	}
++
++	return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].qdPort[boardPortNum];
++}
++
++/*******************************************************************************
++* mvBoardSwitchCpuPortGet - Get the the Ethernet Switch CPU port
++*
++* DESCRIPTION:
++*       This routine returns the Switch CPU port.
++*
++* INPUT:
++*       ethPortNum - Ethernet port number.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       the Switch CPU port, -1 if the port number is wrong or if not relevant.
++*
++*******************************************************************************/
++MV_32	mvBoardSwitchCpuPortGet(MV_U32 ethPortNum)
++{
++	MV_U32 boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardSwitchCpuPortGet: Board unknown.\n");
++		return MV_ERROR;
++	}
++
++	return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].qdCpuPort;
++}
++
++/*******************************************************************************
++* mvBoardIsSwitchConnected - Get switch connection status
++* 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_32	mvBoardIsSwitchConnected(MV_U32 ethPortNum)
++{
++	MV_U32 boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardIsSwitchConnected: Board unknown.\n");
++		return MV_ERROR;
++	}
++
++	if(ethPortNum >= BOARD_INFO(boardId)->numBoardMacInfo)
++	{
++		mvOsPrintf("mvBoardIsSwitchConnected: Illegal port number(%u)\n", ethPortNum);
++		return MV_ERROR;
++	}
++
++	if((MV_32)(BOARD_INFO(boardId)->pSwitchInfo))
++	return (MV_32)(BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].switchOnPort == ethPortNum);
++	else
++		return 0;
++}
++/*******************************************************************************
++* mvBoardSmiScanModeGet - Get Switch SMI scan mode
++*
++* DESCRIPTION:
++*       This routine returns Switch SMI scan mode.
++*
++* INPUT:
++*       ethPortNum - Ethernet port number.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       1 for SMI_MANUAL_MODE, -1 if the port number is wrong or if not relevant.
++*
++*******************************************************************************/
++MV_32	mvBoardSmiScanModeGet(MV_U32 ethPortNum)
++{
++	MV_U32 boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardSmiScanModeGet: Board unknown.\n");
++		return MV_ERROR;
++	}
++
++	return BOARD_INFO(boardId)->pSwitchInfo[ethPortNum].smiScanMode;
++}
++/*******************************************************************************
++* mvBoardSpecInitGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN: Return MV_TRUE and parameters in case board need spesific phy init,
++*	  otherwise return MV_FALSE.
++*
++*
++*******************************************************************************/
++
++MV_BOOL mvBoardSpecInitGet(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(mvCtrlModelGet()==MV_6281_DEV_ID)
++    {
++#if defined(TCLK_AUTO_DETECT)
++	MV_U32 tmpTClkRate = MV_BOARD_TCLK_166MHZ;
++
++    tmpTClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++    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;
++    }
++#else
++    return MV_BOARD_TCLK_200MHZ;
++#endif
++    }
++
++        return MV_BOARD_TCLK_166MHZ;
++
++}
++/*******************************************************************************
++* 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.
++*
++*******************************************************************************/
++static MV_U32  mvBoard6180SysClkGet(MV_VOID)
++{
++	MV_U32	sysClkRate=0;
++	MV_CPU_ARM_CLK _cpu6180_ddr_l2_CLK[] = MV_CPU6180_DDR_L2_CLCK_TBL;
++
++	sysClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++	sysClkRate = sysClkRate & MSAR_CPUCLCK_MASK_6180;
++	sysClkRate = sysClkRate >> MSAR_CPUCLCK_OFFS_6180;
++
++	sysClkRate = _cpu6180_ddr_l2_CLK[sysClkRate].ddrClk;
++
++	return sysClkRate;
++
++}
++
++MV_U32  mvBoardSysClkGet(MV_VOID)
++{
++#ifdef SYSCLK_AUTO_DETECT
++	MV_U32 sysClkRate, tmp, pClkRate, indexDdrRtio;
++	MV_U32 cpuCLK[] = MV_CPU_CLCK_TBL;
++	MV_U32 ddrRtio[][2] = MV_DDR_CLCK_RTIO_TBL;
++
++	if(mvCtrlModelGet() == MV_6180_DEV_ID)
++		return mvBoard6180SysClkGet();
++
++	tmp = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++	pClkRate = MSAR_CPUCLCK_EXTRACT(tmp);
++	pClkRate = cpuCLK[pClkRate];
++
++	indexDdrRtio = tmp & MSAR_DDRCLCK_RTIO_MASK;
++	indexDdrRtio = indexDdrRtio >> MSAR_DDRCLCK_RTIO_OFFS;
++    if(ddrRtio[indexDdrRtio][0] != 0)
++        sysClkRate = ((pClkRate * ddrRtio[indexDdrRtio][1]) / ddrRtio[indexDdrRtio][0]);
++    else
++        sysClkRate = 0;
++	return sysClkRate;
++#else
++	return MV_BOARD_DEFAULT_SYSCLK;
++#endif
++}
++
++
++/*******************************************************************************
++* mvBoardPexBridgeIntPinGet - Get PEX to PCI bridge interrupt pin number
++*
++* DESCRIPTION:
++*		Multi-ported PCI Express bridges that is implemented on the board
++*		collapse interrupts across multiple conventional PCI/PCI-X buses.
++*		A dual-headed PCI Express bridge would map (or "swizzle") the
++*		interrupts per the following table (in accordance with the respective
++*		logical PCI/PCI-X bridge's Device Number), collapse the INTA#-INTD#
++*		signals from its two logical PCI/PCI-X bridges, collapse the
++*		INTA#-INTD# signals from any internal sources, and convert the
++*		signals to in-band PCI Express messages. 10
++*		This function returns the upstream interrupt as it was converted by
++*		the bridge, according to board configuration and the following table:
++*							PCI dev num
++*			Interrupt pin	7,	8,	9
++*					A  ->	A	D	C
++*					B  ->	B	A	D
++*					C  ->	C	B	A
++*					D  ->	D	C	B
++*
++*
++* INPUT:
++*       devNum - PCI/PCIX device number.
++*       intPin - PCI Int pin
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       Int pin connected to the Interrupt controller
++*
++*******************************************************************************/
++MV_U32 mvBoardPexBridgeIntPinGet(MV_U32 devNum, MV_U32 intPin)
++{
++	MV_U32 realIntPin = ((intPin + (3 - (devNum % 4))) %4 );
++
++	if (realIntPin == 0) return 4;
++		else return realIntPin;
++
++}
++
++/*******************************************************************************
++* 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.
++*	       Note: assume MPP leds are part of group 0 only.
++*
++* INPUT:
++*       hexNum - Number to be displied in hex by Leds.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_VOID mvBoardDebugLed(MV_U32 hexNum)
++{
++    MV_U32 val = 0,totalMask, currentBitMask = 1,i;
++    MV_U32 boardId= mvBoardIdGet();
++
++    if (BOARD_INFO(boardId)->pLedGppPin == NULL)
++	return;
++
++    totalMask = (1 << BOARD_INFO(boardId)->activeLedsNumber) -1;
++    hexNum &= totalMask;
++    totalMask = 0;
++
++    for (i = 0 ; i < BOARD_INFO(boardId)->activeLedsNumber ; i++)
++    {
++	if (hexNum & currentBitMask)
++	{
++	    val |= (1 << BOARD_INFO(boardId)->pLedGppPin[i]);
++	}
++
++	totalMask |= (1 << BOARD_INFO(boardId)->pLedGppPin[i]);
++
++	currentBitMask = (currentBitMask << 1);
++    }
++
++    if (BOARD_INFO(boardId)->ledsPolarity)
++    {
++	mvGppValueSet(0, totalMask, val);
++    }
++    else
++    {
++	mvGppValueSet(0, totalMask, ~val);
++    }
++}
++
++
++/*******************************************************************************
++* mvBoarGpioPinGet - mvBoarGpioPinGet
++*
++* DESCRIPTION:
++*
++* INPUT:
++*		class - 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 class, 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 == class) {
++			if (indexFound == index)
++				return (MV_U32)BOARD_INFO(boardId)->pBoardGppInfo[i].gppPinNum;
++			else
++				indexFound++;
++
++		}
++
++	return MV_ERROR;
++}
++
++
++/*******************************************************************************
++* mvBoardRTCGpioPinGet - mvBoardRTCGpioPinGet
++*
++* DESCRIPTION:
++*
++* INPUT:
++*		None.
++*
++* OUTPUT:
++*		None.
++*
++* RETURN:
++*       GPIO pin number. The function return -1 for bad parameters.
++*
++*******************************************************************************/
++MV_32 mvBoardRTCGpioPinGet(MV_VOID)
++{
++	return mvBoarGpioPinNumGet(BOARD_GPP_RTC, 0);
++}
++
++
++/*******************************************************************************
++* 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:
++*		None.
++*
++* OUTPUT:
++*		None.
++*
++* RETURN:
++*       GPIO pin number. The function return -1 for bad parameters.
++*
++*******************************************************************************/
++MV_32  mvBoardSDIOGpioPinGet(MV_VOID)
++{
++	return mvBoarGpioPinNumGet(BOARD_GPP_SDIO_DETECT, 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_32 mvBoardGpioIntMaskLowGet(MV_VOID)
++{
++	MV_U32 boardId;
++
++	boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardGpioIntMaskGet:Board unknown.\n");
++		return MV_ERROR;
++
++	}
++
++	return BOARD_INFO(boardId)->intsGppMaskLow;
++}
++MV_32 mvBoardGpioIntMaskHighGet(MV_VOID)
++{
++	MV_U32 boardId;
++
++	boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardGpioIntMaskGet:Board unknown.\n");
++		return MV_ERROR;
++
++	}
++
++	return BOARD_INFO(boardId)->intsGppMaskHigh;
++}
++
++
++/*******************************************************************************
++* 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];
++}
++
++
++/*******************************************************************************
++* mvBoardMppGroupId - If MPP group type is AUTO then identify it using twsi
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_VOID mvBoardMppGroupIdUpdate(MV_VOID)
++{
++
++	MV_BOARD_MPP_GROUP_CLASS devClass;
++	MV_BOARD_MODULE_ID_CLASS devClassId;
++	MV_BOARD_MPP_TYPE_CLASS mppGroupType;
++	MV_U32 devId;
++	MV_U32 maxMppGrp = 1;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			maxMppGrp = MV_6281_MPP_MAX_MODULE;
++			break;
++		case MV_6192_DEV_ID:
++			maxMppGrp = MV_6192_MPP_MAX_MODULE;
++			break;
++        case MV_6190_DEV_ID:
++            maxMppGrp = MV_6190_MPP_MAX_MODULE;
++            break;
++		case MV_6180_DEV_ID:
++			maxMppGrp = MV_6180_MPP_MAX_MODULE;
++			break;
++	}
++
++	for (devClass = 0; devClass < maxMppGrp; devClass++)
++	{
++		/* If MPP group can be defined by the module connected to it */
++		if (mvBoardMppGroupTypeGet(devClass) == MV_BOARD_AUTO)
++		{
++			/* Get MPP module ID */
++			devClassId = mvBoarModuleTypeGet(devClass);
++			if (MV_ERROR != devClassId)
++			{
++				switch(devClassId)
++				{
++				case MV_BOARD_MODULE_TDM_ID:
++				case MV_BOARD_MODULE_TDM_5CHAN_ID:
++					mppGroupType = MV_BOARD_TDM;
++					break;
++				case MV_BOARD_MODULE_AUDIO_ID:
++					mppGroupType = MV_BOARD_AUDIO;
++					break;
++				case MV_BOARD_MODULE_RGMII_ID:
++					mppGroupType = MV_BOARD_RGMII;
++					break;
++				case MV_BOARD_MODULE_GMII_ID:
++					mppGroupType = MV_BOARD_GMII;
++					break;
++				case MV_BOARD_MODULE_TS_ID:
++					mppGroupType = MV_BOARD_TS;
++					break;
++				case MV_BOARD_MODULE_MII_ID:
++					mppGroupType = MV_BOARD_MII;
++					break;
++				default:
++					mppGroupType = MV_BOARD_OTHER;
++					break;
++				}
++			}
++			else
++				/* The module bay is empty */
++				mppGroupType = MV_BOARD_OTHER;
++
++			/* Update MPP group type */
++			mvBoardMppGroupTypeSet(devClass, mppGroupType);
++		}
++
++		/* Update MPP output voltage for RGMII 1.8V. Set port to GMII for GMII module */
++		if ((mvBoardMppGroupTypeGet(devClass) == MV_BOARD_RGMII))
++			MV_REG_BIT_SET(MPP_OUTPUT_DRIVE_REG,MPP_1_8_RGMII1_OUTPUT_DRIVE | MPP_1_8_RGMII0_OUTPUT_DRIVE);
++		else
++		{
++			if ((mvBoardMppGroupTypeGet(devClass) == MV_BOARD_GMII))
++			{
++				MV_REG_BIT_RESET(MPP_OUTPUT_DRIVE_REG, BIT7 | BIT15);
++				MV_REG_BIT_RESET(ETH_PORT_SERIAL_CTRL_1_REG(0),BIT3);
++				MV_REG_BIT_RESET(ETH_PORT_SERIAL_CTRL_1_REG(1),BIT3);
++			}
++			else if ((mvBoardMppGroupTypeGet(devClass) == MV_BOARD_MII))
++			{
++				/* Assumption that the MDC & MDIO should be 3.3V */
++				MV_REG_BIT_RESET(MPP_OUTPUT_DRIVE_REG, BIT7 | BIT15);
++				/* Assumption that only ETH1 can be MII when using modules on DB */
++				MV_REG_BIT_RESET(ETH_PORT_SERIAL_CTRL_1_REG(1),BIT3);
++			}
++		}
++	}
++}
++
++/*******************************************************************************
++* 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;
++
++	boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardMppGet:Board unknown.\n");
++		return MV_ERROR;
++
++	}
++
++	if (mppGroupClass == MV_BOARD_MPP_GROUP_1)
++		return BOARD_INFO(boardId)->pBoardMppTypeValue[0].boardMppGroup1;
++	else
++		return BOARD_INFO(boardId)->pBoardMppTypeValue[0].boardMppGroup2;
++}
++
++/*******************************************************************************
++* mvBoardMppGroupTypeSet
++*
++* DESCRIPTION:
++*
++* INPUT:
++*       mppGroupClass - MPP group number 0  for MPP[35:20] or 1 for MPP[49:36].
++*       mppGroupType - MPP group type for MPP[35:20] or for MPP[49:36].
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_VOID mvBoardMppGroupTypeSet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass,
++						MV_BOARD_MPP_TYPE_CLASS mppGroupType)
++{
++	MV_U32 boardId;
++
++	boardId = mvBoardIdGet();
++
++	if (!((boardId >= BOARD_ID_BASE)&&(boardId < MV_MAX_BOARD_ID)))
++	{
++		mvOsPrintf("mvBoardMppGet:Board unknown.\n");
++	}
++
++	if (mppGroupClass == MV_BOARD_MPP_GROUP_1)
++		BOARD_INFO(boardId)->pBoardMppTypeValue[0].boardMppGroup1 = mppGroupType;
++	else
++		BOARD_INFO(boardId)->pBoardMppTypeValue[0].boardMppGroup2 = mppGroupType;
++
++}
++
++/*******************************************************************************
++* mvBoardMppMuxSet - Update MPP mux
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_VOID mvBoardMppMuxSet(MV_VOID)
++{
++
++	MV_BOARD_MPP_GROUP_CLASS devClass;
++	MV_BOARD_MPP_TYPE_CLASS mppGroupType;
++	MV_U32 devId;
++	MV_U8 muxVal = 0xf;
++	MV_U32 maxMppGrp = 1;
++    MV_TWSI_SLAVE twsiSlave;
++	MV_TWSI_ADDR slave;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			maxMppGrp = MV_6281_MPP_MAX_MODULE;
++			break;
++		case MV_6192_DEV_ID:
++			maxMppGrp = MV_6192_MPP_MAX_MODULE;
++			break;
++        case MV_6190_DEV_ID:
++            maxMppGrp = MV_6190_MPP_MAX_MODULE;
++            break;
++		case MV_6180_DEV_ID:
++			maxMppGrp = MV_6180_MPP_MAX_MODULE;
++			break;
++	}
++
++	for (devClass = 0; devClass < maxMppGrp; devClass++)
++	{
++		mppGroupType = mvBoardMppGroupTypeGet(devClass);
++
++		switch(mppGroupType)
++		{
++			case MV_BOARD_TDM:
++				muxVal &= ~(devClass ? (0x2 << (devClass * 2)):0x0);
++				break;
++			case MV_BOARD_AUDIO:
++				 muxVal &= ~(devClass ? 0x7 : 0x0); /*old Z0 value 0xd:0x0*/
++				break;
++			case MV_BOARD_TS:
++				 muxVal &= ~(devClass ? (0x2 << (devClass * 2)):0x0);
++				break;
++			default:
++				muxVal |= (devClass ? 0xf : 0);
++				break;
++		}
++	}
++
++	/* TWSI init */
++	slave.type = ADDR7_BIT;
++	slave.address = 0;
++	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
++
++	/* Read MPP module ID */
++	DB(mvOsPrintf("Board: twsi exp set\n"));
++	twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(MV_BOARD_MUX_I2C_ADDR_ENTRY);
++	twsiSlave.slaveAddr.type = mvBoardTwsiExpAddrTypeGet(MV_BOARD_MUX_I2C_ADDR_ENTRY);
++	twsiSlave.validOffset = MV_TRUE;
++	/* Offset is the first command after the address which indicate the register number to be read
++	   in next operation */
++	twsiSlave.offset = 2;
++	twsiSlave.moreThen256 = MV_FALSE;
++
++
++
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) )
++	{
++		DB(mvOsPrintf("Board: twsi exp out val fail\n"));
++		return;
++	}
++	DB(mvOsPrintf("Board: twsi exp out val succeded\n"));
++
++	/* Change twsi exp to output */
++	twsiSlave.offset = 6;
++	muxVal = 0;
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) )
++	{
++		DB(mvOsPrintf("Board: twsi exp change to out fail\n"));
++		return;
++	}
++	DB(mvOsPrintf("Board: twsi exp change to out succeded\n"));
++
++}
++
++/*******************************************************************************
++* mvBoardTdmMppSet - set MPPs in TDM module
++*
++* DESCRIPTION:
++*
++* INPUT: type of second telephony device
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_VOID mvBoardTdmMppSet(MV_32 chType)
++{
++
++	MV_BOARD_MPP_GROUP_CLASS devClass;
++	MV_BOARD_MPP_TYPE_CLASS mppGroupType;
++	MV_U32 devId;
++	MV_U8 muxVal = 1;
++	MV_U8 muxValMask = 1;
++	MV_U8 twsiVal;
++	MV_U32 maxMppGrp = 1;
++	MV_TWSI_SLAVE twsiSlave;
++	MV_TWSI_ADDR slave;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			maxMppGrp = MV_6281_MPP_MAX_MODULE;
++			break;
++		case MV_6192_DEV_ID:
++			maxMppGrp = MV_6192_MPP_MAX_MODULE;
++			break;
++        case MV_6190_DEV_ID:
++            maxMppGrp = MV_6190_MPP_MAX_MODULE;
++            break;
++		case MV_6180_DEV_ID:
++			maxMppGrp = MV_6180_MPP_MAX_MODULE;
++			break;
++	}
++
++	for (devClass = 0; devClass < maxMppGrp; devClass++)
++	{
++		mppGroupType = mvBoardMppGroupTypeGet(devClass);
++		if(mppGroupType == MV_BOARD_TDM)
++			break;
++	}
++
++	if(devClass == maxMppGrp)
++		return;		/* TDM module not found */
++
++	/* TWSI init */
++	slave.type = ADDR7_BIT;
++	slave.address = 0;
++	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
++
++	/* Read MPP module ID */
++	DB(mvOsPrintf("Board: twsi exp set\n"));
++	twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(devClass);
++	twsiSlave.slaveAddr.type = ADDR7_BIT;
++	twsiSlave.validOffset = MV_TRUE;
++	/* Offset is the first command after the address which indicate the register number to be read
++	   in next operation */
++	twsiSlave.offset = 3;
++	twsiSlave.moreThen256 = MV_FALSE;
++
++	if(mvBoardIdGet() == RD_88F6281A_ID)
++	{
++		muxVal = 0xc;
++		muxValMask = 0xf3;
++	}
++
++	mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        muxVal = (twsiVal & muxValMask) | muxVal;
++
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) )
++	{
++		mvOsPrintf("Board: twsi exp out val fail\n");
++		return;
++	}
++	DB(mvOsPrintf("Board: twsi exp out val succeded\n"));
++
++	/* Change twsi exp to output */
++	twsiSlave.offset = 7;
++	muxVal = 0xfe;
++	if(mvBoardIdGet() == RD_88F6281A_ID)
++		muxVal = 0xf3;
++
++	mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++	muxVal = (twsiVal & muxVal);
++
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) )
++	{
++		mvOsPrintf("Board: twsi exp change to out fail\n");
++		return;
++	}
++	DB(mvOsPrintf("Board: twsi exp change to out succeded\n"));
++	/* reset the line to 0 */
++	twsiSlave.offset = 3;
++	muxVal = 0;
++	muxValMask = 1;
++
++	if(mvBoardIdGet() == RD_88F6281A_ID) {
++		muxVal = 0x0;
++		muxValMask = 0xf3;
++	}
++
++	mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        muxVal = (twsiVal & muxValMask) | muxVal;
++
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) )
++	{
++		mvOsPrintf("Board: twsi exp out val fail\n");
++		return;
++	}
++	DB(mvOsPrintf("Board: twsi exp out val succeded\n"));
++
++	mvOsDelay(20);
++
++	/* set the line to 1 */
++	twsiSlave.offset = 3;
++	muxVal = 1;
++	muxValMask = 1;
++
++	if(mvBoardIdGet() == RD_88F6281A_ID)
++	{
++		muxVal = 0xc;
++		muxValMask = 0xf3;
++		if(chType) /* FXS - issue reset properly */
++		{
++			MV_REG_BIT_SET(GPP_DATA_OUT_REG(1), MV_GPP12);
++			mvOsDelay(50);
++			MV_REG_BIT_RESET(GPP_DATA_OUT_REG(1), MV_GPP12);
++		}
++		else /* FXO - issue reset via TDM_CODEC_RST*/
++		{
++		   /* change MPP44 type to TDM_CODEC_RST(0x2) */
++		   MV_REG_WRITE(MPP_CONTROL_REG5, ((MV_REG_READ(MPP_CONTROL_REG5) & 0xFFF0FFFF)  | BIT17));
++		}
++	}
++
++	mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        muxVal = (twsiVal & muxValMask) | muxVal;
++
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) )
++	{
++		mvOsPrintf("Board: twsi exp out val fail\n");
++		return;
++	}
++
++	/* TBD - 5 channels */
++#if defined(MV_TDM_5CHANNELS)
++	/* change MPP38 type to GPIO(0x0) & polarity for TDM_STROBE */
++	MV_REG_WRITE(MPP_CONTROL_REG4, (MV_REG_READ(MPP_CONTROL_REG4) & 0xF0FFFFFF));
++	mvGppPolaritySet(1, MV_GPP6, 0);
++
++	twsiSlave.offset = 6;
++	twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(2);
++
++	mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++	muxVal = (twsiVal & ~BIT2);
++
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) )
++	{
++		mvOsPrintf("Board: twsi exp change to out fail\n");
++		return;
++	}
++
++
++	twsiSlave.offset = 2;
++
++	mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++	muxVal = (twsiVal & ~BIT2);
++
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &muxVal, 1) )
++	{
++		mvOsPrintf("Board: twsi exp change to out fail\n");
++		return;
++	}
++#endif
++	DB(mvOsPrintf("Board: twsi exp out val succeded\n"));
++
++
++}
++/*******************************************************************************
++* mvBoardVoiceConnModeGet - return SLIC/DAA connection & interrupt modes
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*******************************************************************************/
++
++MV_VOID mvBoardVoiceConnModeGet(MV_32* connMode, MV_32* irqMode)
++{
++	switch(mvBoardIdGet())
++	{
++		case RD_88F6281A_ID:
++			*connMode = DAISY_CHAIN_MODE;
++			*irqMode = INTERRUPT_TO_TDM;
++			break;
++		case DB_88F6281A_BP_ID:
++			 *connMode = DUAL_CHIP_SELECT_MODE;
++			 *irqMode = INTERRUPT_TO_TDM;
++			break;
++		case RD_88F6192A_ID:
++			*connMode = DUAL_CHIP_SELECT_MODE;
++			*irqMode = INTERRUPT_TO_TDM;
++			break;
++		case DB_88F6192A_BP_ID:
++			 *connMode = DUAL_CHIP_SELECT_MODE;
++			 *irqMode = INTERRUPT_TO_TDM;
++			break;
++		default:
++			*connMode = *irqMode = -1;
++			mvOsPrintf("mvBoardVoiceAssembleModeGet: TDM not supported(boardId=0x%x)\n",mvBoardIdGet());
++	}
++		return;
++
++}
++
++/*******************************************************************************
++* mvBoardMppModuleTypePrint - print module detect
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_VOID mvBoardMppModuleTypePrint(MV_VOID)
++{
++
++	MV_BOARD_MPP_GROUP_CLASS devClass;
++	MV_BOARD_MPP_TYPE_CLASS mppGroupType;
++	MV_U32 devId;
++	MV_U32 maxMppGrp = 1;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			maxMppGrp = MV_6281_MPP_MAX_MODULE;
++			break;
++		case MV_6192_DEV_ID:
++			maxMppGrp = MV_6192_MPP_MAX_MODULE;
++			break;
++        case MV_6190_DEV_ID:
++            maxMppGrp = MV_6190_MPP_MAX_MODULE;
++            break;
++		case MV_6180_DEV_ID:
++			maxMppGrp = MV_6180_MPP_MAX_MODULE;
++			break;
++	}
++
++	for (devClass = 0; devClass < maxMppGrp; devClass++)
++	{
++		mppGroupType = mvBoardMppGroupTypeGet(devClass);
++
++		switch(mppGroupType)
++		{
++			case MV_BOARD_TDM:
++                if(devId != MV_6190_DEV_ID)
++                    mvOsPrintf("Module %d is TDM\n", devClass);
++				break;
++			case MV_BOARD_AUDIO:
++                if(devId != MV_6190_DEV_ID)
++                    mvOsPrintf("Module %d is AUDIO\n", devClass);
++				break;
++            case MV_BOARD_RGMII:
++                if(devId != MV_6190_DEV_ID)
++                    mvOsPrintf("Module %d is RGMII\n", devClass);
++				break;
++			case MV_BOARD_GMII:
++                if(devId != MV_6190_DEV_ID)
++                    mvOsPrintf("Module %d is GMII\n", devClass);
++				break;
++			case MV_BOARD_TS:
++                if(devId != MV_6190_DEV_ID)
++                    mvOsPrintf("Module %d is TS\n", devClass);
++				break;
++			default:
++				break;
++		}
++	}
++}
++
++/* 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 8;
++	}
++
++	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++)
++	{
++		/* TBR */
++		/*if (BOARD_INFO(boardId)->pDevCsInfo[devIndex].deviceCS == MV_BOOTDEVICE_INDEX)
++		     continue;*/
++
++		if (BOARD_INFO(boardId)->pDevCsInfo[devIndex].devClass == devClass)
++		{
++			if (foundIndex == devNum)
++			{
++				return &(BOARD_INFO(boardId)->pDevCsInfo[devIndex]);
++			}
++			foundIndex++;
++		}
++	}
++
++	/* device not found */
++	return NULL;
++}
++
++/* Get device CS number */
++
++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;
++
++}
++
++/*******************************************************************************
++* mvBoardRtcTwsiAddrTypeGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_U8 mvBoardRtcTwsiAddrTypeGet()
++{
++	int i;
++	MV_U32 boardId= mvBoardIdGet();
++
++	for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++)
++		if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_TWSI_RTC)
++			return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType;
++	return (MV_ERROR);
++}
++
++/*******************************************************************************
++* mvBoardRtcTwsiAddrGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_U8 mvBoardRtcTwsiAddrGet()
++{
++	int i;
++	MV_U32 boardId= mvBoardIdGet();
++
++	for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++)
++		if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_TWSI_RTC)
++			return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr;
++	return (0xFF);
++}
++
++/*******************************************************************************
++* mvBoardA2DTwsiAddrTypeGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_U8 mvBoardA2DTwsiAddrTypeGet()
++{
++	int i;
++	MV_U32 boardId= mvBoardIdGet();
++
++	for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++)
++		if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_TWSI_AUDIO_DEC)
++			return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType;
++	return (MV_ERROR);
++}
++
++/*******************************************************************************
++* mvBoardA2DTwsiAddrGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_U8 mvBoardA2DTwsiAddrGet()
++{
++	int i;
++	MV_U32 boardId= mvBoardIdGet();
++
++	for (i = 0; i < BOARD_INFO(boardId)->numBoardTwsiDev; i++)
++		if (BOARD_INFO(boardId)->pBoardTwsiDev[i].devClass == BOARD_TWSI_AUDIO_DEC)
++			return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr;
++	return (0xFF);
++}
++
++/*******************************************************************************
++* mvBoardTwsiExpAddrTypeGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_U8 mvBoardTwsiExpAddrTypeGet(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 == BOARD_DEV_TWSI_EXP)
++		{
++			if (indexFound == index)
++				return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType;
++			else
++				indexFound++;
++		}
++
++	return (MV_ERROR);
++}
++
++/*******************************************************************************
++* mvBoardTwsiExpAddrGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_U8 mvBoardTwsiExpAddrGet(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 == BOARD_DEV_TWSI_EXP)
++		{
++			if (indexFound == index)
++				return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr;
++			else
++				indexFound++;
++		}
++
++	return (0xFF);
++}
++
++
++/*******************************************************************************
++* mvBoardTwsiSatRAddrTypeGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_U8 mvBoardTwsiSatRAddrTypeGet(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 == BOARD_DEV_TWSI_SATR)
++		{
++			if (indexFound == index)
++				return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddrType;
++			else
++				indexFound++;
++		}
++
++	return (MV_ERROR);
++}
++
++/*******************************************************************************
++* mvBoardTwsiSatRAddrGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_U8 mvBoardTwsiSatRAddrGet(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 == BOARD_DEV_TWSI_SATR)
++		{
++			if (indexFound == index)
++				return BOARD_INFO(boardId)->pBoardTwsiDev[i].twsiDevAddr;
++			else
++				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(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_88F6281A)
++		tmpBoardId = DB_88F6281A_BP_ID;
++		#elif defined(RD_88F6281A)
++		tmpBoardId = RD_88F6281A_ID;
++		#elif defined(DB_88F6192A)
++		tmpBoardId = DB_88F6192A_BP_ID;
++		#elif defined(DB_88F6190A)
++		tmpBoardId = DB_88F6190A_BP_ID;
++		#elif defined(RD_88F6192A)
++		tmpBoardId = RD_88F6192A_ID;
++		#elif defined(RD_88F6190A)
++		tmpBoardId = RD_88F6190A_ID;
++		#elif defined(DB_88F6180A)
++		tmpBoardId = DB_88F6180A_BP_ID;
++		#elif defined(RD_88F6281A_PCAC)
++		tmpBoardId = RD_88F6281A_PCAC_ID;
++		#elif defined(RD_88F6281A_SHEEVA_PLUG)
++		tmpBoardId = SHEEVA_PLUG_ID;
++		#elif defined(DB_CUSTOMER)
++		tmpBoardId = DB_CUSTOMER_ID;
++		#endif
++		gBoardId = tmpBoardId;
++	}
++
++	return gBoardId;
++}
++
++
++/*******************************************************************************
++* mvBoarModuleTypeGet - mvBoarModuleTypeGet
++*
++* DESCRIPTION:
++*
++* INPUT:
++*		group num - MV_BOARD_MPP_GROUP_CLASS enum
++*
++* OUTPUT:
++*		None.
++*
++* RETURN:
++*		module num - MV_BOARD_MODULE_CLASS enum
++*
++*******************************************************************************/
++MV_BOARD_MODULE_ID_CLASS mvBoarModuleTypeGet(MV_BOARD_MPP_GROUP_CLASS devClass)
++{
++	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 MPP module ID\n"));
++	twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(devClass);
++	twsiSlave.slaveAddr.type = mvBoardTwsiExpAddrTypeGet(devClass);
++	twsiSlave.validOffset = MV_TRUE;
++	/* Offset is the first command after the address which indicate the register number to be read
++	   in next operation */
++	twsiSlave.offset = 0;
++	twsiSlave.moreThen256 = MV_FALSE;
++
++
++
++	if( MV_OK != mvTwsiRead (0, &twsiSlave, &data, 1) )
++	{
++		DB(mvOsPrintf("Board: Read MPP module ID fail\n"));
++		return MV_ERROR;
++	}
++	DB(mvOsPrintf("Board: Read MPP module ID succeded\n"));
++
++	return data;
++}
++
++/*******************************************************************************
++* mvBoarTwsiSatRGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*		device num - one of three devices
++*		reg num - 0 or 1
++*
++* OUTPUT:
++*		None.
++*
++* RETURN:
++*		reg value
++*
++*******************************************************************************/
++MV_U8 mvBoarTwsiSatRGet(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 = mvBoardTwsiSatRAddrGet(devNum);
++	twsiSlave.slaveAddr.type = mvBoardTwsiSatRAddrTypeGet(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;
++}
++
++/*******************************************************************************
++* mvBoarTwsiSatRSet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*		devNum - one of three devices
++*		regNum - 0 or 1
++*		regVal - value
++*
++*
++* OUTPUT:
++*		None.
++*
++* RETURN:
++*		reg value
++*
++*******************************************************************************/
++MV_STATUS mvBoarTwsiSatRSet(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 = mvBoardTwsiSatRAddrGet(devNum);
++	twsiSlave.slaveAddr.type = mvBoardTwsiSatRAddrTypeGet(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;
++}
++
++/*******************************************************************************
++* mvBoardSlicGpioPinGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*
++*
++*******************************************************************************/
++MV_32 mvBoardSlicGpioPinGet(MV_U32 slicNum)
++{
++	MV_U32 boardId;
++	boardId = mvBoardIdGet();
++
++	switch (boardId)
++	{
++	case DB_88F6281A_BP_ID:
++	case RD_88F6281A_ID:
++	default:
++		return MV_ERROR;
++		break;
++
++	}
++}
++
++/*******************************************************************************
++* mvBoardFanPowerControl - Turn on/off the fan power control on the RD-6281A
++*
++* DESCRIPTION:
++*
++* INPUT:
++*        mode - MV_TRUE = on ; MV_FALSE = off
++*
++* OUTPUT:
++*       MV_STATUS - MV_OK , MV_ERROR.
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_STATUS mvBoardFanPowerControl(MV_BOOL mode)
++{
++
++	MV_U8 val = 1, twsiVal;
++	MV_TWSI_SLAVE twsiSlave;
++	MV_TWSI_ADDR slave;
++
++	if(mvBoardIdGet() != RD_88F6281A_ID)
++        return MV_ERROR;
++
++	/* TWSI init */
++	slave.type = ADDR7_BIT;
++	slave.address = 0;
++	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
++
++	/* Read MPP module ID */
++	DB(mvOsPrintf("Board: twsi exp set\n"));
++	twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(1);
++	twsiSlave.slaveAddr.type = ADDR7_BIT;
++	twsiSlave.validOffset = MV_TRUE;
++	/* Offset is the first command after the address which indicate the register number to be read
++	   in next operation */
++	twsiSlave.offset = 3;
++	twsiSlave.moreThen256 = MV_FALSE;
++        if(mode == MV_TRUE)
++            val = 0x1;
++        else
++            val = 0;
++        mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        val = (twsiVal & 0xfe) | val;
++
++        if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) )
++	{
++		DB(mvOsPrintf("Board: twsi exp out val fail\n"));
++		return MV_ERROR;
++	}
++	DB(mvOsPrintf("Board: twsi exp out val succeded\n"));
++
++	/* Change twsi exp to output */
++	twsiSlave.offset = 7;
++        mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        val = (twsiVal & 0xfe);
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) )
++	{
++		DB(mvOsPrintf("Board: twsi exp change to out fail\n"));
++		return MV_ERROR;
++	}
++	DB(mvOsPrintf("Board: twsi exp change to out succeded\n"));
++        return MV_OK;
++}
++
++/*******************************************************************************
++* mvBoardHDDPowerControl - Turn on/off the HDD power control on the RD-6281A
++*
++* DESCRIPTION:
++*
++* INPUT:
++*        mode - MV_TRUE = on ; MV_FALSE = off
++*
++* OUTPUT:
++*       MV_STATUS - MV_OK , MV_ERROR.
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_STATUS mvBoardHDDPowerControl(MV_BOOL mode)
++{
++
++	MV_U8 val = 1, twsiVal;
++	MV_TWSI_SLAVE twsiSlave;
++	MV_TWSI_ADDR slave;
++
++	if(mvBoardIdGet() != RD_88F6281A_ID)
++        return MV_ERROR;
++
++	/* TWSI init */
++	slave.type = ADDR7_BIT;
++	slave.address = 0;
++	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
++
++	/* Read MPP module ID */
++	DB(mvOsPrintf("Board: twsi exp set\n"));
++	twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(1);
++	twsiSlave.slaveAddr.type = ADDR7_BIT;
++	twsiSlave.validOffset = MV_TRUE;
++	/* Offset is the first command after the address which indicate the register number to be read
++	   in next operation */
++	twsiSlave.offset = 3;
++	twsiSlave.moreThen256 = MV_FALSE;
++        if(mode == MV_TRUE)
++            val = 0x2;
++        else
++            val = 0;
++        mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        val = (twsiVal & 0xfd) | val;
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) )
++	{
++		DB(mvOsPrintf("Board: twsi exp out val fail\n"));
++		return MV_ERROR;
++	}
++	DB(mvOsPrintf("Board: twsi exp out val succeded\n"));
++
++	/* Change twsi exp to output */
++	twsiSlave.offset = 7;
++        mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        val = (twsiVal & 0xfd);
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) )
++	{
++		DB(mvOsPrintf("Board: twsi exp change to out fail\n"));
++		return MV_ERROR;
++	}
++	DB(mvOsPrintf("Board: twsi exp change to out succeded\n"));
++        return MV_OK;
++}
++
++/*******************************************************************************
++* mvBoardSDioWPControl - Turn on/off the SDIO WP on the RD-6281A
++*
++* DESCRIPTION:
++*
++* INPUT:
++*        mode - MV_TRUE = on ; MV_FALSE = off
++*
++* OUTPUT:
++*       MV_STATUS - MV_OK , MV_ERROR.
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_STATUS mvBoardSDioWPControl(MV_BOOL mode)
++{
++
++	MV_U8 val = 1, twsiVal;
++	MV_TWSI_SLAVE twsiSlave;
++	MV_TWSI_ADDR slave;
++
++	if(mvBoardIdGet() != RD_88F6281A_ID)
++        return MV_ERROR;
++
++	/* TWSI init */
++	slave.type = ADDR7_BIT;
++	slave.address = 0;
++	mvTwsiInit(0, TWSI_SPEED, mvBoardTclkGet(), &slave, 0);
++
++	/* Read MPP module ID */
++	DB(mvOsPrintf("Board: twsi exp set\n"));
++	twsiSlave.slaveAddr.address = mvBoardTwsiExpAddrGet(0);
++	twsiSlave.slaveAddr.type = ADDR7_BIT;
++	twsiSlave.validOffset = MV_TRUE;
++	/* Offset is the first command after the address which indicate the register number to be read
++	   in next operation */
++	twsiSlave.offset = 3;
++	twsiSlave.moreThen256 = MV_FALSE;
++        if(mode == MV_TRUE)
++            val = 0x10;
++        else
++            val = 0;
++        mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        val = (twsiVal & 0xef) | val;
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) )
++	{
++		DB(mvOsPrintf("Board: twsi exp out val fail\n"));
++		return MV_ERROR;
++	}
++	DB(mvOsPrintf("Board: twsi exp out val succeded\n"));
++
++	/* Change twsi exp to output */
++	twsiSlave.offset = 7;
++        mvTwsiRead(0, &twsiSlave, &twsiVal, 1);
++        val = (twsiVal & 0xef);
++	if( MV_OK != mvTwsiWrite (0, &twsiSlave, &val, 1) )
++	{
++		DB(mvOsPrintf("Board: twsi exp change to out fail\n"));
++		return MV_ERROR;
++	}
++	DB(mvOsPrintf("Board: twsi exp change to out succeded\n"));
++        return MV_OK;
++}
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.h b/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.h
+new file mode 100644
+index 0000000..dead633
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.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 __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"
++
++
++/* 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	5
++
++#define	MV_BOARD_MAX_USB_IF		1
++#define MV_BOARD_MAX_MPP		7
++#define MV_BOARD_NAME_LEN		0x20
++
++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_MAX_MPP_GROUP
++}MV_BOARD_MPP_GROUP_CLASS;
++
++typedef enum _devBoardMppTypeClass
++{
++	MV_BOARD_AUTO,
++	MV_BOARD_TDM,
++	MV_BOARD_AUDIO,
++	MV_BOARD_RGMII,
++	MV_BOARD_GMII,
++	MV_BOARD_TS,
++	MV_BOARD_MII,
++	MV_BOARD_OTHER
++}MV_BOARD_MPP_TYPE_CLASS;
++
++typedef enum _devBoardModuleIdClass
++{
++	MV_BOARD_MODULE_TDM_ID = 1,
++	MV_BOARD_MODULE_AUDIO_ID,
++	MV_BOARD_MODULE_RGMII_ID,
++	MV_BOARD_MODULE_GMII_ID,
++	MV_BOARD_MODULE_TS_ID,
++	MV_BOARD_MODULE_MII_ID,
++	MV_BOARD_MODULE_TDM_5CHAN_ID,
++	MV_BOARD_MODULE_OTHER_ID
++}MV_BOARD_MODULE_ID_CLASS;
++
++typedef struct _boardMppTypeInfo
++{
++	MV_BOARD_MPP_TYPE_CLASS	boardMppGroup1;
++	MV_BOARD_MPP_TYPE_CLASS	boardMppGroup2;
++
++}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_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_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;
++
++
++#define MV_BOARD_PHY_FORCE_10MB		0x0
++#define MV_BOARD_PHY_FORCE_100MB	0x1
++#define MV_BOARD_PHY_FORCE_1000MB	0x2
++#define MV_BOARD_PHY_SPEED_AUTO		0x3
++
++typedef struct _boardSwitchInfo
++{
++	MV_32	linkStatusIrq;
++	MV_32	qdPort[BOARD_ETH_SWITCH_PORT_NUM];
++	MV_32	qdCpuPort;
++	MV_32	smiScanMode; /* 1 for SMI_MANUAL_MODE, 0 otherwise */
++	MV_32	switchOnPort;
++
++}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 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				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				gppOutEnValHigh;
++	MV_U32				gppOutValLow;
++	MV_U32				gppOutValHigh;
++	MV_U32				gppPolarityValLow;
++	MV_U32				gppPolarityValHigh;
++
++	/* Switch Configuration */
++	MV_BOARD_SWITCH_INFO*		pSwitchInfo;
++}MV_BOARD_INFO;
++
++
++
++MV_VOID	mvBoardEnvInit(MV_VOID);
++MV_U32		mvBoardIdGet(MV_VOID);
++MV_U16		mvBoardModelGet(MV_VOID);
++MV_U16		mvBoardRevGet(MV_VOID);
++MV_STATUS	mvBoardNameGet(char *pNameBuff);
++MV_32		mvBoardPhyAddrGet(MV_U32 ethPortNum);
++MV_BOARD_MAC_SPEED      mvBoardMacSpeedGet(MV_U32 ethPortNum);
++MV_32		mvBoardLinkStatusIrqGet(MV_U32 ethPortNum);
++MV_32		mvBoardSwitchPortGet(MV_U32 ethPortNum, MV_U8 boardPortNum);
++MV_32		mvBoardSwitchCpuPortGet(MV_U32 ethPortNum);
++MV_32		mvBoardIsSwitchConnected(MV_U32 ethPortNum);
++MV_32		mvBoardSmiScanModeGet(MV_U32 ethPortNum);
++MV_BOOL	mvBoardIsPortInSgmii(MV_U32 ethPortNum);
++MV_BOOL	mvBoardIsPortInGmii(MV_VOID);
++MV_U32			mvBoardTclkGet(MV_VOID);
++MV_U32		mvBoardSysClkGet(MV_VOID);
++MV_U32			mvBoardDebugLedNumGet(MV_U32 boardId);
++MV_VOID	mvBoardDebugLed(MV_U32 hexNum);
++MV_32		mvBoardMppGet(MV_U32 mppGroupNum);
++
++MV_U8		mvBoardRtcTwsiAddrTypeGet(MV_VOID);
++MV_U8		mvBoardRtcTwsiAddrGet(MV_VOID);
++
++MV_U8		mvBoardA2DTwsiAddrTypeGet(MV_VOID);
++MV_U8		mvBoardA2DTwsiAddrGet(MV_VOID);
++
++MV_U8		mvBoardTwsiExpAddrGet(MV_U32 index);
++MV_U8		mvBoardTwsiSatRAddrTypeGet(MV_U32 index);
++MV_U8		mvBoardTwsiSatRAddrGet(MV_U32 index);
++MV_U8		mvBoardTwsiExpAddrTypeGet(MV_U32 index);
++MV_BOARD_MODULE_ID_CLASS	mvBoarModuleTypeGet(MV_BOARD_MPP_GROUP_CLASS devClass);
++MV_BOARD_MPP_TYPE_CLASS	mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass);
++MV_VOID	mvBoardMppGroupTypeSet(MV_BOARD_MPP_GROUP_CLASS mppGroupClass,
++						MV_BOARD_MPP_TYPE_CLASS mppGroupType);
++MV_VOID	mvBoardMppGroupIdUpdate(MV_VOID);
++MV_VOID	mvBoardMppMuxSet(MV_VOID);
++MV_VOID	mvBoardTdmMppSet(MV_32 chType);
++MV_VOID	mvBoardVoiceConnModeGet(MV_32* connMode, MV_32* irqMode);
++
++MV_VOID	mvBoardMppModuleTypePrint(MV_VOID);
++MV_VOID		mvBoardReset(MV_VOID);
++MV_U8		mvBoarTwsiSatRGet(MV_U8 devNum, MV_U8 regNum);
++MV_STATUS		mvBoarTwsiSatRSet(MV_U8 devNum, MV_U8 regNum, MV_U8 regVal);
++MV_BOOL	mvBoardSpecInitGet(MV_U32* regOff, MV_U32* data);
++/* Board devices API managments */
++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);
++
++/* Gpio Pin Connections API */
++MV_32	    mvBoardUSBVbusGpioPinGet(int devId);
++MV_32	    mvBoardUSBVbusEnGpioPinGet(int devId);
++MV_U32      mvBoardPexBridgeIntPinGet(MV_U32 devNum, MV_U32 intPin);
++
++MV_32	    mvBoardResetGpioPinGet(MV_VOID);
++MV_32	    mvBoardRTCGpioPinGet(MV_VOID);
++MV_32	    mvBoardGpioIntMaskLowGet(MV_VOID);
++MV_32	    mvBoardGpioIntMaskHighGet(MV_VOID);
++MV_32	    mvBoardSlicGpioPinGet(MV_U32 slicNum);
++
++MV_32	    mvBoardSDIOGpioPinGet(MV_VOID);
++MV_STATUS   mvBoardSDioWPControl(MV_BOOL mode);
++MV_32	    mvBoarGpioPinNumGet(MV_BOARD_GPP_CLASS class, MV_U32 index);
++
++MV_32	    mvBoardNandWidthGet(void);
++MV_STATUS   mvBoardFanPowerControl(MV_BOOL mode);
++MV_STATUS   mvBoardHDDPowerControl(MV_BOOL mode);
++#endif /* __INCmvBoardEnvLibh */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.c b/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.c
+new file mode 100644
+index 0000000..e256c4f
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.c
+@@ -0,0 +1,848 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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"
++
++#define DB_88F6281A_BOARD_PCI_IF_NUM            0x0
++#define DB_88F6281A_BOARD_TWSI_DEF_NUM		    0x7
++#define DB_88F6281A_BOARD_MAC_INFO_NUM		    0x2
++#define DB_88F6281A_BOARD_GPP_INFO_NUM		    0x3
++#define DB_88F6281A_BOARD_MPP_CONFIG_NUM		0x1
++#define DB_88F6281A_BOARD_MPP_GROUP_TYPE_NUM	0x1
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++    #define DB_88F6281A_BOARD_DEVICE_CONFIG_NUM	    0x1
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++    #define DB_88F6281A_BOARD_DEVICE_CONFIG_NUM	    0x2
++#else
++    #define DB_88F6281A_BOARD_DEVICE_CONFIG_NUM	    0x1
++#endif
++#define DB_88F6281A_BOARD_DEBUG_LED_NUM		    0x0
++
++
++MV_BOARD_TWSI_INFO	db88f6281AInfoBoardTwsiDev[] =
++	/* {{MV_BOARD_DEV_CLASS	devClass, MV_U8	twsiDevAddr, MV_U8 twsiDevAddrType}} */
++	{
++	{BOARD_DEV_TWSI_EXP, 0x20, ADDR7_BIT},
++	{BOARD_DEV_TWSI_EXP, 0x21, ADDR7_BIT},
++	{BOARD_DEV_TWSI_EXP, 0x27, ADDR7_BIT},
++	{BOARD_DEV_TWSI_SATR, 0x4C, ADDR7_BIT},
++	{BOARD_DEV_TWSI_SATR, 0x4D, ADDR7_BIT},
++	{BOARD_DEV_TWSI_SATR, 0x4E, ADDR7_BIT},
++	{BOARD_TWSI_AUDIO_DEC, 0x4A, ADDR7_BIT}
++	};
++
++MV_BOARD_MAC_INFO db88f6281AInfoBoardMacInfo[] =
++	/* {{MV_BOARD_MAC_SPEED	boardMacSpeed, MV_U8 boardEthSmiAddr}} */
++	{
++	{BOARD_MAC_SPEED_AUTO, 0x8},
++	{BOARD_MAC_SPEED_AUTO, 0x9}
++	};
++
++MV_BOARD_MPP_TYPE_INFO db88f6281AInfoBoardMppTypeInfo[] =
++	/* {{MV_BOARD_MPP_TYPE_CLASS	boardMppGroup1,
++		MV_BOARD_MPP_TYPE_CLASS	boardMppGroup2}} */
++	{{MV_BOARD_AUTO, MV_BOARD_AUTO}
++	};
++
++MV_BOARD_GPP_INFO db88f6281AInfoBoardGppInfo[] =
++	/* {{MV_BOARD_GPP_CLASS	devClass, MV_U8	gppPinNum}} */
++	{
++	{BOARD_GPP_TSU_DIRCTION, 33}
++	/*muxed with TDM/Audio module via IOexpender
++	{BOARD_GPP_SDIO_DETECT, 38},
++	{BOARD_GPP_USB_VBUS, 49}*/
++	};
++
++MV_DEV_CS_INFO db88f6281AInfoBoardDeCsInfo[] =
++		/*{deviceCS, params, devType, devWidth}*/
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++		 {{0, N_A, BOARD_DEV_NAND_FLASH, 8}};	   /* NAND DEV */
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++		 {
++         {0, N_A, BOARD_DEV_NAND_FLASH, 8},	   /* NAND DEV */
++         {1, N_A, BOARD_DEV_SPI_FLASH, 8},	   /* SPI DEV */
++         };
++#else
++	 {{1, N_A, BOARD_DEV_SPI_FLASH, 8}};	   /* SPI DEV */
++#endif
++
++MV_BOARD_MPP_INFO	db88f6281AInfoBoardMppConfigValue[] =
++	{{{
++	DB_88F6281A_MPP0_7,
++	DB_88F6281A_MPP8_15,
++	DB_88F6281A_MPP16_23,
++	DB_88F6281A_MPP24_31,
++	DB_88F6281A_MPP32_39,
++	DB_88F6281A_MPP40_47,
++	DB_88F6281A_MPP48_55
++	}}};
++
++
++MV_BOARD_INFO db88f6281AInfo = {
++	"DB-88F6281A-BP",				/* boardName[MAX_BOARD_NAME_LEN] */
++	DB_88F6281A_BOARD_MPP_GROUP_TYPE_NUM,		/* numBoardMppGroupType */
++	db88f6281AInfoBoardMppTypeInfo,
++	DB_88F6281A_BOARD_MPP_CONFIG_NUM,		/* numBoardMppConfig */
++	db88f6281AInfoBoardMppConfigValue,
++	0,						/* intsGppMaskLow */
++	0,						/* intsGppMaskHigh */
++	DB_88F6281A_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	db88f6281AInfoBoardDeCsInfo,
++	DB_88F6281A_BOARD_TWSI_DEF_NUM,			/* numBoardTwsiDev */
++	db88f6281AInfoBoardTwsiDev,
++	DB_88F6281A_BOARD_MAC_INFO_NUM,			/* numBoardMacInfo */
++	db88f6281AInfoBoardMacInfo,
++	DB_88F6281A_BOARD_GPP_INFO_NUM,			/* numBoardGppInfo */
++	db88f6281AInfoBoardGppInfo,
++	DB_88F6281A_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	NULL,
++	0,						/* ledsPolarity */
++	DB_88F6281A_OE_LOW,				/* gppOutEnLow */
++	DB_88F6281A_OE_HIGH,				/* gppOutEnHigh */
++	DB_88F6281A_OE_VAL_LOW,				/* gppOutValLow */
++	DB_88F6281A_OE_VAL_HIGH,				/* gppOutValHigh */
++	0,						/* gppPolarityValLow */
++	BIT6,						/* gppPolarityValHigh */
++	NULL						/* pSwitchInfo */
++};
++
++
++#define RD_88F6281A_BOARD_PCI_IF_NUM		0x0
++#define RD_88F6281A_BOARD_TWSI_DEF_NUM		0x2
++#define RD_88F6281A_BOARD_MAC_INFO_NUM		0x2
++#define RD_88F6281A_BOARD_GPP_INFO_NUM		0x5
++#define RD_88F6281A_BOARD_MPP_GROUP_TYPE_NUM	0x1
++#define RD_88F6281A_BOARD_MPP_CONFIG_NUM		0x1
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++    #define RD_88F6281A_BOARD_DEVICE_CONFIG_NUM	    0x1
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++    #define RD_88F6281A_BOARD_DEVICE_CONFIG_NUM	    0x2
++#else
++    #define RD_88F6281A_BOARD_DEVICE_CONFIG_NUM	    0x1
++#endif
++#define RD_88F6281A_BOARD_DEBUG_LED_NUM		0x0
++
++MV_BOARD_MAC_INFO rd88f6281AInfoBoardMacInfo[] =
++	/* {{MV_BOARD_MAC_SPEED	boardMacSpeed, MV_U8 boardEthSmiAddr}} */
++	{{BOARD_MAC_SPEED_1000M, 0xa},
++    {BOARD_MAC_SPEED_AUTO, 0xb}
++	};
++
++MV_BOARD_SWITCH_INFO rd88f6281AInfoBoardSwitchInfo[] =
++	/* MV_32 linkStatusIrq, {MV_32 qdPort0, MV_32 qdPort1, MV_32 qdPort2, MV_32 qdPort3, MV_32 qdPort4},
++		MV_32 qdCpuPort, MV_32 smiScanMode, MV_32 switchOnPort} */
++	{{38, {0, 1, 2, 3, -1}, 5, 2, 0},
++	 {-1, {-1}, -1, -1, -1}};
++
++MV_BOARD_TWSI_INFO	rd88f6281AInfoBoardTwsiDev[] =
++	/* {{MV_BOARD_DEV_CLASS	devClass, MV_U8	twsiDevAddr, MV_U8 twsiDevAddrType}} */
++	{
++	{BOARD_DEV_TWSI_EXP, 0xFF, ADDR7_BIT}, /* dummy entry to align with modules indexes */
++	{BOARD_DEV_TWSI_EXP, 0x27, ADDR7_BIT}
++	};
++
++MV_BOARD_MPP_TYPE_INFO rd88f6281AInfoBoardMppTypeInfo[] =
++	{{MV_BOARD_RGMII, MV_BOARD_TDM}
++	};
++
++MV_DEV_CS_INFO rd88f6281AInfoBoardDeCsInfo[] =
++		/*{deviceCS, params, devType, devWidth}*/
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++		 {{0, N_A, BOARD_DEV_NAND_FLASH, 8}};	   /* NAND DEV */
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++		 {
++         {0, N_A, BOARD_DEV_NAND_FLASH, 8},	   /* NAND DEV */
++         {1, N_A, BOARD_DEV_SPI_FLASH, 8},	   /* SPI DEV */
++         };
++#else
++		 {{1, N_A, BOARD_DEV_SPI_FLASH, 8}};	   /* SPI DEV */
++#endif
++
++MV_BOARD_GPP_INFO rd88f6281AInfoBoardGppInfo[] =
++	/* {{MV_BOARD_GPP_CLASS	devClass, MV_U8	gppPinNum}} */
++	{{BOARD_GPP_SDIO_DETECT, 28},
++    {BOARD_GPP_USB_OC, 29},
++    {BOARD_GPP_WPS_BUTTON, 35},
++    {BOARD_GPP_MV_SWITCH, 38},
++    {BOARD_GPP_USB_VBUS, 49}
++	};
++
++MV_BOARD_MPP_INFO	rd88f6281AInfoBoardMppConfigValue[] =
++	{{{
++	RD_88F6281A_MPP0_7,
++	RD_88F6281A_MPP8_15,
++	RD_88F6281A_MPP16_23,
++	RD_88F6281A_MPP24_31,
++	RD_88F6281A_MPP32_39,
++	RD_88F6281A_MPP40_47,
++	RD_88F6281A_MPP48_55
++	}}};
++
++MV_BOARD_INFO rd88f6281AInfo = {
++	"RD-88F6281A",				/* boardName[MAX_BOARD_NAME_LEN] */
++	RD_88F6281A_BOARD_MPP_GROUP_TYPE_NUM,		/* numBoardMppGroupType */
++	rd88f6281AInfoBoardMppTypeInfo,
++	RD_88F6281A_BOARD_MPP_CONFIG_NUM,		/* numBoardMppConfig */
++	rd88f6281AInfoBoardMppConfigValue,
++	0,						/* intsGppMaskLow */
++	(1 << 3),					/* intsGppMaskHigh */
++	RD_88F6281A_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	rd88f6281AInfoBoardDeCsInfo,
++	RD_88F6281A_BOARD_TWSI_DEF_NUM,			/* numBoardTwsiDev */
++	rd88f6281AInfoBoardTwsiDev,
++	RD_88F6281A_BOARD_MAC_INFO_NUM,			/* numBoardMacInfo */
++	rd88f6281AInfoBoardMacInfo,
++	RD_88F6281A_BOARD_GPP_INFO_NUM,			/* numBoardGppInfo */
++	rd88f6281AInfoBoardGppInfo,
++	RD_88F6281A_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	NULL,
++	0,										/* ledsPolarity */
++	RD_88F6281A_OE_LOW,				/* gppOutEnLow */
++	RD_88F6281A_OE_HIGH,				/* gppOutEnHigh */
++	RD_88F6281A_OE_VAL_LOW,				/* gppOutValLow */
++	RD_88F6281A_OE_VAL_HIGH,				/* gppOutValHigh */
++	0,						/* gppPolarityValLow */
++	BIT6,						/* gppPolarityValHigh */
++	rd88f6281AInfoBoardSwitchInfo			/* pSwitchInfo */
++};
++
++
++#define DB_88F6192A_BOARD_PCI_IF_NUM            0x0
++#define DB_88F6192A_BOARD_TWSI_DEF_NUM		    0x7
++#define DB_88F6192A_BOARD_MAC_INFO_NUM		    0x2
++#define DB_88F6192A_BOARD_GPP_INFO_NUM		    0x3
++#define DB_88F6192A_BOARD_MPP_GROUP_TYPE_NUM	0x1
++#define DB_88F6192A_BOARD_MPP_CONFIG_NUM		0x1
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++    #define DB_88F6192A_BOARD_DEVICE_CONFIG_NUM	    0x1
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++    #define DB_88F6192A_BOARD_DEVICE_CONFIG_NUM	    0x2
++#else
++    #define DB_88F6192A_BOARD_DEVICE_CONFIG_NUM	    0x1
++#endif
++#define DB_88F6192A_BOARD_DEBUG_LED_NUM		    0x0
++
++MV_BOARD_TWSI_INFO	db88f6192AInfoBoardTwsiDev[] =
++	/* {{MV_BOARD_DEV_CLASS	devClass, MV_U8	twsiDevAddr, MV_U8 twsiDevAddrType}} */
++	{
++	{BOARD_DEV_TWSI_EXP, 0x20, ADDR7_BIT},
++	{BOARD_DEV_TWSI_EXP, 0x21, ADDR7_BIT},
++	{BOARD_DEV_TWSI_EXP, 0x27, ADDR7_BIT},
++	{BOARD_DEV_TWSI_SATR, 0x4C, ADDR7_BIT},
++	{BOARD_DEV_TWSI_SATR, 0x4D, ADDR7_BIT},
++	{BOARD_DEV_TWSI_SATR, 0x4E, ADDR7_BIT},
++	{BOARD_TWSI_AUDIO_DEC, 0x4A, ADDR7_BIT}
++	};
++
++MV_BOARD_MAC_INFO db88f6192AInfoBoardMacInfo[] =
++	/* {{MV_BOARD_MAC_SPEED	boardMacSpeed, MV_U8 boardEthSmiAddr}} */
++	{
++	{BOARD_MAC_SPEED_AUTO, 0x8},
++	{BOARD_MAC_SPEED_AUTO, 0x9}
++	};
++
++MV_BOARD_MPP_TYPE_INFO db88f6192AInfoBoardMppTypeInfo[] =
++	/* {{MV_BOARD_MPP_TYPE_CLASS	boardMppGroup1,
++		MV_BOARD_MPP_TYPE_CLASS	boardMppGroup2}} */
++	{{MV_BOARD_AUTO, MV_BOARD_OTHER}
++	};
++
++MV_DEV_CS_INFO db88f6192AInfoBoardDeCsInfo[] =
++		/*{deviceCS, params, devType, devWidth}*/
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++		 {{0, N_A, BOARD_DEV_NAND_FLASH, 8}};	   /* NAND DEV */
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++		 {
++         {0, N_A, BOARD_DEV_NAND_FLASH, 8},	   /* NAND DEV */
++         {1, N_A, BOARD_DEV_SPI_FLASH, 8},	   /* SPI DEV */
++         };
++#else
++		 {{1, N_A, BOARD_DEV_SPI_FLASH, 8}};	   /* SPI DEV */
++#endif
++
++MV_BOARD_GPP_INFO db88f6192AInfoBoardGppInfo[] =
++	/* {{MV_BOARD_GPP_CLASS	devClass, MV_U8	gppPinNum}} */
++	{
++    {BOARD_GPP_SDIO_WP, 20},
++	{BOARD_GPP_USB_VBUS, 22},
++	{BOARD_GPP_SDIO_DETECT, 23},
++	};
++
++MV_BOARD_MPP_INFO	db88f6192AInfoBoardMppConfigValue[] =
++	{{{
++	DB_88F6192A_MPP0_7,
++	DB_88F6192A_MPP8_15,
++	DB_88F6192A_MPP16_23,
++	DB_88F6192A_MPP24_31,
++	DB_88F6192A_MPP32_35
++	}}};
++
++MV_BOARD_INFO db88f6192AInfo = {
++	"DB-88F6192A-BP",				/* boardName[MAX_BOARD_NAME_LEN] */
++	DB_88F6192A_BOARD_MPP_GROUP_TYPE_NUM,		/* numBoardMppGroupType */
++	db88f6192AInfoBoardMppTypeInfo,
++	DB_88F6192A_BOARD_MPP_CONFIG_NUM,		/* numBoardMppConfig */
++	db88f6192AInfoBoardMppConfigValue,
++	0,						/* intsGppMaskLow */
++	(1 << 3),					/* intsGppMaskHigh */
++	DB_88F6192A_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	db88f6192AInfoBoardDeCsInfo,
++	DB_88F6192A_BOARD_TWSI_DEF_NUM,			/* numBoardTwsiDev */
++	db88f6192AInfoBoardTwsiDev,
++	DB_88F6192A_BOARD_MAC_INFO_NUM,			/* numBoardMacInfo */
++	db88f6192AInfoBoardMacInfo,
++	DB_88F6192A_BOARD_GPP_INFO_NUM,			/* numBoardGppInfo */
++	db88f6192AInfoBoardGppInfo,
++	DB_88F6192A_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	NULL,
++	0,										/* ledsPolarity */
++	DB_88F6192A_OE_LOW,				/* gppOutEnLow */
++	DB_88F6192A_OE_HIGH,				/* gppOutEnHigh */
++	DB_88F6192A_OE_VAL_LOW,				/* gppOutValLow */
++	DB_88F6192A_OE_VAL_HIGH,				/* gppOutValHigh */
++	0,						/* gppPolarityValLow */
++	0,						/* gppPolarityValHigh */
++	NULL						/* pSwitchInfo */
++};
++
++#define DB_88F6190A_BOARD_MAC_INFO_NUM		0x1
++
++MV_BOARD_INFO db88f6190AInfo = {
++	"DB-88F6190A-BP",				/* boardName[MAX_BOARD_NAME_LEN] */
++	DB_88F6192A_BOARD_MPP_GROUP_TYPE_NUM,		/* numBoardMppGroupType */
++	db88f6192AInfoBoardMppTypeInfo,
++	DB_88F6192A_BOARD_MPP_CONFIG_NUM,		/* numBoardMppConfig */
++	db88f6192AInfoBoardMppConfigValue,
++	0,						/* intsGppMaskLow */
++	(1 << 3),					/* intsGppMaskHigh */
++	DB_88F6192A_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	db88f6192AInfoBoardDeCsInfo,
++	DB_88F6192A_BOARD_TWSI_DEF_NUM,			/* numBoardTwsiDev */
++	db88f6192AInfoBoardTwsiDev,
++	DB_88F6190A_BOARD_MAC_INFO_NUM,			/* numBoardMacInfo */
++	db88f6192AInfoBoardMacInfo,
++	DB_88F6192A_BOARD_GPP_INFO_NUM,			/* numBoardGppInfo */
++	db88f6192AInfoBoardGppInfo,
++	DB_88F6192A_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	NULL,
++	0,										/* ledsPolarity */
++	DB_88F6192A_OE_LOW,				/* gppOutEnLow */
++	DB_88F6192A_OE_HIGH,				/* gppOutEnHigh */
++	DB_88F6192A_OE_VAL_LOW,				/* gppOutValLow */
++	DB_88F6192A_OE_VAL_HIGH,				/* gppOutValHigh */
++	0,						/* gppPolarityValLow */
++	0,						/* gppPolarityValHigh */
++	NULL						/* pSwitchInfo */
++};
++
++#define RD_88F6192A_BOARD_PCI_IF_NUM		0x0
++#define RD_88F6192A_BOARD_TWSI_DEF_NUM		0x0
++#define RD_88F6192A_BOARD_MAC_INFO_NUM		0x1
++#define RD_88F6192A_BOARD_GPP_INFO_NUM		0xE
++#define RD_88F6192A_BOARD_MPP_GROUP_TYPE_NUM	0x1
++#define RD_88F6192A_BOARD_MPP_CONFIG_NUM		0x1
++#define RD_88F6192A_BOARD_DEVICE_CONFIG_NUM	0x1
++#define RD_88F6192A_BOARD_DEBUG_LED_NUM		0x3
++
++MV_U8	rd88f6192AInfoBoardDebugLedIf[] =
++	{17, 28, 29};
++
++MV_BOARD_MAC_INFO rd88f6192AInfoBoardMacInfo[] =
++	/* {{MV_BOARD_MAC_SPEED	boardMacSpeed, MV_U8 boardEthSmiAddr}} */
++	{{BOARD_MAC_SPEED_AUTO, 0x8}
++	};
++
++MV_BOARD_MPP_TYPE_INFO rd88f6192AInfoBoardMppTypeInfo[] =
++	/* {{MV_BOARD_MPP_TYPE_CLASS	boardMppGroup1,
++		MV_BOARD_MPP_TYPE_CLASS	boardMppGroup2}} */
++	{{MV_BOARD_OTHER, MV_BOARD_OTHER}
++	};
++
++MV_DEV_CS_INFO rd88f6192AInfoBoardDeCsInfo[] =
++		/*{deviceCS, params, devType, devWidth}*/
++		 {{1, N_A, BOARD_DEV_SPI_FLASH, 8}};	   /* SPI DEV */
++
++MV_BOARD_GPP_INFO rd88f6192AInfoBoardGppInfo[] =
++	/* {{MV_BOARD_GPP_CLASS	devClass, MV_U8	gppPinNum}} */
++	{
++	{BOARD_GPP_USB_VBUS_EN, 10},
++	{BOARD_GPP_USB_HOST_DEVICE, 11},
++	{BOARD_GPP_RESET, 14},
++	{BOARD_GPP_POWER_ON_LED, 15},
++	{BOARD_GPP_HDD_POWER, 16},
++	{BOARD_GPP_WPS_BUTTON, 24},
++	{BOARD_GPP_TS_BUTTON_C, 25},
++	{BOARD_GPP_USB_VBUS, 26},
++	{BOARD_GPP_USB_OC, 27},
++	{BOARD_GPP_TS_BUTTON_U, 30},
++	{BOARD_GPP_TS_BUTTON_R, 31},
++	{BOARD_GPP_TS_BUTTON_L, 32},
++	{BOARD_GPP_TS_BUTTON_D, 34},
++	{BOARD_GPP_FAN_POWER, 35}
++	};
++
++MV_BOARD_MPP_INFO	rd88f6192AInfoBoardMppConfigValue[] =
++	{{{
++	RD_88F6192A_MPP0_7,
++	RD_88F6192A_MPP8_15,
++	RD_88F6192A_MPP16_23,
++	RD_88F6192A_MPP24_31,
++	RD_88F6192A_MPP32_35
++	}}};
++
++MV_BOARD_INFO rd88f6192AInfo = {
++	"RD-88F6192A-NAS",				/* boardName[MAX_BOARD_NAME_LEN] */
++	RD_88F6192A_BOARD_MPP_GROUP_TYPE_NUM,		/* numBoardMppGroupType */
++	rd88f6192AInfoBoardMppTypeInfo,
++	RD_88F6192A_BOARD_MPP_CONFIG_NUM,		/* numBoardMppConfig */
++	rd88f6192AInfoBoardMppConfigValue,
++	0,						/* intsGppMaskLow */
++	(1 << 3),					/* intsGppMaskHigh */
++	RD_88F6192A_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	rd88f6192AInfoBoardDeCsInfo,
++	RD_88F6192A_BOARD_TWSI_DEF_NUM,			/* numBoardTwsiDev */
++	NULL,
++	RD_88F6192A_BOARD_MAC_INFO_NUM,			/* numBoardMacInfo */
++	rd88f6192AInfoBoardMacInfo,
++	RD_88F6192A_BOARD_GPP_INFO_NUM,			/* numBoardGppInfo */
++	rd88f6192AInfoBoardGppInfo,
++	RD_88F6192A_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	rd88f6192AInfoBoardDebugLedIf,
++	0,										/* ledsPolarity */
++	RD_88F6192A_OE_LOW,				/* gppOutEnLow */
++	RD_88F6192A_OE_HIGH,				/* gppOutEnHigh */
++	RD_88F6192A_OE_VAL_LOW,				/* gppOutValLow */
++	RD_88F6192A_OE_VAL_HIGH,				/* gppOutValHigh */
++	0,						/* gppPolarityValLow */
++	0,						/* gppPolarityValHigh */
++	NULL						/* pSwitchInfo */
++};
++
++MV_BOARD_INFO rd88f6190AInfo = {
++	"RD-88F6190A-NAS",				/* boardName[MAX_BOARD_NAME_LEN] */
++	RD_88F6192A_BOARD_MPP_GROUP_TYPE_NUM,		/* numBoardMppGroupType */
++	rd88f6192AInfoBoardMppTypeInfo,
++	RD_88F6192A_BOARD_MPP_CONFIG_NUM,		/* numBoardMppConfig */
++	rd88f6192AInfoBoardMppConfigValue,
++	0,						/* intsGppMaskLow */
++	(1 << 3),					/* intsGppMaskHigh */
++	RD_88F6192A_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	rd88f6192AInfoBoardDeCsInfo,
++	RD_88F6192A_BOARD_TWSI_DEF_NUM,			/* numBoardTwsiDev */
++	NULL,
++	RD_88F6192A_BOARD_MAC_INFO_NUM,			/* numBoardMacInfo */
++	rd88f6192AInfoBoardMacInfo,
++	RD_88F6192A_BOARD_GPP_INFO_NUM,			/* numBoardGppInfo */
++	rd88f6192AInfoBoardGppInfo,
++	RD_88F6192A_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	rd88f6192AInfoBoardDebugLedIf,
++	0,										/* ledsPolarity */
++	RD_88F6192A_OE_LOW,				/* gppOutEnLow */
++	RD_88F6192A_OE_HIGH,				/* gppOutEnHigh */
++	RD_88F6192A_OE_VAL_LOW,				/* gppOutValLow */
++	RD_88F6192A_OE_VAL_HIGH,				/* gppOutValHigh */
++	0,						/* gppPolarityValLow */
++	0,						/* gppPolarityValHigh */
++	NULL						/* pSwitchInfo */
++};
++
++#define DB_88F6180A_BOARD_PCI_IF_NUM		0x0
++#define DB_88F6180A_BOARD_TWSI_DEF_NUM		0x5
++#define DB_88F6180A_BOARD_MAC_INFO_NUM		0x1
++#define DB_88F6180A_BOARD_GPP_INFO_NUM		0x0
++#define DB_88F6180A_BOARD_MPP_GROUP_TYPE_NUM	0x2
++#define DB_88F6180A_BOARD_MPP_CONFIG_NUM		0x1
++#define DB_88F6180A_BOARD_DEVICE_CONFIG_NUM	    0x1
++#define DB_88F6180A_BOARD_DEBUG_LED_NUM		0x0
++
++MV_BOARD_TWSI_INFO	db88f6180AInfoBoardTwsiDev[] =
++	/* {{MV_BOARD_DEV_CLASS	devClass, MV_U8	twsiDevAddr, MV_U8 twsiDevAddrType}} */
++	{
++    {BOARD_DEV_TWSI_EXP, 0x20, ADDR7_BIT},
++    {BOARD_DEV_TWSI_EXP, 0x21, ADDR7_BIT},
++    {BOARD_DEV_TWSI_EXP, 0x27, ADDR7_BIT},
++	{BOARD_DEV_TWSI_SATR, 0x4C, ADDR7_BIT},
++	{BOARD_TWSI_AUDIO_DEC, 0x4A, ADDR7_BIT}
++	};
++
++MV_BOARD_MAC_INFO db88f6180AInfoBoardMacInfo[] =
++	/* {{MV_BOARD_MAC_SPEED	boardMacSpeed, MV_U8 boardEthSmiAddr}} */
++	{{BOARD_MAC_SPEED_AUTO, 0x8}
++	};
++
++MV_BOARD_GPP_INFO db88f6180AInfoBoardGppInfo[] =
++	/* {{MV_BOARD_GPP_CLASS	devClass, MV_U8	gppPinNum}} */
++	{
++	/* Muxed with TDM/Audio module via IOexpender
++	{BOARD_GPP_USB_VBUS, 6} */
++	};
++
++MV_BOARD_MPP_TYPE_INFO db88f6180AInfoBoardMppTypeInfo[] =
++	/* {{MV_BOARD_MPP_TYPE_CLASS	boardMppGroup1,
++		MV_BOARD_MPP_TYPE_CLASS	boardMppGroup2}} */
++	{{MV_BOARD_OTHER, MV_BOARD_AUTO}
++	};
++
++MV_DEV_CS_INFO db88f6180AInfoBoardDeCsInfo[] =
++		/*{deviceCS, params, devType, devWidth}*/
++#if defined(MV_NAND_BOOT)
++		 {{0, N_A, BOARD_DEV_NAND_FLASH, 8}};	   /* NAND DEV */
++#else
++		 {{1, N_A, BOARD_DEV_SPI_FLASH, 8}};	   /* SPI DEV */
++#endif
++
++MV_BOARD_MPP_INFO	db88f6180AInfoBoardMppConfigValue[] =
++	{{{
++	DB_88F6180A_MPP0_7,
++	DB_88F6180A_MPP8_15,
++    DB_88F6180A_MPP16_23,
++    DB_88F6180A_MPP24_31,
++    DB_88F6180A_MPP32_39,
++    DB_88F6180A_MPP40_44
++	}}};
++
++MV_BOARD_INFO db88f6180AInfo = {
++	"DB-88F6180A-BP",				/* boardName[MAX_BOARD_NAME_LEN] */
++	DB_88F6180A_BOARD_MPP_GROUP_TYPE_NUM,		/* numBoardMppGroupType */
++	db88f6180AInfoBoardMppTypeInfo,
++	DB_88F6180A_BOARD_MPP_CONFIG_NUM,		/* numBoardMppConfig */
++	db88f6180AInfoBoardMppConfigValue,
++	0,						/* intsGppMaskLow */
++	0,					/* intsGppMaskHigh */
++	DB_88F6180A_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	db88f6180AInfoBoardDeCsInfo,
++	DB_88F6180A_BOARD_TWSI_DEF_NUM,			/* numBoardTwsiDev */
++	db88f6180AInfoBoardTwsiDev,
++	DB_88F6180A_BOARD_MAC_INFO_NUM,			/* numBoardMacInfo */
++	db88f6180AInfoBoardMacInfo,
++	DB_88F6180A_BOARD_GPP_INFO_NUM,			/* numBoardGppInfo */
++	NULL,
++	DB_88F6180A_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	NULL,
++	0,										/* ledsPolarity */
++	DB_88F6180A_OE_LOW,				/* gppOutEnLow */
++	DB_88F6180A_OE_HIGH,				/* gppOutEnHigh */
++	DB_88F6180A_OE_VAL_LOW,				/* gppOutValLow */
++	DB_88F6180A_OE_VAL_HIGH,				/* gppOutValHigh */
++	0,						/* gppPolarityValLow */
++	0,						/* gppPolarityValHigh */
++	NULL						/* pSwitchInfo */
++};
++
++
++#define RD_88F6281A_PCAC_BOARD_PCI_IF_NUM		0x0
++#define RD_88F6281A_PCAC_BOARD_TWSI_DEF_NUM		0x1
++#define RD_88F6281A_PCAC_BOARD_MAC_INFO_NUM		0x1
++#define RD_88F6281A_PCAC_BOARD_GPP_INFO_NUM		0x0
++#define RD_88F6281A_PCAC_BOARD_MPP_GROUP_TYPE_NUM	0x1
++#define RD_88F6281A_PCAC_BOARD_MPP_CONFIG_NUM		0x1
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++    #define RD_88F6281A_PCAC_BOARD_DEVICE_CONFIG_NUM	    0x1
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++    #define RD_88F6281A_PCAC_BOARD_DEVICE_CONFIG_NUM	    0x2
++#else
++    #define RD_88F6281A_PCAC_BOARD_DEVICE_CONFIG_NUM	    0x1
++#endif
++#define RD_88F6281A_PCAC_BOARD_DEBUG_LED_NUM		0x4
++
++MV_U8	rd88f6281APcacInfoBoardDebugLedIf[] =
++	{38, 39, 40, 41};
++
++MV_BOARD_MAC_INFO rd88f6281APcacInfoBoardMacInfo[] =
++	/* {{MV_BOARD_MAC_SPEED	boardMacSpeed, MV_U8 boardEthSmiAddr}} */
++	{{BOARD_MAC_SPEED_AUTO, 0x8}
++	};
++
++MV_BOARD_TWSI_INFO	rd88f6281APcacInfoBoardTwsiDev[] =
++	/* {{MV_BOARD_DEV_CLASS	devClass, MV_U8	twsiDevAddr, MV_U8 twsiDevAddrType}} */
++	{
++	{BOARD_TWSI_OTHER, 0xa7, ADDR7_BIT}
++	};
++
++MV_BOARD_MPP_TYPE_INFO rd88f6281APcacInfoBoardMppTypeInfo[] =
++	{{MV_BOARD_OTHER, MV_BOARD_OTHER}
++	};
++
++MV_DEV_CS_INFO rd88f6281APcacInfoBoardDeCsInfo[] =
++		/*{deviceCS, params, devType, devWidth}*/
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++		 {{0, N_A, BOARD_DEV_NAND_FLASH, 8}};	   /* NAND DEV */
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++		 {
++         {0, N_A, BOARD_DEV_NAND_FLASH, 8},	   /* NAND DEV */
++         {1, N_A, BOARD_DEV_SPI_FLASH, 8},	   /* SPI DEV */
++         };
++#else
++	 {{1, N_A, BOARD_DEV_SPI_FLASH, 8}};	   /* SPI DEV */
++#endif
++
++MV_BOARD_MPP_INFO	rd88f6281APcacInfoBoardMppConfigValue[] =
++	{{{
++	RD_88F6281A_PCAC_MPP0_7,
++	RD_88F6281A_PCAC_MPP8_15,
++	RD_88F6281A_PCAC_MPP16_23,
++	RD_88F6281A_PCAC_MPP24_31,
++	RD_88F6281A_PCAC_MPP32_39,
++	RD_88F6281A_PCAC_MPP40_47,
++	RD_88F6281A_PCAC_MPP48_55
++	}}};
++
++MV_BOARD_INFO rd88f6281APcacInfo = {
++	"RD-88F6281A-PCAC",				/* boardName[MAX_BOARD_NAME_LEN] */
++	RD_88F6281A_PCAC_BOARD_MPP_GROUP_TYPE_NUM,	/* numBoardMppGroupType */
++	rd88f6281APcacInfoBoardMppTypeInfo,
++	RD_88F6281A_PCAC_BOARD_MPP_CONFIG_NUM,		/* numBoardMppConfig */
++	rd88f6281APcacInfoBoardMppConfigValue,
++	0,						/* intsGppMaskLow */
++	(1 << 3),					/* intsGppMaskHigh */
++	RD_88F6281A_PCAC_BOARD_DEVICE_CONFIG_NUM,	/* numBoardDevIf */
++	rd88f6281APcacInfoBoardDeCsInfo,
++	RD_88F6281A_PCAC_BOARD_TWSI_DEF_NUM,		/* numBoardTwsiDev */
++	rd88f6281APcacInfoBoardTwsiDev,
++	RD_88F6281A_PCAC_BOARD_MAC_INFO_NUM,		/* numBoardMacInfo */
++	rd88f6281APcacInfoBoardMacInfo,
++	RD_88F6281A_PCAC_BOARD_GPP_INFO_NUM,		/* numBoardGppInfo */
++	0,
++	RD_88F6281A_PCAC_BOARD_DEBUG_LED_NUM,		/* activeLedsNumber */
++	NULL,
++	0,										/* ledsPolarity */
++	RD_88F6281A_PCAC_OE_LOW,			/* gppOutEnLow */
++	RD_88F6281A_PCAC_OE_HIGH,			/* gppOutEnHigh */
++	RD_88F6281A_PCAC_OE_VAL_LOW,			/* gppOutValLow */
++	RD_88F6281A_PCAC_OE_VAL_HIGH,			/* gppOutValHigh */
++	0,						/* gppPolarityValLow */
++	0,						/* gppPolarityValHigh */
++	NULL						/* pSwitchInfo */
++};
++
++
++/* 6281 Sheeva Plug*/
++
++#define SHEEVA_PLUG_BOARD_PCI_IF_NUM		        0x0
++#define SHEEVA_PLUG_BOARD_TWSI_DEF_NUM		        0x0
++#define SHEEVA_PLUG_BOARD_MAC_INFO_NUM		        0x1
++#define SHEEVA_PLUG_BOARD_GPP_INFO_NUM		        0x0
++#define SHEEVA_PLUG_BOARD_MPP_GROUP_TYPE_NUN        0x1
++#define SHEEVA_PLUG_BOARD_MPP_CONFIG_NUM		    0x1
++#define SHEEVA_PLUG_BOARD_DEVICE_CONFIG_NUM	        0x1
++#define SHEEVA_PLUG_BOARD_DEBUG_LED_NUM		        0x1
++
++MV_U8	sheevaPlugInfoBoardDebugLedIf[] =
++	{49};
++
++MV_BOARD_MAC_INFO sheevaPlugInfoBoardMacInfo[] =
++    /* {{MV_BOARD_MAC_SPEED	boardMacSpeed,	MV_U8	boardEthSmiAddr}} */
++	{{BOARD_MAC_SPEED_AUTO, 0x0}};
++
++MV_BOARD_TWSI_INFO	sheevaPlugInfoBoardTwsiDev[] =
++	/* {{MV_BOARD_DEV_CLASS	devClass, MV_U8	twsiDevAddr, MV_U8 twsiDevAddrType}} */
++	{{BOARD_TWSI_OTHER, 0x0, ADDR7_BIT}};
++
++MV_BOARD_MPP_TYPE_INFO sheevaPlugInfoBoardMppTypeInfo[] =
++	{{MV_BOARD_OTHER, MV_BOARD_OTHER}
++	};
++
++MV_DEV_CS_INFO sheevaPlugInfoBoardDeCsInfo[] =
++		/*{deviceCS, params, devType, devWidth}*/
++		 {{0, N_A, BOARD_DEV_NAND_FLASH, 8}};	   /* NAND DEV */
++
++MV_BOARD_MPP_INFO	sheevaPlugInfoBoardMppConfigValue[] =
++	{{{
++	RD_SHEEVA_PLUG_MPP0_7,
++	RD_SHEEVA_PLUG_MPP8_15,
++	RD_SHEEVA_PLUG_MPP16_23,
++	RD_SHEEVA_PLUG_MPP24_31,
++	RD_SHEEVA_PLUG_MPP32_39,
++	RD_SHEEVA_PLUG_MPP40_47,
++	RD_SHEEVA_PLUG_MPP48_55
++	}}};
++
++MV_BOARD_INFO sheevaPlugInfo = {
++	"SHEEVA PLUG",				                /* boardName[MAX_BOARD_NAME_LEN] */
++	SHEEVA_PLUG_BOARD_MPP_GROUP_TYPE_NUN,		/* numBoardMppGroupType */
++	sheevaPlugInfoBoardMppTypeInfo,
++	SHEEVA_PLUG_BOARD_MPP_CONFIG_NUM,		    /* numBoardMppConfig */
++	sheevaPlugInfoBoardMppConfigValue,
++	0,						                    /* intsGppMaskLow */
++	0,					                        /* intsGppMaskHigh */
++	SHEEVA_PLUG_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	sheevaPlugInfoBoardDeCsInfo,
++	SHEEVA_PLUG_BOARD_TWSI_DEF_NUM,			    /* numBoardTwsiDev */
++	sheevaPlugInfoBoardTwsiDev,
++	SHEEVA_PLUG_BOARD_MAC_INFO_NUM,			    /* numBoardMacInfo */
++	sheevaPlugInfoBoardMacInfo,
++	SHEEVA_PLUG_BOARD_GPP_INFO_NUM,			    /* numBoardGppInfo */
++	0,
++	SHEEVA_PLUG_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	sheevaPlugInfoBoardDebugLedIf,
++	0,										/* ledsPolarity */
++	RD_SHEEVA_PLUG_OE_LOW,				            /* gppOutEnLow */
++	RD_SHEEVA_PLUG_OE_HIGH,				        /* gppOutEnHigh */
++	RD_SHEEVA_PLUG_OE_VAL_LOW,				        /* gppOutValLow */
++	RD_SHEEVA_PLUG_OE_VAL_HIGH,				    /* gppOutValHigh */
++	0,						                    /* gppPolarityValLow */
++	0,						                    /* gppPolarityValHigh */
++    NULL										/* pSwitchInfo */
++};
++
++/* Customer specific 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
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++    #define DB_CUSTOMER_BOARD_DEVICE_CONFIG_NUM	    0x0
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++    #define DB_CUSTOMER_BOARD_DEVICE_CONFIG_NUM	    0x0
++#else
++    #define DB_CUSTOMER_BOARD_DEVICE_CONFIG_NUM	    0x0
++#endif
++#define DB_CUSTOMER_BOARD_DEBUG_LED_NUM		0x0
++
++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}
++	};
++
++MV_DEV_CS_INFO dbCustomerInfoBoardDeCsInfo[] =
++		/*{deviceCS, params, devType, devWidth}*/
++#if defined(MV_NAND) && defined(MV_NAND_BOOT)
++		 {{0, N_A, BOARD_DEV_NAND_FLASH, 8}};	   /* NAND DEV */
++#elif defined(MV_NAND) && defined(MV_SPI_BOOT)
++		 {
++         {0, N_A, BOARD_DEV_NAND_FLASH, 8},	   /* NAND DEV */
++         {2, N_A, BOARD_DEV_SPI_FLASH, 8},	   /* SPI DEV */
++         };
++#else
++		 {{2, N_A, BOARD_DEV_SPI_FLASH, 8}};	   /* SPI DEV */
++#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 = {
++	"DB-CUSTOMER",				                /* boardName[MAX_BOARD_NAME_LEN] */
++	DB_CUSTOMER_BOARD_MPP_GROUP_TYPE_NUN,		/* numBoardMppGroupType */
++	dbCustomerInfoBoardMppTypeInfo,
++	DB_CUSTOMER_BOARD_MPP_CONFIG_NUM,		    /* numBoardMppConfig */
++	dbCustomerInfoBoardMppConfigValue,
++	0,						                    /* intsGppMaskLow */
++	0,					                        /* intsGppMaskHigh */
++	DB_CUSTOMER_BOARD_DEVICE_CONFIG_NUM,		/* numBoardDevIf */
++	dbCustomerInfoBoardDeCsInfo,
++	DB_CUSTOMER_BOARD_TWSI_DEF_NUM,			    /* numBoardTwsiDev */
++	dbCustomerInfoBoardTwsiDev,
++	DB_CUSTOMER_BOARD_MAC_INFO_NUM,			    /* numBoardMacInfo */
++	dbCustomerInfoBoardMacInfo,
++	DB_CUSTOMER_BOARD_GPP_INFO_NUM,			    /* numBoardGppInfo */
++	0,
++	DB_CUSTOMER_BOARD_DEBUG_LED_NUM,			/* activeLedsNumber */
++	NULL,
++	0,										/* ledsPolarity */
++	DB_CUSTOMER_OE_LOW,				            /* gppOutEnLow */
++	DB_CUSTOMER_OE_HIGH,				        /* gppOutEnHigh */
++	DB_CUSTOMER_OE_VAL_LOW,				        /* gppOutValLow */
++	DB_CUSTOMER_OE_VAL_HIGH,				    /* gppOutValHigh */
++	0,						                    /* gppPolarityValLow */
++	0,						                    /* gppPolarityValHigh */
++    NULL										/* pSwitchInfo */
++};
++
++MV_BOARD_INFO*	boardInfoTbl[] =	{
++                    &db88f6281AInfo,
++                    &rd88f6281AInfo,
++                    &db88f6192AInfo,
++                    &rd88f6192AInfo,
++                    &db88f6180AInfo,
++                    &db88f6190AInfo,
++                    &rd88f6190AInfo,
++                    &rd88f6281APcacInfo,
++                    &dbCustomerInfo,
++                    &sheevaPlugInfo
++					};
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.h b/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.h
+new file mode 100644
+index 0000000..0372eee
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.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 __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
++
++/* 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_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
++
++/* Board specific */
++/* =============================== */
++
++/* boards ID numbers */
++
++#define BOARD_ID_BASE				0x0
++
++/* New board ID numbers */
++#define DB_88F6281A_BP_ID			(BOARD_ID_BASE)
++#define DB_88F6281_BP_MLL_ID        1680
++#define RD_88F6281A_ID				(BOARD_ID_BASE+0x1)
++#define RD_88F6281_MLL_ID			1682
++#define DB_88F6192A_BP_ID			(BOARD_ID_BASE+0x2)
++#define RD_88F6192A_ID				(BOARD_ID_BASE+0x3)
++#define RD_88F6192_MLL_ID			1681
++#define DB_88F6180A_BP_ID			(BOARD_ID_BASE+0x4)
++#define DB_88F6190A_BP_ID			(BOARD_ID_BASE+0x5)
++#define RD_88F6190A_ID				(BOARD_ID_BASE+0x6)
++#define RD_88F6281A_PCAC_ID			(BOARD_ID_BASE+0x7)
++#define DB_CUSTOMER_ID			    (BOARD_ID_BASE+0x8)
++#define SHEEVA_PLUG_ID			    (BOARD_ID_BASE+0x9)
++#define MV_MAX_BOARD_ID			(SHEEVA_PLUG_ID + 1)
++
++/* DB-88F6281A-BP */
++#if defined(MV_NAND)
++    #define DB_88F6281A_MPP0_7				0x21111111
++#else
++    #define DB_88F6281A_MPP0_7				0x21112220
++#endif
++#define DB_88F6281A_MPP8_15			0x11113311
++#define DB_88F6281A_MPP16_23				0x00551111
++#define DB_88F6281A_MPP24_31				0x00000000
++#define DB_88F6281A_MPP32_39				0x00000000
++#define DB_88F6281A_MPP40_47				0x00000000
++#define DB_88F6281A_MPP48_55				0x00000000
++#define DB_88F6281A_OE_LOW                       0x0
++#if defined(MV_TDM_5CHANNELS)
++	#define DB_88F6281A_OE_HIGH		(BIT6)
++#else
++#define DB_88F6281A_OE_HIGH                      0x0
++#endif
++#define DB_88F6281A_OE_VAL_LOW                   0x0
++#define DB_88F6281A_OE_VAL_HIGH                  0x0
++
++/* RD-88F6281A */
++#if defined(MV_NAND)
++    #define RD_88F6281A_MPP0_7				0x21111111
++#else
++    #define RD_88F6281A_MPP0_7				0x21112220
++#endif
++#define RD_88F6281A_MPP8_15			0x11113311
++#define RD_88F6281A_MPP16_23				0x33331111
++#define RD_88F6281A_MPP24_31				0x33003333
++#define RD_88F6281A_MPP32_39				0x20440533
++#define RD_88F6281A_MPP40_47				0x22202222
++#define RD_88F6281A_MPP48_55				0x00000002
++#define RD_88F6281A_OE_LOW                      (BIT28 | BIT29)
++#define RD_88F6281A_OE_HIGH                     (BIT3 | BIT6 | BIT17)
++#define RD_88F6281A_OE_VAL_LOW                   0x0
++#define RD_88F6281A_OE_VAL_HIGH                  0x0
++
++/* DB-88F6192A-BP */
++#if defined(MV_NAND)
++    #define DB_88F6192A_MPP0_7				0x21111111
++#else
++    #define DB_88F6192A_MPP0_7				0x21112220
++#endif
++#define DB_88F6192A_MPP8_15			0x11113311
++#define DB_88F6192A_MPP16_23				0x00501111
++#define DB_88F6192A_MPP24_31				0x00000000
++#define DB_88F6192A_MPP32_35				0x00000000
++#define DB_88F6192A_OE_LOW                       (BIT22 | BIT23)
++#define DB_88F6192A_OE_HIGH                      0x0
++#define DB_88F6192A_OE_VAL_LOW                   0x0
++#define DB_88F6192A_OE_VAL_HIGH                  0x0
++
++/* RD-88F6192A */
++#define RD_88F6192A_MPP0_7			0x01222222
++#define RD_88F6192A_MPP8_15			0x00000011
++#define RD_88F6192A_MPP16_23				0x05550000
++#define RD_88F6192A_MPP24_31				0x0
++#define RD_88F6192A_MPP32_35				0x0
++#define RD_88F6192A_OE_LOW                      (BIT11 | BIT14 | BIT24 | BIT25 | BIT26 | BIT27 | BIT30 | BIT31)
++#define RD_88F6192A_OE_HIGH                     (BIT0 | BIT2)
++#define RD_88F6192A_OE_VAL_LOW                  0x18400
++#define RD_88F6192A_OE_VAL_HIGH                 0x8
++
++/* DB-88F6180A-BP */
++#if defined(MV_NAND)
++    #define DB_88F6180A_MPP0_7				0x21111111
++#else
++    #define DB_88F6180A_MPP0_7				0x01112222
++#endif
++#define DB_88F6180A_MPP8_15			0x11113311
++#define DB_88F6180A_MPP16_23				0x00001111
++#define DB_88F6180A_MPP24_31				0x0
++#define DB_88F6180A_MPP32_39				0x4444c000
++#define DB_88F6180A_MPP40_44				0x00044444
++#define DB_88F6180A_OE_LOW                       0x0
++#define DB_88F6180A_OE_HIGH                      0x0
++#define DB_88F6180A_OE_VAL_LOW                   0x0
++#define DB_88F6180A_OE_VAL_HIGH                  0x0
++
++/* RD-88F6281A_PCAC */
++#define RD_88F6281A_PCAC_MPP0_7			0x21111111
++#define RD_88F6281A_PCAC_MPP8_15			0x00003311
++#define RD_88F6281A_PCAC_MPP16_23			0x00001100
++#define RD_88F6281A_PCAC_MPP24_31			0x00000000
++#define RD_88F6281A_PCAC_MPP32_39			0x00000000
++#define RD_88F6281A_PCAC_MPP40_47			0x00000000
++#define RD_88F6281A_PCAC_MPP48_55			0x00000000
++#define RD_88F6281A_PCAC_OE_LOW                 0x0
++#define RD_88F6281A_PCAC_OE_HIGH                0x0
++#define RD_88F6281A_PCAC_OE_VAL_LOW             0x0
++#define RD_88F6281A_PCAC_OE_VAL_HIGH            0x0
++
++/* SHEEVA PLUG */
++#define RD_SHEEVA_PLUG_MPP0_7                   0x01111111
++#define RD_SHEEVA_PLUG_MPP8_15                  0x11113322
++#define RD_SHEEVA_PLUG_MPP16_23                 0x00001111
++#define RD_SHEEVA_PLUG_MPP24_31                 0x00100000
++#define RD_SHEEVA_PLUG_MPP32_39                 0x00000000
++#define RD_SHEEVA_PLUG_MPP40_47                 0x00000000
++#define RD_SHEEVA_PLUG_MPP48_55                 0x00000000
++#define RD_SHEEVA_PLUG_OE_LOW                   0x0
++#define RD_SHEEVA_PLUG_OE_HIGH                  0x0
++#define RD_SHEEVA_PLUG_OE_VAL_LOW               (BIT29)
++#define RD_SHEEVA_PLUG_OE_VAL_HIGH              ((~(BIT17 | BIT16 | BIT15)) | BIT14)
++
++/* 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
++
++#endif /* __INCmvBoardEnvSpech */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.c b/crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.c
+new file mode 100644
+index 0000000..fed0fa1
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.c
+@@ -0,0 +1,320 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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"
++
++/* defines  */
++#ifdef MV_DEBUG
++	#define DB(x)	x
++#else
++	#define DB(x)
++#endif
++
++/* locals */
++
++/*******************************************************************************
++* 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.
++*
++*******************************************************************************/
++/* 6180 have different clk reset sampling */
++
++static MV_U32 mvCpu6180PclkGet(MV_VOID)
++{
++	MV_U32	tmpPClkRate=0;
++	MV_CPU_ARM_CLK cpu6180_ddr_l2_CLK[] = MV_CPU6180_DDR_L2_CLCK_TBL;
++
++	tmpPClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++	tmpPClkRate = tmpPClkRate & MSAR_CPUCLCK_MASK_6180;
++	tmpPClkRate = tmpPClkRate >> MSAR_CPUCLCK_OFFS_6180;
++
++	tmpPClkRate = cpu6180_ddr_l2_CLK[tmpPClkRate].cpuClk;
++
++	return tmpPClkRate;
++}
++
++
++MV_U32 mvCpuPclkGet(MV_VOID)
++{
++#if defined(PCLCK_AUTO_DETECT)
++	MV_U32	tmpPClkRate=0;
++	MV_U32 cpuCLK[] = MV_CPU_CLCK_TBL;
++
++	if(mvCtrlModelGet() == MV_6180_DEV_ID)
++		return mvCpu6180PclkGet();
++
++	tmpPClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++	tmpPClkRate = MSAR_CPUCLCK_EXTRACT(tmpPClkRate);
++	tmpPClkRate = cpuCLK[tmpPClkRate];
++
++	return tmpPClkRate;
++#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.
++*
++*******************************************************************************/
++static MV_U32  mvCpu6180L2ClkGet(MV_VOID)
++{
++	MV_U32	L2ClkRate=0;
++	MV_CPU_ARM_CLK _cpu6180_ddr_l2_CLK[] = MV_CPU6180_DDR_L2_CLCK_TBL;
++
++	L2ClkRate = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++	L2ClkRate = L2ClkRate & MSAR_CPUCLCK_MASK_6180;
++	L2ClkRate = L2ClkRate >> MSAR_CPUCLCK_OFFS_6180;
++
++	L2ClkRate = _cpu6180_ddr_l2_CLK[L2ClkRate].l2Clk;
++
++	return L2ClkRate;
++
++}
++
++MV_U32  mvCpuL2ClkGet(MV_VOID)
++{
++#ifdef L2CLK_AUTO_DETECT
++	MV_U32 L2ClkRate, tmp, pClkRate, indexL2Rtio;
++	MV_U32 L2Rtio[][2] = MV_L2_CLCK_RTIO_TBL;
++
++	if(mvCtrlModelGet() == MV_6180_DEV_ID)
++		return mvCpu6180L2ClkGet();
++
++	pClkRate = mvCpuPclkGet();
++
++	tmp = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++	indexL2Rtio = MSAR_L2CLCK_EXTRACT(tmp);
++
++	L2ClkRate = ((pClkRate * L2Rtio[indexL2Rtio][1]) / L2Rtio[indexL2Rtio][0]);
++
++	return L2ClkRate;
++#else
++	return MV_BOARD_DEFAULT_L2CLK;
++#endif
++}
++
++
++/*******************************************************************************
++* 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];
++
++  mvCpuIfGetL2Mode(L2_En_str);
++  mvCpuIfGetL2EccMode(L2_ECC_str);
++  mvCpuIfGetL2PrefetchMode(L2_Prefetch_str);
++  mvCpuIfGetWriteAllocMode(Write_Alloc_str);
++  mvCpuIfGetCpuStreamMode(Cpu_Stream_str);
++  mvCpuIfPrintCpuRegs();
++
++  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);
++  return count;
++}
++
++MV_U32 whoAmI(MV_VOID)
++{
++	return 0;
++}
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.h b/crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.h
+new file mode 100644
+index 0000000..7f58b03
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_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"
++
++/* 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	      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_U32 mvCpuIfPrintSystemConfig(MV_8 *buffer, MV_U32 index);
++MV_U32 whoAmI(MV_VOID);
++
++#endif /* MV_ASMLANGUAGE */
++
++
++#endif /* __INCmvCpuh */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c
+new file mode 100644
+index 0000000..fbe7c56
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c
+@@ -0,0 +1,296 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "ctrlEnv/mvCtrlEnvAddrDec.h"
++#include "ctrlEnv/sys/mvAhbToMbusRegs.h"
++#include "ddr2/mvDramIfRegs.h"
++#include "pex/mvPexRegs.h"
++
++#define 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;
++/* Dram\AHBToMbus\PEX share regsiter */
++
++#define CTRL_DEC_BASE_OFFS		16
++#define CTRL_DEC_BASE_MASK		(0xffff << CTRL_DEC_BASE_OFFS)
++#define CTRL_DEC_BASE_ALIGNMENT	0x10000
++
++#define CTRL_DEC_SIZE_OFFS		16
++#define CTRL_DEC_SIZE_MASK		(0xffff << CTRL_DEC_SIZE_OFFS)
++#define CTRL_DEC_SIZE_ALIGNMENT	0x10000
++
++#define CTRL_DEC_WIN_EN			BIT0
++
++
++
++/*******************************************************************************
++* mvCtrlAddrDecToReg - Get address decode register format values
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*
++* RETURN:
++*
++*******************************************************************************/
++MV_STATUS mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin, MV_DEC_REGS *pAddrDecRegs)
++{
++
++	MV_U32 baseToReg=0 , sizeToReg=0;
++
++	/* BaseLow[31:16] => base register [31:16]		*/
++	baseToReg = pAddrDecWin->baseLow & CTRL_DEC_BASE_MASK;
++
++	/* Write to address decode Base Address Register                  */
++	pAddrDecRegs->baseReg &= ~CTRL_DEC_BASE_MASK;
++	pAddrDecRegs->baseReg |= baseToReg;
++
++	/* Get size register value according to window size						*/
++	sizeToReg = ctrlSizeToReg(pAddrDecWin->size, CTRL_DEC_SIZE_ALIGNMENT);
++
++	/* Size parameter validity check.                                   */
++	if (-1 == sizeToReg)
++	{
++		return MV_BAD_PARAM;
++	}
++
++	/* set size */
++	pAddrDecRegs->sizeReg &= ~CTRL_DEC_SIZE_MASK;
++	pAddrDecRegs->sizeReg |= (sizeToReg << CTRL_DEC_SIZE_OFFS);
++
++
++	return MV_OK;
++
++}
++
++/*******************************************************************************
++* mvCtrlRegToAddrDec - Extract address decode struct from registers.
++*
++* DESCRIPTION:
++*       This function extract address decode struct from address decode
++*       registers given as parameters.
++*
++* INPUT:
++*       pAddrDecRegs - Address decode register struct.
++*
++* OUTPUT:
++*       pAddrDecWin - Target window data structure.
++*
++* RETURN:
++*		MV_BAD_PARAM if address decode registers data is invalid.
++*
++*******************************************************************************/
++MV_STATUS mvCtrlRegToAddrDec(MV_DEC_REGS *pAddrDecRegs, MV_ADDR_WIN *pAddrDecWin)
++{
++	MV_U32 sizeRegVal;
++
++	sizeRegVal = (pAddrDecRegs->sizeReg & CTRL_DEC_SIZE_MASK) >>
++					CTRL_DEC_SIZE_OFFS;
++
++	pAddrDecWin->size = ctrlRegToSize(sizeRegVal, CTRL_DEC_SIZE_ALIGNMENT);
++
++
++	/* Extract base address						*/
++	/* Base register [31:16] ==> baseLow[31:16]		*/
++	pAddrDecWin->baseLow = pAddrDecRegs->baseReg & CTRL_DEC_BASE_MASK;
++
++	pAddrDecWin->baseHigh =  0;
++
++	return MV_OK;
++
++}
++
++/*******************************************************************************
++* mvCtrlAttribGet -
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*
++* RETURN:
++*
++*******************************************************************************/
++
++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:
++*
++*******************************************************************************/
++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;
++}
++
++MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin,
++                                MV_DEC_WIN_PARAMS *pWinParam)
++{
++	MV_U32 baseToReg=0, sizeToReg=0;
++
++	/* BaseLow[31:16] => base register [31:16]		*/
++	baseToReg = pAddrDecWin->addrWin.baseLow & CTRL_DEC_BASE_MASK;
++
++	/* Write to address decode Base Address Register                  */
++	pWinParam->baseAddr &= ~CTRL_DEC_BASE_MASK;
++	pWinParam->baseAddr |= baseToReg;
++
++	/* Get size register value according to window size						*/
++	sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, CTRL_DEC_SIZE_ALIGNMENT);
++
++	/* Size parameter validity check.                                   */
++	if (-1 == sizeToReg)
++	{
++        mvOsPrintf("mvCtrlAddrDecToParams: ERR. ctrlSizeToReg failed.\n");
++		return MV_BAD_PARAM;
++	}
++    pWinParam->size = sizeToReg;
++
++    pWinParam->attrib   = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(pAddrDecWin->target)].attrib;
++    pWinParam->targetId = mvTargetDefaultsArray[MV_CHANGE_BOOT_CS(pAddrDecWin->target)].targetId;
++
++    return MV_OK;
++}
++
++MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam,
++                                MV_DEC_WIN *pAddrDecWin)
++{
++    MV_TARGET_ATTRIB    targetAttrib;
++
++    pAddrDecWin->addrWin.baseLow = pWinParam->baseAddr;
++
++	/* Upper 32bit address base is supported under PCI High Address remap */
++	pAddrDecWin->addrWin.baseHigh = 0;
++
++	/* Prepare sizeReg to ctrlRegToSize function */
++    pAddrDecWin->addrWin.size = ctrlRegToSize(pWinParam->size, CTRL_DEC_SIZE_ALIGNMENT);
++
++	if (-1 == pAddrDecWin->addrWin.size)
++	{
++		DB(mvOsPrintf("mvCtrlParamsToAddrDec: ERR. ctrlRegToSize failed.\n"));
++		return MV_BAD_PARAM;
++	}
++    targetAttrib.targetId = pWinParam->targetId;
++    targetAttrib.attrib = pWinParam->attrib;
++
++    pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++    return MV_OK;
++}
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h
+new file mode 100644
+index 0000000..946737f
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h
+@@ -0,0 +1,203 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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
++
++/* 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 _mvDecRegs
++{
++	MV_U32 baseReg;
++    MV_U32 baseRegHigh;
++    MV_U32 sizeReg;
++
++}MV_DEC_REGS;
++
++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 mvCtrlAddrDecToReg(MV_ADDR_WIN *pAddrDecWin,
++							 MV_DEC_REGS *pAddrDecRegs);
++
++MV_STATUS mvCtrlRegToAddrDec(MV_DEC_REGS *pAddrDecRegs,
++							 MV_ADDR_WIN *pAddrDecWin);
++
++MV_STATUS mvCtrlAttribGet(MV_TARGET target,
++						  MV_TARGET_ATTRIB *targetAttrib);
++
++MV_TARGET mvCtrlTargetGet(MV_TARGET_ATTRIB *targetAttrib);
++
++
++MV_STATUS mvCtrlAddrDecToParams(MV_DEC_WIN *pAddrDecWin,
++                                MV_DEC_WIN_PARAMS *pWinParam);
++
++MV_STATUS mvCtrlParamsToAddrDec(MV_DEC_WIN_PARAMS *pWinParam,
++                                MV_DEC_WIN *pAddrDecWin);
++
++
++
++
++#endif /* __INCmvCtrlEnvAddrDech */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAsm.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAsm.h
+new file mode 100644
+index 0000000..6f6367a
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAsm.h
+@@ -0,0 +1,98 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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					0x10034
++#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/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.c
+new file mode 100644
+index 0000000..adf451d
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.c
+@@ -0,0 +1,1825 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "mvCtrlEnvLib.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++#if defined(MV_INCLUDE_PEX)
++#include "pex/mvPex.h"
++#include "ctrlEnv/sys/mvSysPex.h"
++#endif
++
++#if defined(MV_INCLUDE_GIG_ETH)
++#include "ctrlEnv/sys/mvSysGbe.h"
++#endif
++
++#if defined(MV_INCLUDE_XOR)
++#include "ctrlEnv/sys/mvSysXor.h"
++#endif
++
++#if defined(MV_INCLUDE_SATA)
++#include "ctrlEnv/sys/mvSysSata.h"
++#endif
++
++#if defined(MV_INCLUDE_USB)
++#include "ctrlEnv/sys/mvSysUsb.h"
++#endif
++
++#if defined(MV_INCLUDE_AUDIO)
++#include "ctrlEnv/sys/mvSysAudio.h"
++#endif
++
++#if defined(MV_INCLUDE_CESA)
++#include "ctrlEnv/sys/mvSysCesa.h"
++#endif
++
++#if defined(MV_INCLUDE_TS)
++#include "ctrlEnv/sys/mvSysTs.h"
++#endif
++
++/* defines  */
++#ifdef MV_DEBUG
++	#define DB(x)	x
++#else
++	#define DB(x)
++#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 maxMppGrp = 1;
++	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;
++
++	devId = mvCtrlModelGet();
++	boardId= mvBoardIdGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			maxMppGrp = MV_6281_MPP_MAX_GROUP;
++			break;
++		case MV_6192_DEV_ID:
++			maxMppGrp = MV_6192_MPP_MAX_GROUP;
++			break;
++        case MV_6190_DEV_ID:
++            maxMppGrp = MV_6190_MPP_MAX_GROUP;
++            break;
++		case MV_6180_DEV_ID:
++			maxMppGrp = MV_6180_MPP_MAX_GROUP;
++			break;
++	}
++
++	/* MPP Init */
++	/* We split mpp init to 3 phases:
++	 * 1. We init mpp[19:0] from the board info. mpp[23:20] will be over write
++	 * 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[19: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 (mvCtrlIsBootFromSPI())
++		    {
++			mppVal &= ~0xffff;
++			bootVal &= 0xffff;
++			mppVal |= bootVal;
++		    }
++		    else if (mvCtrlIsBootFromSPIUseNAND())
++		    {
++			mppVal &= ~0xf0000000;
++			bootVal &= 0xf0000000;
++			mppVal |= bootVal;
++		    }
++		    else if (mvCtrlIsBootFromNAND())
++		    {
++			mppVal &= ~0xffffff;
++			bootVal &= 0xffffff;
++			mppVal |= bootVal;
++		    }
++		}
++
++		if (mppGroup == 2)
++		{
++		    bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
++		    if (mvCtrlIsBootFromNAND())
++		    {
++			mppVal &= ~0xff00;
++			bootVal &= 0xff00;
++			mppVal |= bootVal;
++		    }
++		}
++
++		MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal);
++	}
++
++	/* Identify MPPs group */
++	mvBoardMppGroupIdUpdate();
++
++	/* Update MPPs mux relevent only on Marvell DB */
++	if ((boardId == DB_88F6281A_BP_ID) ||
++		(boardId == DB_88F6180A_BP_ID))
++		mvBoardMppMuxSet();
++
++	mppGroupType = mvBoardMppGroupTypeGet(MV_BOARD_MPP_GROUP_1);
++
++	/* Mpp phase 2 */
++	/* Read MPP group from board level and assign to MPP register */
++    if (devId != MV_6180_DEV_ID)
++    {
++        i = 0;
++	for (mppGroup = 2; mppGroup < 5; mppGroup++)
++	{
++		if ((mppGroupType == MV_BOARD_OTHER) ||
++			(boardId == RD_88F6281A_ID) ||
++			(boardId == RD_88F6192A_ID) ||
++                (boardId == RD_88F6190A_ID) ||
++                (boardId == RD_88F6281A_PCAC_ID) ||
++                (boardId == SHEEVA_PLUG_ID))
++			mppVal = mvBoardMppGet(mppGroup);
++		else
++		{
++			mppVal = mppGroup1[mppGroupType][i];
++			i++;
++		}
++
++		/* Group 2 is shared mpp[23:16] */
++		if (mppGroup == 2)
++		{
++                bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
++			mppVal &= ~0xffff;
++			bootVal &= 0xffff;
++			mppVal |= bootVal;
++		}
++
++		MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal);
++	}
++    }
++
++	if ((devId == MV_6192_DEV_ID) || (devId == MV_6190_DEV_ID))
++		return MV_OK;
++
++	/* Mpp phase 3 */
++	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) ||
++			(boardId == RD_88F6281A_ID) ||
++            (boardId == RD_88F6281A_PCAC_ID) ||
++            (boardId == SHEEVA_PLUG_ID))
++			mppVal = mvBoardMppGet(mppGroup);
++		else
++		{
++			mppVal = mppGroup2[mppGroupType][i];
++			i++;
++		}
++
++		/* Group 4 is shared mpp[35:32] */
++		if (mppGroup == 4)
++		{
++            bootVal = MV_REG_READ(mvCtrlMppRegGet(mppGroup));
++			mppVal &= ~0xffff;
++			bootVal &= 0xffff;
++			mppVal |= bootVal;
++		}
++
++		MV_REG_WRITE(mvCtrlMppRegGet(mppGroup), mppVal);
++	}
++    /* Update SSCG configuration register*/
++    if(mvBoardIdGet() == DB_88F6281A_BP_ID || mvBoardIdGet() == DB_88F6192A_BP_ID ||
++       mvBoardIdGet() == DB_88F6190A_BP_ID || mvBoardIdGet() == DB_88F6180A_BP_ID)
++        MV_REG_WRITE(0x100d8, 0x53);
++
++	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;
++
++        switch(mppGroup){
++                case (0):       ret = MPP_CONTROL_REG0;
++                                break;
++                case (1):       ret = MPP_CONTROL_REG1;
++                                break;
++                case (2):       ret = MPP_CONTROL_REG2;
++                                break;
++                case (3):       ret = MPP_CONTROL_REG3;
++                                break;
++                case (4):       ret = MPP_CONTROL_REG4;
++                                break;
++                case (5):       ret = MPP_CONTROL_REG5;
++                                break;
++                case (6):       ret = MPP_CONTROL_REG6;
++                                break;
++                default:        ret = MPP_CONTROL_REG0;
++                                break;
++        }
++        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)
++{
++
++	return MV_PEX_MAX_IF;
++}
++#endif
++
++#if defined(MV_INCLUDE_GIG_ETH)
++/*******************************************************************************
++* 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 devId;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			return MV_6281_ETH_MAX_PORTS;
++			break;
++		case MV_6192_DEV_ID:
++			return MV_6192_ETH_MAX_PORTS;
++			break;
++        case MV_6190_DEV_ID:
++            return MV_6190_ETH_MAX_PORTS;
++            break;
++		case MV_6180_DEV_ID:
++			return MV_6180_ETH_MAX_PORTS;
++			break;
++	}
++	return 0;
++
++}
++#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)
++{
++	return MV_XOR_MAX_CHAN;
++}
++#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)
++{
++	return MV_USB_MAX_PORTS;
++}
++#endif
++
++
++#if defined(MV_INCLUDE_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)
++{
++	MV_U32 devId;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			return MV_6281_NAND;
++			break;
++		case MV_6192_DEV_ID:
++			return MV_6192_NAND;
++			break;
++        case MV_6190_DEV_ID:
++            return MV_6190_NAND;
++            break;
++		case MV_6180_DEV_ID:
++			return MV_6180_NAND;
++			break;
++	}
++	return 0;
++
++}
++#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;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			return MV_6281_SDIO;
++			break;
++		case MV_6192_DEV_ID:
++			return MV_6192_SDIO;
++			break;
++        case MV_6190_DEV_ID:
++            return MV_6190_SDIO;
++            break;
++		case MV_6180_DEV_ID:
++			return MV_6180_SDIO;
++			break;
++	}
++	return 0;
++
++}
++#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)
++{
++	MV_U32 devId;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			return MV_6281_TS;
++			break;
++		case MV_6192_DEV_ID:
++			return MV_6192_TS;
++			break;
++        case MV_6190_DEV_ID:
++            return MV_6190_TS;
++            break;
++		case MV_6180_DEV_ID:
++			return MV_6180_TS;
++			break;
++	}
++	return 0;
++}
++#endif
++
++#if defined(MV_INCLUDE_AUDIO)
++/*******************************************************************************
++* mvCtrlAudioSupport - Return if this controller has integrated AUDIO flash support
++*
++* DESCRIPTION:
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       MV_TRUE if AUDIO is supported and MV_FALSE otherwise
++*
++*******************************************************************************/
++MV_U32	  mvCtrlAudioSupport(MV_VOID)
++{
++	MV_U32 devId;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			return MV_6281_AUDIO;
++			break;
++		case MV_6192_DEV_ID:
++			return MV_6192_AUDIO;
++			break;
++        case MV_6190_DEV_ID:
++            return MV_6190_AUDIO;
++            break;
++		case MV_6180_DEV_ID:
++			return MV_6180_AUDIO;
++			break;
++	}
++	return 0;
++
++}
++#endif
++
++#if defined(MV_INCLUDE_TDM)
++/*******************************************************************************
++* 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)
++{
++	MV_U32 devId;
++
++	devId = mvCtrlModelGet();
++
++	switch(devId){
++		case MV_6281_DEV_ID:
++			return MV_6281_TDM;
++			break;
++		case MV_6192_DEV_ID:
++			return MV_6192_TDM;
++			break;
++        case MV_6190_DEV_ID:
++            return MV_6190_TDM;
++            break;
++		case MV_6180_DEV_ID:
++			return MV_6180_TDM;
++			break;
++	}
++	return 0;
++
++}
++#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;
++
++	devId = MV_REG_READ(CHIP_BOND_REG);
++	devId &= PCKG_OPT_MASK;
++
++	switch(devId){
++		case 2:
++			return	MV_6281_DEV_ID;
++			break;
++    case 1:
++            if (((MV_REG_READ(PEX_CFG_DIRECT_ACCESS(0,PEX_DEVICE_AND_VENDOR_ID))& 0xffff0000) >> 16)
++                 == MV_6190_DEV_ID)
++                return	MV_6190_DEV_ID;
++            else
++                return	MV_6192_DEV_ID;
++			break;
++		case 0:
++			return	MV_6180_DEV_ID;
++			break;
++	}
++
++	return 0;
++}
++/*******************************************************************************
++* 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)
++	/* Check pex power state */
++	MV_U32 pexPower;
++	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_6281_A0_ID:
++                mvOsSPrintf (pNameBuff, "%s",MV_6281_A0_NAME);
++                break;
++        case MV_6192_A0_ID:
++                mvOsSPrintf (pNameBuff, "%s",MV_6192_A0_NAME);
++                break;
++        case MV_6180_A0_ID:
++                mvOsSPrintf (pNameBuff, "%s",MV_6180_A0_NAME);
++                break;
++        case MV_6190_A0_ID:
++                mvOsSPrintf (pNameBuff, "%s",MV_6190_A0_NAME);
++                break;
++        case MV_6281_A1_ID:
++                mvOsSPrintf (pNameBuff, "%s",MV_6281_A1_NAME);
++                break;
++        case MV_6192_A1_ID:
++                mvOsSPrintf (pNameBuff, "%s",MV_6192_A1_NAME);
++                break;
++        case MV_6180_A1_ID:
++                mvOsSPrintf (pNameBuff, "%s",MV_6180_A1_NAME);
++                break;
++        case MV_6190_A1_ID:
++                mvOsSPrintf (pNameBuff, "%s",MV_6190_A1_NAME);
++                break;
++        default:
++                mvCtrlNameGet(pNameBuff);
++                break;
++        }
++
++        return MV_OK;
++}
++
++
++/*******************************************************************************
++* ctrlWinOverlapTest - Test address windows for overlaping.
++*
++* 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 ctrlWinOverlapTest(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;
++    }
++}
++
++/*******************************************************************************
++* ctrlWinWithinWinTest - Test address windows for overlaping.
++*
++* 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 ctrlWinWithinWinTest(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;
++    }
++}
++
++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];
++}
++
++/*******************************************************************************
++* 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)
++	mvPexAddrDecShow();
++#endif
++#if defined(MV_INCLUDE_USB)
++	mvUsbAddrDecShow();
++#endif
++#if defined(MV_INCLUDE_GIG_ETH)
++	mvEthAddrDecShow();
++#endif
++#if defined(MV_INCLUDE_XOR)
++	mvXorAddrDecShow();
++#endif
++#if defined(MV_INCLUDE_SATA)
++    mvSataAddrDecShow();
++#endif
++#if defined(MV_INCLUDE_AUDIO)
++    mvAudioAddrDecShow();
++#endif
++#if defined(MV_INCLUDE_TS)
++    mvTsuAddrDecShow();
++#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;
++    }
++}
++/*******************************************************************************
++* mvCtrlSysRstLengthCounterGet - Return number of milliseconds the reset button
++*				 was pressed and clear counter
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*
++* RETURN: number of milliseconds the reset button was pressed
++*******************************************************************************/
++MV_U32	mvCtrlSysRstLengthCounterGet(MV_VOID)
++{
++	static volatile MV_U32 Count = 0;
++
++	if(!Count) {
++		Count = (MV_REG_READ(SYSRST_LENGTH_COUNTER_REG) & SLCR_COUNT_MASK);
++		Count = (Count / (MV_BOARD_REFCLK_25MHZ / 1000));
++		/* clear counter for next boot */
++		MV_REG_BIT_SET(SYSRST_LENGTH_COUNTER_REG, SLCR_CLR_MASK);
++	}
++
++	DB(mvOsPrintf("mvCtrlSysRstLengthCounterGet: Reset button was pressed for %u milliseconds\n", Count));
++
++	return Count;
++}
++
++MV_BOOL	  mvCtrlIsBootFromSPI(MV_VOID)
++{
++    MV_U32 satr = 0;
++    satr = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++    if(mvCtrlModelGet() == MV_6180_DEV_ID)
++    {
++        if (MSAR_BOOT_MODE_6180(satr) == MSAR_BOOT_SPI_WITH_BOOTROM_6180)
++            return MV_TRUE;
++        else
++            return MV_FALSE;
++    }
++    satr = satr & MSAR_BOOT_MODE_MASK;
++    if (satr == MSAR_BOOT_SPI_WITH_BOOTROM)
++        return MV_TRUE;
++    else
++        return MV_FALSE;
++}
++
++MV_BOOL	  mvCtrlIsBootFromSPIUseNAND(MV_VOID)
++{
++    MV_U32 satr = 0;
++    if(mvCtrlModelGet() == MV_6180_DEV_ID)
++        return MV_FALSE;
++    satr = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++    satr = satr & MSAR_BOOT_MODE_MASK;
++
++    if (satr == MSAR_BOOT_SPI_USE_NAND_WITH_BOOTROM)
++        return MV_TRUE;
++    else
++        return MV_FALSE;
++}
++
++MV_BOOL	  mvCtrlIsBootFromNAND(MV_VOID)
++{
++    MV_U32 satr = 0;
++    satr = MV_REG_READ(MPP_SAMPLE_AT_RESET);
++    if(mvCtrlModelGet() == MV_6180_DEV_ID)
++    {
++        if (MSAR_BOOT_MODE_6180(satr) == MSAR_BOOT_NAND_WITH_BOOTROM_6180)
++            return MV_TRUE;
++        else
++            return MV_FALSE;
++    }
++    satr = satr & MSAR_BOOT_MODE_MASK;
++    if ((satr == MSAR_BOOT_NAND_WITH_BOOTROM))
++        return MV_TRUE;
++    else
++        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;
++	/* Disable int */
++	__asm__ __volatile__("mrs %0, cpsr\n"
++			     "orr %1, %0, #0xc0\n"
++			     "msr cpsr_c, %1"
++			     : "=r" (old), "=r" (temp)
++			     :
++			     : "memory");
++
++	/* Set SoC in power save */
++	MV_REG_BIT_SET(POWER_MNG_CTRL_REG, BIT11);
++	/* Wait for int */
++	__asm__ __volatile__("mcr    p15, 0, r0, c7, c0, 4");
++
++	/* 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;
++	/* Disable int */
++	__asm__ __volatile__("mrs %0, cpsr\n"
++			     "orr %1, %0, #0xc0\n"
++			     "msr cpsr_c, %1"
++			     : "=r" (old), "=r" (temp)
++			     :
++			     : "memory");
++
++	/* Set SoC in power save */
++	MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, BIT11);
++	/* Wait for int */
++	__asm__ __volatile__("mcr    p15, 0, r0, c7, c0, 4");
++
++	/* Enabled int */
++	__asm__ __volatile__("msr cpsr_c, %0"
++			     :
++			     : "r" (old)
++			     : "memory");
++}
++
++/*******************************************************************************
++* mvCtrlPwrClckSet - Set Power State for specific Unit
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*
++* RETURN:
++*******************************************************************************/
++MV_VOID   mvCtrlPwrClckSet(MV_UNIT_ID unitId, MV_U32 index, MV_BOOL enable)
++{
++	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);
++		}
++		else
++		{
++			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_PEXSTOPCLOCK_MASK);
++		}
++		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(index));
++		}
++		else
++		{
++			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_SATASTOPCLOCK_MASK(index));
++		}
++		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_AUDIO)
++	case AUDIO_UNIT_ID:
++		if (enable == MV_FALSE)
++		{
++			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_AUDIOSTOPCLOCK_MASK);
++		}
++		else
++		{
++			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_AUDIOSTOPCLOCK_MASK);
++		}
++		break;
++#endif
++#if defined(MV_INCLUDE_TS)
++	case TS_UNIT_ID:
++		if (enable == MV_FALSE)
++		{
++			MV_REG_BIT_RESET(POWER_MNG_CTRL_REG, PMC_TSSTOPCLOCK_MASK);
++		}
++		else
++		{
++			MV_REG_BIT_SET(POWER_MNG_CTRL_REG, PMC_TSSTOPCLOCK_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_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
++
++	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;
++
++	switch (unitId)
++    {
++#if defined(MV_INCLUDE_PEX)
++	case PEX_UNIT_ID:
++		if ((reg & PMC_PEXSTOPCLOCK_MASK) == PMC_PEXSTOPCLOCK_STOP)
++		{
++			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(index)) == PMC_SATASTOPCLOCK_STOP(index))
++		{
++			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_AUDIO)
++	case AUDIO_UNIT_ID:
++		if ((reg & PMC_AUDIOSTOPCLOCK_MASK) == PMC_AUDIOSTOPCLOCK_STOP)
++		{
++			state = MV_FALSE;
++		}
++		else state = MV_TRUE;
++		break;
++#endif
++#if defined(MV_INCLUDE_TS)
++	case TS_UNIT_ID:
++		if ((reg & PMC_TSSTOPCLOCK_MASK) == PMC_TSSTOPCLOCK_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_UNIT_ID:
++		if ((reg & PMC_TDMSTOPCLOCK_MASK) == PMC_TDMSTOPCLOCK_STOP)
++		{
++			state = MV_FALSE;
++		}
++		else state = MV_TRUE;
++		break;
++#endif
++
++	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)
++{
++	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);
++		}
++		else
++		{
++			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_PEXSTOPMEM_MASK);
++		}
++		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(index));
++		}
++		else
++		{
++			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_SATASTOPMEM_MASK(index));
++		}
++		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_AUDIO)
++	case AUDIO_UNIT_ID:
++		if (enable == MV_FALSE)
++		{
++			MV_REG_BIT_SET(POWER_MNG_MEM_CTRL_REG, PMC_AUDIOSTOPMEM_MASK);
++		}
++		else
++		{
++			MV_REG_BIT_RESET(POWER_MNG_MEM_CTRL_REG, PMC_AUDIOSTOPMEM_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
++	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;
++
++	switch (unitId)
++    {
++#if defined(MV_INCLUDE_PEX)
++	case PEX_UNIT_ID:
++		if ((reg & PMC_PEXSTOPMEM_MASK) == PMC_PEXSTOPMEM_STOP)
++		{
++			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(index)) == PMC_SATASTOPMEM_STOP(index))
++		{
++			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_AUDIO)
++	case AUDIO_UNIT_ID:
++		if ((reg & PMC_AUDIOSTOPMEM_MASK) == PMC_AUDIOSTOPMEM_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
++
++	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) */
++
++
++/*******************************************************************************
++* mvMPPConfigToSPI - Change MPP[3:0] configuration to SPI mode
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*
++* RETURN:
++******************************************************************************/
++MV_VOID   mvMPPConfigToSPI(MV_VOID)
++{
++	MV_U32 mppVal = 0;
++	MV_U32 bootVal = 0;
++
++    if(!mvCtrlIsBootFromSPIUseNAND())
++        return;
++    mppVal = 0x00002220; /* Set MPP [3:1] to SPI mode */
++    bootVal = MV_REG_READ(mvCtrlMppRegGet(0));
++    bootVal &= 0xffff000f;
++        mppVal |= bootVal;
++
++    MV_REG_WRITE(mvCtrlMppRegGet(0), mppVal);
++}
++
++
++/*******************************************************************************
++* mvMPPConfigToDefault - Change MPP[7:0] configuration to default configuration
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*
++* RETURN:
++******************************************************************************/
++MV_VOID   mvMPPConfigToDefault(MV_VOID)
++{
++	MV_U32 mppVal = 0;
++	MV_U32 bootVal = 0;
++
++    if(!mvCtrlIsBootFromSPIUseNAND())
++        return;
++    mppVal = mvBoardMppGet(0);
++    bootVal = MV_REG_READ(mvCtrlMppRegGet(0));
++    mppVal &= ~0xffff000f;
++    bootVal &= 0xffff000f;
++        mppVal |= bootVal;
++
++    MV_REG_WRITE(mvCtrlMppRegGet(0), mppVal);
++}
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.h
+new file mode 100644
+index 0000000..6e2e813
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.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.
++
++*******************************************************************************/
++
++
++#ifndef __INCmvCtrlEnvLibh
++#define __INCmvCtrlEnvLibh
++
++/* includes */
++#include "mvSysHwConfig.h"
++#include "mvCommon.h"
++#include "mvTypes.h"
++#include "mvOs.h"
++#include "boardEnv/mvBoardEnvLib.h"
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++#include "ctrlEnv/mvCtrlEnvRegs.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.h"
++
++
++/* typedefs */
++
++/* 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;
++
++/* 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;
++
++
++/* mcspLib.h API list */
++
++MV_STATUS mvCtrlEnvInit(MV_VOID);
++MV_U32    mvCtrlMppRegGet(MV_U32 mppGroup);
++
++#if defined(MV_INCLUDE_PEX)
++MV_U32	  mvCtrlPexMaxIfGet(MV_VOID);
++#else
++#define   mvCtrlPexMaxIfGet()	(0)
++#endif
++
++#define   mvCtrlPciIfMaxIfGet()	(0)
++
++#if defined(MV_INCLUDE_GIG_ETH)
++MV_U32	  mvCtrlEthMaxPortGet(MV_VOID);
++#endif
++#if defined(MV_INCLUDE_XOR)
++MV_U32 mvCtrlXorMaxChanGet(MV_VOID);
++#endif
++#if defined(MV_INCLUDE_USB)
++MV_U32		  mvCtrlUsbMaxGet(MV_VOID);
++#endif
++#if defined(MV_INCLUDE_NAND)
++MV_U32	  mvCtrlNandSupport(MV_VOID);
++#endif
++#if defined(MV_INCLUDE_SDIO)
++MV_U32	  mvCtrlSdioSupport(MV_VOID);
++#endif
++#if defined(MV_INCLUDE_TS)
++MV_U32	  mvCtrlTsSupport(MV_VOID);
++#endif
++#if defined(MV_INCLUDE_AUDIO)
++MV_U32	  mvCtrlAudioSupport(MV_VOID);
++#endif
++#if defined(MV_INCLUDE_TDM)
++MV_U32	  mvCtrlTdmSupport(MV_VOID);
++#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);
++#if defined(MV_INCLUDE_CLK_PWR_CNTRL)
++MV_VOID   mvCtrlPwrSaveOn(MV_VOID);
++MV_VOID   mvCtrlPwrSaveOff(MV_VOID);
++#endif
++MV_BOOL	  mvCtrlPwrMemGet(MV_UNIT_ID unitId, MV_U32 index);
++MV_VOID   mvMPPConfigToSPI(MV_VOID);
++MV_VOID   mvMPPConfigToDefault(MV_VOID);
++
++
++#endif /* __INCmvCtrlEnvLibh */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvRegs.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvRegs.h
+new file mode 100644
+index 0000000..ae3f141
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvRegs.h
+@@ -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.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++        this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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
++
++/* 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 */
++
++/* Power Managment Control */
++#define POWER_MNG_MEM_CTRL_REG			0x20118
++
++#define PMC_GESTOPMEM_OFFS(port)		((port)? 13 : 0)
++#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_PEXSTOPMEM_OFFS			1
++#define PMC_PEXSTOPMEM_MASK			(1 << PMC_PEXSTOPMEM_OFFS)
++#define PMC_PEXSTOPMEM_EN			(0 << PMC_PEXSTOPMEM_OFFS)
++#define PMC_PEXSTOPMEM_STOP			(1 << PMC_PEXSTOPMEM_OFFS)
++
++#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(port)		(6+(port*5))
++#define PMC_SATASTOPMEM_MASK(port)		(1 << PMC_SATASTOPMEM_OFFS(port))
++#define PMC_SATASTOPMEM_EN(port)		(0 << PMC_SATASTOPMEM_OFFS(port))
++#define PMC_SATASTOPMEM_STOP(port)		(1 << PMC_SATASTOPMEM_OFFS(port))
++
++#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_AUDIOSTOPMEM_OFFS			9
++#define PMC_AUDIOSTOPMEM_MASK			(1 << PMC_AUDIOSTOPMEM_OFFS)
++#define PMC_AUDIOSTOPMEM_EN			(0 << PMC_AUDIOSTOPMEM_OFFS)
++#define PMC_AUDIOSTOPMEM_STOP			(1 << PMC_AUDIOSTOPMEM_OFFS)
++
++#define POWER_MNG_CTRL_REG			0x2011C
++
++#define PMC_GESTOPCLOCK_OFFS(port)		((port)? 19 : 0)
++#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_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			2
++#define PMC_PEXSTOPCLOCK_MASK			(1 << PMC_PEXSTOPCLOCK_OFFS)
++#define PMC_PEXSTOPCLOCK_EN			(1 << PMC_PEXSTOPCLOCK_OFFS)
++#define PMC_PEXSTOPCLOCK_STOP			(0 << PMC_PEXSTOPCLOCK_OFFS)
++
++#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_TSSTOPCLOCK_OFFS			5
++#define PMC_TSSTOPCLOCK_MASK			(1 << PMC_TSSTOPCLOCK_OFFS)
++#define PMC_TSSTOPCLOCK_EN			(1 << PMC_TSSTOPCLOCK_OFFS)
++#define PMC_TSSTOPCLOCK_STOP			(0 << PMC_TSSTOPCLOCK_OFFS)
++
++#define PMC_AUDIOSTOPCLOCK_OFFS			9
++#define PMC_AUDIOSTOPCLOCK_MASK			(1 << PMC_AUDIOSTOPCLOCK_OFFS)
++#define PMC_AUDIOSTOPCLOCK_EN			(1 << PMC_AUDIOSTOPCLOCK_OFFS)
++#define PMC_AUDIOSTOPCLOCK_STOP			(0 << PMC_AUDIOSTOPCLOCK_OFFS)
++
++#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(port)		(14+(port))
++#define PMC_SATASTOPCLOCK_MASK(port)		(1 << PMC_SATASTOPCLOCK_OFFS(port))
++#define PMC_SATASTOPCLOCK_EN(port)		(1 << PMC_SATASTOPCLOCK_OFFS(port))
++#define PMC_SATASTOPCLOCK_STOP(port)		(0 << PMC_SATASTOPCLOCK_OFFS(port))
++
++#define PMC_SESTOPCLOCK_OFFS			17
++#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_TDMSTOPCLOCK_OFFS			20
++#define PMC_TDMSTOPCLOCK_MASK			(1 << PMC_TDMSTOPCLOCK_OFFS)
++#define PMC_TDMSTOPCLOCK_EN			(1 << PMC_TDMSTOPCLOCK_OFFS)
++#define PMC_TDMSTOPCLOCK_STOP			(0 << PMC_TDMSTOPCLOCK_OFFS)
++
++
++/* Controler environment registers offsets */
++#define MPP_CONTROL_REG0			0x10000
++#define MPP_CONTROL_REG1			0x10004
++#define MPP_CONTROL_REG2			0x10008
++#define MPP_CONTROL_REG3			0x1000C
++#define MPP_CONTROL_REG4			0x10010
++#define MPP_CONTROL_REG5			0x10014
++#define MPP_CONTROL_REG6			0x10018
++#define MPP_SAMPLE_AT_RESET			0x10030
++#define CHIP_BOND_REG				0x10034
++#define SYSRST_LENGTH_COUNTER_REG		0x10050
++#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 PCKG_OPT_MASK				0x3
++#define MPP_OUTPUT_DRIVE_REG			0x100E0
++#define MPP_RGMII0_OUTPUT_DRIVE_OFFS            7
++#define MPP_3_3_RGMII0_OUTPUT_DRIVE		(0x0 << MPP_RGMII0_OUTPUT_DRIVE_OFFS)
++#define MPP_1_8_RGMII0_OUTPUT_DRIVE		(0x1 << MPP_RGMII0_OUTPUT_DRIVE_OFFS)
++#define MPP_RGMII1_OUTPUT_DRIVE_OFFS            15
++#define MPP_3_3_RGMII1_OUTPUT_DRIVE		(0x0 << MPP_RGMII1_OUTPUT_DRIVE_OFFS)
++#define MPP_1_8_RGMII1_OUTPUT_DRIVE		(0x1 << MPP_RGMII1_OUTPUT_DRIVE_OFFS)
++
++#define MSAR_BOOT_MODE_OFFS                     12
++#define MSAR_BOOT_MODE_MASK                     (0x7 << MSAR_BOOT_MODE_OFFS)
++#define MSAR_BOOT_NAND_WITH_BOOTROM		        (0x5 << MSAR_BOOT_MODE_OFFS)
++#define MSAR_BOOT_SPI_WITH_BOOTROM              (0x4 << MSAR_BOOT_MODE_OFFS)
++#define MSAR_BOOT_SPI_USE_NAND_WITH_BOOTROM		(0x2 << MSAR_BOOT_MODE_OFFS)
++
++#define MSAR_BOOT_MODE_6180(X)                  (((X & 0x3000) >> 12) | \
++                                                ((X & 0x2) << 1))
++#define MSAR_BOOT_SPI_WITH_BOOTROM_6180         0x1
++#define MSAR_BOOT_NAND_WITH_BOOTROM_6180        0x5
++
++#define MSAR_TCLCK_OFFS				21
++#define MSAR_TCLCK_MASK				(0x1 << MSAR_TCLCK_OFFS)
++#define MSAR_TCLCK_166				(0x1 << MSAR_TCLCK_OFFS)
++#define MSAR_TCLCK_200				(0x0 << MSAR_TCLCK_OFFS)
++
++
++#define MSAR_CPUCLCK_EXTRACT(X)     (((X & 0x2) >> 1) | ((X & 0x400000) >> 21) | \
++                                    ((X & 0x18) >> 1))
++
++#define MSAR_CPUCLCK_OFFS_6180		2
++#define MSAR_CPUCLCK_MASK_6180		(0x7 << MSAR_CPUCLCK_OFFS_6180)
++
++#define MSAR_DDRCLCK_RTIO_OFFS		5
++#define MSAR_DDRCLCK_RTIO_MASK		(0xF << MSAR_DDRCLCK_RTIO_OFFS)
++
++#define MSAR_L2CLCK_EXTRACT(X)      (((X & 0x600) >> 9) | ((X & 0x80000) >> 17))
++
++#ifndef MV_ASMLANGUAGE
++/* CPU clock for 6281,6192  0->Resereved */
++#define MV_CPU_CLCK_TBL {	0,		0,		0,		0,	\
++				600000000,	0,		800000000,	1000000000,	\
++				0,		1200000000,	0,		0,		\
++				1500000000,	0,		0,		0}
++
++/* DDR clock RATIO for 6281,6192 {0,0}->Reserved */
++#define MV_DDR_CLCK_RTIO_TBL	{\
++	{0, 0}, {0, 0}, {2, 1}, {0, 0}, \
++	{3, 1}, {0, 0}, {4, 1}, {9, 2}, \
++	{5, 1}, {6, 1}, {0, 0}, {0, 0}, \
++	{0, 0}, {0, 0}, {0, 0}, {0, 0} \
++}
++
++/* L2 clock RATIO for 6281,6192 {1,1}->Reserved */
++#define MV_L2_CLCK_RTIO_TBL	{\
++	{0, 0}, {2, 1}, {0, 0}, {3, 1}, \
++	{0, 0}, {0, 0}, {0, 0}, {0, 0} \
++}
++
++/* 6180 have different clk reset sampling		*/
++/* ARM CPU, DDR, L2 clock for 6180 {0,0,0}->Reserved	*/
++#define MV_CPU6180_DDR_L2_CLCK_TBL    { \
++	{0,		0,		0		},\
++	{0,		0,		0		},\
++	{0,		0,		0		},\
++	{0,		0,		0		},\
++	{0,		0,		0		},\
++	{600000000,	200000000,	300000000	},\
++	{800000000,	200000000,	400000000	},\
++	{0,		0,		0		}\
++}
++
++
++
++/* 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)   0
++
++#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) == (sampleAtResetTargetArray[ \
++                     (mvCtrlModelGet() == MV_6180_DEV_ID)? MSAR_BOOT_MODE_6180 \
++                     (MV_REG_READ(MPP_SAMPLE_AT_RESET)):((MV_REG_READ(MPP_SAMPLE_AT_RESET)\
++						 & MSAR_BOOT_MODE_MASK) >> MSAR_BOOT_MODE_OFFS)]))
++
++
++#define MV_CHANGE_BOOT_CS(target)	(((target) == DEV_BOOCS)?\
++					sampleAtResetTargetArray[(mvCtrlModelGet() == MV_6180_DEV_ID)? \
++                    MSAR_BOOT_MODE_6180(MV_REG_READ(MPP_SAMPLE_AT_RESET)): \
++                    ((MV_REG_READ(MPP_SAMPLE_AT_RESET) & MSAR_BOOT_MODE_MASK)\
++                     >> MSAR_BOOT_MODE_OFFS)]:(target))
++
++#define TCLK_TO_COUNTER_RATIO   1   /* counters running in Tclk */
++
++#define BOOT_TARGETS_NAME_ARRAY {       \
++    TBL_TERM,		\
++    TBL_TERM,		\
++    BOOT_ROM_CS,		\
++    TBL_TERM,		\
++    BOOT_ROM_CS,		\
++    BOOT_ROM_CS,          \
++    TBL_TERM,		\
++    TBL_TERM           \
++}
++
++#define BOOT_TARGETS_NAME_ARRAY_6180 {       \
++    TBL_TERM,		\
++    BOOT_ROM_CS,		\
++    TBL_TERM,           \
++    TBL_TERM,           \
++    TBL_TERM,           \
++    BOOT_ROM_CS,          \
++    TBL_TERM,           \
++    TBL_TERM           \
++}
++
++
++/* For old competability */
++#define DEVICE_CS0		NFLASH_CS
++#define DEVICE_CS1		SPI_CS
++#define DEVICE_CS2		BOOT_ROM_CS
++#define DEVICE_CS3		DEV_BOOCS
++#define MV_BOOTDEVICE_INDEX	0
++
++#define START_DEV_CS			DEV_CS0
++#define DEV_TO_TARGET(dev)	((dev) + DEVICE_CS0)
++
++#define PCI_IF0_MEM0		PEX0_MEM
++#define PCI_IF0_IO		PEX0_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 -> Nand/SPI		*/
++    PEX0_TARGET_ID  = 4 ,    /* Port 4 -> PCI Express0			*/
++    CRYPT_TARGET_ID = 3 ,    /* Port 3 --> Crypto Engine	*/
++    SAGE_TARGET_ID = 12 ,    /* Port 12 -> SAGE Unit	*/
++    MAX_TARGETS_ID
++}MV_TARGET_ID;
++
++
++/* 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                          */
++    PEX0_MEM,		/* PCI Express 0 Memory				*/
++    PEX0_IO,		/* PCI Express 0 IO				*/
++    INTER_REGS,	/* Internal registers                           */
++    NFLASH_CS,		/* NFLASH_CS					*/
++    SPI_CS,		/* SPI_CS					*/
++    BOOT_ROM_CS,        /* BOOT_ROM_CS                                  */
++    DEV_BOOCS,		/* DEV_BOOCS					*/
++    CRYPT_ENG,		/* Crypto Engine				*/
++#ifdef MV_INCLUDE_SAGE
++    SAGE_UNIT,		/* SAGE Unit					*/
++#endif
++    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 */		\
++    {0xE8, PEX0_TARGET_ID }, /* PEX0_MEM */			\
++    {0xE0, PEX0_TARGET_ID }, /* PEX0_IO */			\
++    {0xFF, 0xFF           }, /* INTER_REGS */		\
++    {0x2F, DEV_TARGET_ID  },  /* NFLASH_CS */		\
++    {0x1E, DEV_TARGET_ID  },  /* SPI_CS */			\
++    {0x1D, DEV_TARGET_ID  },  /* BOOT_ROM_CS */     \
++    {0x1E, DEV_TARGET_ID  },  /* DEV_BOOCS */		\
++    {0x01, CRYPT_TARGET_ID}, /* CRYPT_ENG */        \
++    {0x00, SAGE_TARGET_ID }						\
++}
++
++
++#define TARGETS_NAME_ARRAY	{	\
++    "SDRAM_CS0",    /* SDRAM_CS0 */	\
++    "SDRAM_CS1",    /* SDRAM_CS1 */	\
++    "SDRAM_CS2",    /* SDRAM_CS2 */	\
++    "SDRAM_CS3",    /* SDRAM_CS3 */	\
++    "PEX0_MEM",	    /* PEX0_MEM */	\
++    "PEX0_IO",	    /* PEX0_IO */	\
++    "INTER_REGS",   /* INTER_REGS */	\
++    "NFLASH_CS",    /* NFLASH_CS */	\
++    "SPI_CS",	    /* SPI_CS */	\
++    "BOOT_ROM_CS",  /* BOOT_ROM_CS */ \
++    "DEV_BOOTCS",   /* DEV_BOOCS */	\
++    "CRYPT_ENG",    /* CRYPT_ENG */  \
++    "SAGE_UNIT"	   /* SAGE_UNIT */	\
++}
++#endif /* MV_ASMLANGUAGE */
++
++
++#endif
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvSpec.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvSpec.h
+new file mode 100644
+index 0000000..e41d80a
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvSpec.h
+@@ -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.
++
++*******************************************************************************/
++
++#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 XOR_UNIT_BASE(unit)		0x60800
++#else
++#define MV_XOR_REG_BASE			0x60000
++#define XOR_UNIT_BASE(unit)		((unit)? 0x60900:0x60800)
++#endif
++
++#define TDM_REG_BASE			0xD0000
++#define USB_REG_BASE(dev)		0x50000
++#define AUDIO_REG_BASE			0xA0000
++#define SATA_REG_BASE			0x80000
++#define MV_CESA_REG_BASE                0x3D000
++#define MV_CESA_TDMA_REG_BASE		0x30000
++#define MV_SDIO_REG_BASE		0x90000
++#define MV_ETH_REG_BASE(port)		(((port) == 0) ? 0x72000 : 0x76000)
++#define MV_UART_CHAN_BASE(chanNum)	(0x12000 + (chanNum * 0x100))
++#define DRAM_BASE			0x0
++#define CNTMR_BASE			0x20300
++#define TWSI_SLAVE_BASE(chanNum)	0x11000
++#define PEX_IF_BASE(pexIf)		0x40000
++#define MPP_REG_BASE			0x10000
++#define TSU_GLOBAL_REG_BASE             0xB4000
++#define MAX_AHB_TO_MBUS_REG_BASE	0x20000
++
++#define INTER_REGS_SIZE			_1M
++/* This define describes the TWSI interrupt bit and location */
++#define TWSI_CPU_MAIN_INT_CAUSE_REG		0x20200
++#define TWSI0_CPU_MAIN_INT_BIT			(1<<29)
++#define TWSI_SPEED				100000
++
++#define MV_GPP_MAX_GROUP		2
++#define MV_CNTMR_MAX_COUNTER		2
++#define MV_UART_MAX_CHAN		2
++#define MV_XOR_MAX_UNIT		2
++#define MV_XOR_MAX_CHAN		4 /* total channels for all units together*/
++#define MV_XOR_MAX_CHAN_PER_UNIT		2 /* channels for units */
++#define MV_SATA_MAX_CHAN		2
++
++#define MV_6281_MPP_MAX_MODULE		2
++#define MV_6192_MPP_MAX_MODULE		1
++#define MV_6190_MPP_MAX_MODULE		1
++#define MV_6180_MPP_MAX_MODULE		2
++#define MV_6281_MPP_MAX_GROUP		7
++#define MV_6192_MPP_MAX_GROUP		4
++#define MV_6190_MPP_MAX_GROUP		4
++#define MV_6180_MPP_MAX_GROUP		3
++
++#define MV_DRAM_MAX_CS			4
++
++/* 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		1
++#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_ETH_MAX_PORTS		2
++#define MV_6281_ETH_MAX_PORTS		2
++#define MV_6192_ETH_MAX_PORTS		2
++#define MV_6190_ETH_MAX_PORTS		1
++#define MV_6180_ETH_MAX_PORTS		1
++
++#define MV_IDMA_MAX_CHAN		0
++
++#define MV_USB_MAX_PORTS		1
++
++#define MV_USB_VERSION              1
++
++
++#define MV_6281_NAND			1
++#define MV_6192_NAND			1
++#define MV_6190_NAND			1
++#define MV_6180_NAND			0
++
++#define MV_6281_SDIO			1
++#define MV_6192_SDIO			1
++#define MV_6190_SDIO			1
++#define MV_6180_SDIO			1
++
++#define MV_6281_TS			1
++#define MV_6192_TS			1
++#define MV_6190_TS			0
++#define MV_6180_TS			0
++
++#define MV_6281_AUDIO			1
++#define MV_6192_AUDIO			1
++#define MV_6190_AUDIO			0
++#define MV_6180_AUDIO			1
++
++#define MV_6281_TDM			1
++#define MV_6192_TDM			1
++#define MV_6190_TDM			0
++#define MV_6180_TDM			0
++
++#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)		(PEX0_IO)
++#define PCI_MEM(pciIf, memNum)  (PEX0_MEM0)
++/* CESA version #2: One channel, 2KB SRAM, TDMA */
++#if defined(MV_CESA_CHAIN_MODE_SUPPORT)
++	#define MV_CESA_VERSION			3
++#else
++#define MV_CESA_VERSION			2
++#endif
++#define MV_CESA_SRAM_SIZE               2*1024
++/* This define describes the maximum number of supported Ethernet ports	*/
++#define MV_ETH_VERSION				4
++#define MV_ETH_MAX_RXQ			8
++#define MV_ETH_MAX_TXQ			8
++#define MV_ETH_PORT_SGMII		{ MV_FALSE, MV_FALSE }
++/* This define describes the the support of USB	*/
++#define MV_USB_VERSION			1
++
++#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_TYPE {\
++	{0, 0, 0}, /* Reserved for AUTO */ \
++	{0x22220000, 0x22222222, 0x2222}, /* TDM */ \
++	{0x44440000, 0x00044444, 0x0000}, /* AUDIO */ \
++	{0x33330000, 0x33003333, 0x0033}, /* RGMII */ \
++	{0x33330000, 0x03333333, 0x0033}, /* GMII */ \
++	{0x11110000, 0x11111111, 0x0001}, /* TS */ \
++	{0x33330000, 0x33333333, 0x3333}  /* MII */ \
++}
++
++#define MPP_GROUP_2_TYPE {\
++	{0, 0, 0}, /* Reserved for AUTO */ \
++	{0x22220000, 0x22222222, 0x22}, /* TDM */ \
++	{0x44440000, 0x00044444, 0x0}, /* AUDIO */ \
++	{0, 0, 0}, /* N_A */ \
++	{0, 0, 0}, /* N_A */ \
++	{0x11110000, 0x11111111, 0x01}  /* TS */ \
++}
++
++#ifndef MV_ASMLANGUAGE
++
++/* 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_UNIT_ID,
++    UART_UNIT_ID,
++    CESA_UNIT_ID,
++    SPI_UNIT_ID,
++    AUDIO_UNIT_ID,
++    SDIO_UNIT_ID,
++    TS_UNIT_ID,
++    MAX_UNITS_ID
++
++}MV_UNIT_ID;
++
++#endif
++
++#endif /* __INCmvCtrlEnvSpech */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.c
+new file mode 100644
+index 0000000..d21bb07
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.c
+@@ -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.
++
++*******************************************************************************/
++
++
++/* includes */
++#include "ctrlEnv/sys/mvAhbToMbus.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.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;
++
++	/* 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));
++	}
++
++	if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs))
++	{
++		mvOsPrintf("mvAhbToMbusWinSet:mvCtrlAddrDecToReg Failed\n");
++		return MV_ERROR;
++	}
++
++	/* 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;
++
++
++	/* 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);
++	}
++
++
++
++	if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin)))
++	{
++		mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n");
++		return MV_ERROR;
++	}
++
++	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 Illigal\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;
++
++
++}
++/*******************************************************************************
++* 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 Illigal\n", target1);
++		return MV_ERROR;
++	}
++
++	if (target2 >= MAX_TARGETS)
++	{
++		mvOsPrintf("mvAhbToMbusWinTargetSwap: target %d is Illigal\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;
++
++
++}
++
++
++
++#if defined(MV_88F1181)
++
++/*******************************************************************************
++* mvAhbToMbusXbarCtrlSet - Set The CPU master Xbar arbitration.
++*
++* DESCRIPTION:
++*       This function sets CPU Mbus Arbiter
++*
++* INPUT:
++*       pPizzaArbArray - A priority Structure describing 16 "pizza slices". At
++*                    each clock cycle, the crossbar arbiter samples all
++*                    requests and gives the bus to the next agent according
++*                    to the "pizza".
++*
++* OUTPUT:
++*       N/A
++*
++* RETURN:
++*       MV_ERROR if paramers to function invalid.
++*
++*******************************************************************************/
++MV_STATUS  mvMbusArbSet(MV_MBUS_ARB_TARGET *pPizzaArbArray)
++{
++	MV_U32 sliceNum;
++	MV_U32 xbarCtrl = 0;
++	MV_MBUS_ARB_TARGET xbarTarget;
++
++	/* 1) Set crossbar control low register */
++	for (sliceNum = 0; sliceNum < MRLR_SLICE_NUM; sliceNum++)
++	{
++		xbarTarget = pPizzaArbArray[sliceNum];
++
++		/* sliceNum parameter check */
++		if (xbarTarget > MAX_MBUS_ARB_TARGETS)
++		{
++			mvOsPrintf("mvAhbToMbusXbarCtrlSet: ERR. Can't set Target %d\n",
++																  xbarTarget);
++			return MV_ERROR;
++		}
++		xbarCtrl |= (xbarTarget << MRLR_LOW_ARB_OFFS(sliceNum));
++	}
++	/* Write to crossbar control low register */
++    MV_REG_WRITE(MBUS_ARBITER_LOW_REG, xbarCtrl);
++
++	xbarCtrl = 0;
++
++	/* 2) Set crossbar control high register */
++	for (sliceNum = MRLR_SLICE_NUM;
++		 sliceNum < MRLR_SLICE_NUM+MRHR_SLICE_NUM;
++		 sliceNum++)
++	{
++
++		xbarTarget = pPizzaArbArray[sliceNum];
++
++		/* sliceNum parameter check */
++		if (xbarTarget > MAX_MBUS_ARB_TARGETS)
++		{
++			mvOsPrintf("mvAhbToMbusXbarCtrlSet: ERR. Can't set Target %d\n",
++																  xbarTarget);
++			return MV_ERROR;
++		}
++		xbarCtrl |= (xbarTarget << MRHR_HIGH_ARB_OFFS(sliceNum));
++	}
++	/* Write to crossbar control high register */
++    MV_REG_WRITE(MBUS_ARBITER_HIGH_REG, xbarCtrl);
++
++	return MV_OK;
++}
++
++/*******************************************************************************
++* mvMbusArbCtrlSet - Set MBus Arbiter control register
++*
++* DESCRIPTION:
++*
++* INPUT:
++*       ctrl  - pointer to MV_MBUS_ARB_CTRL register
++*
++* OUTPUT:
++*       N/A
++*
++* RETURN:
++*       MV_ERROR if paramers to function invalid.
++*
++*******************************************************************************/
++MV_STATUS mvMbusArbCtrlSet(MV_MBUS_ARB_CTRL *ctrl)
++{
++
++	if (ctrl->highPrio == MV_FALSE)
++	{
++		MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_ARM_TOP);
++	}
++	else
++	{
++		MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_ARM_TOP);
++	}
++
++	if (ctrl->fixedRoundRobin == MV_FALSE)
++	{
++		MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_TARGET_FIXED);
++	}
++	else
++	{
++		MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_TARGET_FIXED);
++	}
++
++	if (ctrl->starvEn == MV_FALSE)
++	{
++		MV_REG_BIT_RESET(MBUS_ARBITER_CTRL_REG, MACR_ARB_REQ_CTRL_EN);
++	}
++	else
++	{
++		MV_REG_BIT_SET(MBUS_ARBITER_CTRL_REG, MACR_ARB_REQ_CTRL_EN);
++	}
++
++	return MV_OK;
++}
++
++/*******************************************************************************
++* mvMbusArbCtrlGet - Get MBus Arbiter control register
++*
++* DESCRIPTION:
++*
++* INPUT:
++*       ctrl  - pointer to MV_MBUS_ARB_CTRL register
++*
++* OUTPUT:
++*       ctrl  - pointer to MV_MBUS_ARB_CTRL register
++*
++* RETURN:
++*       MV_ERROR if paramers to function invalid.
++*
++*******************************************************************************/
++MV_STATUS mvMbusArbCtrlGet(MV_MBUS_ARB_CTRL *ctrl)
++{
++
++	MV_U32 ctrlReg = MV_REG_READ(MBUS_ARBITER_CTRL_REG);
++
++	if (ctrlReg & MACR_ARB_ARM_TOP)
++	{
++		ctrl->highPrio = MV_TRUE;
++	}
++	else
++	{
++		ctrl->highPrio = MV_FALSE;
++	}
++
++	if (ctrlReg & MACR_ARB_TARGET_FIXED)
++	{
++		ctrl->fixedRoundRobin = MV_TRUE;
++	}
++	else
++	{
++		ctrl->fixedRoundRobin = MV_FALSE;
++	}
++
++	if (ctrlReg & MACR_ARB_REQ_CTRL_EN)
++	{
++		ctrl->starvEn = MV_TRUE;
++	}
++	else
++	{
++		ctrl->starvEn = MV_FALSE;
++	}
++
++
++	return MV_OK;
++}
++
++#endif  /* #if defined(MV_88F1181) */
++
++
++
++/*******************************************************************************
++* 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:
++			pRemapRegs->lowRegOffs  = AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum);
++			pRemapRegs->highRegOffs = AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum);
++			break;
++		case 2:
++		case 3:
++			if((mvCtrlModelGet() == MV_5281_DEV_ID) ||
++				(mvCtrlModelGet() == MV_1281_DEV_ID) ||
++				(mvCtrlModelGet() == MV_6183_DEV_ID) ||
++               (mvCtrlModelGet() == MV_6183L_DEV_ID))
++			{
++				pRemapRegs->lowRegOffs  = AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum);
++				pRemapRegs->highRegOffs = AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum);
++				break;
++			}
++			else
++			{
++				pRemapRegs->lowRegOffs  = 0;
++				pRemapRegs->highRegOffs = 0;
++
++				DB(mvOsPrintf("ahbToMbusRemapRegOffsGet: ERR. Invalid winNum %d\n",
++							winNum));
++				return MV_NO_SUCH;
++			}
++		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/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.h
+new file mode 100644
+index 0000000..1b352a1
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.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 __INCmvAhbToMbush
++#define __INCmvAhbToMbush
++
++/* includes */
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/sys/mvAhbToMbusRegs.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.h"
++
++/* defines  */
++
++#if defined(MV_88F1181)
++/* This enumerator defines the Marvell controller possible MBUS arbiter     */
++/* target ports. It is used to define crossbar priority scheame (pizza)     */
++typedef enum _mvMBusArbTargetId
++{
++    DRAM_MBUS_ARB_TARGET = 0,    /* Port 0 -> DRAM interface         */
++    TWSI_MBUS_ARB_TARGET  = 1,     /* Port 1 -> TWSI		    */
++    ARM_MBUS_ARB_TARGET   = 2,     /* Port 2 -> ARM		    */
++	PEX1_MBUS_ARB_TARGET  = 3,    /* Port 3 -> PCI Express 1		    */
++    PEX0_MBUS_ARB_TARGET  = 4,    /* Port 4 -> PCI Express0		    */
++	MAX_MBUS_ARB_TARGETS
++}MV_MBUS_ARB_TARGET;
++
++typedef struct _mvMBusArbCtrl
++{
++	MV_BOOL starvEn;
++	MV_BOOL highPrio;
++	MV_BOOL fixedRoundRobin;
++
++}MV_MBUS_ARB_CTRL;
++
++#endif /* #if defined(MV_88F1181) */
++
++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	  mvAhbToMbusWinTargetGet(MV_TARGET target);
++MV_U32    mvAhbToMbusWinAvailGet(MV_VOID);
++MV_STATUS mvAhbToMbusWinTargetSwap(MV_TARGET target1,MV_TARGET target2);
++
++#if defined(MV_88F1181)
++
++MV_STATUS mvMbusArbSet(MV_MBUS_ARB_TARGET *pPizzaArbArray);
++MV_STATUS mvMbusArbCtrlSet(MV_MBUS_ARB_CTRL *ctrl);
++MV_STATUS mvMbusArbCtrlGet(MV_MBUS_ARB_CTRL *ctrl);
++
++#endif /* #if defined(MV_88F1181) */
++
++
++MV_VOID   mvAhbToMbusAddDecShow(MV_VOID);
++
++
++#endif /* __INCmvAhbToMbush */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h
+new file mode 100644
+index 0000000..97dc631
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_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	9
++#define MV_AHB_TO_MBUS_INTREG_WIN	8
++
++
++#define AHB_TO_MBUS_WIN_CTRL_REG(winNum)		(0x20000 + (winNum)*0x10)
++#define AHB_TO_MBUS_WIN_BASE_REG(winNum)		(0x20004 + (winNum)*0x10)
++#define AHB_TO_MBUS_WIN_REMAP_LOW_REG(winNum)	(0x20008 + (winNum)*0x10)
++#define AHB_TO_MBUS_WIN_REMAP_HIGH_REG(winNum)	(0x2000C + (winNum)*0x10)
++#define AHB_TO_MBUS_WIN_INTEREG_REG				 0x20080
++
++/* 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)
++
++
++/*
++Used with the Base register to set the address window size and location
++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 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/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.c
+new file mode 100644
+index 0000000..872dc6e
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.c
+@@ -0,0 +1,1036 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "mvSysDram.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;
++MV_TARGET sampleAtResetTargetArrayP[] = BOOT_TARGETS_NAME_ARRAY;
++MV_TARGET sampleAtResetTargetArray6180P[] = BOOT_TARGETS_NAME_ARRAY_6180;
++/*******************************************************************************
++* 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;
++	}
++
++    /*Initialize the boot target array according to device type*/
++    if(mvCtrlModelGet() == MV_6180_DEV_ID)
++        sampleAtResetTargetArray = sampleAtResetTargetArray6180P;
++    else
++        sampleAtResetTargetArray = sampleAtResetTargetArrayP;
++
++	/* 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));
++			}
++
++
++		}
++    }
++
++	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 Illigal\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 winow 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;
++
++	target = MV_CHANGE_BOOT_CS(target);
++
++	/* Check parameters */
++	if (target >= MAX_TARGETS)
++	{
++		mvOsPrintf("mvCpuIfTargetWinGet: target %d is Illigal\n", target);
++		return MV_ERROR;
++	}
++
++	if (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",
++					   __FUNCTION__, 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 Illigal\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",__FUNCTION__, 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",__FUNCTION__, 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 Illigal\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 Illigal\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 Illigal\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 Illigal\n",pexTarget);
++			return 0xffffffff;
++		}
++
++	}
++	else
++	{
++		if (!MV_TARGET_IS_PEX0(pexTarget))
++		{
++			mvOsPrintf("mvCpuIfPexRemap: target %d is Illigal\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 Illigal\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 == ctrlWinOverlapTest(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 )
++			{
++				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" );
++		}
++	}
++}
++
++/*******************************************************************************
++* mvCpuIfEnablePex - Enable PCI Express.
++*
++* DESCRIPTION:
++*		This function Enable PCI Express.
++*
++* INPUT:
++*       pexIf   -  PEX interface number.
++*       pexType -  MV_PEX_ROOT_COMPLEX - root complex device
++*		   MV_PEX_END_POINT - end point device
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++#if defined(MV_INCLUDE_PEX)
++MV_VOID mvCpuIfEnablePex(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);
++	}
++
++	/* CPU config register Pex enable */
++	MV_REG_BIT_SET(CPU_CTRL_STAT_REG,CCSR_PCI_ACCESS_MASK);
++}
++#endif
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.h
+new file mode 100644
+index 0000000..224ed07
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.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 __INCmvCpuIfh
++#define __INCmvCpuIfh
++
++/* includes */
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/sys/mvCpuIfRegs.h"
++#include "ctrlEnv/sys/mvAhbToMbus.h"
++#include "ddr2/mvDramIf.h"
++#include "ctrlEnv/sys/mvSysDram.h"
++#if defined(MV_INCLUDE_PEX)
++#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, MV_PEX_TYPE pexType);
++#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);
++
++#if defined(MV88F6281)
++MV_STATUS mvCpuIfBridgeReorderWAInit(void);
++#endif
++
++#endif /* __INCmvCpuIfh */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIfRegs.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIfRegs.h
+new file mode 100644
+index 0000000..8cfeee2
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIfRegs.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.
++
++*******************************************************************************/
++
++
++#ifndef __INCmvCpuIfRegsh
++#define __INCmvCpuIfRegsh
++
++/****************************************/
++/* ARM Control and Status Registers Map */
++/****************************************/
++
++#define CPU_CONFIG_REG				0x20100
++#define CPU_CTRL_STAT_REG			0x20104
++#define CPU_RSTOUTN_MASK_REG			0x20108
++#define CPU_SYS_SOFT_RST_REG			0x2010C
++#define CPU_AHB_MBUS_CAUSE_INT_REG		0x20110
++#define CPU_AHB_MBUS_MASK_INT_REG		0x20114
++#define CPU_FTDLL_CONFIG_REG			0x20120
++#define CPU_L2_CONFIG_REG			0x20128
++
++
++
++/* 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			0
++#define CCSR_PCI_ACCESS_MASK			BIT0
++#define CCSR_PCI_ACCESS_ENABLE			(0 << CCSR_PCI_ACCESS_OFFS)
++#define CCSR_PCI_ACCESS_DISBALE			(1 << CCSR_PCI_ACCESS_OFFS)
++
++#define CCSR_ARM_RESET				BIT1
++#define CCSR_SELF_INT				BIT2
++#define CCSR_BIG_ENDIAN				BIT15
++
++
++/* 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			0x20200
++#define CPU_MAIN_IRQ_MASK_REG			0x20204
++#define CPU_MAIN_FIQ_MASK_REG			0x20208
++#define CPU_ENPOINT_MASK_REG			0x2020C
++#define CPU_MAIN_INT_CAUSE_HIGH_REG		0x20210
++#define CPU_MAIN_IRQ_MASK_HIGH_REG		0x20214
++#define CPU_MAIN_FIQ_MASK_HIGH_REG		0x20218
++#define CPU_ENPOINT_MASK_HIGH_REG		0x2021C
++
++
++/*******************************************/
++/* ARM Doorbell Registers Map		   */
++/*******************************************/
++
++#define CPU_HOST_TO_ARM_DRBL_REG		0x20400
++#define CPU_HOST_TO_ARM_MASK_REG		0x20404
++#define CPU_ARM_TO_HOST_DRBL_REG		0x20408
++#define CPU_ARM_TO_HOST_MASK_REG		0x2040C
++
++
++
++/* 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/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.c
+new file mode 100644
+index 0000000..769475f
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.c
+@@ -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.
++
++*******************************************************************************/
++#include "mvSysAudio.h"
++
++/*******************************************************************************
++* mvAudioWinSet - Set AUDIO 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 AUDIO will be able to access the
++*       target within the address window.
++*
++* INPUT:
++*       winNum      - AUDIO target address decode window number.
++*       pAddrDecWin - AUDIO 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 mvAudioWinSet(MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin)
++{
++    MV_TARGET_ATTRIB    targetAttribs;
++    MV_DEC_REGS         decRegs;
++
++    /* Parameter checking   */
++    if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN)
++    {
++        mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, 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("mvAudioWinSet:Error setting AUDIO 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;
++    }
++
++    decRegs.baseReg = 0;
++    decRegs.sizeReg = 0;
++
++    if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs))
++    {
++        mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__);
++        return MV_ERROR;
++    }
++
++    mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs);
++
++    /* set attributes */
++    decRegs.sizeReg &= ~MV_AUDIO_WIN_ATTR_MASK;
++    decRegs.sizeReg |= (targetAttribs.attrib << MV_AUDIO_WIN_ATTR_OFFSET);
++
++    /* set target ID */
++    decRegs.sizeReg &= ~MV_AUDIO_WIN_TARGET_MASK;
++    decRegs.sizeReg |= (targetAttribs.targetId << MV_AUDIO_WIN_TARGET_OFFSET);
++
++    if (pAddrDecWin->enable == MV_TRUE)
++    {
++        decRegs.sizeReg |= MV_AUDIO_WIN_ENABLE_MASK;
++    }
++    else
++    {
++        decRegs.sizeReg &= ~MV_AUDIO_WIN_ENABLE_MASK;
++    }
++
++    MV_REG_WRITE( MV_AUDIO_WIN_CTRL_REG(winNum), decRegs.sizeReg);
++    MV_REG_WRITE( MV_AUDIO_WIN_BASE_REG(winNum), decRegs.baseReg);
++
++    return MV_OK;
++}
++
++/*******************************************************************************
++* mvAudioWinGet - Get AUDIO peripheral target address window.
++*
++* DESCRIPTION:
++*       Get AUDIO peripheral target address window.
++*
++* INPUT:
++*       winNum - AUDIO target address decode window number.
++*
++* OUTPUT:
++*       pAddrDecWin - AUDIO target window data structure.
++*
++* RETURN:
++*       MV_ERROR if register parameters are invalid.
++*
++*******************************************************************************/
++MV_STATUS mvAudioWinGet(MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin)
++{
++    MV_DEC_REGS         decRegs;
++    MV_TARGET_ATTRIB    targetAttrib;
++
++    /* Parameter checking   */
++    if (winNum >= MV_AUDIO_MAX_ADDR_DECODE_WIN)
++    {
++        mvOsPrintf("%s : ERR. Invalid winNum %d\n",
++                    __FUNCTION__,  winNum);
++        return MV_NOT_SUPPORTED;
++    }
++
++    decRegs.baseReg = MV_REG_READ( MV_AUDIO_WIN_BASE_REG(winNum) );
++    decRegs.sizeReg = MV_REG_READ( MV_AUDIO_WIN_CTRL_REG(winNum) );
++
++    if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) )
++    {
++        mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__);
++        return MV_ERROR;
++    }
++
++    /* attrib and targetId */
++    targetAttrib.attrib = (decRegs.sizeReg & MV_AUDIO_WIN_ATTR_MASK) >>
++		MV_AUDIO_WIN_ATTR_OFFSET;
++    targetAttrib.targetId = (decRegs.sizeReg & MV_AUDIO_WIN_TARGET_MASK) >>
++		MV_AUDIO_WIN_TARGET_OFFSET;
++
++    pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++    /* Check if window is enabled   */
++    if(decRegs.sizeReg & MV_AUDIO_WIN_ENABLE_MASK)
++    {
++        pAddrDecWin->enable = MV_TRUE;
++    }
++    else
++    {
++        pAddrDecWin->enable = MV_FALSE;
++    }
++    return MV_OK;
++}
++/*******************************************************************************
++* mvAudioAddrDecShow - Print the AUDIO address decode map.
++*
++* DESCRIPTION:
++*		This function print the AUDIO address decode map.
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_VOID mvAudioAddrDecShow(MV_VOID)
++{
++
++	MV_AUDIO_DEC_WIN win;
++	int i;
++
++	if (MV_FALSE == mvCtrlPwrClckGet(AUDIO_UNIT_ID, 0))
++		return;
++
++
++	mvOsOutput( "\n" );
++	mvOsOutput( "AUDIO:\n" );
++	mvOsOutput( "----\n" );
++
++	for( i = 0; i < MV_AUDIO_MAX_ADDR_DECODE_WIN; i++ )
++	{
++            memset( &win, 0, sizeof(MV_AUDIO_DEC_WIN) );
++
++	    mvOsOutput( "win%d - ", i );
++
++	    if( mvAudioWinGet( 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" );
++	    }
++	}
++}
++
++
++/*******************************************************************************
++* mvAudioWinInit - Initialize the integrated AUDIO target address window.
++*
++* DESCRIPTION:
++*       Initialize the AUDIO peripheral target address window.
++*
++* INPUT:
++*
++*
++* OUTPUT:
++*
++*
++* RETURN:
++*       MV_ERROR if register parameters are invalid.
++*
++*******************************************************************************/
++MV_STATUS mvAudioInit(MV_VOID)
++{
++    int             winNum;
++    MV_AUDIO_DEC_WIN  audioWin;
++    MV_CPU_DEC_WIN  cpuAddrDecWin;
++    MV_U32          status;
++
++    mvAudioHalInit();
++
++    /* 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(winNum));
++        regVal &= ~MV_AUDIO_WIN_ENABLE_MASK;
++        MV_REG_WRITE(MV_AUDIO_WIN_CTRL_REG(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 */
++		status = mvCpuIfTargetWinGet(SDRAM_CS0,
++									 &cpuAddrDecWin);
++
++		if (MV_OK != status)
++		{
++				mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__);
++			return MV_ERROR;
++		}
++
++		if (cpuAddrDecWin.enable == MV_TRUE)
++		{
++			audioWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++			audioWin.addrWin.baseLow  = cpuAddrDecWin.addrWin.baseLow;
++			audioWin.addrWin.size     = cpuAddrDecWin.addrWin.size;
++			audioWin.enable           = MV_TRUE;
++			audioWin.target           = SDRAM_CS0;
++
++			if(MV_OK != mvAudioWinSet(winNum, &audioWin))
++			{
++				return MV_ERROR;
++			}
++		}
++	}
++
++    return MV_OK;
++}
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.h
+new file mode 100644
+index 0000000..f59eb9a
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.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.
++
++*******************************************************************************/
++#ifndef __INCMVSysAudioH
++#define __INCMVSysAudioH
++
++#include "mvCommon.h"
++#include "audio/mvAudio.h"
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++/***********************************/
++/* Audio Address Decoding registers*/
++/***********************************/
++
++#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(win)        (AUDIO_REG_BASE + 0xA04 + ((win)<<3))
++#define MV_AUDIO_WIN_BASE_REG(win)        (AUDIO_REG_BASE + 0xA00 + ((win)<<3))
++
++#define MV_AUDIO_RECORD_WIN_CTRL_REG		MV_AUDIO_WIN_CTRL_REG(MV_AUDIO_RECORD_WIN_NUM)
++#define MV_AUDIO_RECORD_WIN_BASE_REG		MV_AUDIO_WIN_BASE_REG(MV_AUDIO_RECORD_WIN_NUM)
++#define MV_AUDIO_PLAYBACK_WIN_CTRL_REG		MV_AUDIO_WIN_CTRL_REG(MV_AUDIO_PLAYBACK_WIN_NUM)
++#define MV_AUDIO_PLAYBACK_WIN_BASE_REG		MV_AUDIO_WIN_BASE_REG(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)
++
++
++typedef struct _mvAudioDecWin
++{
++    MV_TARGET     target;
++    MV_ADDR_WIN   addrWin;    /* An address window*/
++    MV_BOOL       enable;     /* Address decode window is enabled/disabled    */
++
++} MV_AUDIO_DEC_WIN;
++
++
++MV_STATUS mvAudioInit(MV_VOID);
++MV_STATUS mvAudioWinGet(MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin);
++MV_STATUS mvAudioWinSet(MV_U32 winNum, MV_AUDIO_DEC_WIN *pAddrDecWin);
++MV_STATUS mvAudioWinInit(MV_VOID);
++MV_VOID   mvAudioAddrDecShow(MV_VOID);
++
++
++#endif
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.c
+new file mode 100644
+index 0000000..84d0cd0
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.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 "mvSysCesa.h"
++
++#if (MV_CESA_VERSION >= 2)
++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
++#if defined(MV_INCLUDE_PEX)
++    PEX0_MEM,
++#endif
++
++    TBL_TERM
++};
++
++/*******************************************************************************
++* mvCesaWinGet - Get TDMA target address window.
++*
++* DESCRIPTION:
++*       Get TDMA target address window.
++*
++* INPUT:
++*       winNum - TDMA target address decode window number.
++*
++* OUTPUT:
++*       pDecWin - TDMA target window data structure.
++*
++* RETURN:
++*       MV_ERROR if register parameters are invalid.
++*
++*******************************************************************************/
++static MV_STATUS mvCesaWinGet(MV_U32 winNum, MV_DEC_WIN *pDecWin)
++{
++    MV_DEC_WIN_PARAMS   winParam;
++    MV_U32              sizeReg, baseReg;
++
++    /* Parameter checking   */
++    if (winNum >= MV_CESA_TDMA_ADDR_DEC_WIN)
++    {
++        mvOsPrintf("%s : ERR. Invalid winNum %d\n",
++                    __FUNCTION__, winNum);
++        return MV_NOT_SUPPORTED;
++    }
++
++    baseReg = MV_REG_READ( MV_CESA_TDMA_BASE_ADDR_REG(winNum) );
++    sizeReg = MV_REG_READ( MV_CESA_TDMA_WIN_CTRL_REG(winNum) );
++
++   /* Check if window is enabled   */
++    if(sizeReg & MV_CESA_TDMA_WIN_ENABLE_MASK)
++    {
++        pDecWin->enable = MV_TRUE;
++
++        /* Extract window parameters from registers */
++        winParam.targetId = (sizeReg & MV_CESA_TDMA_WIN_TARGET_MASK) >> MV_CESA_TDMA_WIN_TARGET_OFFSET;
++        winParam.attrib   = (sizeReg & MV_CESA_TDMA_WIN_ATTR_MASK) >> MV_CESA_TDMA_WIN_ATTR_OFFSET;
++        winParam.size     = (sizeReg & MV_CESA_TDMA_WIN_SIZE_MASK) >> MV_CESA_TDMA_WIN_SIZE_OFFSET;
++        winParam.baseAddr = (baseReg & MV_CESA_TDMA_WIN_BASE_MASK);
++
++        /* Translate the decode window parameters to address decode struct */
++        if (MV_OK != mvCtrlParamsToAddrDec(&winParam, pDecWin))
++        {
++            mvOsPrintf("Failed to translate register parameters to CESA address" \
++                       " decode window structure\n");
++            return MV_ERROR;
++        }
++    }
++    else
++    {
++        pDecWin->enable = MV_FALSE;
++    }
++    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:
++*       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_U32 winNum, MV_ADDR_WIN *pAddrWin)
++{
++    MV_U32          winNumIndex;
++    MV_DEC_WIN      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 != mvCesaWinGet(winNumIndex, &addrDecWin))
++        {
++            mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__);
++            return MV_ERROR;
++        }
++
++        /* Do not check disabled windows    */
++        if(addrDecWin.enable == MV_FALSE)
++        {
++            continue;
++        }
++
++        if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
++        {
++            return MV_TRUE;
++        }
++    }
++    return MV_FALSE;
++}
++
++/*******************************************************************************
++* mvCesaTdmaWinSet - Set CESA TDMA 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 CESA TDMA will be able to access the
++*       target within the address window.
++*
++* INPUT:
++*       winNum      - CESA TDMA target address decode window number.
++*       pAddrDecWin - CESA TDMA 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 mvCesaTdmaWinSet(MV_U32 winNum, MV_DEC_WIN *pDecWin)
++{
++    MV_DEC_WIN_PARAMS   winParams;
++    MV_U32              sizeReg, baseReg;
++
++    /* 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(winNum, &pDecWin->addrWin))
++    {
++        mvOsPrintf("%s: ERR. Window %d overlap\n", __FUNCTION__, 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 to "\
++                   "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n",
++                   winNum,
++                   mvCtrlTargetNameGet(pDecWin->target),
++                   pDecWin->addrWin.baseLow,
++                   pDecWin->addrWin.size);
++        return MV_ERROR;
++    }
++
++    if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams))
++    {
++        mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__);
++        return MV_ERROR;
++    }
++
++    /* set Size, Attributes and TargetID */
++    sizeReg = (((winParams.targetId << MV_CESA_TDMA_WIN_TARGET_OFFSET) & MV_CESA_TDMA_WIN_TARGET_MASK) |
++               ((winParams.attrib   << MV_CESA_TDMA_WIN_ATTR_OFFSET)   & MV_CESA_TDMA_WIN_ATTR_MASK)   |
++               ((winParams.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 = (winParams.baseAddr & MV_CESA_TDMA_WIN_BASE_MASK);
++
++    MV_REG_WRITE( MV_CESA_TDMA_WIN_CTRL_REG(winNum), sizeReg);
++    MV_REG_WRITE( MV_CESA_TDMA_BASE_ADDR_REG(winNum), baseReg);
++
++    return MV_OK;
++}
++
++
++static MV_STATUS   mvCesaTdmaAddrDecInit (void)
++{
++    MV_U32          winNum;
++    MV_STATUS       status;
++    MV_CPU_DEC_WIN  cpuAddrDecWin;
++    MV_DEC_WIN      cesaWin;
++    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(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) )    {
++
++        /* first get attributes from CPU If */
++        status = mvCpuIfTargetWinGet(tdmaAddrDecPrioTable[winPrioIndex],
++                                     &cpuAddrDecWin);
++        if(MV_NO_SUCH == status){
++	    winPrioIndex++;
++            continue;
++	}
++
++        if (MV_OK != status)
++        {
++            mvOsPrintf("cesaInit: TargetWinGet failed. winNum=%d, winIdx=%d, target=%d, status=0x%x\n",
++                        winNum, winPrioIndex, tdmaAddrDecPrioTable[winPrioIndex], status);
++            return MV_ERROR;
++        }
++        if (cpuAddrDecWin.enable == MV_TRUE)
++        {
++            cesaWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++            cesaWin.addrWin.baseLow  = cpuAddrDecWin.addrWin.baseLow;
++            cesaWin.addrWin.size     = cpuAddrDecWin.addrWin.size;
++            cesaWin.enable           = MV_TRUE;
++            cesaWin.target           = tdmaAddrDecPrioTable[winPrioIndex];
++
++#if defined(MV646xx)
++            /* Get the default attributes for that target window */
++            mvCtrlDefAttribGet(cesaWin.target, &cesaWin.addrWinAttr);
++#endif /* MV646xx */
++
++            if(MV_OK != mvCesaTdmaWinSet(winNum, &cesaWin))
++            {
++                mvOsPrintf("mvCesaTdmaWinSet FAILED: winNum=%d\n",
++                           winNum);
++                return MV_ERROR;
++            }
++            winNum++;
++        }
++        winPrioIndex++;
++    }
++    return MV_OK;
++}
++#endif /* MV_CESA_VERSION >= 2 */
++
++
++
++
++MV_STATUS mvCesaInit (int numOfSession, int queueDepth, char* pSramBase, void *osHandle)
++{
++    MV_U32 cesaCryptEngBase;
++    MV_CPU_DEC_WIN addrDecWin;
++
++    if(sizeof(MV_CESA_SRAM_MAP) > MV_CESA_SRAM_SIZE)
++    {
++        mvOsPrintf("mvCesaInit: Wrong SRAM map - %ld > %d\n",
++                sizeof(MV_CESA_SRAM_MAP), MV_CESA_SRAM_SIZE);
++        return MV_FAIL;
++    }
++#if 0
++    if (mvCpuIfTargetWinGet(CRYPT_ENG, &addrDecWin) == MV_OK)
++        cesaCryptEngBase = addrDecWin.addrWin.baseLow;
++    else
++    {
++        mvOsPrintf("mvCesaInit: ERR. mvCpuIfTargetWinGet failed\n");
++        return MV_ERROR;
++    }
++#else
++        cesaCryptEngBase = (MV_U32)pSramBase;
++#endif
++
++#if 0 /* Already done in the platform init */
++#if (MV_CESA_VERSION >= 2)
++    mvCesaTdmaAddrDecInit();
++#endif /* MV_CESA_VERSION >= 2 */
++#endif
++	return mvCesaHalInit(numOfSession, queueDepth, pSramBase, cesaCryptEngBase,
++			     osHandle);
++
++}
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.h
+new file mode 100644
+index 0000000..73bcdc5
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.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 __mvSysCesa_h__
++#define __mvSysCesa_h__
++
++
++#include "mvCommon.h"
++#include "cesa/mvCesa.h"
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++/***************************** TDMA Registers *************************************/
++
++#define MV_CESA_TDMA_ADDR_DEC_WIN           4
++
++#define MV_CESA_TDMA_BASE_ADDR_REG(win)     (MV_CESA_TDMA_REG_BASE + 0xa00 + (win<<3))
++
++#define MV_CESA_TDMA_WIN_CTRL_REG(win)      (MV_CESA_TDMA_REG_BASE + 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)
++
++
++MV_STATUS   mvCesaInit (int numOfSession, int queueDepth, char* pSramBase, void *osHandle);
++
++#endif
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.c
+new file mode 100644
+index 0000000..6f76c2c
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.c
+@@ -0,0 +1,348 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "ddr2/mvDramIf.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++#include "ctrlEnv/sys/mvSysDram.h"
++
++/* #define MV_DEBUG */
++#ifdef MV_DEBUG
++#define DB(x) x
++#else
++#define DB(x)
++#endif
++
++static MV_BOOL sdramIfWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin);
++
++/*******************************************************************************
++* 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 baseToReg=0 , sizeToReg=0;
++
++    /* Check parameters */
++	if (!MV_TARGET_IS_DRAM(target))
++	{
++		mvOsPrintf("mvDramIfWinSet: target %d is not SDRAM\n", target);
++		return MV_BAD_PARAM;
++	}
++
++    /* 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));
++
++	/* BaseLow[31:16] => base register [31:16]		*/
++	baseToReg = pAddrDecWin->addrWin.baseLow & SCBAR_BASE_MASK;
++
++	/* Write to address decode Base Address Register                  */
++	baseReg &= ~SCBAR_BASE_MASK;
++	baseReg |= baseToReg;
++
++	/* Translate the given window size to register format			*/
++	sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, SCSR_SIZE_ALIGNMENT);
++
++	/* Size parameter validity check.                                   */
++	if (-1 == sizeToReg)
++	{
++		mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n",target);
++		return MV_BAD_PARAM;
++	}
++
++	/* 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;
++	/* Check parameters */
++	if (!MV_TARGET_IS_DRAM(target))
++	{
++		mvOsPrintf("mvDramIfWinGet: target %d is Illigal\n", target);
++		return MV_ERROR;
++	}
++
++	/* 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 = ctrlRegToSize(sizeRegVal,
++							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;
++
++	/* Check parameters */
++	if (!MV_TARGET_IS_DRAM(target))
++	{
++		mvOsPrintf("mvDramIfWinEnable: target %d is Illigal\n", target);
++		return MV_ERROR;
++	}
++
++	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;
++}
++
++/*******************************************************************************
++* 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 == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin))
++		{
++			mvOsPrintf(
++			"sdramIfWinOverlap: Required target %d overlap winNum %d\n",
++			target, targetNum);
++			return MV_TRUE;
++		}
++	}
++
++	return MV_FALSE;
++}
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.h
+new file mode 100644
+index 0000000..7bd9c9d
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.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.
++
++*******************************************************************************/
++
++
++#ifndef __sysDram
++#define __sysDram
++
++/* This structure describes CPU interface address decode window               */
++typedef struct _mvDramIfDecWin
++{
++	MV_ADDR_WIN   addrWin;    /* An address window*/
++	MV_BOOL       enable;     /* Address decode window is enabled/disabled    */
++}MV_DRAM_DEC_WIN;
++
++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);
++
++#endif
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.c
+new file mode 100644
+index 0000000..7f6e4a5
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.c
+@@ -0,0 +1,658 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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/sys/mvSysGbe.h"
++
++
++
++typedef struct _mvEthDecWin
++{
++    MV_TARGET     target;
++    MV_ADDR_WIN   addrWin;  /* An address window*/
++    MV_BOOL       enable;   /* Address decode window is enabled/disabled */
++
++}MV_ETH_DEC_WIN;
++
++MV_TARGET ethAddrDecPrioTap[] =
++{
++#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)
++        PEX0_IO,
++#endif
++        TBL_TERM
++};
++
++static MV_STATUS   ethWinOverlapDetect(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
++static MV_STATUS   mvEthWinSet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin);
++static MV_STATUS   mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin);
++
++
++/*******************************************************************************
++* mvEthWinInit - Initialize ETH address decode windows
++*
++* DESCRIPTION:
++*               This function initialize ETH window decode unit. It set the
++*               default address decode windows of the unit.
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       MV_ERROR if setting fail.
++*******************************************************************************/
++/* Configure EthDrv memory map registes. */
++MV_STATUS	mvEthWinInit (int port)
++{
++    MV_U32          winNum, status, winPrioIndex=0, i, regVal=0;
++    MV_ETH_DEC_WIN  ethWin;
++    MV_CPU_DEC_WIN  cpuAddrDecWin;
++    static MV_U32   accessProtReg = 0;
++
++#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; ((ethAddrDecPrioTap[winPrioIndex] != TBL_TERM) &&
++                    (winNum < ETH_MAX_DECODE_WIN)); )
++    {
++        /* first get attributes from CPU If */
++        status = mvCpuIfTargetWinGet(ethAddrDecPrioTap[winPrioIndex],
++                                     &cpuAddrDecWin);
++
++        if(MV_NO_SUCH == status)
++        {
++            winPrioIndex++;
++            continue;
++        }
++		if (MV_OK != status)
++		{
++			mvOsPrintf("mvEthWinInit: ERR. mvCpuIfTargetWinGet failed\n");
++			return MV_ERROR;
++		}
++
++        if (cpuAddrDecWin.enable == MV_TRUE)
++        {
++            ethWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++            ethWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow;
++            ethWin.addrWin.size = cpuAddrDecWin.addrWin.size;
++            ethWin.enable = MV_TRUE;
++            ethWin.target = ethAddrDecPrioTap[winPrioIndex];
++
++            if(MV_OK != mvEthWinSet(port, winNum, &ethWin))
++            {
++                mvOsPrintf("mvEthWinInit: ERR. mvEthWinSet failed winNum=%d\n",
++                           winNum);
++                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;
++}
++
++/*******************************************************************************
++* mvEthWinSet - Set ETH 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 ETH will be able to access the
++*       target within the address window.
++*
++* INPUT:
++*       winNum      - ETH to target address decode window number.
++*       pAddrDecWin - ETH 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 mvEthWinSet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin)
++{
++    MV_TARGET_ATTRIB    targetAttribs;
++    MV_DEC_REGS         decRegs;
++
++    /* 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("mvEthWinSet: 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 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;
++	}
++
++
++    decRegs.baseReg = MV_REG_READ(ETH_WIN_BASE_REG(port, winNum));
++    decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum));
++
++    if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs))
++    {
++        mvOsPrintf("mvEthWinSet:mvCtrlAddrDecToReg Failed\n");
++        return MV_ERROR;
++    }
++
++    mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs);
++
++    /* set attributes */
++    decRegs.baseReg &= ~ETH_WIN_ATTR_MASK;
++    decRegs.baseReg |= targetAttribs.attrib << ETH_WIN_ATTR_OFFS;
++    /* set target ID */
++    decRegs.baseReg &= ~ETH_WIN_TARGET_MASK;
++    decRegs.baseReg |= targetAttribs.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), decRegs.baseReg);
++
++    /* Write to address decode Size Register                            */
++    MV_REG_WRITE(ETH_WIN_SIZE_REG(port, winNum), decRegs.sizeReg);
++
++    /* Enable address decode target window                              */
++    if (pAddrDecWin->enable == MV_TRUE)
++    {
++            mvEthWinEnable(port, winNum, MV_TRUE);
++    }
++
++    return MV_OK;
++}
++
++/*******************************************************************************
++* mvETHWinGet - Get dma peripheral target address window.
++*
++* DESCRIPTION:
++*               Get ETH peripheral target address window.
++*
++* INPUT:
++*       winNum - ETH to target address decode window number.
++*
++* OUTPUT:
++*       pAddrDecWin - ETH target window data structure.
++*
++* RETURN:
++*       MV_ERROR if register parameters are invalid.
++*
++*******************************************************************************/
++MV_STATUS mvEthWinGet(int port, MV_U32 winNum, MV_ETH_DEC_WIN *pAddrDecWin)
++{
++    MV_DEC_REGS decRegs;
++    MV_TARGET_ATTRIB targetAttrib;
++
++    /* Parameter checking   */
++    if (winNum >= ETH_MAX_DECODE_WIN)
++    {
++        mvOsPrintf("mvEthWinGet: ERR. Invalid winNum %d\n", winNum);
++        return MV_NOT_SUPPORTED;
++    }
++
++    decRegs.baseReg =  MV_REG_READ(ETH_WIN_BASE_REG(port, winNum));
++    decRegs.sizeReg = MV_REG_READ(ETH_WIN_SIZE_REG(port, winNum));
++
++    if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin)))
++    {
++        mvOsPrintf("mvAhbToMbusWinGet: mvCtrlRegToAddrDec Failed \n");
++        return MV_ERROR;
++    }
++
++    /* attrib and targetId */
++    targetAttrib.attrib =
++     (decRegs.baseReg & ETH_WIN_ATTR_MASK) >> ETH_WIN_ATTR_OFFS;
++    targetAttrib.targetId =
++     (decRegs.baseReg & ETH_WIN_TARGET_MASK) >> ETH_WIN_TARGET_OFFS;
++
++    pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++    /* 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(int port, MV_U32 winNum,MV_BOOL enable)
++{
++    MV_ETH_DEC_WIN addrDecWin;
++
++    /* Parameter checking   */
++    if (winNum >= ETH_MAX_DECODE_WIN)
++    {
++        mvOsPrintf("mvEthTargetWinEnable:ERR. Invalid winNum%d\n",winNum);
++        return MV_ERROR;
++    }
++
++    if (enable == MV_TRUE)
++    {   /* First check for overlap with other enabled windows               */
++        /* Get current window */
++        if (MV_OK != mvEthWinGet(port, winNum, &addrDecWin))
++        {
++            mvOsPrintf("mvEthTargetWinEnable:ERR. targetWinGet fail\n");
++            return MV_ERROR;
++        }
++        /* Check for overlapping */
++        if (MV_FALSE == ethWinOverlapDetect(port, winNum, &(addrDecWin.addrWin)))
++        {
++            /* No Overlap. Enable address decode target window              */
++            MV_REG_BIT_RESET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum));
++        }
++        else
++        {   /* Overlap detected */
++            mvOsPrintf("mvEthTargetWinEnable:ERR. Overlap detected\n");
++            return MV_ERROR;
++        }
++    }
++    else
++    {   /* Disable address decode target window                             */
++        MV_REG_BIT_SET(ETH_BASE_ADDR_ENABLE_REG(port), (1 << winNum));
++    }
++    return MV_OK;
++}
++
++/*******************************************************************************
++* mvEthWinTargetGet - Get Window number associated with target
++*
++* DESCRIPTION:
++*
++* INPUT:
++*
++* OUTPUT:
++*
++* RETURN:
++*       window number
++*
++*******************************************************************************/
++MV_U32  mvEthWinTargetGet(int port, MV_TARGET target)
++{
++    MV_ETH_DEC_WIN decWin;
++    MV_U32 winNum;
++
++    /* Check parameters */
++    if (target >= MAX_TARGETS)
++    {
++        mvOsPrintf("mvAhbToMbusWinTargetGet: target %d is Illigal\n", target);
++        return 0xffffffff;
++    }
++
++    for (winNum=0; winNum<ETH_MAX_DECODE_WIN; winNum++)
++    {
++        if (mvEthWinGet(port, winNum,&decWin) != MV_OK)
++        {
++            mvOsPrintf("mvAhbToMbusWinTargetGet: window returned error\n");
++            return 0xffffffff;
++        }
++
++        if (decWin.enable == MV_TRUE)
++        {
++            if (decWin.target == target)
++            {
++                return winNum;
++            }
++        }
++    }
++    return 0xFFFFFFFF;
++}
++
++/*******************************************************************************
++* 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 >= mvCtrlEthMaxPortGet())
++    {
++        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;
++}
++
++/*******************************************************************************
++* 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(int port, MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
++{
++    MV_U32              baseAddrEnableReg;
++    MV_U32              winNumIndex;
++    MV_ETH_DEC_WIN      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 != mvEthWinGet(port, winNumIndex, &addrDecWin))
++        {
++            mvOsPrintf("ethWinOverlapDetect: ERR. TargetWinGet failed\n");
++            return MV_ERROR;
++        }
++/*
++        mvOsPrintf("ethWinOverlapDetect:\n
++            winNumIndex =%d baseHigh =0x%x baseLow=0x%x size=0x%x enable=0x%x\n",
++            winNumIndex,
++            addrDecWin.addrWin.baseHigh,
++            addrDecWin.addrWin.baseLow,
++            addrDecWin.addrWin.size,
++            addrDecWin.enable);
++*/
++        if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
++        {
++            return MV_TRUE;
++        }
++    }
++    return MV_FALSE;
++}
++
++/*******************************************************************************
++* mvEthAddrDecShow - Print the Etherent address decode map.
++*
++* DESCRIPTION:
++*       This function print the Etherent address decode map.
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++void    mvEthPortAddrDecShow(int port)
++{
++    MV_ETH_DEC_WIN  win;
++    int             i;
++
++    mvOsOutput( "\n" );
++    mvOsOutput( "ETH %d:\n", port );
++    mvOsOutput( "----\n" );
++
++    for( i = 0; i < ETH_MAX_DECODE_WIN; i++ )
++    {
++        memset( &win, 0, sizeof(ETH_MAX_DECODE_WIN) );
++
++        mvOsOutput( "win%d - ", i );
++
++        if( mvEthWinGet(port, 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" );
++        }
++    }
++    return;
++}
++
++void    mvEthAddrDecShow(void)
++{
++    int port;
++
++    for(port=0; port<mvCtrlEthMaxPortGet(); port++)
++    {
++	if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) continue;
++
++        mvEthPortAddrDecShow(port);
++    }
++}
++
++
++void    mvEthInit(void)
++{
++    MV_U32 port;
++
++    /* Power down all existing ports */
++    for(port=0; port<mvCtrlEthMaxPortGet(); port++)
++    {
++	    if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port))
++            continue;
++
++        mvEthPortPowerUp(port);
++	    mvEthWinInit(port);
++    }
++    mvEthHalInit();
++}
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.h
+new file mode 100644
+index 0000000..615af51
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.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.
++
++*******************************************************************************/
++
++#ifndef __INCmvSysGbeh
++#define __INCmvSysGbeh
++
++#include "mvCommon.h"
++#include "eth/mvEth.h"
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++#define ETH_WIN_BASE_REG(port, win)         (MV_ETH_REG_BASE(port) + 0x200 + ((win)<<3))
++#define ETH_WIN_SIZE_REG(port, win)         (MV_ETH_REG_BASE(port) + 0x204 + ((win)<<3))
++#define ETH_WIN_REMAP_REG(port, win)        (MV_ETH_REG_BASE(port) + 0x280 + ((win)<<2))
++#define ETH_BASE_ADDR_ENABLE_REG(port)      (MV_ETH_REG_BASE(port) + 0x290)
++#define ETH_ACCESS_PROTECT_REG(port)        (MV_ETH_REG_BASE(port) + 0x294)
++
++/**** Address decode parameters ****/
++
++/* Ethernet Base Address Register bits */
++#define ETH_MAX_DECODE_WIN              6
++#define ETH_MAX_HIGH_ADDR_REMAP_WIN     4
++
++/* Ethernet Port Access Protect (EPAP) register */
++
++/* 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)
++
++/* Ethernet Port Access Protect Register (EPAPR) */
++#define ETH_PROT_NO_ACCESS              NO_ACCESS_ALLOWED
++#define ETH_PROT_READ_ONLY              READ_ONLY
++#define ETH_PROT_FULL_ACCESS            FULL_ACCESS
++#define ETH_PROT_WIN_OFFS(winNum)       (2 * (winNum))
++#define ETH_PROT_WIN_MASK(winNum)       (0x3 << ETH_PROT_WIN_OFFS(winNum))
++
++MV_STATUS   mvEthWinInit (int port);
++MV_STATUS   mvEthWinEnable(int port, MV_U32 winNum, MV_BOOL enable);
++MV_U32      mvEthWinTargetGet(int port, MV_TARGET target);
++MV_STATUS mvEthProtWinSet(MV_U32 portNo, MV_U32 winNum, MV_ACCESS_RIGHTS
++		access);
++
++void        mvEthPortAddrDecShow(int port);
++
++MV_VOID     mvEthAddrDecShow(MV_VOID);
++
++void        mvEthInit(void);
++
++#endif
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.c
+new file mode 100644
+index 0000000..b0cb466
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.c
+@@ -0,0 +1,1697 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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/sys/mvSysPex.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
++};
++
++
++/* 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;
++
++static MV_STATUS pexWinOverlapDetect(MV_U32 pexIf, MV_U32 winNum,
++									 MV_ADDR_WIN *pAddrWin);
++static MV_STATUS pexWinRegInfoGet(MV_U32 pexIf, MV_U32 winNum,
++								  PEX_WIN_REG_INFO *pWinRegInfo);
++
++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);
++const MV_8* pexBarNameGet( MV_U32 bar );
++
++
++/*******************************************************************************
++* mvPexInit - 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 mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType)
++{
++	MV_U32			bar;
++	MV_U32			winNum;
++	MV_PEX_BAR		pexBar;
++	MV_PEX_DEC_WIN		pexWin;
++	MV_CPU_DEC_WIN		addrDecWin;
++	MV_TARGET		target;
++	MV_U32			pexCurrWin=0;
++	MV_U32			status;
++	/* 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
++
++	/* Parameter checking   */
++	if(pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexInit: ERR. Invalid PEX interface %d\n", pexIf);
++		return MV_BAD_PARAM;
++	}
++
++	/* Enabled CPU access to PCI-Express */
++	mvCpuIfEnablePex(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;
++
++	/* we only open the bar , no need to open windows for this bar */
++
++	/* first get the CS attribute from the CPU Interface */
++	if (MV_OK !=mvCpuIfTargetWinGet(INTER_REGS,&addrDecWin))
++	{
++		mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",INTER_REGS);
++		return MV_ERROR;
++	}
++
++	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++ )
++	{
++
++		status = mvCpuIfTargetWinGet(target,&addrDecWin);
++
++		if((MV_NO_SUCH == status)&&(target != SDRAM_CS0))
++		{
++			continue;
++		}
++
++		/* first get attributes from CPU If */
++		if (MV_OK != status)
++		{
++			mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target);
++			return MV_ERROR;
++		}
++		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 */
++			pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh;
++			pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow;
++			pexWin.addrWin.size = addrDecWin.addrWin.size;
++
++			/* 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 != mvPexTargetWinSet(pexIf,pexCurrWin++,&pexWin))
++			{
++				mvOsPrintf("mvPexInit: ERR. mvPexTargetWinSet failed\n");
++				return MV_ERROR;
++			}
++		}
++	}
++
++	/* check if the size of the bar is illeggal */
++	if (-1 == ctrlSizeToReg(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT))
++	{
++		/* try to get a good size */
++		pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size,
++												 PXBCR_BAR_SIZE_ALIGNMENT);
++	}
++
++	/* 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++ )
++	{
++		status = mvCpuIfTargetWinGet(target,&addrDecWin);
++
++		if (MV_NO_SUCH == status)
++		{
++			continue;
++		}
++
++		if (MV_OK != status)
++		{
++			mvOsPrintf("mvPexInit: ERR. mvCpuIfTargetWinGet failed target =%d\n",target);
++			return MV_ERROR;
++		}
++
++		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 !  */
++						pexWin.addrWin.baseHigh = addrDecWin.addrWin.baseHigh;
++						pexWin.addrWin.baseLow = addrDecWin.addrWin.baseLow;
++						pexWin.addrWin.size = addrDecWin.addrWin.size;
++
++						/* 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 != mvPexTargetWinSet(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 (-1 == ctrlSizeToReg(pexBar.addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT))
++	{
++		/* try to get a good size */
++		pexBar.addrWin.size = ctrlSizeRegRoundUp(pexBar.addrWin.size,
++												 PXBCR_BAR_SIZE_ALIGNMENT);
++	}
++
++	/* 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 mvPexHalInit(pexIf, pexType);
++
++}
++
++/*******************************************************************************
++* mvPexTargetWinSet - Set PEX to peripheral target address window BAR
++*
++* DESCRIPTION:
++*
++* 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 mvPexTargetWinSet(MV_U32 pexIf, MV_U32 winNum,
++                            MV_PEX_DEC_WIN *pAddrDecWin)
++{
++
++	MV_DEC_REGS decRegs;
++	PEX_WIN_REG_INFO winRegInfo;
++	MV_TARGET_ATTRIB targetAttribs;
++
++	/* Parameter checking   */
++	if(pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexTargetWinSet: ERR. Invalid PEX interface %d\n", pexIf);
++		return MV_BAD_PARAM;
++	}
++
++	if (winNum >= PEX_MAX_TARGET_WIN)
++	{
++		mvOsPrintf("mvPexTargetWinSet: 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)
++	{
++
++		/* 2) Check if the requested window overlaps with current windows  */
++		if (MV_TRUE == pexWinOverlapDetect(pexIf,winNum, &pAddrDecWin->addrWin))
++		{
++			mvOsPrintf("mvPexTargetWinSet: 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("mvPexTargetWinSet: Win %d should be in bar boundries\n",
++					   winNum);
++			return MV_BAD_PARAM;
++		}
++
++	}
++
++
++
++	/* read base register*/
++
++	if (winRegInfo.baseLowRegOffs)
++	{
++		decRegs.baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs);
++	}
++	else
++	{
++		decRegs.baseReg = 0;
++	}
++
++	if (winRegInfo.sizeRegOffs)
++	{
++		decRegs.sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs);
++	}
++	else
++	{
++		decRegs.sizeReg =0;
++	}
++
++	if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs))
++	{
++		mvOsPrintf("mvPexTargetWinSet:mvCtrlAddrDecToReg Failed\n");
++		return MV_ERROR;
++	}
++
++	/* enable\Disable */
++	if (MV_TRUE == pAddrDecWin->enable)
++	{
++		decRegs.sizeReg |= PXWCR_WIN_EN;
++	}
++	else
++	{
++		decRegs.sizeReg &= ~PXWCR_WIN_EN;
++	}
++
++
++	/* clear bit location */
++	decRegs.sizeReg &= ~PXWCR_WIN_BAR_MAP_MASK;
++
++	/* set bar Mapping */
++	if (pAddrDecWin->targetBar == 1)
++	{
++		decRegs.sizeReg |= PXWCR_WIN_BAR_MAP_BAR1;
++	}
++	else if (pAddrDecWin->targetBar == 2)
++	{
++		decRegs.sizeReg |= PXWCR_WIN_BAR_MAP_BAR2;
++	}
++
++	mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs);
++
++	/* set attributes */
++	decRegs.sizeReg &= ~PXWCR_ATTRIB_MASK;
++	decRegs.sizeReg |= targetAttribs.attrib << PXWCR_ATTRIB_OFFS;
++	/* set target ID */
++	decRegs.sizeReg &= ~PXWCR_TARGET_MASK;
++	decRegs.sizeReg |= targetAttribs.targetId << PXWCR_TARGET_OFFS;
++
++
++	/* 3) Write to address decode Base Address Register                   */
++
++	if (winRegInfo.baseLowRegOffs)
++	{
++		MV_REG_WRITE(winRegInfo.baseLowRegOffs, decRegs.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*/
++			decRegs.sizeReg &= ~PXWCR_SIZE_MASK;
++
++			/* clear enable because there is no enable field*/
++			decRegs.sizeReg &= ~PXWCR_WIN_EN;
++
++		}
++
++		MV_REG_WRITE(winRegInfo.sizeRegOffs, decRegs.sizeReg);
++	}
++
++
++    return MV_OK;
++
++}
++
++/*******************************************************************************
++* mvPexTargetWinGet - Get PEX to peripheral target address window
++*
++* 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 mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum,
++                            MV_PEX_DEC_WIN *pAddrDecWin)
++{
++	MV_TARGET_ATTRIB targetAttrib;
++	MV_DEC_REGS decRegs;
++
++	PEX_WIN_REG_INFO winRegInfo;
++
++	/* Parameter checking   */
++	if(pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexTargetWinGet: ERR. Invalid PEX interface %d\n", pexIf);
++		return MV_BAD_PARAM;
++	}
++
++	if (winNum >= PEX_MAX_TARGET_WIN)
++	{
++		mvOsPrintf("mvPexTargetWinGet: 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)
++	{
++		decRegs.baseReg = MV_REG_READ(winRegInfo.baseLowRegOffs);
++	}
++	else
++	{
++		decRegs.baseReg = 0;
++	}
++
++	/* read size reg */
++	if (winRegInfo.sizeRegOffs)
++	{
++		decRegs.sizeReg = MV_REG_READ(winRegInfo.sizeRegOffs);
++	}
++	else
++	{
++		decRegs.sizeReg =0;
++	}
++
++	if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin)))
++	{
++		mvOsPrintf("mvPexTargetWinGet: mvCtrlRegToAddrDec Failed \n");
++		return MV_ERROR;
++
++	}
++
++	if (decRegs.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 ((decRegs.sizeReg & PXWCR_WIN_BAR_MAP_MASK) == PXWCR_WIN_BAR_MAP_BAR1 )
++	{
++		pAddrDecWin->targetBar = 1;
++	}
++	else if ((decRegs.sizeReg & PXWCR_WIN_BAR_MAP_MASK) ==
++			 PXWCR_WIN_BAR_MAP_BAR2 )
++	{
++		pAddrDecWin->targetBar = 2;
++	}
++
++	/* attrib and targetId */
++	pAddrDecWin->attrib = (decRegs.sizeReg & PXWCR_ATTRIB_MASK) >>
++													PXWCR_ATTRIB_OFFS;
++	pAddrDecWin->targetId = (decRegs.sizeReg & PXWCR_TARGET_MASK) >>
++													PXWCR_TARGET_OFFS;
++
++	targetAttrib.attrib = pAddrDecWin->attrib;
++	targetAttrib.targetId = pAddrDecWin->targetId;
++
++	pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++	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)
++{
++	PEX_WIN_REG_INFO winRegInfo;
++	MV_PEX_DEC_WIN addrDecWin;
++
++	/* Parameter checking   */
++	if(pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexTargetWinEnable: ERR. Invalid PEX If %d\n", pexIf);
++		return MV_BAD_PARAM;
++	}
++
++	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 != mvPexTargetWinGet(pexIf,winNum, &addrDecWin))
++		{
++			mvOsPrintf("mvPexTargetWinEnable: mvPexTargetWinGet 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;
++
++	/* Parameter checking   */
++	if (pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n",
++																		pexIf);
++		return MV_BAD_PARAM;
++	}
++	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;
++
++	/* Parameter checking   */
++	if (pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexTargetWinRemap: ERR. Invalid PEX interface num %d\n",
++																		pexIf);
++		return MV_BAD_PARAM;
++	}
++	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(pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexBarSet: ERR. Invalid PEX interface %d\n", pexIf);
++		return MV_BAD_PARAM;
++	}
++
++	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 Illigal\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 = ctrlSizeToReg(pAddrWin->addrWin.size, PXBCR_BAR_SIZE_ALIGNMENT);
++
++	/* 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)
++{
++	/* check parameters */
++	if(pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexBarGet: ERR. Invalid PEX interface %d\n", pexIf);
++		return MV_BAD_PARAM;
++	}
++
++	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 = ctrlRegToSize(pAddrWin->addrWin.size,
++											   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;
++
++	/* check parameters */
++	if(pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexBarEnable: ERR. Invalid PEX interface %d\n", pexIf);
++		return MV_BAD_PARAM;
++	}
++
++
++	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 addrDecWin;
++
++
++	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 != mvPexTargetWinGet(pexIf, win, &addrDecWin))
++		{
++			mvOsPrintf("pexWinOverlapDetect: ERR. TargetWinGet failed win=%x\n",
++					   win);
++            return MV_ERROR;
++		}
++
++		/* Do not check disabled windows	*/
++		if (MV_FALSE == addrDecWin.enable)
++		{
++			continue;
++		}
++
++
++        if(MV_TRUE == ctrlWinOverlapTest(pAddrWin, &addrDecWin.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 == ctrlWinWithinWinTest(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'nt check disabled bars */
++        if (barDecWin.enable == MV_FALSE)
++		{
++			continue;
++		}
++
++
++        if(MV_TRUE == ctrlWinOverlapTest(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
++*
++*******************************************************************************/
++static 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";
++	}
++}
++/*******************************************************************************
++* 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" );
++		}
++
++	}
++}
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.h
+new file mode 100644
+index 0000000..3505613
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.h
+@@ -0,0 +1,348 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 __INCSysPEXH
++#define __INCSysPEXH
++
++#include "mvCommon.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.h"
++
++/* 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)		(0x41804 + (bar-1)*4- (pexIf)*0x10000)
++#define PEX_EXP_ROM_BAR_CTRL_REG(pexIf)	(0x4180C - (pexIf)*0x10000)
++
++
++/* 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)       \
++                                (0x41820 + (winNum) * 0x10 - (pexIf) * 0x10000)
++#define PEX_WIN0_3_BASE_REG(pexIf,winNum)       \
++                                (0x41824 + (winNum) * 0x10 - (pexIf) * 0x10000)
++#define PEX_WIN0_3_REMAP_REG(pexIf,winNum)      \
++                                (0x4182C + (winNum) * 0x10 - (pexIf) * 0x10000)
++#define PEX_WIN4_5_CTRL_REG(pexIf,winNum)       \
++                            (0x41860 + (winNum - 4) * 0x20 - (pexIf) * 0x10000)
++#define PEX_WIN4_5_BASE_REG(pexIf,winNum)       \
++                            (0x41864 + (winNum - 4) * 0x20 - (pexIf) * 0x10000)
++#define PEX_WIN4_5_REMAP_REG(pexIf,winNum)      \
++                            (0x4186C + (winNum - 4) * 0x20 - (pexIf) * 0x10000)
++#define PEX_WIN4_5_REMAP_HIGH_REG(pexIf,winNum) \
++                            (0x41870 + (winNum - 4) * 0x20 - (pexIf) * 0x10000)
++
++#define PEX_WIN_DEFAULT_CTRL_REG(pexIf)         (0x418B0 - (pexIf) * 0x10000)
++#define PEX_WIN_EXP_ROM_CTRL_REG(pexIf)         (0x418C0 - (pexIf) * 0x10000)
++#define PEX_WIN_EXP_ROM_REMAP_REG(pexIf)        (0x418C4 - (pexIf) * 0x10000)
++
++/* 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)
++
++/* 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 Remap Window attributes */
++typedef struct _mvPexDecWin
++{
++	MV_TARGET	  target;
++	MV_ADDR_WIN   addrWin;    /* An address window*/
++	MV_U32		  targetBar;
++	MV_U8			attrib;			/* chip select attributes */
++	MV_TARGET_ID	targetId;		/* Target Id of this MV_TARGET */
++	MV_BOOL       enable;     /* Address decode window is enabled/disabled    */
++
++}MV_PEX_DEC_WIN;
++
++/* Global Functions prototypes */
++/* mvPexHalInit - Initialize PEX interfaces*/
++MV_STATUS mvPexInit(MV_U32 pexIf, MV_PEX_TYPE pexType);
++
++
++/* mvPexTargetWinSet - Set PEX to peripheral target address window BAR*/
++MV_STATUS mvPexTargetWinSet(MV_U32 pexIf, MV_U32 winNum,
++                            MV_PEX_DEC_WIN *pAddrDecWin);
++
++/* mvPexTargetWinGet - Get PEX to peripheral target address window*/
++MV_STATUS mvPexTargetWinGet(MV_U32 pexIf, MV_U32 winNum,
++                            MV_PEX_DEC_WIN *pAddrDecWin);
++
++/* mvPexTargetWinEnable - Enable/disable a PEX BAR window*/
++MV_STATUS mvPexTargetWinEnable(MV_U32 pexIf,MV_U32 winNum, MV_BOOL enable);
++
++/* mvPexTargetWinRemap - Set PEX to target address window remap.*/
++MV_STATUS mvPexTargetWinRemap(MV_U32 pexIf, MV_U32 winNum,
++                           MV_PEX_REMAP_WIN *pAddrWin);
++
++/* mvPexTargetWinRemapEnable -enable\disable a PEX Window remap.*/
++MV_STATUS mvPexTargetWinRemapEnable(MV_U32 pexIf, MV_U32 winNum,
++                           MV_BOOL enable);
++
++/* mvPexBarSet - Set PEX bar address and size */
++MV_STATUS mvPexBarSet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *addrWin);
++
++/* mvPexBarGet - Get PEX bar address and size */
++MV_STATUS mvPexBarGet(MV_U32 pexIf, MV_U32 barNum, MV_PEX_BAR *addrWin);
++
++/* mvPexBarEnable - enable\disable a PEX bar*/
++MV_STATUS mvPexBarEnable(MV_U32 pexIf, MV_U32 barNum, MV_BOOL enable);
++
++/* mvPexAddrDecShow - Display address decode windows attributes */
++MV_VOID mvPexAddrDecShow(MV_VOID);
++
++#endif
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.c
+new file mode 100644
+index 0000000..f100a12
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.c
+@@ -0,0 +1,430 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "mvCommon.h"
++#include "mvOs.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "cpu/mvCpu.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++#include "sata/CoreDriver/mvRegs.h"
++#include "ctrlEnv/sys/mvSysSata.h"
++
++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_SATA_DEC_WIN  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 != mvSataWinGet(dev, winNumIndex, &addrDecWin))
++        {
++            mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__);
++            return MV_ERROR;
++        }
++
++        /* Do not check disabled windows    */
++        if(addrDecWin.enable == MV_FALSE)
++        {
++            continue;
++        }
++
++        if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
++        {
++            return MV_TRUE;
++        }
++    }
++    return MV_FALSE;
++}
++
++
++/*******************************************************************************
++* mvSataWinSet - 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 mvSataWinSet(int dev, MV_U32 winNum, MV_SATA_DEC_WIN *pAddrDecWin)
++{
++    MV_TARGET_ATTRIB    targetAttribs;
++    MV_DEC_REGS         decRegs;
++
++    /* Parameter checking   */
++    if (winNum >= MV_SATA_MAX_ADDR_DECODE_WIN)
++    {
++        mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, 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", __FUNCTION__, 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 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;
++    }
++
++    decRegs.baseReg = 0;
++    decRegs.sizeReg = 0;
++
++    if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs))
++    {
++        mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__);
++        return MV_ERROR;
++    }
++
++    mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs);
++
++    /* set attributes */
++    decRegs.sizeReg &= ~MV_SATA_WIN_ATTR_MASK;
++    decRegs.sizeReg |= (targetAttribs.attrib << MV_SATA_WIN_ATTR_OFFSET);
++
++    /* set target ID */
++    decRegs.sizeReg &= ~MV_SATA_WIN_TARGET_MASK;
++    decRegs.sizeReg |= (targetAttribs.targetId << MV_SATA_WIN_TARGET_OFFSET);
++
++    if (pAddrDecWin->enable == MV_TRUE)
++    {
++        decRegs.sizeReg |= MV_SATA_WIN_ENABLE_MASK;
++    }
++    else
++    {
++        decRegs.sizeReg &= ~MV_SATA_WIN_ENABLE_MASK;
++    }
++
++    MV_REG_WRITE( MV_SATA_WIN_CTRL_REG(dev, winNum), decRegs.sizeReg);
++    MV_REG_WRITE( MV_SATA_WIN_BASE_REG(dev, winNum), decRegs.baseReg);
++
++    return MV_OK;
++}
++
++/*******************************************************************************
++* mvSataWinGet - 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 mvSataWinGet(int dev, MV_U32 winNum, MV_SATA_DEC_WIN *pAddrDecWin)
++{
++    MV_DEC_REGS         decRegs;
++    MV_TARGET_ATTRIB    targetAttrib;
++
++    /* Parameter checking   */
++    if (winNum >= MV_SATA_MAX_ADDR_DECODE_WIN)
++    {
++        mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n",
++                    __FUNCTION__, dev, winNum);
++        return MV_NOT_SUPPORTED;
++    }
++
++    decRegs.baseReg = MV_REG_READ( MV_SATA_WIN_BASE_REG(dev, winNum) );
++    decRegs.sizeReg = MV_REG_READ( MV_SATA_WIN_CTRL_REG(dev, winNum) );
++
++    if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) )
++    {
++        mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__);
++        return MV_ERROR;
++    }
++
++    /* attrib and targetId */
++    targetAttrib.attrib = (decRegs.sizeReg & MV_SATA_WIN_ATTR_MASK) >>
++		MV_SATA_WIN_ATTR_OFFSET;
++    targetAttrib.targetId = (decRegs.sizeReg & MV_SATA_WIN_TARGET_MASK) >>
++		MV_SATA_WIN_TARGET_OFFSET;
++
++    pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++    /* Check if window is enabled   */
++    if(decRegs.sizeReg & MV_SATA_WIN_ENABLE_MASK)
++    {
++        pAddrDecWin->enable = MV_TRUE;
++    }
++    else
++    {
++        pAddrDecWin->enable = MV_FALSE;
++    }
++    return MV_OK;
++}
++/*******************************************************************************
++* 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" );
++	    }
++	}
++    }
++}
++
++
++/*******************************************************************************
++* 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_VOID)
++{
++    int             winNum;
++    MV_SATA_DEC_WIN  sataWin;
++    MV_CPU_DEC_WIN  cpuAddrDecWin;
++    MV_U32          status, 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) )
++    {
++        /* first get attributes from CPU If */
++        status = mvCpuIfTargetWinGet(sataAddrDecPrioTab[winPrioIndex],
++                                     &cpuAddrDecWin);
++
++        if(MV_NO_SUCH == status)
++        {
++            winPrioIndex++;
++            continue;
++        }
++	if (MV_OK != status)
++	{
++            mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__);
++	    return MV_ERROR;
++	}
++
++        if (cpuAddrDecWin.enable == MV_TRUE)
++        {
++            sataWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++            sataWin.addrWin.baseLow  = cpuAddrDecWin.addrWin.baseLow;
++            sataWin.addrWin.size     = cpuAddrDecWin.addrWin.size;
++            sataWin.enable           = MV_TRUE;
++            sataWin.target           = sataAddrDecPrioTab[winPrioIndex];
++
++            if(MV_OK != mvSataWinSet(0/*dev*/, winNum, &sataWin))
++            {
++                return MV_ERROR;
++            }
++            winNum++;
++        }
++        winPrioIndex++;
++    }
++    return MV_OK;
++}
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.h
+new file mode 100644
+index 0000000..325fb8d
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.h
+@@ -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.
++
++*******************************************************************************/
++#ifndef __INCMVSysSataAddrDech
++#define __INCMVSysSataAddrDech
++
++#include "mvCommon.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct _mvSataDecWin
++{
++    MV_TARGET     target;
++    MV_ADDR_WIN   addrWin;    /* An address window*/
++    MV_BOOL       enable;     /* Address decode window is enabled/disabled    */
++
++} MV_SATA_DEC_WIN;
++
++
++#define MV_SATA_MAX_ADDR_DECODE_WIN 4
++
++#define MV_SATA_WIN_CTRL_REG(dev, win)        (SATA_REG_BASE + 0x30 + ((win)<<4))
++#define MV_SATA_WIN_BASE_REG(dev, win)        (SATA_REG_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)
++
++MV_STATUS mvSataWinGet(int dev, MV_U32 winNum, MV_SATA_DEC_WIN *pAddrDecWin);
++MV_STATUS mvSataWinSet(int dev, MV_U32 winNum, MV_SATA_DEC_WIN *pAddrDecWin);
++MV_STATUS mvSataWinByTargetGet(MV_TARGET target, MV_SATA_DEC_WIN *pAddrDecWin);
++MV_STATUS mvSataWinInit(MV_VOID);
++MV_VOID   mvSataAddrDecShow(MV_VOID);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++
++#endif
++
++
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.c
+new file mode 100644
+index 0000000..6d2a919
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.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.
++
++*******************************************************************************/
++
++
++#include "mvTypes.h"
++#include "mvCommon.h"
++#include "mvOs.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "cpu/mvCpu.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++#include "mvRegs.h"
++#include "ctrlEnv/sys/mvSysSdmmc.h"
++
++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_SDMMC_DEC_WIN  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 != mvSdmmcWinGet(dev, winNumIndex, &addrDecWin))
++        {
++            mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__);
++            return MV_ERROR;
++        }
++
++        /* Do not check disabled windows    */
++        if(addrDecWin.enable == MV_FALSE)
++        {
++            continue;
++        }
++
++        if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
++        {
++            return MV_TRUE;
++        }
++    }
++    return MV_FALSE;
++}
++
++
++/*******************************************************************************
++* mvSdmmcWinSet - 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 mvSdmmcWinSet(int dev, MV_U32 winNum, MV_SDMMC_DEC_WIN *pAddrDecWin)
++{
++    MV_TARGET_ATTRIB    targetAttribs;
++    MV_DEC_REGS         decRegs;
++
++    /* Parameter checking   */
++    if (winNum >= MV_SDMMC_MAX_ADDR_DECODE_WIN)
++    {
++        mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, 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", __FUNCTION__, winNum);
++        return MV_ERROR;
++    }
++
++    /* check if address is aligned to the size */
++    if(MV_IS_NOT_ALIGN(pAddrDecWin->addrWin.baseLow, pAddrDecWin->addrWin.size))
++    {
++	mvOsPrintf("mvSdmmcWinSet:Error setting SDMMC 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;
++    }
++
++    decRegs.baseReg = 0;
++    decRegs.sizeReg = 0;
++
++    if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs))
++    {
++        mvOsPrintf("%s: mvCtrlAddrDecToReg Failed\n", __FUNCTION__);
++        return MV_ERROR;
++    }
++
++    mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs);
++
++    /* set attributes */
++    decRegs.sizeReg &= ~MV_SDMMC_WIN_ATTR_MASK;
++    decRegs.sizeReg |= (targetAttribs.attrib << MV_SDMMC_WIN_ATTR_OFFSET);
++
++    /* set target ID */
++    decRegs.sizeReg &= ~MV_SDMMC_WIN_TARGET_MASK;
++    decRegs.sizeReg |= (targetAttribs.targetId << MV_SDMMC_WIN_TARGET_OFFSET);
++
++    if (pAddrDecWin->enable == MV_TRUE)
++    {
++        decRegs.sizeReg |= MV_SDMMC_WIN_ENABLE_MASK;
++    }
++    else
++    {
++        decRegs.sizeReg &= ~MV_SDMMC_WIN_ENABLE_MASK;
++    }
++
++    MV_REG_WRITE( MV_SDMMC_WIN_CTRL_REG(dev, winNum), decRegs.sizeReg);
++    MV_REG_WRITE( MV_SDMMC_WIN_BASE_REG(dev, winNum), decRegs.baseReg);
++
++    return MV_OK;
++}
++
++/*******************************************************************************
++* mvSdmmcWinGet - Get SDMMC peripheral target address window.
++*
++* DESCRIPTION:
++*       Get SDMMC peripheral target address window.
++*
++* INPUT:
++*       winNum - SDMMC target address decode window number.
++*d
++* OUTPUT:
++*       pAddrDecWin - SDMMC target window data structure.
++*
++* RETURN:
++*       MV_ERROR if register parameters are invalid.
++*
++*******************************************************************************/
++MV_STATUS mvSdmmcWinGet(int dev, MV_U32 winNum, MV_SDMMC_DEC_WIN *pAddrDecWin)
++{
++    MV_DEC_REGS         decRegs;
++    MV_TARGET_ATTRIB    targetAttrib;
++
++    /* Parameter checking   */
++    if (winNum >= MV_SDMMC_MAX_ADDR_DECODE_WIN)
++    {
++        mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n",
++                    __FUNCTION__, dev, winNum);
++        return MV_NOT_SUPPORTED;
++    }
++
++    decRegs.baseReg = MV_REG_READ( MV_SDMMC_WIN_BASE_REG(dev, winNum) );
++    decRegs.sizeReg = MV_REG_READ( MV_SDMMC_WIN_CTRL_REG(dev, winNum) );
++
++    if (MV_OK != mvCtrlRegToAddrDec(&decRegs, &pAddrDecWin->addrWin) )
++    {
++        mvOsPrintf("%s: mvCtrlRegToAddrDec Failed\n", __FUNCTION__);
++        return MV_ERROR;
++    }
++
++    /* attrib and targetId */
++    targetAttrib.attrib = (decRegs.sizeReg & MV_SDMMC_WIN_ATTR_MASK) >>
++		MV_SDMMC_WIN_ATTR_OFFSET;
++    targetAttrib.targetId = (decRegs.sizeReg & MV_SDMMC_WIN_TARGET_MASK) >>
++		MV_SDMMC_WIN_TARGET_OFFSET;
++
++    pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++    /* Check if window is enabled   */
++    if(decRegs.sizeReg & MV_SDMMC_WIN_ENABLE_MASK)
++    {
++        pAddrDecWin->enable = MV_TRUE;
++    }
++    else
++    {
++        pAddrDecWin->enable = MV_FALSE;
++    }
++    return MV_OK;
++}
++/*******************************************************************************
++* mvSdmmcAddrDecShow - Print the SDMMC address decode map.
++*
++* DESCRIPTION:
++*		This function print the SDMMC address decode map.
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_VOID mvSdmmcAddrDecShow(MV_VOID)
++{
++
++	MV_SDMMC_DEC_WIN win;
++	int i,j=0;
++
++
++
++	if (MV_FALSE == mvCtrlPwrClckGet(SDIO_UNIT_ID, 0))
++		return;
++
++	mvOsOutput( "\n" );
++	mvOsOutput( "SDMMC %d:\n", j );
++	mvOsOutput( "----\n" );
++
++	for( i = 0; i < MV_SDMMC_MAX_ADDR_DECODE_WIN; i++ )
++	{
++            memset( &win, 0, sizeof(MV_SDMMC_DEC_WIN) );
++
++	    mvOsOutput( "win%d - ", i );
++
++	    if( mvSdmmcWinGet(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" );
++	    }
++	}
++}
++
++
++/*******************************************************************************
++* 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_VOID)
++{
++    int             winNum;
++    MV_SDMMC_DEC_WIN  sdmmcWin;
++    MV_CPU_DEC_WIN  cpuAddrDecWin;
++    MV_U32          status, 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) )
++    {
++        /* first get attributes from CPU If */
++        status = mvCpuIfTargetWinGet(sdmmcAddrDecPrioTab[winPrioIndex],
++                                     &cpuAddrDecWin);
++
++        if(MV_NO_SUCH == status)
++        {
++            winPrioIndex++;
++            continue;
++        }
++	if (MV_OK != status)
++	{
++            mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__);
++	    return MV_ERROR;
++	}
++
++        if (cpuAddrDecWin.enable == MV_TRUE)
++        {
++            sdmmcWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++            sdmmcWin.addrWin.baseLow  = cpuAddrDecWin.addrWin.baseLow;
++            sdmmcWin.addrWin.size     = cpuAddrDecWin.addrWin.size;
++            sdmmcWin.enable           = MV_TRUE;
++            sdmmcWin.target           = sdmmcAddrDecPrioTab[winPrioIndex];
++
++            if(MV_OK != mvSdmmcWinSet(0/*dev*/, winNum, &sdmmcWin))
++            {
++                return MV_ERROR;
++            }
++            winNum++;
++        }
++        winPrioIndex++;
++    }
++    return MV_OK;
++}
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.h
+new file mode 100644
+index 0000000..4c50a2b
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.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 __INCMVSysSdmmcAddrDech
++#define __INCMVSysSdmmcAddrDech
++
++#include "mvCommon.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef struct _mvSdmmcDecWin
++{
++    MV_TARGET     target;
++    MV_ADDR_WIN   addrWin;    /* An address window*/
++    MV_BOOL       enable;     /* Address decode window is enabled/disabled    */
++
++} MV_SDMMC_DEC_WIN;
++
++
++#define MV_SDMMC_MAX_ADDR_DECODE_WIN 4
++
++#define MV_SDMMC_WIN_CTRL_REG(dev, win)        (MV_SDIO_REG_BASE + 0x108 + ((win)<<3))
++#define MV_SDMMC_WIN_BASE_REG(dev, win)        (MV_SDIO_REG_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)
++
++MV_STATUS mvSdmmcWinGet(int dev, MV_U32 winNum, MV_SDMMC_DEC_WIN *pAddrDecWin);
++MV_STATUS mvSdmmcWinSet(int dev, MV_U32 winNum, MV_SDMMC_DEC_WIN *pAddrDecWin);
++MV_STATUS mvSdmmcWinByTargetGet(MV_TARGET target, MV_SDMMC_DEC_WIN *pAddrDecWin);
++MV_STATUS mvSdmmcWinInit(MV_VOID);
++MV_VOID   mvSdmmcAddrDecShow(MV_VOID);
++
++
++#ifdef __cplusplus
++}
++#endif
++
++
++#endif
++
++
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.c
+new file mode 100644
+index 0000000..ecf6944
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.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 "mvSysTdm.h"
++
++
++/* defines  */
++#ifdef MV_DEBUG
++	#define DB(x)	x
++#else
++	#define DB(x)
++#endif
++
++static MV_TARGET tdmAddrDecPrioTap[] =
++{
++        PEX0_MEM,
++        SDRAM_CS0,
++        SDRAM_CS1,
++        SDRAM_CS2,
++        SDRAM_CS3,
++        DEVICE_CS0,
++        DEVICE_CS1,
++        DEVICE_CS2,
++        DEV_BOOCS,
++        PEX0_IO,
++        TBL_TERM
++};
++
++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(void)
++{
++	MV_U32		winNum;
++	MV_U32		winPrioIndex = 0;
++	MV_CPU_DEC_WIN cpuAddrDecWin;
++	MV_TDM_DEC_WIN tdmWin;
++	MV_STATUS status;
++
++	/*Disable all windows*/
++	for (winNum = 0; winNum < TDM_MBUS_MAX_WIN; winNum++)
++	{
++		mvTdmWinEnable(winNum, MV_FALSE);
++	}
++
++	for (winNum = 0; ((tdmAddrDecPrioTap[winPrioIndex] != TBL_TERM) &&
++					  (winNum < TDM_MBUS_MAX_WIN)); )
++	{
++		status = mvCpuIfTargetWinGet(tdmAddrDecPrioTap[winPrioIndex],
++									 &cpuAddrDecWin);
++        if (MV_NO_SUCH == status)
++        {
++            winPrioIndex++;
++            continue;
++        }
++		if (MV_OK != status)
++		{
++			mvOsPrintf("mvTdmInit: ERR. mvCpuIfTargetWinGet failed\n");
++			return MV_ERROR;
++		}
++
++        if (cpuAddrDecWin.enable == MV_TRUE)
++		{
++			tdmWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++			tdmWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow;
++			tdmWin.addrWin.size = cpuAddrDecWin.addrWin.size;
++			tdmWin.enable = MV_TRUE;
++		    tdmWin.target = tdmAddrDecPrioTap[winPrioIndex];
++		    if (MV_OK != mvTdmWinSet(winNum, &tdmWin))
++		    {
++			    return MV_ERROR;
++		    }
++		    winNum++;
++		}
++		winPrioIndex++;
++    }
++	return MV_OK;
++}
++
++/*******************************************************************************
++* mvTdmWinSet - 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.
++*       pAddrDecWin - 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.
++*
++*******************************************************************************/
++
++MV_STATUS mvTdmWinSet(MV_U32 winNum, MV_TDM_DEC_WIN *pAddrDecWin)
++{
++	MV_TARGET_ATTRIB targetAttribs;
++	MV_DEC_REGS decRegs;
++	MV_U32 ctrlReg = 0;
++
++    /* Parameter checking   */
++    if (winNum >= TDM_MBUS_MAX_WIN)
++    {
++		mvOsPrintf("mvTdmWinSet: 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, &pAddrDecWin->addrWin))
++	{
++		mvOsPrintf("mvTdmWinSet: 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("mvTdmWinSet: Error setting TDM 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;
++	}
++
++	decRegs.baseReg = MV_REG_READ(TDM_WIN_BASE_REG(winNum));
++	decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >>  TDM_WIN_SIZE_OFFS;
++
++	if (MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs))
++	{
++			mvOsPrintf("mvTdmWinSet: mvCtrlAddrDecToReg Failed\n");
++			return MV_ERROR;
++	}
++
++	mvCtrlAttribGet(pAddrDecWin->target, &targetAttribs);
++
++	/* for the safe side we disable the window before writing the new
++	values */
++	mvTdmWinEnable(winNum, MV_FALSE);
++
++	ctrlReg |= (targetAttribs.attrib << TDM_WIN_ATTRIB_OFFS);
++	ctrlReg |= (targetAttribs.targetId << TDM_WIN_TARGET_OFFS);
++	ctrlReg |= (decRegs.sizeReg & TDM_WIN_SIZE_MASK);
++
++	/* Write to address base and control registers  */
++	MV_REG_WRITE(TDM_WIN_BASE_REG(winNum), decRegs.baseReg);
++	MV_REG_WRITE(TDM_WIN_CTRL_REG(winNum), ctrlReg);
++	/* Enable address decode target window  */
++	if (pAddrDecWin->enable == MV_TRUE)
++	{
++		mvTdmWinEnable(winNum, MV_TRUE);
++	}
++	return MV_OK;
++}
++
++/*******************************************************************************
++* mvTdmWinGet - Get peripheral target address window.
++*
++* DESCRIPTION:
++*               Get TDM peripheral target address window.
++*
++* INPUT:
++*       winNum - TDM to target address decode window number.
++*
++* OUTPUT:
++*       pAddrDecWin - TDM target window data structure.
++*
++* RETURN:
++*       MV_ERROR if register parameters are invalid.
++*
++*******************************************************************************/
++
++MV_STATUS mvTdmWinGet(MV_U32 winNum, MV_TDM_DEC_WIN *pAddrDecWin)
++{
++
++	MV_DEC_REGS decRegs;
++	MV_TARGET_ATTRIB targetAttrib;
++
++	/* Parameter checking   */
++	if (winNum >= TDM_MBUS_MAX_WIN)
++	{
++		mvOsPrintf("mvTdmWinGet: ERR. Invalid winNum %d\n", winNum);
++		return MV_NOT_SUPPORTED;
++	}
++
++	decRegs.baseReg =  MV_REG_READ(TDM_WIN_BASE_REG(winNum));
++	decRegs.sizeReg = (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_SIZE_MASK) >>  TDM_WIN_SIZE_OFFS;
++
++	if (MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin)))
++	{
++		mvOsPrintf("mvTdmWinGet: mvCtrlRegToAddrDec Failed \n");
++		return MV_ERROR;
++	}
++
++	/* attrib and targetId */
++	targetAttrib.attrib =
++		(MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ATTRIB_MASK) >>  TDM_WIN_ATTRIB_OFFS;
++	targetAttrib.targetId =
++		(MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_TARGET_MASK) >>  TDM_WIN_TARGET_OFFS;
++
++	pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++	/* Check if window is enabled   */
++	if (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ENABLE_MASK)
++	{
++		pAddrDecWin->enable = MV_TRUE;
++	}
++	else
++	{
++		pAddrDecWin->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 (before enabling the window it is
++*       tested for overlapping). 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.
++*
++*******************************************************************************/
++MV_STATUS mvTdmWinEnable(int winNum, MV_BOOL enable)
++{
++	MV_TDM_DEC_WIN addrDecWin;
++
++	if (MV_TRUE == enable)
++	{
++		if (winNum >= TDM_MBUS_MAX_WIN)
++		{
++			mvOsPrintf("mvTdmWinEnable:ERR. Invalid winNum%d\n",winNum);
++			return MV_ERROR;
++		}
++
++		/* First check for overlap with other enabled windows				*/
++		/* Get current window */
++		if (MV_OK != mvTdmWinGet(winNum, &addrDecWin))
++		{
++			mvOsPrintf("mvTdmWinEnable:ERR. targetWinGet fail\n");
++			return MV_ERROR;
++		}
++		/* Check for overlapping */
++		if (MV_FALSE == tdmWinOverlapDetect(winNum, &(addrDecWin.addrWin)))
++		{
++			/* No Overlap. Enable address decode target window */
++			MV_REG_BIT_SET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK);
++		}
++		else
++		{   /* Overlap detected	*/
++			mvOsPrintf("mvTdmWinEnable:ERR. Overlap detected\n");
++			return MV_ERROR;
++		}
++	}
++	else
++	{
++		MV_REG_BIT_RESET(TDM_WIN_CTRL_REG(winNum), TDM_WIN_ENABLE_MASK);
++	}
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* 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.
++*       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 tdmWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
++{
++    MV_U32		winNumIndex;
++    MV_TDM_DEC_WIN	addrDecWin;
++
++    for (winNumIndex = 0; winNumIndex < TDM_MBUS_MAX_WIN; winNumIndex++)
++    {
++		/* Do not check window itself		*/
++        if (winNumIndex == winNum)
++		{
++			continue;
++		}
++		/* Do not check disabled windows	*/
++		if (MV_REG_READ(TDM_WIN_CTRL_REG(winNum)) & TDM_WIN_ENABLE_MASK)
++		{
++			/* Get window parameters	*/
++			if (MV_OK != mvTdmWinGet(winNumIndex, &addrDecWin))
++			{
++				DB(mvOsPrintf("dmaWinOverlapDetect: ERR. TargetWinGet failed\n"));
++			return MV_ERROR;
++			}
++
++			if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
++			{
++				return MV_TRUE;
++			}
++		}
++    }
++	return MV_FALSE;
++}
++
++/*******************************************************************************
++* mvTdmAddrDecShow - Print the TDM address decode map.
++*
++* DESCRIPTION:
++*       This function print the TDM address decode map.
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_VOID mvTdmAddrDecShow(MV_VOID)
++{
++	MV_TDM_DEC_WIN win;
++	int i;
++
++	mvOsOutput( "\n" );
++	mvOsOutput( "TDM:\n" );
++	mvOsOutput( "----\n" );
++
++	for( i = 0; i < TDM_MBUS_MAX_WIN; i++ )
++	{
++		memset( &win, 0, sizeof(MV_TDM_DEC_WIN) );
++
++		mvOsOutput( "win%d - ", i );
++
++		if (mvTdmWinGet(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" );
++		}
++	}
++}
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.h
+new file mode 100644
+index 0000000..0d3140f
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.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.
++
++*******************************************************************************/
++
++#ifndef __INCmvSysTdmh
++#define __INCmvSysTdmh
++
++#include "ctrlEnv/sys/mvCpuIf.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.h"
++
++typedef struct _mvTdmDecWin
++{
++        MV_TARGET     target;
++        MV_ADDR_WIN   addrWin; /* An address window*/
++        MV_BOOL       enable;  /* Address decode window is enabled/disabled */
++} MV_TDM_DEC_WIN;
++
++MV_STATUS mvTdmWinInit(MV_VOID);
++MV_STATUS mvTdmWinSet(MV_U32 winNum, MV_TDM_DEC_WIN *pAddrDecWin);
++MV_STATUS mvTdmWinGet(MV_U32 winNum, MV_TDM_DEC_WIN *pAddrDecWin);
++MV_STATUS mvTdmWinEnable(int winNum, MV_BOOL enable);
++MV_VOID mvTdmAddrDecShow(MV_VOID);
++
++
++#define TDM_MBUS_MAX_WIN	4
++#define TDM_WIN_CTRL_REG(win)	((TDM_REG_BASE + 0x4030) + (win<<4))
++#define TDM_WIN_BASE_REG(win)	((TDM_REG_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)
++
++#endif /*__INCmvSysTdmh*/
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.c
+new file mode 100644
+index 0000000..4415c7c
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.c
+@@ -0,0 +1,591 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++	notice, this list of conditions and the following disclaimer in the
++	documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++	used to endorse or promote products derived from this software without
++	specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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/sys/mvSysTs.h"
++
++
++typedef struct _mvTsuDecWin
++{
++        MV_TARGET     target;
++        MV_ADDR_WIN   addrWin; /* An address window*/
++        MV_BOOL       enable;  /* Address decode window is enabled/disabled */
++
++}MV_TSU_DEC_WIN;
++
++
++MV_TARGET tsuAddrDecPrioTap[] =
++{
++#if defined(MV_INCLUDE_PEX)
++        PEX0_MEM,
++#endif
++#if defined(MV_INCLUDE_PCI)
++        PCI0_MEM,
++#endif
++#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)
++        PEX0_IO,
++#endif
++#if defined(MV_INCLUDE_PCI)
++        PCI0_IO,
++#endif
++        TBL_TERM
++};
++
++static MV_STATUS tsuWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin);
++static MV_STATUS mvTsuWinSet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin);
++static MV_STATUS mvTsuWinGet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin);
++MV_STATUS mvTsuWinEnable(MV_U32 winNum,MV_BOOL enable);
++
++/*******************************************************************************
++* mvTsuWinInit
++*
++* DESCRIPTION:
++*	Initialize the TSU unit address decode windows.
++*
++* INPUT:
++*       None.
++* OUTPUT:
++*	None.
++* RETURN:
++*       MV_OK	- on success,
++*
++*******************************************************************************/
++MV_STATUS mvTsuWinInit(void)
++{
++	MV_U32          winNum, status, winPrioIndex=0;
++	MV_TSU_DEC_WIN  tsuWin;
++	MV_CPU_DEC_WIN  cpuAddrDecWin;
++
++	/* 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));)
++	{
++		/* first get attributes from CPU If */
++		status = mvCpuIfTargetWinGet(tsuAddrDecPrioTap[winPrioIndex],
++					     &cpuAddrDecWin);
++
++		if(MV_NO_SUCH == status)
++		{
++			winPrioIndex++;
++			continue;
++		}
++		if(MV_OK != status)
++		{
++			mvOsPrintf("mvTsuWinInit: ERR. mvCpuIfTargetWinGet failed\n");
++			return MV_ERROR;
++		}
++
++		if (cpuAddrDecWin.enable == MV_TRUE)
++		{
++			tsuWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++			tsuWin.addrWin.baseLow = cpuAddrDecWin.addrWin.baseLow;
++			tsuWin.addrWin.size = cpuAddrDecWin.addrWin.size;
++			tsuWin.enable = MV_TRUE;
++			tsuWin.target = tsuAddrDecPrioTap[winPrioIndex];
++
++			if(MV_OK != mvTsuWinSet(winNum, &tsuWin))
++			{
++				mvOsPrintf("mvTsuWinInit: ERR. mvTsuWinSet failed winNum=%d\n",
++					   winNum);
++				return MV_ERROR;
++			}
++			winNum++;
++		}
++		winPrioIndex ++;
++	}
++
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* mvTsuWinSet
++*
++* 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:
++*       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 mvTsuWinSet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin)
++{
++	MV_TARGET_ATTRIB    targetAttribs;
++	MV_DEC_REGS         decRegs;
++
++	/* 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 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;
++	}
++
++	decRegs.baseReg = MV_REG_READ(MV_TSU_WIN_BASE_REG(winNum));
++	decRegs.sizeReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum));
++
++	if(MV_OK != mvCtrlAddrDecToReg(&(pAddrDecWin->addrWin),&decRegs))
++	{
++		mvOsPrintf("mvTsuWinSet: mvCtrlAddrDecToReg Failed\n");
++		return MV_ERROR;
++	}
++
++	mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs);
++
++	/* set attributes */
++	decRegs.sizeReg &= ~TSU_WIN_CTRL_ATTR_MASK;
++	decRegs.sizeReg |= targetAttribs.attrib << TSU_WIN_CTRL_ATTR_OFFS;
++	/* set target ID */
++	decRegs.sizeReg &= ~TSU_WIN_CTRL_TARGET_MASK;
++	decRegs.sizeReg |= targetAttribs.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),decRegs.sizeReg);
++
++	/* Write to address decode Size Register                            */
++	MV_REG_WRITE(MV_TSU_WIN_BASE_REG(winNum), decRegs.baseReg);
++
++	/* Enable address decode target window                              */
++	if(pAddrDecWin->enable == MV_TRUE)
++	{
++		mvTsuWinEnable(winNum,MV_TRUE);
++	}
++
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* mvTsuWinGet
++*
++* DESCRIPTION:
++*	Get TSU peripheral target address window.
++*
++* INPUT:
++*	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 mvTsuWinGet(MV_U32 winNum, MV_TSU_DEC_WIN *pAddrDecWin)
++{
++	MV_DEC_REGS decRegs;
++	MV_TARGET_ATTRIB targetAttrib;
++
++	/* Parameter checking   */
++	if(winNum >= TSU_MAX_DECODE_WIN)
++	{
++		mvOsPrintf("mvTsuWinGet: ERR. Invalid winNum %d\n", winNum);
++		return MV_NOT_SUPPORTED;
++	}
++
++	decRegs.baseReg = MV_REG_READ(MV_TSU_WIN_BASE_REG(winNum));
++	decRegs.sizeReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNum));
++
++	if(MV_OK != mvCtrlRegToAddrDec(&decRegs,&(pAddrDecWin->addrWin)))
++	{
++		mvOsPrintf("mvTsuWinGet: mvCtrlRegToAddrDec Failed \n");
++		return MV_ERROR;
++	}
++
++	/* attrib and targetId */
++	targetAttrib.attrib =
++		(decRegs.sizeReg & TSU_WIN_CTRL_ATTR_MASK) >> TSU_WIN_CTRL_ATTR_OFFS;
++	targetAttrib.targetId =
++		(decRegs.sizeReg & TSU_WIN_CTRL_TARGET_MASK) >> TSU_WIN_CTRL_TARGET_OFFS;
++
++	pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++	/* 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
++*
++* DESCRIPTION:
++*       This function enable/disable a TSU to target address window.
++*       According to parameter 'enable' the routine will enable the
++*       window, thus enabling TSU accesses (before enabling the window it is
++*       tested for overlapping). Otherwise, the window will be disabled.
++*
++* INPUT:
++*       winNum - TSU 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 mvTsuWinEnable(MV_U32 winNum,MV_BOOL enable)
++{
++	MV_TSU_DEC_WIN addrDecWin;
++
++	/* Parameter checking   */
++	if(winNum >= TSU_MAX_DECODE_WIN)
++	{
++		mvOsPrintf("mvTsuWinEnable: ERR. Invalid winNum%d\n",winNum);
++		return MV_ERROR;
++	}
++
++	if(enable == MV_TRUE)
++	{
++		/* First check for overlap with other enabled windows   */
++		/* Get current window.					*/
++		if(MV_OK != mvTsuWinGet(winNum,&addrDecWin))
++		{
++			mvOsPrintf("mvTsuWinEnable: ERR. targetWinGet fail\n");
++			return MV_ERROR;
++		}
++		/* Check for overlapping.	*/
++		if(MV_FALSE == tsuWinOverlapDetect(winNum,&(addrDecWin.addrWin)))
++		{
++			/* No Overlap. Enable address decode target window   */
++			MV_REG_BIT_SET(MV_TSU_WIN_CTRL_REG(winNum),
++				       TSU_WIN_CTRL_EN_MASK);
++		}
++		else
++		{
++			/* Overlap detected */
++			mvOsPrintf("mvTsuWinEnable: ERR. Overlap detected\n");
++			return MV_ERROR;
++		}
++	}
++	else
++	{
++		/* Disable address decode target window */
++		MV_REG_BIT_RESET(MV_TSU_WIN_CTRL_REG(winNum),
++				 TSU_WIN_CTRL_EN_MASK);
++	}
++	return MV_OK;
++}
++
++/*******************************************************************************
++* mvTsuWinTargetGet
++*
++* DESCRIPTION:
++*	Get Window number associated with target
++*
++* INPUT:
++*	target	- Target ID to get the window number for.
++* OUTPUT:
++*
++* RETURN:
++*       window number or 0xFFFFFFFF on error.
++*
++*******************************************************************************/
++MV_U32  mvTsuWinTargetGet(MV_TARGET target)
++{
++	MV_TSU_DEC_WIN decWin;
++	MV_U32 winNum;
++
++	/* Check parameters */
++	if(target >= MAX_TARGETS)
++	{
++		mvOsPrintf("mvTsuWinTargetGet: target %d is Illigal\n", target);
++		return 0xffffffff;
++	}
++
++	for(winNum = 0; winNum < TSU_MAX_DECODE_WIN; winNum++)
++	{
++		if(mvTsuWinGet(winNum,&decWin) != MV_OK)
++		{
++			mvOsPrintf("mvTsuWinGet: window returned error\n");
++			return 0xffffffff;
++		}
++
++		if (decWin.enable == MV_TRUE)
++		{
++			if(decWin.target == target)
++			{
++				return winNum;
++			}
++		}
++	}
++	return 0xFFFFFFFF;
++}
++
++
++/*******************************************************************************
++* tsuWinOverlapDetect
++*
++* DESCRIPTION:
++*	Detect TSU address windows overlapping
++*	An unpredicted behaviur is expected in case TSU address decode
++*	windows overlapps.
++*	This function detects TSU 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 tsuWinOverlapDetect(MV_U32 winNum, MV_ADDR_WIN *pAddrWin)
++{
++	MV_U32              ctrlReg;
++	MV_U32              winNumIndex;
++	MV_TSU_DEC_WIN      addrDecWin;
++
++	for(winNumIndex = 0; winNumIndex < TSU_MAX_DECODE_WIN; winNumIndex++)
++	{
++		/* Do not check window itself           */
++		if(winNumIndex == winNum)
++		{
++			continue;
++		}
++
++		/* Do not check disabled windows        */
++		ctrlReg = MV_REG_READ(MV_TSU_WIN_CTRL_REG(winNumIndex));
++		if((ctrlReg & TSU_WIN_CTRL_EN_MASK) == 0)
++		{
++			continue;
++		}
++
++		/* Get window parameters        */
++		if (MV_OK != mvTsuWinGet(winNumIndex, &addrDecWin))
++		{
++			mvOsPrintf("tsuWinOverlapDetect: ERR. mvTsuWinGet failed\n");
++			return MV_ERROR;
++		}
++
++		if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
++		{
++			return MV_TRUE;
++		}
++	}
++	return MV_FALSE;
++}
++
++
++/*******************************************************************************
++* mvTsuAddrDecShow
++*
++* DESCRIPTION:
++*	Print the TSU address decode map.
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++void mvTsuAddrDecShow(void)
++{
++	MV_TSU_DEC_WIN  win;
++	int             i;
++
++	if (MV_FALSE == mvCtrlPwrClckGet(TS_UNIT_ID, 0))
++		return;
++
++	mvOsOutput( "\n" );
++	mvOsOutput( "TSU:\n");
++	mvOsOutput( "----\n" );
++
++	for(i = 0; i < TSU_MAX_DECODE_WIN; i++)
++	{
++		memset(&win, 0, sizeof(TSU_MAX_DECODE_WIN));
++		mvOsOutput( "win%d - ", i );
++
++		if(mvTsuWinGet(i, &win ) == MV_OK )
++		{
++			if(win.enable == MV_TRUE)
++			{
++				mvOsOutput("%s base %08x, ",
++					   mvCtrlTargetNameGet(win.target),
++					   win.addrWin.baseLow);
++				mvOsOutput( "...." );
++				mvSizePrint(win.addrWin.size );
++				mvOsOutput( "\n" );
++			}
++			else
++			{
++				mvOsOutput( "disable\n" );
++			}
++		}
++	}
++	return;
++}
++
++
++/*******************************************************************************
++* mvTsuInit
++*
++* 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).
++*	memHandle	- Memory handle used for memory allocations.
++* OUTPUT:
++*	None.
++* RETURN:
++*       MV_OK	- on success,
++*
++*******************************************************************************/
++MV_STATUS mvTsuInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode,
++	            void *osHandle)
++{
++	MV_STATUS status;
++
++	status = mvTsuWinInit();
++	if(status == MV_OK)
++		status = mvTsuHalInit(coreClock,mode,osHandle);
++
++	return status;
++}
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.h
+new file mode 100644
+index 0000000..4282589
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.h
+@@ -0,0 +1,110 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++        this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 __INCmvSysTsh
++#define __INCmvSysTsh
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++/* includes */
++#include "ts/mvTsu.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.h"
++
++#define TSU_MAX_DECODE_WIN	4
++
++
++/*******************************************/
++/* TSU Windows Registers                   */
++/*******************************************/
++#define MV_TSU_WIN_CTRL_REG(win)	(TSU_GLOBAL_REG_BASE +0x30 + 0x10 * win)
++#define MV_TSU_WIN_BASE_REG(win)	(TSU_GLOBAL_REG_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)
++
++/* TSU windows base register.			*/
++#define TSU_WIN_BASE_OFFS		16
++#define TSU_WIN_BASE_MASK		(0xFFFF << TSU_WIN_BASE_OFFS)
++
++MV_STATUS mvTsuWinInit(void);
++
++void mvTsuAddrDecShow(void);
++MV_STATUS mvTsuInit(MV_TSU_CORE_CLOCK coreClock, MV_TSU_PORTS_MODE mode,
++	            void *osHandle);
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* __INCmvTsh */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.c
+new file mode 100644
+index 0000000..195b5e1
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.c
+@@ -0,0 +1,497 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++        this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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/sys/mvSysUsb.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)
++    PEX0_MEM,
++#endif
++    TBL_TERM
++};
++
++
++
++MV_STATUS   mvUsbInit(int dev, MV_BOOL isHost)
++{
++    MV_STATUS       status;
++
++    status = mvUsbWinInit(dev);
++    if(status != MV_OK)
++        return status;
++
++    return mvUsbHalInit(dev, isHost);
++}
++
++
++/*******************************************************************************
++* 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(int dev, MV_U32 winNum,
++                                     MV_ADDR_WIN *pAddrWin)
++{
++    MV_U32          winNumIndex;
++    MV_DEC_WIN      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 != mvUsbWinGet(dev, winNumIndex, &addrDecWin))
++        {
++            mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__);
++            return MV_ERROR;
++        }
++
++        /* Do not check disabled windows    */
++        if(addrDecWin.enable == MV_FALSE)
++        {
++            continue;
++        }
++
++        if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
++        {
++            return MV_TRUE;
++        }
++    }
++    return MV_FALSE;
++}
++
++/*******************************************************************************
++* mvUsbWinSet - 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 mvUsbWinSet(int dev, MV_U32 winNum, MV_DEC_WIN *pDecWin)
++{
++    MV_DEC_WIN_PARAMS   winParams;
++    MV_U32              sizeReg, baseReg;
++
++    /* Parameter checking   */
++    if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN)
++    {
++        mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, 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", __FUNCTION__, winNum);
++        return MV_ERROR;
++    }
++
++    /* check if address is aligned to the size */
++    if(MV_IS_NOT_ALIGN(pDecWin->addrWin.baseLow, pDecWin->addrWin.size))
++    {
++        mvOsPrintf("mvUsbWinSet:Error setting USB window %d to "\
++                   "target %s.\nAddress 0x%08x is unaligned to size 0x%x.\n",
++                   winNum,
++                   mvCtrlTargetNameGet(pDecWin->target),
++                   pDecWin->addrWin.baseLow,
++                   pDecWin->addrWin.size);
++        return MV_ERROR;
++    }
++
++    if(MV_OK != mvCtrlAddrDecToParams(pDecWin, &winParams))
++    {
++        mvOsPrintf("%s: mvCtrlAddrDecToParams Failed\n", __FUNCTION__);
++        return MV_ERROR;
++    }
++
++    /* set Size, Attributes and TargetID */
++    sizeReg = (((winParams.targetId << MV_USB_WIN_TARGET_OFFSET) & MV_USB_WIN_TARGET_MASK) |
++               ((winParams.attrib   << MV_USB_WIN_ATTR_OFFSET)   & MV_USB_WIN_ATTR_MASK)   |
++               ((winParams.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 = (winParams.baseAddr & 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;
++}
++
++/*******************************************************************************
++* mvUsbWinGet - 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 mvUsbWinGet(int dev, MV_U32 winNum, MV_DEC_WIN *pDecWin)
++{
++    MV_DEC_WIN_PARAMS   winParam;
++    MV_U32              sizeReg, baseReg;
++
++    /* Parameter checking   */
++    if (winNum >= MV_USB_MAX_ADDR_DECODE_WIN)
++    {
++        mvOsPrintf("%s (dev=%d): ERR. Invalid winNum %d\n",
++                    __FUNCTION__, 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 */
++        winParam.targetId = (sizeReg & MV_USB_WIN_TARGET_MASK) >> MV_USB_WIN_TARGET_OFFSET;
++        winParam.attrib   = (sizeReg & MV_USB_WIN_ATTR_MASK) >> MV_USB_WIN_ATTR_OFFSET;
++        winParam.size     = (sizeReg & MV_USB_WIN_SIZE_MASK) >> MV_USB_WIN_SIZE_OFFSET;
++        winParam.baseAddr = (baseReg & MV_USB_WIN_BASE_MASK);
++
++        /* Translate the decode window parameters to address decode struct */
++        if (MV_OK != mvCtrlParamsToAddrDec(&winParam, pDecWin))
++        {
++            mvOsPrintf("Failed to translate register parameters to USB address" \
++                       " decode window structure\n");
++            return MV_ERROR;
++        }
++    }
++    else
++    {
++        pDecWin->enable = MV_FALSE;
++    }
++    return MV_OK;
++}
++
++/*******************************************************************************
++* mvUsbWinInit -
++*
++* INPUT:
++*
++* OUTPUT:
++*
++* RETURN:
++*       MV_ERROR if register parameters are invalid.
++*
++*******************************************************************************/
++MV_STATUS   mvUsbWinInit(int dev)
++{
++    MV_STATUS       status;
++    MV_DEC_WIN      usbWin;
++    MV_CPU_DEC_WIN  cpuAddrDecWin;
++    int             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) )
++    {
++        /* first get attributes from CPU If */
++        status = mvCpuIfTargetWinGet(usbAddrDecPrioTab[winPrioIndex],
++                                     &cpuAddrDecWin);
++
++        if(MV_NO_SUCH == status)
++        {
++            winPrioIndex++;
++            continue;
++        }
++        if (MV_OK != status)
++        {
++            mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__);
++            return MV_ERROR;
++        }
++
++        if (cpuAddrDecWin.enable == MV_TRUE)
++        {
++            usbWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++            usbWin.addrWin.baseLow  = cpuAddrDecWin.addrWin.baseLow;
++            usbWin.addrWin.size     = cpuAddrDecWin.addrWin.size;
++            usbWin.enable           = MV_TRUE;
++            usbWin.target           = usbAddrDecPrioTab[winPrioIndex];
++
++#if defined(MV645xx) || defined(MV646xx)
++            /* Get the default attributes for that target window */
++            mvCtrlDefAttribGet(usbWin.target, &usbWin.addrWinAttr);
++#endif /* MV645xx || MV646xx */
++
++            if(MV_OK != mvUsbWinSet(dev, winNum, &usbWin))
++            {
++                return MV_ERROR;
++            }
++            winNum++;
++        }
++        winPrioIndex++;
++    }
++    return MV_OK;
++}
++
++/*******************************************************************************
++* mvUsbAddrDecShow - Print the USB address decode map.
++*
++* DESCRIPTION:
++*       This function print the USB address decode map.
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_VOID mvUsbAddrDecShow(MV_VOID)
++{
++    MV_DEC_WIN  addrDecWin;
++    int         i, winNum;
++
++    mvOsOutput( "\n" );
++    mvOsOutput( "USB:\n" );
++    mvOsOutput( "----\n" );
++
++    for(i=0; i<mvCtrlUsbMaxGet(); i++)
++    {
++        mvOsOutput( "Device %d:\n", i);
++
++        for(winNum = 0; winNum < MV_USB_MAX_ADDR_DECODE_WIN; winNum++)
++        {
++            memset(&addrDecWin, 0, sizeof(MV_DEC_WIN) );
++
++            mvOsOutput( "win%d - ", winNum );
++
++            if( mvUsbWinGet(i, winNum, &addrDecWin ) == MV_OK )
++            {
++                if( addrDecWin.enable )
++                {
++                    mvOsOutput( "%s base %08x, ",
++                        mvCtrlTargetNameGet(addrDecWin.target), addrDecWin.addrWin.baseLow );
++
++                    mvSizePrint( addrDecWin.addrWin.size );
++
++#if defined(MV645xx) || defined(MV646xx)
++                    switch( addrDecWin.addrWinAttr.swapType)
++                    {
++                        case MV_BYTE_SWAP:
++                            mvOsOutput( "BYTE_SWAP, " );
++                            break;
++                        case MV_NO_SWAP:
++                            mvOsOutput( "NO_SWAP  , " );
++                            break;
++                        case MV_BYTE_WORD_SWAP:
++                            mvOsOutput( "BYTE_WORD_SWAP, " );
++                            break;
++                        case MV_WORD_SWAP:
++                            mvOsOutput( "WORD_SWAP, " );
++                            break;
++                        default:
++                            mvOsOutput( "SWAP N/A , " );
++                    }
++
++                    switch( addrDecWin.addrWinAttr.cachePolicy )
++                    {
++                        case NO_COHERENCY:
++                            mvOsOutput( "NO_COHERENCY , " );
++                            break;
++                        case WT_COHERENCY:
++                            mvOsOutput( "WT_COHERENCY , " );
++                            break;
++                        case WB_COHERENCY:
++                            mvOsOutput( "WB_COHERENCY , " );
++                            break;
++                        default:
++                            mvOsOutput( "COHERENCY N/A, " );
++                    }
++
++                    switch( addrDecWin.addrWinAttr.pcixNoSnoop )
++                    {
++                        case 0:
++                            mvOsOutput( "PCI-X NS inactive, " );
++                            break;
++                        case 1:
++                            mvOsOutput( "PCI-X NS active  , " );
++                            break;
++                        default:
++                            mvOsOutput( "PCI-X NS N/A     , " );
++                    }
++
++                    switch( addrDecWin.addrWinAttr.p2pReq64 )
++                    {
++                        case 0:
++                            mvOsOutput( "REQ64 force" );
++                            break;
++                        case 1:
++                            mvOsOutput( "REQ64 detect" );
++                            break;
++                        default:
++                            mvOsOutput( "REQ64 N/A" );
++                    }
++#endif /* MV645xx || MV646xx */
++                    mvOsOutput( "\n" );
++                }
++                else
++                    mvOsOutput( "disable\n" );
++            }
++        }
++    }
++}
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.h
+new file mode 100644
+index 0000000..07f98de
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.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 __INCmvSysUsbh
++#define __INCmvSysUsbh
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++/* includes */
++#include "usb/mvUsb.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.h"
++
++#define MV_USB_MAX_ADDR_DECODE_WIN  4
++
++/*******************************************/
++/* USB Bridge Registers                    */
++/*******************************************/
++#define MV_USB_BRIDGE_CTRL_REG(dev)              (USB_REG_BASE(dev) + 0x300)
++
++#define MV_USB_WIN_CTRL_REG(dev, win)        (USB_REG_BASE(dev) + 0x320 + ((win)<<4))
++#define MV_USB_WIN_BASE_REG(dev, win)        (USB_REG_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_BRIDGE_IPG_REG(dev)          (USB_REG_BASE(dev) + 0x360)
++
++
++MV_STATUS   mvUsbInit(int dev, MV_BOOL isHost);
++
++MV_STATUS   mvUsbWinInit(int dev);
++MV_STATUS   mvUsbWinSet(int dev, MV_U32 winNum, MV_DEC_WIN *pAddrWin);
++MV_STATUS   mvUsbWinGet(int dev, MV_U32 winNum, MV_DEC_WIN *pAddrWin);
++
++void        mvUsbAddrDecShow(void);
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* __INCmvUsbh */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.c b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.c
+new file mode 100644
+index 0000000..f9d0ab3
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.c
+@@ -0,0 +1,662 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "xor/mvXor.h"
++#include "mvSysXor.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_DEVICE_CS0)
++    DEVICE_CS0,
++#endif
++#if defined(MV_INCLUDE_PEX)
++	PEX0_MEM,
++#endif
++#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_CS1)
++    DEVICE_CS1,
++#endif
++#if defined(MV_INCLUDE_CESA)
++   CRYPT_ENG,
++#endif
++	TBL_TERM
++};
++static MV_STATUS mvXorInitWinsUnit (MV_U32 unit)
++{
++	MV_U32         winNum;
++	MV_XOR_DEC_WIN addrDecWin;
++	MV_CPU_DEC_WIN cpuAddrDecWin;
++	MV_U32          status;
++	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));)
++	{
++		/* first get attributes from CPU If */
++		status = mvCpuIfTargetWinGet(xorAddrDecPrioTap[winPrioIndex],
++									 &cpuAddrDecWin);
++
++        if(MV_NO_SUCH == status)
++        {
++            winPrioIndex++;
++            continue;
++        }
++		if (MV_OK != status)
++		{
++            mvOsPrintf("%s: ERR. mvCpuIfTargetWinGet failed\n", __FUNCTION__);
++			return MV_ERROR;
++		}
++
++
++        if (cpuAddrDecWin.enable == MV_TRUE)
++		{
++
++			addrDecWin.target           = xorAddrDecPrioTap[winPrioIndex];
++			addrDecWin.addrWin.baseLow  = cpuAddrDecWin.addrWin.baseLow;
++			addrDecWin.addrWin.baseHigh = cpuAddrDecWin.addrWin.baseHigh;
++			addrDecWin.addrWin.size     = cpuAddrDecWin.addrWin.size;
++			addrDecWin.enable           = MV_TRUE;
++
++			if (MV_OK != mvXorTargetWinSet(unit,winNum, &addrDecWin))
++			{
++				DB(mvOsPrintf("mvXorInit: ERR. mvDmaTargetWinSet failed\n"));
++				return MV_ERROR;
++			}
++			winNum++;
++		}
++		winPrioIndex++;
++
++	}
++
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* mvXorInit - Initialize XOR engine
++*
++* DESCRIPTION:
++*		This function initialize XOR unit. It set 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 mvXorInit (MV_VOID)
++{
++	MV_U32         i;
++
++	/* Initiate XOR address decode */
++	for(i = 0; i < MV_XOR_MAX_UNIT; i++)
++	    mvXorInitWinsUnit(i);
++
++	mvXorHalInit(MV_XOR_MAX_CHAN);
++
++	return MV_OK;
++}
++
++/*******************************************************************************
++* mvXorTargetWinSet - 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 mvXorTargetWinSet(MV_U32 unit, MV_U32 winNum, MV_XOR_DEC_WIN *pAddrDecWin)
++{
++    MV_DEC_REGS xorDecRegs;
++	MV_TARGET_ATTRIB targetAttribs;
++    MV_U32      chan;
++
++    /* Parameter checking */
++    if (winNum >= XOR_MAX_ADDR_DEC_WIN)
++    {
++		DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__, winNum));
++        return MV_BAD_PARAM;
++    }
++    if (pAddrDecWin == NULL)
++    {
++        DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ ));
++        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",__FUNCTION__,winNum));
++	return MV_ERROR;
++    }
++
++    xorDecRegs.baseReg = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum));
++    xorDecRegs.sizeReg = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum));
++
++    /* Get Base Address and size registers values */
++    if(MV_OK != mvCtrlAddrDecToReg(&pAddrDecWin->addrWin, &xorDecRegs))
++    {
++		DB(mvOsPrintf("%s: ERR. Invalid addr dec window\n",__FUNCTION__));
++        return MV_BAD_PARAM;
++	}
++
++
++	mvCtrlAttribGet(pAddrDecWin->target,&targetAttribs);
++
++	/* set attributes */
++	xorDecRegs.baseReg &= ~XEBARX_ATTR_MASK;
++	xorDecRegs.baseReg |= targetAttribs.attrib << XEBARX_ATTR_OFFS;
++	/* set target ID */
++	xorDecRegs.baseReg &= ~XEBARX_TARGET_MASK;
++	xorDecRegs.baseReg |= targetAttribs.targetId << XEBARX_TARGET_OFFS;
++
++
++    /* Write to address decode Base Address Register */
++	MV_REG_WRITE(XOR_BASE_ADDR_REG(unit,winNum), xorDecRegs.baseReg);
++
++    /* Write to Size Register */
++	MV_REG_WRITE(XOR_SIZE_MASK_REG(unit,winNum), xorDecRegs.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;
++}
++
++/*******************************************************************************
++* mvXorTargetWinGet - 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 mvXorTargetWinGet(MV_U32 unit,MV_U32 winNum, MV_XOR_DEC_WIN *pAddrDecWin)
++{
++    MV_DEC_REGS xorDecRegs;
++	MV_TARGET_ATTRIB targetAttrib;
++    MV_U32      chan=0,chanWinEn;
++
++    /* Parameter checking */
++    if (winNum >= XOR_MAX_ADDR_DEC_WIN)
++    {
++		DB(mvOsPrintf("%s: ERR. Invalid win num %d\n",__FUNCTION__ , winNum));
++        return MV_ERROR;
++    }
++
++    if (NULL == pAddrDecWin)
++    {
++        DB(mvOsPrintf("%s: ERR. pAddrDecWin is NULL pointer\n", __FUNCTION__ ));
++        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",__FUNCTION__, chan);
++            return MV_ERROR;
++        }
++    }
++
++
++
++	xorDecRegs.baseReg  = MV_REG_READ(XOR_BASE_ADDR_REG(unit,winNum));
++	xorDecRegs.sizeReg  = MV_REG_READ(XOR_SIZE_MASK_REG(unit,winNum));
++
++	if (MV_OK != mvCtrlRegToAddrDec(&xorDecRegs, &pAddrDecWin->addrWin))
++	{
++		mvOsPrintf("%s: ERR. mvCtrlRegToAddrDec failed\n", __FUNCTION__);
++		return MV_ERROR;
++	}
++
++	/* attrib and targetId */
++	targetAttrib.attrib =
++		(xorDecRegs.baseReg & XEBARX_ATTR_MASK) >> XEBARX_ATTR_OFFS;
++	targetAttrib.targetId =
++		(xorDecRegs.baseReg & XEBARX_TARGET_MASK) >> XEBARX_TARGET_OFFS;
++
++
++	pAddrDecWin->target = mvCtrlTargetGet(&targetAttrib);
++
++	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_XOR_DEC_WIN  addrDecWin;
++    MV_U32          chan;
++
++	/* Parameter checking   */
++    if (winNum >= XOR_MAX_ADDR_DEC_WIN)
++    {
++        DB(mvOsPrintf("%s: ERR. Invalid winNum%d\n", __FUNCTION__, winNum));
++        return MV_ERROR;
++    }
++
++	if (enable == MV_TRUE)
++	{
++		/* Get current window */
++	    if (MV_OK != mvXorTargetWinGet(unit,winNum, &addrDecWin))
++		{
++			DB(mvOsPrintf("%s: ERR. targetWinGet fail\n", __FUNCTION__));
++			return MV_ERROR;
++		}
++
++		/* Check for overlapping */
++	    if (MV_TRUE == xorWinOverlapDetect(unit,winNum, &(addrDecWin.addrWin)))
++		{
++			/* Overlap detected	*/
++			DB(mvOsPrintf("%s: ERR. Overlap detected\n", __FUNCTION__));
++			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", __FUNCTION__ , chan));
++        return MV_BAD_PARAM;
++    }
++    if (winNum >= XOR_MAX_ADDR_DEC_WIN)
++    {
++		DB(mvOsPrintf("%s: ERR. Invalid win num %d\n", __FUNCTION__, 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", __FUNCTION__, 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_XOR_DEC_WIN  addrDecWin;
++
++	if (pAddrWin == NULL)
++	{
++		DB(mvOsPrintf("%s: ERR. pAddrWin is NULL pointer\n", __FUNCTION__ ));
++		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 != mvXorTargetWinGet(unit,winNumIndex, &addrDecWin))
++			{
++				DB(mvOsPrintf("%s: ERR. TargetWinGet failed\n", __FUNCTION__ ));
++				return MV_ERROR;
++			}
++
++			if (MV_TRUE == ctrlWinOverlapTest(pAddrWin, &(addrDecWin.addrWin)))
++			{
++				return MV_TRUE;
++			}
++		}
++	}
++
++	return MV_FALSE;
++}
++
++static MV_VOID mvXorAddrDecShowUnit(MV_U32 unit)
++{
++	MV_XOR_DEC_WIN win;
++	int            i;
++
++	mvOsOutput( "\n" );
++	mvOsOutput( "XOR %d:\n", unit );
++	mvOsOutput( "----\n" );
++
++	for( i = 0; i < XOR_MAX_ADDR_DEC_WIN; i++ )
++	{
++		memset( &win, 0, sizeof(MV_XOR_DEC_WIN) );
++
++		mvOsOutput( "win%d - ", i );
++
++		if( mvXorTargetWinGet(unit, i, &win ) == MV_OK )
++		{
++			if( win.enable )
++			{
++				mvOsOutput( "%s base %x, ",
++				mvCtrlTargetNameGet(win.target), win.addrWin.baseLow );
++
++				mvSizePrint( win.addrWin.size );
++
++                mvOsOutput( "\n" );
++			}
++			else
++				mvOsOutput( "disable\n" );
++		}
++	}
++}
++
++/*******************************************************************************
++* mvXorAddrDecShow - Print the XOR address decode map.
++*
++* DESCRIPTION:
++*		This function print the XOR address decode map.
++*
++* INPUT:
++*       None.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_VOID mvXorAddrDecShow(MV_VOID)
++{
++	int            i;
++
++	for( i = 0; i < MV_XOR_MAX_UNIT; i++ )
++	    mvXorAddrDecShowUnit(i);
++
++}
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.h b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.h
+new file mode 100644
+index 0000000..73b2d9e
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.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 Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 __INCMVSysXorh
++#define __INCMVSysXorh
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.h"
++
++#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)     (XOR_UNIT_BASE(unit)+(0x240 + ((chan) * 4)))
++#define XOR_BASE_ADDR_REG(unit,winNum)     (XOR_UNIT_BASE(unit)+(0x250 + ((winNum) * 4)))
++#define XOR_SIZE_MASK_REG(unit,winNum)     (XOR_UNIT_BASE(unit)+(0x270 + ((winNum) * 4)))
++#define XOR_HIGH_ADDR_REMAP_REG(unit,winNum) (XOR_UNIT_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)
++
++/* XOR Engine High Address Remap Register (XEHARRx1) */
++#define XEHARRX_REMAP_OFFS                  (0)
++#define XEHARRX_REMAP_MASK                  (0xFFFFFFFF << XEHARRX_REMAP_OFFS)
++
++typedef struct _mvXorDecWin
++{
++    MV_TARGET     target;
++    MV_ADDR_WIN   addrWin; /* An address window*/
++    MV_BOOL       enable;  /* Address decode window is enabled/disabled */
++
++}MV_XOR_DEC_WIN;
++
++MV_STATUS   mvXorInit (MV_VOID);
++MV_STATUS   mvXorTargetWinSet(MV_U32 unit, MV_U32 winNum,
++			      MV_XOR_DEC_WIN *pAddrDecWin);
++MV_STATUS   mvXorTargetWinGet(MV_U32 unit, MV_U32 winNum,
++			      MV_XOR_DEC_WIN *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);
++
++MV_VOID     mvXorAddrDecShow(MV_VOID);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.c b/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.c
+new file mode 100644
+index 0000000..80325fc
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.c
+@@ -0,0 +1,75 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "device/mvDevice.h"
++
++/* defines  */
++#ifdef MV_DEBUG
++	#define DB(x)	x
++#else
++	#define DB(x)
++#endif
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.h b/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.h
+new file mode 100644
+index 0000000..9350779
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.h
+@@ -0,0 +1,74 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "mvCommon.h"
++#include "mvOs.h"
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++#include "device/mvDeviceRegs.h"
++
++
++#endif /* #ifndef __INCmvDeviceH */
+diff --git a/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDeviceRegs.h b/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDeviceRegs.h
+new file mode 100644
+index 0000000..80778ad
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDeviceRegs.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 __INCmvDeviceRegsH
++#define __INCmvDeviceRegsH
++
++#ifndef MV_ASMLANGUAGE
++#include "ctrlEnv/mvCtrlEnvLib.h"
++/* 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
++#if defined(MV_INCLUDE_DEVICE_CS4)
++	DEV_CS4 = 4,        /* Device connected to BOOT dev    */
++#endif
++	MV_DEV_MAX_CS = MV_DEVICE_MAX_CS
++}MV_DEVICE;
++
++
++#endif /* MV_ASMLANGUAGE */
++
++
++#define NAND_CTRL_REG		0x10470
++
++#define NAND_ACTCEBOOT_BIT	BIT1
++
++
++#endif /* #ifndef __INCmvDeviceRegsH */
+diff --git a/crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.c b/crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.c
+new file mode 100644
+index 0000000..75f7e88
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/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_KERNEL );
++    *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/crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.h b/crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.h
+new file mode 100644
+index 0000000..8da562a
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.h
+@@ -0,0 +1,423 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding 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/autoconf.h>
++#include <linux/interrupt.h>
++#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 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 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
++
++
++#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)                            \
++    pci_map_single( (pDev), (pVirtAddr), 0, PCI_DMA_BIDIRECTIONAL )
++
++#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 */
++
++#ifdef CONFIG_L2_CACHE_ENABLE
++/* Data cache flush one line */
++#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");		\
++}
++
++#else
++
++/* Data cache flush one line */
++#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
++
++#ifdef CONFIG_L2_CACHE_ENABLE
++#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)); \
++}
++#else
++#define mvOsCacheLineInv(handle,addr)                           \
++{                                                               \
++  __asm__ __volatile__ ("mcr p15, 0, %0, c7, c6, 1" : : "r" (addr)); \
++}
++#endif
++
++#ifdef CONFIG_L2_CACHE_ENABLE
++/* Data cache flush one line */
++#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");          \
++}
++
++#else
++/* Data cache flush one line */
++#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
++
++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
++
++
++
++/* 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/crypto/ocf/kirkwood/mvHal/linux_oss/mvOsSata.h b/crypto/ocf/kirkwood/mvHal/linux_oss/mvOsSata.h
+new file mode 100644
+index 0000000..c925a9e
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/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/crypto/ocf/kirkwood/mvHal/mvSysHwConfig.h b/crypto/ocf/kirkwood/mvHal/mvSysHwConfig.h
+new file mode 100644
+index 0000000..d761060
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mvSysHwConfig.h
+@@ -0,0 +1,375 @@
++/*******************************************************************************
++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.
++
++*******************************************************************************/
++/*******************************************************************************
++* 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_NAND
++#define MV_INCLUDE_NAND
++#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_SFLASH_MTD
++#define MV_INCLUDE_SFLASH_MTD
++#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_MV_NAND_BOOT
++#define MV_NAND_BOOT
++#endif
++#ifdef CONFIG_MV_NAND
++#define MV_NAND
++#endif
++
++/* SPI flash stuff */
++#ifdef CONFIG_MV_SPI_BOOT
++#define MV_SPI_BOOT
++#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
++
++#define MV_CESA_MAX_CHAN               4
++
++/* Use 2K of SRAM */
++#define MV_CESA_MAX_BUF_SIZE           1600
++
++#endif /* MV_INCLUDE_CESA */
++
++#if defined(CONFIG_MV_INCLUDE_GIG_ETH)
++
++#ifdef CONFIG_MV_NFP_STATS
++#define MV_FP_STATISTICS
++#else
++#undef MV_FP_STATISTICS
++#endif
++/* Default configuration for SKB_REUSE: 0 - Disabled, 1 - Enabled */
++#define MV_ETH_SKB_REUSE_DEFAULT    1
++/* 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 */
++
++/* put descriptors in uncached memory */
++/* #define ETH_DESCR_UNCACHED */
++
++/* 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
++
++/* DRAM cache coherency configuration */
++#define MV_CACHE_COHERENCY  MV_CACHE_COHER_SW
++
++
++#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 ETH_DEF_RXQ         0
++
++#define MV_ETH_RX_Q_NUM     CONFIG_MV_ETH_RX_Q_NUM
++#define MV_ETH_TX_Q_NUM     CONFIG_MV_ETH_TX_Q_NUM
++
++/* 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_INCLUDE_GIG_ETH */
++
++/****************************************************************/
++/*************** Telephony configuration ************************/
++/****************************************************************/
++#if defined(CONFIG_MV_TDM_LINEAR_MODE)
++ #define MV_TDM_LINEAR_MODE
++#elif defined(CONFIG_MV_TDM_ULAW_MODE)
++ #define MV_TDM_ULAW_MODE
++#endif
++
++#if defined(CONFIG_MV_TDM_5CHANNELS)
++ #define MV_TDM_5CHANNELS
++#endif
++
++#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 0xe8000000
++#define PEX0_MEM_SIZE _128M
++
++#define PEX0_IO_BASE 0xf2000000
++#define PEX0_IO_SIZE _1M
++
++/* Device Chip Selects */
++#define NFLASH_CS_BASE 0xfa000000
++#define NFLASH_CS_SIZE _2M
++
++#define SPI_CS_BASE 0xf4000000
++#define SPI_CS_SIZE _16M
++
++#define CRYPT_ENG_BASE	0xf0000000
++#define CRYPT_ENG_SIZE	_2M
++
++#define BOOTDEV_CS_BASE	0xff800000
++#define BOOTDEV_CS_SIZE _8M
++
++/* CS2 - BOOTROM */
++#define DEVICE_CS2_BASE 0xff900000
++#define DEVICE_CS2_SIZE _1M
++
++/* 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
++
++/* Internal registers: size is defined in Controllerenvironment */
++#define INTER_REGS_BASE	0xFEE00000
++
++/* 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/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.c b/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.c
+new file mode 100644
+index 0000000..717c150
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.c
+@@ -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.
++
++*******************************************************************************/
++
++#include "mvCntmr.h"
++#include "cpu/mvCpu.h"
++
++/* defines  */
++#ifdef MV_DEBUG
++	#define DB(x)	x
++#else
++	#define DB(x)
++#endif
++
++extern unsigned int whoAmI(void);
++
++/*******************************************************************************
++* 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. Illigal 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. Illigal 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. Illigal 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. Illigal 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. Illigal 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. Illigal 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/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.h b/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.h
+new file mode 100644
+index 0000000..b911d0f
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.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 __INCmvTmrWtdgh
++#define __INCmvTmrWtdgh
++
++/* includes */
++#include "mvCommon.h"
++#include "mvOs.h"
++#include "cntmr/mvCntmrRegs.h"
++#include "ctrlEnv/mvCtrlEnvSpec.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);
++
++#endif /* __INCmvTmrWtdgh */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmrRegs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmrRegs.h
+new file mode 100644
+index 0000000..b69bc66
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmrRegs.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 __INCmvTmrwtdgRegsh
++#define __INCmvTmrwtdgRegsh
++
++/*******************************************/
++/* ARM Timers Registers Map                */
++/*******************************************/
++
++#define CNTMR_RELOAD_REG(tmrNum)	(CNTMR_BASE + 0x10 + (tmrNum)*8 + \
++						(((tmrNum) <= 3)?0:8))
++#define CNTMR_VAL_REG(tmrNum)		(CNTMR_BASE + 0x14 + (tmrNum)*8 + \
++						(((tmrNum) <= 3)?0:8))
++#define CNTMR_CTRL_REG			(CNTMR_BASE)
++
++/*For MV78XX0*/
++#define CNTMR_CAUSE_REG		(CPU_AHB_MBUS_CAUSE_INT_REG(whoAmI()))
++#define CNTMR_MASK_REG		(CPU_AHB_MBUS_MASK_INT_REG(whoAmI()))
++
++/* 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
++
++
++
++#endif /* __INCmvTmrwtdgRegsh */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.c b/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.c
+new file mode 100644
+index 0000000..609e674
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.c
+@@ -0,0 +1,207 @@
++/*
++ * 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_CPU_CNTRS_NUM][MV_CPU_CNTRS_OPS_NUM] =
++{
++    /*0*/
++    {
++        MV_CPU_CNTRS_CYCLES,            MV_CPU_CNTRS_DCACHE_READ_HIT,       MV_CPU_CNTRS_DCACHE_READ_MISS,
++        MV_CPU_CNTRS_DCACHE_WRITE_HIT,  MV_CPU_CNTRS_DCACHE_WRITE_MISS,     MV_CPU_CNTRS_INSTRUCTIONS,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_INVALID,
++        MV_CPU_CNTRS_MMU_READ_LATENCY,  MV_CPU_CNTRS_ICACHE_READ_LATENCY,   MV_CPU_CNTRS_WB_WRITE_LATENCY,
++        MV_CPU_CNTRS_LDM_STM_HOLD,      MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_INVALID,
++        MV_CPU_CNTRS_DATA_WRITE_ACCESS, MV_CPU_CNTRS_DATA_READ_ACCESS,      MV_CPU_CNTRS_INVALID,
++        MV_CPU_CNTRS_BRANCH_PREDICT_COUNT,
++    },
++    /*1*/
++    {
++        MV_CPU_CNTRS_CYCLES,            MV_CPU_CNTRS_ICACHE_READ_MISS,      MV_CPU_CNTRS_DCACHE_READ_MISS,
++        MV_CPU_CNTRS_DCACHE_WRITE_MISS, MV_CPU_CNTRS_ITLB_MISS,             MV_CPU_CNTRS_SINGLE_ISSUE,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_BRANCH_RETIRED,        MV_CPU_CNTRS_INVALID,
++        MV_CPU_CNTRS_MMU_READ_BEAT,     MV_CPU_CNTRS_ICACHE_READ_LATENCY,   MV_CPU_CNTRS_WB_WRITE_BEAT,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_IS_HOLD,               MV_CPU_CNTRS_DATA_READ_ACCESS,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_INVALID,
++        MV_CPU_CNTRS_INVALID,
++    },
++    /*2*/
++    {
++        MV_CPU_CNTRS_CYCLES,            MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_DCACHE_ACCESS,
++        MV_CPU_CNTRS_DTLB_MISS,         MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_INVALID,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_BRANCH_PREDICT_MISS,   MV_CPU_CNTRS_WB_WRITE_BEAT,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_DCACHE_READ_LATENCY,   MV_CPU_CNTRS_DCACHE_WRITE_LATENCY,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_BIU_SIMULT_ACCESS,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_INVALID,
++        MV_CPU_CNTRS_INVALID,
++    },
++    /*3*/
++    {
++        MV_CPU_CNTRS_CYCLES,            MV_CPU_CNTRS_DCACHE_READ_MISS,      MV_CPU_CNTRS_DCACHE_WRITE_MISS,
++        MV_CPU_CNTRS_TLB_MISS,          MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_INVALID,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_BRANCH_TAKEN,          MV_CPU_CNTRS_WB_FULL_CYCLES,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_DCACHE_READ_BEAT,      MV_CPU_CNTRS_DCACHE_WRITE_BEAT,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_BIU_ANY_ACCESS,
++        MV_CPU_CNTRS_INVALID,           MV_CPU_CNTRS_INVALID,               MV_CPU_CNTRS_DATA_WRITE_ACCESS,
++        MV_CPU_CNTRS_INVALID,
++    }
++};
++
++MV_CPU_CNTRS_ENTRY  mvCpuCntrsTbl[MV_CPU_CNTRS_NUM];
++
++MV_CPU_CNTRS_EVENT*   mvCpuCntrsEventTbl[128];
++
++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 program_counter(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;
++
++        case 1:
++         __asm__ __volatile__ ("mcr p15, 0, %0, c15, c12, 1" : : "r" (reg));
++         return;
++
++        case 2:
++         __asm__ __volatile__ ("mcr p15, 0, %0, c15, c12, 2" : : "r" (reg));
++         return;
++
++        case 3:
++         __asm__ __volatile__ ("mcr p15, 0, %0, c15, c12, 3" : : "r" (reg));
++         return;
++
++        default:
++            mvOsPrintf("error in program_counter: bad counter number (%d)\n", counter);
++    }
++    return;
++}
++
++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     i;
++
++    /* Find required operations */
++    for(i=0; i<MV_CPU_CNTRS_OPS_NUM; i++)
++    {
++        if( mvCpuCntrsOpsTbl[counter][i] == op)
++        {
++            strncpy(mvCpuCntrsTbl[counter].name, name, sizeof(mvCpuCntrsTbl[counter].name));
++            mvCpuCntrsTbl[counter].operation = op;
++            mvCpuCntrsTbl[counter].opIdx = i+1;
++            mvCpuCntrsTbl[counter].overhead = overhead;
++            program_counter(counter, mvCpuCntrsTbl[counter].opIdx);
++            mvOsPrintf("Counter=%d, opIdx=%d, overhead=%d\n",
++                        counter, mvCpuCntrsTbl[counter].opIdx, mvCpuCntrsTbl[counter].overhead);
++            return MV_OK;
++        }
++    }
++    return MV_NOT_FOUND;
++}
++
++void    mvCpuCntrsShow(MV_CPU_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_CNTRS_NUM; i++)
++    {
++        counters_avg = mvOsDivMod64(pEvent->counters_sum[i],
++                                  pEvent->num_of_measurements, NULL);
++        if(counters_avg >= mvCpuCntrsTbl[i].overhead)
++            counters_avg -= mvCpuCntrsTbl[i].overhead;
++        else
++            counters_avg = 0;
++
++        mvOsPrintf("%s=%5llu, ", mvCpuCntrsTbl[i].name, counters_avg);
++    }
++    mvOsPrintf("\n");
++    mvCpuCntrsEventClear(pEvent);
++    mvCpuCntrsReset();
++}
++
++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);
++    }
++}
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.h
+new file mode 100644
+index 0000000..8d49af0
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.h
+@@ -0,0 +1,213 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding 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 __mvCpuCntrs_h__
++#define __mvCpuCntrs_h__
++
++#include "mvTypes.h"
++#include "mvOs.h"
++
++
++#define MV_CPU_CNTRS_NUM            4
++#define MV_CPU_CNTRS_OPS_NUM        32
++
++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_COUNT,
++    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_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[MV_CPU_CNTRS_NUM];
++
++
++MV_STATUS           mvCpuCntrsProgram(int counter, MV_CPU_CNTRS_OPS op,
++                                      char* name, MV_U32 overhead);
++void                mvCpuCntrsInit(void);
++MV_CPU_CNTRS_EVENT* mvCpuCntrsEventCreate(char* name, MV_U32 print_threshold);
++void                mvCpuCntrsEventDelete(MV_CPU_CNTRS_EVENT* event);
++void                mvCpuCntrsReset(void);
++void                mvCpuCntrsShow(MV_CPU_CNTRS_EVENT* pEvent);
++void		    mvCpuCntrsEventClear(MV_CPU_CNTRS_EVENT* pEvent);
++
++/* internal */
++void		    program_counter(int counter, int op);
++
++static INLINE MV_U64 mvCpuCntrsRead(const int counter)
++{
++    MV_U32 low = 0, high = 0;
++    MV_U32 ll = 0;
++
++    switch(counter)
++    {
++        case 0:
++            MV_ASM  ("mcr p15, 0, %0, c15, c12, 0" : : "r" (ll));
++            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  ("mcr p15, 0, %0, c15, c12, 1" : : "r" (ll));
++            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  ("mcr p15, 0, %0, c15, c12, 2" : : "r" (ll));
++            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  ("mcr p15, 0, %0, c15, c12, 3" : : "r" (ll));
++            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);
++    }
++    program_counter(counter, mvCpuCntrsTbl[counter].opIdx);
++    return (((MV_U64)high << 32 ) | low);
++
++}
++
++
++static INLINE void mvCpuCntrsReadBefore(MV_CPU_CNTRS_EVENT* pEvent)
++{
++#if 0
++    int i;
++
++    /* order is important - we want to measure the cycle count last here! */
++    for(i=0; i<MV_CPU_CNTRS_NUM; i++)
++        pEvent->counters_before[i] = mvCpuCntrsRead(i);
++#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
++}
++
++static INLINE void mvCpuCntrsReadAfter(MV_CPU_CNTRS_EVENT* pEvent)
++{
++    int i;
++
++#if 0
++    /* order is important - we want to measure the cycle count first here! */
++    for(i=0; i<MV_CPU_CNTRS_NUM; i++)
++        pEvent->counters_after[i] = mvCpuCntrsRead(i);
++#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
++
++    for(i=0; i<MV_CPU_CNTRS_NUM; i++)
++    {
++        pEvent->counters_sum[i] += (pEvent->counters_after[i] - pEvent->counters_before[i]);
++    }
++    pEvent->num_of_measurements++;
++}
++
++
++#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)	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 */
++
++
++#endif /* __mvCpuCntrs_h__ */
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.c b/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.c
+new file mode 100644
+index 0000000..0333862
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.c
+@@ -0,0 +1,143 @@
++/*
++ * 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/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.h
+new file mode 100644
+index 0000000..570d701
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.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 GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND 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 __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/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.c b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.c
+new file mode 100644
+index 0000000..d1b8a3d
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.c
+@@ -0,0 +1,1479 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "ddr1_2/mvDram.h"
++#include "boardEnv/mvBoardEnvLib.h"
++
++#undef 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 */
++    memset(pBankInfo, 0, sizeof(*pBankInfo));
++
++    if((NULL == pBankInfo) || (bankNum >= MV_DRAM_MAX_CS ))
++    {
++        DB(mvOsPrintf("Dram: mvDramBankInfoGet bad params \n"));
++        return MV_BAD_PARAM;
++    }
++    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_TWSI_SLAVE twsiSlave;
++    MV_U8 data[SPD_SIZE];
++
++    /* zero dimmInfo structure */
++    memset(data, 0, SPD_SIZE);
++
++    /* read the dimm eeprom */
++    DB(mvOsPrintf("DRAM: Read Dimm eeprom\n"));
++    twsiSlave.slaveAddr.address = MV_BOARD_DIMM0_I2C_ADDR;
++    twsiSlave.slaveAddr.type = ADDR7_BIT;
++    twsiSlave.validOffset = MV_TRUE;
++    twsiSlave.offset = 0;
++    twsiSlave.moreThen256 = MV_FALSE;
++
++    if( MV_OK != mvTwsiRead (MV_BOARD_DIMM_I2C_CHANNEL,
++			&twsiSlave, 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 */
++    twsiSlave.slaveAddr.address = MV_BOARD_DIMM1_I2C_ADDR;
++    twsiSlave.slaveAddr.type = ADDR7_BIT;
++    twsiSlave.validOffset = MV_TRUE;
++    twsiSlave.offset = 0;
++    twsiSlave.moreThen256 = MV_FALSE;
++
++    for(i = 0 ; i < SPD_SIZE ; i++)
++    {
++	twsiSlave.offset = i;
++	if( MV_OK != mvTwsiWrite (MV_BOARD_DIMM_I2C_CHANNEL,
++				&twsiSlave, &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_TWSI_SLAVE twsiSlave;
++    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"));
++    twsiSlave.slaveAddr.address = (dimmNum == 0) ?
++                            MV_BOARD_DIMM0_I2C_ADDR : MV_BOARD_DIMM1_I2C_ADDR;
++    twsiSlave.slaveAddr.type = ADDR7_BIT;
++    twsiSlave.validOffset = MV_TRUE;
++    twsiSlave.offset = 0;
++    twsiSlave.moreThen256 = MV_FALSE;
++
++    if( MV_OK != mvTwsiRead (MV_BOARD_DIMM_I2C_CHANNEL,
++			&twsiSlave, 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_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 / (mvBoardSysClkGet() / 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[91], spdRawData[92]);
++
++    /* 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/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.h
+new file mode 100644
+index 0000000..678e224
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.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.
++
++*******************************************************************************/
++
++#ifndef __INCmvDram
++#define __INCmvDram
++
++#include "ddr1_2/mvDramIf.h"
++#include "twsi/mvTwsi.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
++
++/* 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_STATUS dimmSpdCpy(MV_VOID);
++
++#endif /* __INCmvDram */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.c b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.c
+new file mode 100644
+index 0000000..12fb26a
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.c
+@@ -0,0 +1,1599 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "ddr1_2/mvDramIf.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++
++
++#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   */
++static MV_BOOL sdramIfWinOverlap(MV_TARGET target, MV_ADDR_WIN *pAddrWin);
++#if defined(MV_INC_BOARD_DDIM)
++static void sdramDDr2OdtConfig(MV_DRAM_BANK_INFO *pBankInfo);
++static MV_U32 dunitCtrlLowRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 minCas);
++static MV_U32 sdramModeRegCalc(MV_U32 minCas);
++static MV_U32 sdramExtModeRegCalc(MV_DRAM_BANK_INFO *pBankInfo);
++static MV_U32 sdramAddrCtrlRegCalc(MV_DRAM_BANK_INFO *pBankInfo);
++static MV_U32 sdramConfigRegCalc(MV_DRAM_BANK_INFO *pBankInfo, MV_U32 busClk);
++static MV_U32 minCasCalc(MV_DRAM_BANK_INFO *pBankInfo, 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);
++
++/*******************************************************************************
++* 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.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_STATUS mvDramIfDetect(MV_U32 forcedCl)
++{
++	MV_U32 retVal = MV_OK;	/* return value */
++	MV_DRAM_BANK_INFO bankInfo[MV_DRAM_MAX_CS];
++	MV_U32  busClk, size, base = 0, i, temp, deviceW, dimmW;
++	MV_U8	minCas;
++	MV_DRAM_DEC_WIN dramDecWin;
++
++	dramDecWin.addrWin.baseHigh = 0;
++
++	busClk = mvBoardSysClkGet();
++
++	if (0 == busClk)
++	{
++		mvOsPrintf("Dram: ERR. Can't detect system clock! \n");
++		return MV_ERROR;
++	}
++
++	/* Close DRAM banks except bank 0 (in case code is excecuting from it...) */
++#if defined(MV_INCLUDE_SDRAM_CS1)
++	for(i= SDRAM_CS1; i < MV_DRAM_MAX_CS; i++)
++		mvCpuIfTargetWinEnable(i, MV_FALSE);
++#endif
++
++	/* 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]))
++		{
++			/* check it isn't SDRAM */
++			if(bankInfo[i].memoryType == MEM_TYPE_SDRAM)
++			{
++				mvOsPrintf("Dram: ERR. SDRAM type not supported !!!\n");
++				return MV_ERROR;
++			}
++			/* All banks must support registry in order to activate it */
++			if(bankInfo[i].registeredAddrAndControlInputs !=
++			   bankInfo[0].registeredAddrAndControlInputs)
++			{
++				mvOsPrintf("Dram: ERR. different Registered settings !!!\n");
++				return MV_ERROR;
++			}
++
++			/* Init the CPU window decode */
++			/* Note that the size in Bank info is in MB units			*/
++			/* Note that the Dimm width might be different then the device DRAM width */
++			temp = MV_REG_READ(SDRAM_CONFIG_REG);
++
++			deviceW = ((temp & SDRAM_DWIDTH_MASK) == SDRAM_DWIDTH_16BIT )? 16 : 32;
++			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	*/
++			if(i == SDRAM_CS0)
++			{
++				MV_U32 sizeToReg;
++
++				/* Translate the given window size to register format */
++				sizeToReg = ctrlSizeToReg(size, SCSR_SIZE_ALIGNMENT);
++
++				/* Size parameter validity check. */
++				if (-1 == sizeToReg)
++				{
++					mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n"
++							   ,i);
++					return MV_BAD_PARAM;
++				}
++
++				/* Size is located at upper 16 bits */
++				sizeToReg <<= SCSR_SIZE_OFFS;
++
++				/* enable it */
++				sizeToReg |= SCSR_WIN_EN;
++
++				MV_REG_WRITE(DRAM_BUF_REG0, sizeToReg);
++			}
++			else
++			{
++				dramDecWin.addrWin.baseLow = base;
++				dramDecWin.addrWin.size = size;
++				dramDecWin.enable = MV_TRUE;
++
++				if (MV_OK != mvDramIfWinSet(SDRAM_CS0 + 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;
++
++		}
++		else
++		{
++			if( i == 0 ) /* bank 0 doesn't exist */
++			{
++				mvOsPrintf("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 */
++			}
++		}
++	}
++
++	/* calculate minimum CAS */
++	minCas = minCasCalc(&bankInfo[0], busClk, forcedCl);
++	if (0 == minCas)
++	{
++		mvOsOutput("Dram: Warn: Could not find CAS compatible to SysClk %dMhz\n",
++				   (busClk / 1000000));
++
++		if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2)
++		{
++			minCas = DDR2_CL_4; /* Continue with this CAS */
++			mvOsPrintf("Set default CAS latency 4\n");
++		}
++		else
++		{
++			minCas = DDR1_CL_3; /* Continue with this CAS */
++			mvOsPrintf("Set default CAS latency 3\n");
++		}
++	}
++
++	/* calc SDRAM_CONFIG_REG  and save it to temp register */
++	temp = sdramConfigRegCalc(&bankInfo[0], busClk);
++	if(-1 == temp)
++	{
++		mvOsPrintf("Dram: ERR. sdramConfigRegCalc failed !!!\n");
++		return MV_ERROR;
++	}
++	MV_REG_WRITE(DRAM_BUF_REG1, temp);
++
++	/* calc SDRAM_MODE_REG  and save it to temp register */
++	temp = sdramModeRegCalc(minCas);
++	if(-1 == temp)
++	{
++		mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n");
++		return MV_ERROR;
++	}
++	MV_REG_WRITE(DRAM_BUF_REG2, temp);
++
++	/* calc SDRAM_EXTENDED_MODE_REG  and save it to temp register */
++	temp = sdramExtModeRegCalc(&bankInfo[0]);
++	if(-1 == temp)
++	{
++		mvOsPrintf("Dram: ERR. sdramModeRegCalc failed !!!\n");
++		return MV_ERROR;
++	}
++	MV_REG_WRITE(DRAM_BUF_REG10, temp);
++
++	/* calc D_UNIT_CONTROL_LOW  and save it to temp register */
++	temp = dunitCtrlLowRegCalc(&bankInfo[0], minCas);
++	if(-1 == temp)
++	{
++		mvOsPrintf("Dram: ERR. dunitCtrlLowRegCalc failed !!!\n");
++		return MV_ERROR;
++	}
++	MV_REG_WRITE(DRAM_BUF_REG3, temp);
++
++	/* calc SDRAM_ADDR_CTRL_REG  and save it to temp register */
++	temp = sdramAddrCtrlRegCalc(&bankInfo[0]);
++	if(-1 == temp)
++	{
++		mvOsPrintf("Dram: ERR. sdramAddrCtrlRegCalc failed !!!\n");
++		return MV_ERROR;
++	}
++	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)
++	{
++		mvOsPrintf("Dram: ERR. sdramTimeCtrlLowRegCalc failed !!!\n");
++		return MV_ERROR;
++	}
++	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)
++	{
++		mvOsPrintf("Dram: ERR. sdramTimeCtrlHighRegCalc failed !!!\n");
++		return MV_ERROR;
++	}
++	MV_REG_WRITE(DRAM_BUF_REG6, temp);
++
++	/* Config DDR2 On Die Termination (ODT) registers */
++	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2)
++	{
++		sdramDDr2OdtConfig(bankInfo);
++	}
++
++	/* Note that DDR SDRAM Address/Control and Data pad calibration     */
++	/* settings is done in mvSdramIfConfig.s                            */
++
++	return retVal;
++}
++
++/*******************************************************************************
++* 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.
++*
++* 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_U32 busClk,
++						 MV_U32 forcedCl)
++{
++	MV_U32 count = 1, j;
++	MV_U32 busClkPs = 1000000000 / (busClk / 1000);  /* in ps units */
++	MV_U32 startBit, stopBit;
++
++	/*     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  *
++			*********************************************************/
++
++
++	/* If we are asked to use the forced CAL */
++	if (forcedCl)
++	{
++		mvOsPrintf("DRAM: Using forced CL %d.%d\n", (forcedCl / 10),
++													(forcedCl % 10));
++
++		if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2)
++		{
++			if (forcedCl == 30)
++				pBankInfo->suportedCasLatencies = 0x08;
++			else if (forcedCl == 40)
++				pBankInfo->suportedCasLatencies = 0x10;
++			else
++			{
++				mvOsPrintf("Forced CL %d.%d not supported. Set default CL 4\n",
++						   (forcedCl / 10), (forcedCl % 10));
++				pBankInfo->suportedCasLatencies = 0x10;
++			}
++		}
++		else
++		{
++			if (forcedCl == 15)
++				pBankInfo->suportedCasLatencies = 0x02;
++			else if (forcedCl == 20)
++				pBankInfo->suportedCasLatencies = 0x04;
++			else if (forcedCl == 25)
++				pBankInfo->suportedCasLatencies = 0x08;
++			else if (forcedCl == 30)
++				pBankInfo->suportedCasLatencies = 0x10;
++			else if (forcedCl == 40)
++				pBankInfo->suportedCasLatencies = 0x40;
++			else
++			{
++				mvOsPrintf("Forced CL %d.%d not supported. Set default CL 3\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 ));
++	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 ));
++
++	/* SDRAM DDR1 controller supports CL 1.5 to 3.5 */
++	/* SDRAM DDR2 controller supports CL 3 to 5     */
++	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2)
++	{
++		startBit = 3;   /* DDR2 support CL start with CL3 (bit 3) */
++		stopBit  = 5;   /* DDR2 support CL stops with CL5 (bit 5) */
++	}
++	else
++	{
++		startBit = 1;   /* DDR1 support CL start with CL1.5 (bit 3) */
++		stopBit  = 4;   /* DDR1 support CL stops with CL3 (bit 4)   */
++	}
++
++	for(j = startBit; j <= stopBit ; j++)
++	{
++		if((pBankInfo->suportedCasLatencies >> j) & BIT0 )
++		{
++			DB(mvOsPrintf("Dram: minCasCalc choose CAS %x \n",(BIT0 << j)));
++			return (BIT0 << j);
++		}
++	}
++
++	return 0;
++}
++
++/*******************************************************************************
++* sdramConfigRegCalc - Calculate sdram config register
++*
++* DESCRIPTION: Calculate sdram config register optimized value based
++*			on the bank info parameters.
++*
++* INPUT:
++*	pBankInfo - sdram bank parameters
++*
++* OUTPUT:
++*       None
++*
++* RETURN:
++*       sdram config reg value.
++*
++*******************************************************************************/
++static MV_U32 sdramConfigRegCalc(MV_DRAM_BANK_INFO *pBankInfo, 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;
++		mvOsPrintf("DRAM Attribute: Registered address and control inputs.\n");
++	}
++
++	/* set DDR SDRAM devices configuration */
++	sdramConfig &= ~SDRAM_DCFG_MASK;    /* Clear Dcfg field */
++
++	switch (pBankInfo->sdramWidth)
++	{
++		case 8:  /* memory is x8 */
++			sdramConfig |= SDRAM_DCFG_X8_DEV;
++			DB(mvOsPrintf("Dram: sdramConfigRegCalc SDRAM device width x8\n"));
++			break;
++		case 16:
++			sdramConfig |= SDRAM_DCFG_X16_DEV;
++			DB(mvOsPrintf("Dram: sdramConfigRegCalc SDRAM device width x16\n"));
++			break;
++		default: /* memory width unsupported */
++			mvOsPrintf("Dram: ERR. DRAM chip width is unknown!\n");
++			return -1;
++	}
++
++	/* 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;
++
++	mvOsPrintf("DRAM CAS Latency ");
++
++	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2)
++	{
++		switch (minCas)
++		{
++			case DDR2_CL_3:
++				sdramMode |= SDRAM_DDR2_CL_3;
++				mvOsPrintf("3.\n");
++				break;
++			case DDR2_CL_4:
++				sdramMode |= SDRAM_DDR2_CL_4;
++				mvOsPrintf("4.\n");
++				break;
++			case DDR2_CL_5:
++				sdramMode |= SDRAM_DDR2_CL_5;
++				mvOsPrintf("5.\n");
++				break;
++			default:
++				mvOsPrintf("\nsdramModeRegCalc ERROR: Max. CL out of range\n");
++				return -1;
++		}
++	sdramMode |= DDR2_MODE_REG_DV;
++	}
++	else	/* DDR1 */
++	{
++		switch (minCas)
++		{
++			case DDR1_CL_1_5:
++				sdramMode |= SDRAM_DDR1_CL_1_5;
++				mvOsPrintf("1.5\n");
++				break;
++			case DDR1_CL_2:
++				sdramMode |= SDRAM_DDR1_CL_2;
++				mvOsPrintf("2\n");
++				break;
++			case DDR1_CL_2_5:
++				sdramMode |= SDRAM_DDR1_CL_2_5;
++				mvOsPrintf("2.5\n");
++				break;
++			case DDR1_CL_3:
++				sdramMode |= SDRAM_DDR1_CL_3;
++				mvOsPrintf("3\n");
++				break;
++			case DDR1_CL_4:
++				sdramMode |= SDRAM_DDR1_CL_4;
++				mvOsPrintf("4\n");
++				break;
++			default:
++				mvOsPrintf("\nsdramModeRegCalc ERROR: Max. CL out of range\n");
++				return -1;
++		}
++		sdramMode |= DDR1_MODE_REG_DV;
++	}
++
++	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
++*
++* OUTPUT:
++*       None
++*
++* RETURN:
++*       sdram Extended mode reg value.
++*
++*******************************************************************************/
++static MV_U32 sdramExtModeRegCalc(MV_DRAM_BANK_INFO *pBankInfo)
++{
++	MV_U32 populateBanks = 0;
++	int bankNum;
++	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2)
++	{
++	/* 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):
++				return DDR_SDRAM_EXT_MODE_CS0_DV;
++
++			case(BANK_PRESENT_CS0_CS1):
++				return DDR_SDRAM_EXT_MODE_CS0_DV;
++
++			case(BANK_PRESENT_CS0_CS2):
++				return DDR_SDRAM_EXT_MODE_CS0_CS2_DV;
++
++			case(BANK_PRESENT_CS0_CS1_CS2):
++				return DDR_SDRAM_EXT_MODE_CS0_CS2_DV;
++
++			case(BANK_PRESENT_CS0_CS2_CS3):
++				return DDR_SDRAM_EXT_MODE_CS0_CS2_DV;
++
++			case(BANK_PRESENT_CS0_CS2_CS3_CS4):
++				return DDR_SDRAM_EXT_MODE_CS0_CS2_DV;
++
++			default:
++				mvOsPrintf("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 dunitCtrlLow;
++
++	dunitCtrlLow = MV_REG_READ(SDRAM_DUNIT_CTRL_REG);
++
++	/* Clear StBurstDel field */
++	dunitCtrlLow &= ~SDRAM_ST_BURST_DEL_MASK;
++
++#ifdef MV_88W8660
++	/* Clear address/control output timing field */
++	dunitCtrlLow &= ~SDRAM_CTRL_POS_RISE;
++#endif /* MV_88W8660 */
++
++	DB(mvOsPrintf("Dram: dunitCtrlLowRegCalc\n"));
++
++	/* For proper sample of read data set the Dunit Control register's      */
++	/* stBurstDel bits [27:24]                                              */
++			/********-********-********-********-********-*********
++			* CL=1.5 |  CL=2  | CL=2.5 |  CL=3  |  CL=4  |  CL=5  *
++			*********-********-********-********-********-*********
++Not Reg.	*  0011  |  0011  |  0100  |  0100  |  0101  |  TBD   *
++			*********-********-********-********-********-*********
++Registered	*  0100  |  0100  |  0101  |  0101  |  0110  |  TBD   *
++			*********-********-********-********-********-*********/
++
++	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2)
++	{
++		switch (minCas)
++		{
++			case DDR2_CL_3:
++					/* registerd DDR SDRAM? */
++				if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
++					dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS;
++				else
++					dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS;
++				break;
++			case DDR2_CL_4:
++				/* registerd DDR SDRAM? */
++				if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
++					dunitCtrlLow |= 0x6 << SDRAM_ST_BURST_DEL_OFFS;
++				else
++					dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS;
++				break;
++			default:
++				mvOsPrintf("Dram: dunitCtrlLowRegCalc Max. CL out of range %d\n",
++						   minCas);
++				return -1;
++		}
++	}
++	else    /* DDR1 */
++	{
++		switch (minCas)
++		{
++			case DDR1_CL_1_5:
++				/* registerd DDR SDRAM? */
++				if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
++					dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS;
++				else
++					dunitCtrlLow |= 0x3 << SDRAM_ST_BURST_DEL_OFFS;
++				break;
++			case DDR1_CL_2:
++				/* registerd DDR SDRAM? */
++				if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
++					dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS;
++				else
++					dunitCtrlLow |= 0x3 << SDRAM_ST_BURST_DEL_OFFS;
++				break;
++			case DDR1_CL_2_5:
++				/* registerd DDR SDRAM? */
++				if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
++					dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS;
++				else
++					dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS;
++				break;
++			case DDR1_CL_3:
++				/* registerd DDR SDRAM? */
++				if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
++					dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS;
++				else
++					dunitCtrlLow |= 0x4 << SDRAM_ST_BURST_DEL_OFFS;
++				break;
++			case DDR1_CL_4:
++				/* registerd DDR SDRAM? */
++				if (pBankInfo->registeredAddrAndControlInputs == MV_TRUE)
++					dunitCtrlLow |= 0x6 << SDRAM_ST_BURST_DEL_OFFS;
++				else
++					dunitCtrlLow |= 0x5 << SDRAM_ST_BURST_DEL_OFFS;
++				break;
++			default:
++				mvOsPrintf("Dram: dunitCtrlLowRegCalc Max. CL out of range %d\n",
++						   minCas);
++				return -1;
++	}
++
++	}
++	DB(mvOsPrintf("Dram: Reg dunit control low = %x\n", dunitCtrlLow ));
++
++	return dunitCtrlLow;
++}
++
++/*******************************************************************************
++* 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_U32 addrCtrl = 0;
++
++	/* Set Address Control register static configuration bits */
++	addrCtrl = MV_REG_READ(SDRAM_ADDR_CTRL_REG);
++
++	/* Set address control default value */
++	addrCtrl |= SDRAM_ADDR_CTRL_DV;
++
++	/* Clear DSize field */
++	addrCtrl &= ~SDRAM_DSIZE_MASK;
++
++	/* Note that density is in MB units */
++	switch (pBankInfo->deviceDensity)
++	{
++		case 128:                 /* 128 Mbit */
++			DB(mvOsPrintf("DRAM Device Density 128Mbit\n"));
++			addrCtrl |= SDRAM_DSIZE_128Mb;
++			break;
++		case 256:                 /* 256 Mbit */
++			DB(mvOsPrintf("DRAM Device Density 256Mbit\n"));
++			addrCtrl |= SDRAM_DSIZE_256Mb;
++			break;
++		case 512:                /* 512 Mbit */
++			DB(mvOsPrintf("DRAM Device Density 512Mbit\n"));
++			addrCtrl |= SDRAM_DSIZE_512Mb;
++			break;
++		default:
++			mvOsPrintf("Dram: sdramAddrCtrl unsupported RAM-Device size %d\n",
++                       pBankInfo->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
++*       busClk    - Bus clock
++*
++* OUTPUT:
++*       None
++*
++* RETURN:
++*       sdram timinf 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 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);
++	/* Micron work around for 133MHz */
++	if (busClk == 133)
++		tRp += 1;
++	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   */
++	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_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));
++	}
++	else
++	{
++		tWr  = ((busClk*SDRAM_TWR) / 1000) + (((busClk*SDRAM_TWR) % 1000)?1:0);
++
++		if ((200 == busClk) || ((100 == busClk) && (DDR1_CL_1_5 == minCas)))
++		{
++			tWtr = 2;
++		}
++		else
++		{
++			tWtr = 1;
++		}
++
++		tRtp = 2; /* Must be set to 0x1 (two cycles) when using DDR1 */
++	}
++
++	DB(mvOsPrintf("tWtr = %d\n", tWtr));
++
++	/* Note: value of 0 in register means one cycle, 1 means two and so on  */
++	return (((tRp  - 1) << SDRAM_TRP_OFFS)	|
++			((tRrd - 1) << SDRAM_TRRD_OFFS)	|
++			((tRcd - 1) << SDRAM_TRCD_OFFS)	|
++			((tRas - 1) << SDRAM_TRAS_OFFS)	|
++			((tWr  - 1) << SDRAM_TWR_OFFS)	|
++			((tWtr - 1) << SDRAM_TWTR_OFFS)	|
++			((tRtp - 1) << SDRAM_TRTP_OFFS));
++}
++
++/*******************************************************************************
++* 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 timinf control high reg value.
++*
++*******************************************************************************/
++static MV_U32 sdramTimeCtrlHighRegCalc(MV_DRAM_BANK_INFO *pBankInfo,
++                                                                MV_U32 busClk)
++{
++	MV_U32 tRfc;
++	MV_U32 timeNs = 0;
++	int bankNum;
++	MV_U32 sdramTw2wCyc = 0;
++
++	busClk = busClk / 1000000;    /* In MHz */
++
++	/* tRfc is different for DDR1 and DDR2. */
++	if (MV_REG_READ(SDRAM_CONFIG_REG) & SDRAM_DTYPE_DDR2)
++	{
++		MV_U32 bankNum;
++
++		/* 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);
++	}
++	else
++	{
++		if (pBankInfo[0].deviceDensity == _1G)
++		{
++			timeNs = SDRAM_TRFC_1G;
++		}
++		else
++		{
++			if (200 == busClk)
++			{
++				timeNs = SDRAM_TRFC_64_512M_AT_200MHZ;
++			}
++			else
++			{
++				timeNs = SDRAM_TRFC_64_512M;
++			}
++		}
++	}
++
++	tRfc = ((busClk * timeNs)  / 1000) + (((busClk * timeNs)  % 1000) ? 1 : 0);
++
++	DB(mvOsPrintf("Dram  Timing High: tRfc = %d\n", tRfc));
++
++
++	/* Represent the populate banks in binary form */
++	for(bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++)
++	{
++		if (0 != pBankInfo[bankNum].size)
++			sdramTw2wCyc++;
++	}
++
++	/* If we have more the 1 bank then we need the TW2W in 1 for ODT switch */
++	if (sdramTw2wCyc > 1)
++		sdramTw2wCyc = 1;
++	else
++		sdramTw2wCyc = 0;
++
++	/* Note: value of 0 in register means one cycle, 1 means two and so on  */
++	return ((((tRfc - 1) & SDRAM_TRFC_MASK)	<< SDRAM_TRFC_OFFS)		|
++			((SDRAM_TR2R_CYC - 1)			<< SDRAM_TR2R_OFFS)		|
++			((SDRAM_TR2WW2R_CYC - 1)		<< SDRAM_TR2W_W2R_OFFS)	|
++			(((tRfc - 1) >> 4)				<< SDRAM_TRFC_EXT_OFFS)	|
++			(sdramTw2wCyc					<< SDRAM_TW2W_OFFS));
++
++}
++
++/*******************************************************************************
++* sdramDDr2OdtConfig - Set DRAM DDR2 On Die Termination registers.
++*
++* DESCRIPTION:
++*       This function config DDR2 On Die Termination (ODT) registers.
++*	ODT configuration is done according to DIMM presence:
++*
++*       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
++*
++* 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):
++			odtCtrlLow   = DDR2_ODT_CTRL_LOW_CS0_DV;
++			odtCtrlHigh  = DDR2_ODT_CTRL_HIGH_CS0_DV;
++			dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_DV;
++			break;
++		case(BANK_PRESENT_CS0_CS1):
++			odtCtrlLow   = DDR2_ODT_CTRL_LOW_CS0_DV;
++			odtCtrlHigh  = DDR2_ODT_CTRL_HIGH_CS0_DV;
++			dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_DV;
++			break;
++		case(BANK_PRESENT_CS0_CS2):
++			odtCtrlLow   = DDR2_ODT_CTRL_LOW_CS0_CS2_DV;
++			odtCtrlHigh  = DDR2_ODT_CTRL_HIGH_CS0_CS2_DV;
++			dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV;
++			break;
++		case(BANK_PRESENT_CS0_CS1_CS2):
++			odtCtrlLow   = DDR2_ODT_CTRL_LOW_CS0_CS2_DV;
++			odtCtrlHigh  = DDR2_ODT_CTRL_HIGH_CS0_CS2_DV;
++			dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV;
++			break;
++		case(BANK_PRESENT_CS0_CS2_CS3):
++			odtCtrlLow   = DDR2_ODT_CTRL_LOW_CS0_CS2_DV;
++			odtCtrlHigh  = DDR2_ODT_CTRL_HIGH_CS0_CS2_DV;
++			dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV;
++			break;
++		case(BANK_PRESENT_CS0_CS2_CS3_CS4):
++			odtCtrlLow   = DDR2_ODT_CTRL_LOW_CS0_CS2_DV;
++			odtCtrlHigh  = DDR2_ODT_CTRL_HIGH_CS0_CS2_DV;
++			dunitOdtCtrl = DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV;
++			break;
++		default:
++			mvOsPrintf("sdramDDr2OdtConfig: Invalid DRAM bank presence\n");
++			return;
++	}
++	MV_REG_WRITE(DRAM_BUF_REG7, odtCtrlLow);
++	MV_REG_WRITE(DRAM_BUF_REG8, odtCtrlHigh);
++	MV_REG_WRITE(DRAM_BUF_REG9, dunitOdtCtrl);
++	return;
++}
++#endif /* defined(MV_INC_BOARD_DDIM) */
++
++/*******************************************************************************
++* 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 baseToReg=0 , sizeToReg=0;
++
++    /* Check parameters */
++	if (!MV_TARGET_IS_DRAM(target))
++	{
++		mvOsPrintf("mvDramIfWinSet: target %d is not SDRAM\n", target);
++		return MV_BAD_PARAM;
++	}
++
++    /* 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(target));
++
++	/* read size register */
++	sizeReg = MV_REG_READ(SDRAM_SIZE_REG(target));
++
++	/* BaseLow[31:16] => base register [31:16]		*/
++	baseToReg = pAddrDecWin->addrWin.baseLow & SCBAR_BASE_MASK;
++
++	/* Write to address decode Base Address Register                  */
++	baseReg &= ~SCBAR_BASE_MASK;
++	baseReg |= baseToReg;
++
++	/* Translate the given window size to register format			*/
++	sizeToReg = ctrlSizeToReg(pAddrDecWin->addrWin.size, SCSR_SIZE_ALIGNMENT);
++
++	/* Size parameter validity check.                                   */
++	if (-1 == sizeToReg)
++	{
++		mvOsPrintf("mvCtrlAddrDecToReg: ERR. Win %d size invalid.\n",target);
++		return MV_BAD_PARAM;
++	}
++
++	/* 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(target), baseReg);
++
++	/* Write to address decode Size Register				*/
++	MV_REG_WRITE(SDRAM_SIZE_REG(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;
++
++	/* Check parameters */
++	if (!MV_TARGET_IS_DRAM(target))
++	{
++		mvOsPrintf("mvDramIfWinGet: target %d is Illigal\n", target);
++		return MV_ERROR;
++	}
++
++	/* Read base and size registers */
++	sizeReg = MV_REG_READ(SDRAM_SIZE_REG(target));
++	baseReg = MV_REG_READ(SDRAM_BASE_ADDR_REG(target));
++
++	sizeRegVal = (sizeReg & SCSR_SIZE_MASK) >> SCSR_SIZE_OFFS;
++
++	pAddrDecWin->addrWin.size = ctrlRegToSize(sizeRegVal,
++											 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;
++
++	/* Check parameters */
++	if (!MV_TARGET_IS_DRAM(target))
++	{
++		mvOsPrintf("mvDramIfWinEnable: target %d is Illigal\n", target);
++		return MV_ERROR;
++	}
++
++	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(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(target), SCSR_WIN_EN);
++	}
++
++	return MV_OK;
++}
++
++/*******************************************************************************
++* 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 == ctrlWinOverlapTest(pAddrWin, &addrDecWin.addrWin))
++		{
++			mvOsPrintf(
++			"sdramIfWinOverlap: Required target %d overlap winNum %d\n",
++			target, targetNum);
++			return MV_TRUE;
++		}
++	}
++
++	return MV_FALSE;
++}
++
++/*******************************************************************************
++* 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_32 mvDramIfBankSizeGet(MV_U32 bankNum)
++{
++    MV_DRAM_DEC_WIN	addrDecWin;
++
++	/* Check parameters */
++	if (!MV_TARGET_IS_DRAM(bankNum))
++	{
++		mvOsPrintf("mvDramIfBankBaseGet: bankNum %d is invalid\n", bankNum);
++		return -1;
++	}
++	/* Get window parameters	*/
++	if (MV_OK != mvDramIfWinGet(bankNum, &addrDecWin))
++	{
++		mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n");
++		return -1;
++	}
++
++	if (MV_TRUE == addrDecWin.enable)
++	{
++		return addrDecWin.addrWin.size;
++	}
++	else
++	{
++		return 0;
++	}
++}
++
++
++/*******************************************************************************
++* 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_32 mvDramIfSizeGet(MV_VOID)
++{
++	MV_U32 totalSize = 0, bankSize = 0, bankNum;
++
++	for(bankNum = 0; bankNum < MV_DRAM_MAX_CS; bankNum++)
++	{
++		bankSize = mvDramIfBankSizeGet(bankNum);
++
++		if (-1 == bankSize)
++		{
++			mvOsPrintf("Dram: mvDramIfSizeGet error with bank %d \n",bankNum);
++			return -1;
++		}
++		else
++		{
++			totalSize += bankSize;
++		}
++	}
++
++	DB(mvOsPrintf("Dram: Total DRAM size is 0x%x \n",totalSize));
++
++	return totalSize;
++}
++
++/*******************************************************************************
++* 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_32 mvDramIfBankBaseGet(MV_U32 bankNum)
++{
++    MV_DRAM_DEC_WIN	addrDecWin;
++
++	/* Check parameters */
++	if (!MV_TARGET_IS_DRAM(bankNum))
++	{
++		mvOsPrintf("mvDramIfBankBaseGet: bankNum %d is invalid\n", bankNum);
++		return -1;
++	}
++	/* Get window parameters	*/
++	if (MV_OK != mvDramIfWinGet(bankNum, &addrDecWin))
++	{
++		mvOsPrintf("sdramIfWinOverlap: ERR. TargetWinGet failed\n");
++		return -1;
++	}
++
++	if (MV_TRUE == addrDecWin.enable)
++	{
++		return addrDecWin.addrWin.baseLow;
++	}
++	else
++	{
++		return -1;
++	}
++}
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.h
+new file mode 100644
+index 0000000..8bfa3e8
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.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 __INCmvDramIfh
++#define __INCmvDramIfh
++
++/* includes */
++#include "ddr1_2/mvDramIfRegs.h"
++#include "ddr1_2/mvDramIfConfig.h"
++#include "ctrlEnv/mvCtrlEnvLib.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 SDRAM_TR2WW2R_CYC            1   /* cycle for tR2wW2r                */
++
++/* typedefs */
++
++/* enumeration for memory types */
++typedef enum _mvMemoryType
++{
++    MEM_TYPE_SDRAM,
++    MEM_TYPE_DDR1,
++    MEM_TYPE_DDR2
++}MV_MEMORY_TYPE;
++
++/* enumeration for DDR1 supported CAS Latencies */
++typedef enum _mvDimmDdr1Cas
++{
++    DDR1_CL_1_5  = 0x02,
++    DDR1_CL_2    = 0x04,
++    DDR1_CL_2_5  = 0x08,
++    DDR1_CL_3    = 0x10,
++    DDR1_CL_4    = 0x40,
++    DDR1_CL_FAULT
++} MV_DIMM_DDR1_CAS;
++
++/* enumeration for DDR2 supported CAS Latencies */
++typedef enum _mvDimmDdr2Cas
++{
++    DDR2_CL_3    = 0x08,
++    DDR2_CL_4    = 0x10,
++    DDR2_CL_5    = 0x20,
++    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_DRAM_BANK_INFO;
++
++/* This structure describes CPU interface address decode window               */
++typedef struct _mvDramIfDecWin
++{
++	MV_ADDR_WIN   addrWin;    /* An address window*/
++	MV_BOOL       enable;     /* Address decode window is enabled/disabled    */
++}MV_DRAM_DEC_WIN;
++
++#include "ddr1_2/mvDram.h"
++
++/* mvDramIf.h API list */
++MV_VOID   mvDramIfBasicAsmInit(MV_VOID);
++MV_STATUS mvDramIfDetect(MV_U32 forcedCl);
++MV_VOID   _mvDramIfConfig(MV_VOID);
++
++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_32 mvDramIfBankSizeGet(MV_U32 bankNum);
++MV_32 mvDramIfBankBaseGet(MV_U32 bankNum);
++MV_32 mvDramIfSizeGet(MV_VOID);
++
++#if 0
++MV_STATUS mvDramIfMbusCtrlSet(MV_XBAR_TARGET *pPizzaArbArray);
++MV_STATUS mvDramIfMbusToutSet(MV_U32 timeout, MV_BOOL enable);
++#endif
++
++#endif /* __INCmvDramIfh */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfConfig.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfConfig.h
+new file mode 100644
+index 0000000..a7c6644
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfConfig.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 __INCmvDramIfConfigh
++#define __INCmvDramIfConfigh
++
++/* includes */
++
++/* defines  */
++
++/* registers defaults values */
++
++#define SDRAM_CONFIG_DV				\
++		(SDRAM_PERR_WRITE			|	\
++		 SDRAM_SRMODE				|	\
++		 SDRAM_SRCLK_GATED)
++
++#define SDRAM_DUNIT_CTRL_LOW_DV			\
++		(SDRAM_CTRL_POS_RISE		|	\
++		 SDRAM_CLK1DRV_NORMAL		|	\
++		 SDRAM_LOCKEN_ENABLE)
++
++#define SDRAM_ADDR_CTRL_DV	    0
++
++#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))
++/* TRFC 0x27, TW2W 0x1 */
++#define SDRAM_TIMING_CTRL_HIGH_REG_DV	(( 0x7 << SDRAM_TRFC_OFFS )	|\
++					( 0x2 << SDRAM_TRFC_EXT_OFFS)	|\
++					( 0x1 << SDRAM_TW2W_OFFS))
++
++#define SDRAM_OPEN_PAGES_CTRL_REG_DV	SDRAM_OPEN_PAGE_EN
++
++/* DDR2 ODT default register values */
++
++/* 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_DV	0x84210000
++#define DDR2_ODT_CTRL_HIGH_CS0_DV	0x00000000
++#define DDR2_DUNIT_ODT_CTRL_CS0_DV	0x0000780F
++#define DDR_SDRAM_EXT_MODE_CS0_DV	0x00000440
++
++#define DDR2_ODT_CTRL_LOW_CS0_CS2_DV	0x030C030C
++#define DDR2_ODT_CTRL_HIGH_CS0_CS2_DV	0x00000000
++#define DDR2_DUNIT_ODT_CTRL_CS0_CS2_DV	0x0000740F
++#define DDR_SDRAM_EXT_MODE_CS0_CS2_DV	0x00000404
++
++
++/* DDR SDRAM Adderss/Control and Data Pads Calibration default values */
++#define DDR1_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV	\
++		(1 << SDRAM_PRE_DRIVER_STRENGTH_OFFS)
++#define DDR2_ADDR_CTRL_PAD_STRENGTH_TYPICAL_DV	\
++		(3 << SDRAM_PRE_DRIVER_STRENGTH_OFFS)
++
++
++#define DDR1_DATA_PAD_STRENGTH_TYPICAL_DV		\
++		(1 << 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 DDR1_MODE_REG_DV			0x00000000
++#define DDR2_MODE_REG_DV			0x00000400
++
++/* DDR SDRAM Timing parameter default values */
++#define DDR1_TIMING_LOW_DV           0x11602220
++#define DDR1_TIMING_HIGH_DV          0x0000000d
++
++#define DDR2_TIMING_LOW_DV           0x11812220
++#define DDR2_TIMING_HIGH_DV          0x0000030f
++
++/* For Guideline (GL# MEM-4) DQS Reference Delay Tuning */
++#define FTDLL_DDR1_166MHZ           ((0x1 << 0)    | \
++                                     (0x7F<< 12)   | \
++                                     (0x1 << 22))
++
++#define FTDLL_DDR1_133MHZ           FTDLL_DDR1_166MHZ
++
++#define FTDLL_DDR1_200MHZ           ((0x1 << 0)    | \
++                                     (0x1 << 12)   | \
++                                     (0x3 << 14)   | \
++                                     (0x1 << 18)   | \
++                                     (0x1 << 22))
++
++
++#define FTDLL_DDR2_166MHZ           ((0x1 << 0)    | \
++                                     (0x1 << 12)   | \
++                                     (0x1 << 14)   | \
++                                     (0x1 << 16)   | \
++                                     (0x1 << 19)   | \
++                                     (0xF << 20))
++
++#define FTDLL_DDR2_133MHZ           FTDLL_DDR2_166MHZ
++
++#define FTDLL_DDR2_200MHZ           ((0x1 << 0)    | \
++                                     (0x1 << 12)   | \
++                                     (0x1 << 14)   | \
++                                     (0x1 << 16)   | \
++                                     (0x1 << 19)   | \
++                                     (0xF << 20))
++
++#define FTDLL_DDR2_250MHZ            0x445001
++
++/* Orion 1 B1 and above */
++#define FTDLL_DDR1_166MHZ_5181_B1    0x45D001
++
++/* Orion nas */
++#define FTDLL_DDR2_166MHZ_5182       0x597001
++
++/* Orion 2 D0 and above */
++#define FTDLL_DDR1_166MHZ_5281_D0    0x8D0001
++#define FTDLL_DDR1_200MHZ_5281_D0    0x8D0001
++#define FTDLL_DDR2_166MHZ_5281_D0    0x485001
++#define FTDLL_DDR2_200MHZ_5281_D0    0x485001
++#define FTDLL_DDR2_250MHZ_5281_D0    0x445001
++#define FTDLL_DDR2_200MHZ_5281_D1    0x995001
++#define FTDLL_DDR2_250MHZ_5281_D1    0x984801
++
++#endif /* __INCmvDramIfh */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfRegs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfRegs.h
+new file mode 100644
+index 0000000..e9cd7c4
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfRegs.h
+@@ -0,0 +1,306 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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
++
++
++/* DDR SDRAM Controller Address Decode Registers */
++/* SDRAM CSn Base Address Register (SCBAR) */
++#define SDRAM_BASE_ADDR_REG(csNum)	(0x1500 + (csNum * 8))
++#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(csNum)	(0x1504 + (csNum * 8))
++#define SCSR_WIN_EN					BIT0
++#define SCSR_SIZE_OFFS				16
++#define SCSR_SIZE_MASK				(0xffff << SCSR_SIZE_OFFS)
++#define SCSR_SIZE_ALIGNMENT			0x10000
++
++/* configuration register */
++#define SDRAM_CONFIG_REG		0x1400
++#define SDRAM_REFRESH_OFFS		0
++#define SDRAM_REFRESH_MAX		0x3000
++#define SDRAM_REFRESH_MASK		(SDRAM_REFRESH_MAX << SDRAM_REFRESH_OFFS)
++#define SDRAM_DWIDTH_OFFS       14
++#define SDRAM_DWIDTH_MASK       (3 << SDRAM_DWIDTH_OFFS)
++#define SDRAM_DWIDTH_16BIT      (1 << SDRAM_DWIDTH_OFFS)
++#define SDRAM_DWIDTH_32BIT      (2 << SDRAM_DWIDTH_OFFS)
++#define SDRAM_DTYPE_OFFS        16
++#define SDRAM_DTYPE_MASK        (1 << SDRAM_DTYPE_OFFS)
++#define SDRAM_DTYPE_DDR1        (0 << SDRAM_DTYPE_OFFS)
++#define SDRAM_DTYPE_DDR2        (1 << SDRAM_DTYPE_OFFS)
++#define SDRAM_REGISTERED		(1 << 17)
++#define SDRAM_PERR_OFFS		18
++#define SDRAM_PERR_MASK		(1 << SDRAM_PERR_OFFS)
++#define SDRAM_PERR_NO_WRITE     (0 << SDRAM_PERR_OFFS)
++#define SDRAM_PERR_WRITE        (1 << SDRAM_PERR_OFFS)
++#define SDRAM_DCFG_OFFS	20
++#define SDRAM_DCFG_MASK	(0x3 << SDRAM_DCFG_OFFS)
++#define SDRAM_DCFG_X16_DEV	(1 << SDRAM_DCFG_OFFS)
++#define SDRAM_DCFG_X8_DEV	(2 << SDRAM_DCFG_OFFS)
++#define SDRAM_SRMODE			(1 << 24)
++#define SDRAM_SRCLK_OFFS		25
++#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_CATTH_OFFS		26
++#define SDRAM_CATTHR_EN			(1 << SDRAM_CATTH_OFFS)
++
++
++/* dunit control register */
++#define SDRAM_DUNIT_CTRL_REG	0x1404
++#define SDRAM_CTRL_POS_OFFS		6
++#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_LOCKEN_OFFS       18
++#define SDRAM_LOCKEN_MASK       (1 << SDRAM_LOCKEN_OFFS)
++#define SDRAM_LOCKEN_DISABLE    (0 << SDRAM_LOCKEN_OFFS)
++#define SDRAM_LOCKEN_ENABLE     (1 << SDRAM_LOCKEN_OFFS)
++#define SDRAM_ST_BURST_DEL_OFFS	24
++#define SDRAM_ST_BURST_DEL_MAX		0xf
++#define SDRAM_ST_BURST_DEL_MASK (SDRAM_ST_BURST_DEL_MAX<<SDRAM_ST_BURST_DEL_OFFS)
++
++/* sdram timing control low register */
++#define SDRAM_TIMING_CTRL_LOW_REG	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		20
++#define SDRAM_TRAS_MASK		(0xF << SDRAM_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)
++
++/* sdram timing control high register */
++#define SDRAM_TIMING_CTRL_HIGH_REG	0x140c
++#define SDRAM_TRFC_OFFS		0
++#define SDRAM_TRFC_MASK		(0xF << SDRAM_TRFC_OFFS)
++#define SDRAM_TR2R_OFFS		4
++#define SDRAM_TR2R_MASK		(0x3 << SDRAM_TR2R_OFFS)
++#define SDRAM_TR2W_W2R_OFFS		6
++#define SDRAM_TR2W_W2R_MASK		(0x3 << SDRAM_TR2W_W2R_OFFS)
++#define SDRAM_TRFC_EXT_OFFS		8
++#define SDRAM_TRFC_EXT_MASK		(0x1 << SDRAM_TRFC_EXT_OFFS)
++#define SDRAM_TW2W_OFFS		    10
++#define SDRAM_TW2W_MASK		    (0x1 << SDRAM_TW2W_OFFS)
++
++/* address control register */
++#define SDRAM_ADDR_CTRL_REG		0x1410
++#define SDRAM_DSIZE_OFFS	    4
++#define SDRAM_DSIZE_MASK	    (0x3 << SDRAM_DSIZE_OFFS)
++#define SDRAM_DSIZE_128Mb	    (0x0 << SDRAM_DSIZE_OFFS)
++#define SDRAM_DSIZE_256Mb	    (0x1 << SDRAM_DSIZE_OFFS)
++#define SDRAM_DSIZE_512Mb	    (0x2 << SDRAM_DSIZE_OFFS)
++
++/* SDRAM Open Pages Control registers */
++#define SDRAM_OPEN_PAGE_CTRL_REG	0x1414
++#define SDRAM_OPEN_PAGE_EN		    (0 << 0)
++#define SDRAM_OPEN_PAGE_DIS		    (1 << 0)
++
++/* sdram opertion register */
++#define SDRAM_OPERATION_REG	0x1418
++#define SDRAM_CMD_OFFS			0
++#define SDRAM_CMD_MASK			(0x7 << 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				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_DDR1_CL_2		(0x2 << SDRAM_CL_OFFS)
++#define SDRAM_DDR1_CL_3	(0x3 << SDRAM_CL_OFFS)
++#define SDRAM_DDR1_CL_4	(0x4 << SDRAM_CL_OFFS)
++#define SDRAM_DDR1_CL_1_5	(0x5 << SDRAM_CL_OFFS)
++#define SDRAM_DDR1_CL_2_5	(0x6 << 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_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		11
++#define SDRAM_WR_MAX		7
++#define SDRAM_WR_MASK		(SDRAM_WR_MAX << 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	0x1420
++#define DSEMR_DLL_ENABLE		(1 << 0)
++#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_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_OCD_OFFS			7
++#define DSEMR_OCD_MASK			(0x7 << DSEMR_OCD_OFFS)
++#define DSEMR_OCD_EXIT_CALIB	(0 << DSEMR_OCD_OFFS)
++#define DSEMR_OCD_DRIVE1		(1 << DSEMR_OCD_OFFS)
++#define DSEMR_OCD_DRIVE0		(2 << DSEMR_OCD_OFFS)
++#define DSEMR_OCD_ADJUST_MODE	(4 << DSEMR_OCD_OFFS)
++#define DSEMR_OCD_CALIB_DEFAULT	(7 << DSEMR_OCD_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	(0 << DSEMR_DQS_OFFS)
++#define DSEMR_RDQS_ENABLE		(1 << 11)
++#define DSEMR_QOFF_OUTPUT_BUFF_EN	(1 << 12)
++
++/* DDR SDRAM Operation Control Register */
++#define SDRAM_OPERATION_CTRL_REG	0x142c
++
++/* Dunit FTDLL Configuration Register */
++#define SDRAM_FTDLL_CONFIG_REG			0x1484
++
++/* Pads Calibration register */
++#define SDRAM_ADDR_CTRL_PADS_CAL_REG	0x14c0
++#define SDRAM_DATA_PADS_CAL_REG		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_LOCK_OFFS		17
++#define SDRAM_LOCK_MAKS		(0x1F << SDRAM_LOCK_OFFS)
++#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  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_WD(odtNum, bank)  ((1 << bank) << DSOCLR_ODT_WR_OFFS(odtNum))
++
++/* DDR2 SDRAM ODT Control (High) Register (DSOCHR) */
++#define DDR2_SDRAM_ODT_CTRL_HIGH_REG    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) ((1 << ctrl) << DSOCHR_ODT_RD_OFFS(odtNum))
++
++/* DDR2 Dunit ODT Control Register (DDOCR)*/
++#define DDR2_DUNIT_ODT_CONTROL_REG  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)
++#define DSOCR_ODT_EN(ctrl)          ((1 << ctrl) << DSOCR_ODT_EN_OFFS)
++#define DSOCR_ODT_SEL_OFFS          10
++#define DSOCR_ODT_SEL_MASK          (0x3 << DSOCR_ODT_SEL_OFFS)
++
++/* DDR SDRAM Initialization Control Register (DSICR) */
++#define DDR_SDRAM_INIT_CTRL_REG		0x1480
++#define DSICR_INIT_EN				(1 << 0)
++
++#endif /* __INCmvDramIfRegsh */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.c b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.c
+new file mode 100644
+index 0000000..a214c95
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.c
+@@ -0,0 +1,1855 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "ddr2/mvDramIf.h"
++#include "ctrlEnv/sys/mvCpuIf.h"
++
++#include "ddr2/mvDramIfStaticInit.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_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
++		};
++	MV_U32  busClk, deviceW, dimmW;
++	MV_U32 numOfAllDevices = 0;
++	MV_STATUS TTMode;
++#ifndef MV_STATIC_DRAM_ON_BOARD
++	MV_DRAM_BANK_INFO bankInfo[MV_DRAM_MAX_CS];
++	MV_U32  size, base = 0, i, j, temp, busClkPs;
++	MV_U8	minCas;
++	MV_CPU_DEC_WIN dramDecWin;
++	dramDecWin.addrWin.baseHigh = 0;
++#endif
++
++	busClk = mvBoardSysClkGet();
++
++	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
++		{
++			if( i == 0 ) /* bank 0 doesn't exist */
++			{
++				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: mvCtrlAddrDecToReg: 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 != mvCpuIfTargetWinSet(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)
++{
++	DB(mvOsPrintf("Dram: mvDramIfBankBaseGet Bank %d base addr is %x \n",
++				  bankNum, mvCpuIfTargetWinBaseLowGet(SDRAM_CS0 + bankNum)));
++	return mvCpuIfTargetWinBaseLowGet(SDRAM_CS0 + bankNum);
++}
++
++/*******************************************************************************
++* 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)
++{
++	DB(mvOsPrintf("Dram: mvDramIfBankSizeGet Bank %d size is %x \n",
++				  bankNum, mvCpuIfTargetWinSizeGet(SDRAM_CS0 + bankNum)));
++	return mvCpuIfTargetWinSizeGet(SDRAM_CS0 + bankNum);
++}
++
++
++/*******************************************************************************
++* 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];
++}
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.h
+new file mode 100644
+index 0000000..23f2e54
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.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 __INCmvDramIfh
++#define __INCmvDramIfh
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++/* includes */
++#include "ddr2/mvDramIfRegs.h"
++#include "ddr2/mvDramIfConfig.h"
++#include "ctrlEnv/mvCtrlEnvLib.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;
++
++#include "ddr2/spd/mvSpd.h"
++
++/* mvDramIf.h API list */
++MV_VOID   mvDramIfBasicAsmInit(MV_VOID);
++MV_STATUS mvDramIfDetect(MV_U32 forcedCl, MV_BOOL eccDisable);
++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/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfConfig.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfConfig.h
+new file mode 100644
+index 0000000..6141c46
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfConfig.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 __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/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfRegs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfRegs.h
+new file mode 100644
+index 0000000..369eda6
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfRegs.h
+@@ -0,0 +1,423 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 */
++
++/* 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		(DRAM_BASE + 0x1400)
++#define SDRAM_REFRESH_OFFS		0
++#define SDRAM_REFRESH_MAX		0x3FFF
++#define SDRAM_REFRESH_MASK		(SDRAM_REFRESH_MAX << SDRAM_REFRESH_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		(DRAM_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	(DRAM_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	(DRAM_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	(DRAM_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	(DRAM_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	(DRAM_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		(DRAM_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	(DRAM_BASE + 0x1414)
++#define SDRAM_OPEN_PAGE_EN			(0 << 0)
++#define SDRAM_OPEN_PAGE_DIS			(1 << 0)
++
++/* sdram opertion register */
++#define SDRAM_OPERATION_REG		(DRAM_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					(DRAM_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		(DRAM_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	(DRAM_BASE + 0x142c)
++
++/* Dunit FTDLL Configuration Register */
++#define SDRAM_FTDLL_CONFIG_LEFT_REG		(DRAM_BASE + 0x1484)
++#define SDRAM_FTDLL_CONFIG_RIGHT_REG		(DRAM_BASE + 0x161C)
++#define SDRAM_FTDLL_CONFIG_UP_REG		(DRAM_BASE + 0x1620)
++
++/* Pads Calibration register */
++#define SDRAM_ADDR_CTRL_PADS_CAL_REG	(DRAM_BASE + 0x14c0)
++#define SDRAM_DATA_PADS_CAL_REG		    (DRAM_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 (DRAM_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		(DRAM_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  (DRAM_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	    (DRAM_BASE + 0x1480)
++#define DSICR_INIT_EN			(1 << 0)
++#define DSICR_T200_SET			(1 << 8)
++
++/* sdram extended mode2 register (SEM2R) */
++#define SDRAM_EXTENDED_MODE2_REG	(DRAM_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	(DRAM_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			(DRAM_BASE + 0x14d0)
++#define SDRAM_ERROR_MASK_REG			(DRAM_BASE + 0x14d4)
++#define SDRAM_ERROR_DATA_LOW_REG		(DRAM_BASE + 0x1444)
++#define SDRAM_ERROR_DATA_HIGH_REG		(DRAM_BASE + 0x1440)
++#define SDRAM_ERROR_ADDR_REG			(DRAM_BASE + 0x1450)
++#define SDRAM_ERROR_ECC_REG			(DRAM_BASE + 0x1448)
++#define SDRAM_CALC_ECC_REG			(DRAM_BASE + 0x144c)
++#define SDRAM_ECC_CONTROL_REG			(DRAM_BASE + 0x1454)
++#define SDRAM_SINGLE_BIT_ERR_CNTR_REG		(DRAM_BASE + 0x1458)
++#define SDRAM_DOUBLE_BIT_ERR_CNTR_REG		(DRAM_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/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfStaticInit.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfStaticInit.h
+new file mode 100644
+index 0000000..f3bf83b
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfStaticInit.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 __INCmvDramIfStaticInith
++#define __INCmvDramIfStaticInith
++
++#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 */
++
++#if 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 */
++#endif /* __INCmvDramIfStaticInith */
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.c b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.c
+new file mode 100644
+index 0000000..7a26f90
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.c
+@@ -0,0 +1,1474 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "ddr2/spd/mvSpd.h"
++#include "boardEnv/mvBoardEnvLib.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_TWSI_SLAVE twsiSlave;
++    MV_U8 data[SPD_SIZE];
++
++    /* zero dimmInfo structure */
++    memset(data, 0, SPD_SIZE);
++
++    /* read the dimm eeprom */
++    DB(mvOsPrintf("DRAM: Read Dimm eeprom\n"));
++    twsiSlave.slaveAddr.address = MV_BOARD_DIMM0_I2C_ADDR;
++    twsiSlave.slaveAddr.type = ADDR7_BIT;
++    twsiSlave.validOffset = MV_TRUE;
++    twsiSlave.offset = 0;
++    twsiSlave.moreThen256 = MV_FALSE;
++
++    if( MV_OK != mvTwsiRead (MV_BOARD_DIMM_I2C_CHANNEL, &twsiSlave, 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 */
++    twsiSlave.slaveAddr.address = MV_BOARD_DIMM1_I2C_ADDR;
++    twsiSlave.slaveAddr.type = ADDR7_BIT;
++    twsiSlave.validOffset = MV_TRUE;
++    twsiSlave.offset = 0;
++    twsiSlave.moreThen256 = MV_FALSE;
++
++    for(i = 0 ; i < SPD_SIZE ; i++)
++    {
++	twsiSlave.offset = i;
++	if( MV_OK != mvTwsiWrite (MV_BOARD_DIMM_I2C_CHANNEL, &twsiSlave, &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_TWSI_SLAVE twsiSlave;
++    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"));
++    twsiSlave.slaveAddr.address = (dimmNum == 0) ?
++                            MV_BOARD_DIMM0_I2C_ADDR : MV_BOARD_DIMM1_I2C_ADDR;
++    twsiSlave.slaveAddr.type = ADDR7_BIT;
++    twsiSlave.validOffset = MV_TRUE;
++    twsiSlave.offset = 0;
++    twsiSlave.moreThen256 = MV_FALSE;
++
++    if( MV_OK != mvTwsiRead (MV_BOARD_DIMM_I2C_CHANNEL, &twsiSlave, 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_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 / (mvBoardSysClkGet() / 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/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.h b/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.h
+new file mode 100644
+index 0000000..f955466
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/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
++
++#include "ddr2/mvDramIf.h"
++#include "twsi/mvTwsi.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_STATUS dimmSpdCpy(MV_VOID);
++
++#endif /* __INCmvDram */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEth.c b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEth.c
+new file mode 100644
+index 0000000..d24e788
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEth.c
+@@ -0,0 +1,2952 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++        this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "mvTypes.h"
++#include "mv802_3.h"
++#include "mvDebug.h"
++#include "mvCommon.h"
++#include "mvOs.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "eth-phy/mvEthPhy.h"
++#include "eth/mvEth.h"
++#include "eth/gbe/mvEthGbe.h"
++#include "cpu/mvCpu.h"
++
++#ifdef INCLUDE_SYNC_BARR
++#include "sys/mvCpuIf.h"
++#endif
++
++#ifdef MV_RT_DEBUG
++#   define ETH_DEBUG
++#endif
++
++
++/* locals */
++MV_BOOL         ethDescInSram;
++MV_BOOL         ethDescSwCoher;
++
++/* 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 MV_U32 mvEthMruGet(MV_U32 maxRxPktSize);
++
++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(void)
++{
++    int port;
++
++    /* 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<mvCtrlEthMaxPortGet(); port++)
++    {
++
++#if defined (MV78200)
++	    /* Skip ports mapped to another CPU*/
++	if (MV_FALSE == mvSocUnitIsMappedToThisCpu(GIGA0+port))
++	{
++		    continue;
++	}
++#endif
++
++	/* Skip power down ports */
++	if (MV_FALSE == mvCtrlPwrClckGet(ETH_GIG_UNIT_ID, port)) continue;
++
++        /* 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;
++#if (ETHER_DRAM_COHER == MV_CACHE_COHER_SW)
++    isSwCoher = MV_TRUE;
++#else
++    isSwCoher = MV_FALSE;
++#endif
++
++#if defined(ETH_DESCR_IN_SRAM)
++    if( mvCtrlSramSizeGet() > 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)mvCtrlEthMaxPortGet()) ||
++        (pEthPortInit->rxDefQ   >= MV_ETH_RX_Q_NUM)  ||
++        (pEthPortInit->maxRxPktSize < 1518) )
++    {
++        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.maxRxPktSize = pEthPortInit->maxRxPktSize;
++    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, mvBoardPhyAddrGet(portNo) );
++
++    /* 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, portSerialCtrlReg, portSerialCtrl1Reg, portSdmaCfgReg;
++    MV_BOARD_MAC_SPEED  boardMacCfg;
++
++    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;
++
++    boardMacCfg = mvBoardMacSpeedGet(ethPortNo);
++
++    if(boardMacCfg == BOARD_MAC_SPEED_100M)
++    {
++        portSerialCtrlReg = PORT_SERIAL_CONTROL_100MB_FORCE_VALUE;
++    }
++    else if(boardMacCfg == BOARD_MAC_SPEED_1000M)
++    {
++        portSerialCtrlReg = PORT_SERIAL_CONTROL_1000MB_FORCE_VALUE;
++    }
++    else
++    {
++        portSerialCtrlReg =  PORT_SERIAL_CONTROL_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);
++
++#if ( (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WB) ||  \
++      (ETHER_DRAM_COHER == MV_CACHE_COHER_HW_WT) )
++    /* 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 |
++                       ETH_DESC_SWAP_MASK);
++# 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);
++
++    portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK;
++
++    portSerialCtrlReg |= mvEthMruGet(pPortCtrl->portConfig.maxRxPktSize);
++
++    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo), portSerialCtrlReg);
++
++    /* 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);
++    }
++
++    /* Allow receiving packes with odd number of preamble nibbles */
++    portSerialCtrl1Reg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(ethPortNo));
++    portSerialCtrl1Reg |= ETH_EN_MII_ODD_PRE_MASK;
++    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(ethPortNo), portSerialCtrl1Reg);
++
++    /* 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;
++
++    /* 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) );
++    }
++
++    /* 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 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) ||
++               ((regData & ETH_TX_IN_PROGRESS_MASK) != 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) &&
++            ((regData & ETH_TX_IN_PROGRESS_MASK) == 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/(mvBoardTclkGet()/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             ethPortNo;
++    ETH_PORT_CTRL*  pPortCtrl = (ETH_PORT_CTRL*)pEthPortHndl;
++    MV_U32      portSerialCtrlReg;
++
++    ethPortNo = pPortCtrl->portNo;
++
++    /* Enable port */
++    portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(ethPortNo));
++    portSerialCtrlReg |= (ETH_DO_NOT_FORCE_LINK_FAIL_MASK | ETH_PORT_ENABLE_MASK);
++
++    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNo), portSerialCtrlReg);
++
++    mvEthMibCountersClear(pEthPortHndl);
++
++    pPortCtrl->portState = MV_PAUSED;
++
++    /* If Link is UP, Start RX and TX traffic */
++    if( MV_REG_READ( ETH_PORT_STATUS_REG(ethPortNo) ) & ETH_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             ethPortNum = 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(ETH_PORT_SERIAL_CTRL_REG(ethPortNum));
++    regData &= ~(ETH_PORT_ENABLE_MASK);
++    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(ethPortNum), regData);
++
++    /* Wait about 2500 tclk cycles */
++    mvDelay = (PORT_DISABLE_WAIT_TCLOCKS*(mvCpuPclkGet()/mvBoardTclkGet()));
++    for(mvDelay; mvDelay>0; mvDelay--);
++
++    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*)pTxDesc->returnInfo;
++	if (pPktInfo)
++		pPktInfo->status = pTxDesc->cmdSts;
++
++        pTxDesc->cmdSts = 0x0;
++        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*)pRxDesc->returnInfo;
++
++    pPktInfo->status  = pRxDesc->cmdSts;
++    pRxDesc->cmdSts = 0x0;
++    pRxDesc->returnInfo = 0x0;
++    ETH_DESCR_FLUSH_INV(pPortCtrl, pRxDesc);
++
++    pQueueCtrl->pCurrentDescr = RX_NEXT_DESC_PTR(pRxDesc, pQueueCtrl);
++    return pPktInfo;
++}
++
++
++/******************************************************************************/
++/*                          Port Configuration functions                      */
++/******************************************************************************/
++/*******************************************************************************
++* mvEthMruGet - Get MRU configuration for Max Rx packet size.
++*
++* INPUT:
++*           MV_U32 maxRxPktSize - max  packet size.
++*
++* RETURN:   MV_U32 - MRU configuration.
++*
++*******************************************************************************/
++static MV_U32 mvEthMruGet(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;
++}
++
++/*******************************************************************************
++* 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 * (mvBoardTclkGet() / 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 * (mvBoardTclkGet() / 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) / (mvBoardTclkGet() / 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) / (mvBoardTclkGet() / 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;
++    MV_U32      portSerialCtrlReg;
++
++    if((maxRxSize < 1518) || (maxRxSize & ~ETH_RX_BUFFER_MASK))
++       return MV_BAD_PARAM;
++
++    pPortCtrl->portConfig.maxRxPktSize = maxRxSize;
++
++    portSerialCtrlReg =  MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo));
++    portSerialCtrlReg &= ~ETH_MAX_RX_PACKET_SIZE_MASK;
++    portSerialCtrlReg |= mvEthMruGet(pPortCtrl->portConfig.maxRxPktSize);
++    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(pPortCtrl->portNo), portSerialCtrlReg);
++
++    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)
++{
++    ETH_PORT_CTRL*  pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
++    int             port = pPortCtrl->portNo;
++    MV_U32      portSerialCtrlReg;
++
++    if( (port < 0) || (port >= (int)mvCtrlEthMaxPortGet()) )
++        return MV_OUT_OF_RANGE;
++
++    pPortCtrl = ethPortCtrl[port];
++    if(pPortCtrl == NULL)
++        return MV_NOT_FOUND;
++
++    /* 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(port));
++    /* Set Speed */
++    switch(speed)
++    {
++        case MV_ETH_SPEED_AN:
++            portSerialCtrlReg &= ~ETH_DISABLE_SPEED_AUTO_NEG_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;
++
++        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_1000:
++            portSerialCtrlReg |= ETH_DISABLE_SPEED_AUTO_NEG_MASK;
++            portSerialCtrlReg |= ETH_SET_GMII_SPEED_1000_MASK;
++            break;
++
++        default:
++            mvOsPrintf("ethDrv: Unexpected Speed value %d\n", speed);
++            return MV_BAD_VALUE;
++    }
++    /* Set duplex */
++    switch(duplex)
++    {
++        case MV_ETH_DUPLEX_AN:
++            portSerialCtrlReg &= ~ETH_DISABLE_DUPLEX_AUTO_NEG_MASK;
++            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("ethDrv: Unexpected Duplex value %d\n", duplex);
++            return MV_BAD_VALUE;
++    }
++    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_REG(port), portSerialCtrlReg);
++
++    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)
++{
++    ETH_PORT_CTRL*  pPortCtrl = (ETH_PORT_CTRL*)pPortHandle;
++    int             port = pPortCtrl->portNo;
++    MV_U32      portSerialCtrlReg;
++
++    if( (port < 0) || (port >= (int)mvCtrlEthMaxPortGet() ) )
++        return MV_OUT_OF_RANGE;
++
++    pPortCtrl = ethPortCtrl[port];
++    if(pPortCtrl == NULL)
++        return MV_NOT_FOUND;
++
++    portSerialCtrlReg = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
++    switch(flowControl)
++    {
++        case MV_ETH_FC_AN_ADV_DIS:
++            portSerialCtrlReg &= ~ETH_DISABLE_FC_AUTO_NEG_MASK;
++            portSerialCtrlReg &= ~ETH_ADVERTISE_SYM_FC_MASK;
++            break;
++
++        case MV_ETH_FC_AN_ADV_SYM:
++            portSerialCtrlReg &= ~ETH_DISABLE_FC_AUTO_NEG_MASK;
++            portSerialCtrlReg |= ETH_ADVERTISE_SYM_FC_MASK;
++            break;
++
++        case MV_ETH_FC_DISABLE:
++            portSerialCtrlReg |= ETH_DISABLE_FC_AUTO_NEG_MASK;
++            portSerialCtrlReg &= ~ETH_SET_FLOW_CTRL_MASK;
++            break;
++
++        case MV_ETH_FC_ENABLE:
++            portSerialCtrlReg |= ETH_DISABLE_FC_AUTO_NEG_MASK;
++            portSerialCtrlReg |= 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), portSerialCtrlReg);
++
++    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 >= mvCtrlEthMaxPortGet()))
++        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 >= mvCtrlEthMaxPortGet()))
++        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  regValue;
++
++    regValue = MV_REG_READ( ETH_PORT_STATUS_REG(port) );
++
++    if(regValue & ETH_GMII_SPEED_1000_MASK)
++        pStatus->speed = MV_ETH_SPEED_1000;
++    else if(regValue & ETH_MII_SPEED_100_MASK)
++        pStatus->speed = MV_ETH_SPEED_100;
++    else
++        pStatus->speed = MV_ETH_SPEED_10;
++
++    if(regValue & ETH_LINK_UP_MASK)
++        pStatus->isLinkUp = MV_TRUE;
++    else
++        pStatus->isLinkUp = MV_FALSE;
++
++    if(regValue & ETH_FULL_DUPLEX_MASK)
++        pStatus->duplex = MV_ETH_DUPLEX_FULL;
++    else
++        pStatus->duplex = MV_ETH_DUPLEX_HALF;
++
++
++    if(regValue & ETH_ENABLE_RCV_FLOW_CTRL_MASK)
++        pStatus->flowControl = MV_ETH_FC_ENABLE;
++    else
++        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++)
++    {
++        pRxDesc->bufSize     = 0x0;
++        pRxDesc->byteCnt     = 0x0;
++        pRxDesc->cmdSts      = ETH_BUFFER_OWNED_BY_HOST;
++        pRxDesc->bufPtr      = 0x0;
++        pRxDesc->returnInfo  = 0x0;
++        pRxPrevDesc = pRxDesc;
++        if(ix == (rxDescNum-1))
++        {
++            /* Closing Rx descriptors ring */
++            pRxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pRxDescBase);
++        }
++        else
++        {
++            pRxDesc = (ETH_RX_DESC*)((MV_ULONG)pRxDesc + ETH_RX_DESC_ALIGNED_SIZE);
++            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)
++        {
++            pRxDesc->bufSize     = 0x0;
++            pRxDesc->byteCnt     = 0x0;
++            pRxDesc->cmdSts      = ETH_BUFFER_OWNED_BY_HOST;
++            pRxDesc->bufPtr      = 0x0;
++            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++)
++    {
++        pTxDesc->byteCnt     = 0x0000;
++        pTxDesc->L4iChk      = 0x0000;
++        pTxDesc->cmdSts      = ETH_BUFFER_OWNED_BY_HOST;
++        pTxDesc->bufPtr      = 0x0;
++        pTxDesc->returnInfo  = 0x0;
++
++        pTxPrevDesc = pTxDesc;
++
++        if(ix == (txDescNum-1))
++        {
++            /* Closing Tx descriptors ring */
++            pTxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pTxDescBase);
++        }
++        else
++        {
++            pTxDesc = (ETH_TX_DESC*)((MV_ULONG)pTxDesc + ETH_TX_DESC_ALIGNED_SIZE);
++            pTxPrevDesc->nextDescPtr = (MV_U32)ethDescVirtToPhy(pQueueCtrl, (void*)pTxDesc);
++        }
++        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)
++        {
++            pTxDesc->byteCnt     = 0x0000;
++            pTxDesc->L4iChk      = 0x0000;
++            pTxDesc->cmdSts      = ETH_BUFFER_OWNED_BY_HOST;
++            pTxDesc->bufPtr      = 0x0;
++            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 = (char*)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 (mvBoardIsPortInSgmii(port))
++    mvEthPortSgmiiConfig(port);
++
++    /* Cancel Port Reset */
++    regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port));
++    regVal &= (~ETH_PORT_RESET_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);
++}
++
++void mvEthPortPowerDown(int port)
++{
++    MV_U32  regVal;
++
++    /* Port must be DISABLED */
++    regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_REG(port));
++    if( (regVal & ETH_PORT_ENABLE_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(ETH_PORT_SERIAL_CTRL_1_REG(port));
++    MV_REG_WRITE(ETH_PORT_SERIAL_CTRL_1_REG(port), regVal | ETH_PORT_RESET_MASK);
++    while((MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port)) & ETH_PORT_RESET_MASK) == 0);
++}
++
++static void mvEthPortSgmiiConfig(int port)
++{
++    MV_U32  regVal;
++
++    regVal = MV_REG_READ(ETH_PORT_SERIAL_CTRL_1_REG(port));
++
++    regVal |= (ETH_SGMII_MODE_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);
++}
++
++
++
++
++
++
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.c b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.c
+new file mode 100644
+index 0000000..f533475
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.c
+@@ -0,0 +1,748 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++        this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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.
++*
++*******************************************************************************/
++
++#include "mvOs.h"
++#include "mvCommon.h"
++#include "mvTypes.h"
++#include "mv802_3.h"
++#include "mvDebug.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "eth-phy/mvEthPhy.h"
++#include "eth/mvEth.h"
++#include "eth/gbe/mvEthDebug.h"
++
++/* #define mvOsPrintf printf */
++
++void    mvEthPortShow(void* pHndl);
++void    mvEthQueuesShow(void* pHndl, int rxQueue, int txQueue, int mode);
++
++/******************************************************************************/
++/*                          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);
++    }
++}
++
++/* 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( ETH_PORT_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 & ETH_GMII_SPEED_1000_MASK)
++        speed = 1000;
++    else if(regValue & ETH_MII_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 & ETH_LINK_UP_MASK) ? "UP" : "DOWN",
++                speed,
++                (regValue & ETH_FULL_DUPLEX_MASK) ? "FULL" : "HALF",
++                (regValue & ETH_ENABLE_RCV_FLOW_CTRL_MASK) ? "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),
++                                pRxDescr->cmdSts, pRxDescr->byteCnt, (MV_U32)pRxDescr->bufSize,
++                                (unsigned int)pRxDescr->bufPtr, (MV_ULONG)pRxDescr->returnInfo,
++                                ((MV_PKT_INFO*)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),
++                                pTxDescr->cmdSts, pTxDescr->byteCnt,
++                                (MV_U32)pTxDescr->bufPtr, (MV_ULONG)pTxDescr->returnInfo,
++                                pTxDescr->returnInfo ? (((MV_PKT_INFO*)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/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.h b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.h
+new file mode 100644
+index 0000000..f026f96
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.h
+@@ -0,0 +1,146 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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__
++
++#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);
++
++#endif
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthGbe.h b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthGbe.h
+new file mode 100644
+index 0000000..f4cae50
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthGbe.h
+@@ -0,0 +1,751 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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__
++
++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;
++
++    pTxCurrDesc->byteCnt = pBufInfo->dataSize;
++
++    /* Flash Buffer */
++    if(pPktInfo->pktSize != 0)
++    {
++#ifdef MV_NETBSD
++        pTxCurrDesc->bufPtr = pBufInfo->bufPhysAddr;
++        ETH_PACKET_CACHE_FLUSH(pBufInfo->bufVirtPtr, pPktInfo->pktSize);
++#else
++        pTxCurrDesc->bufPtr = ETH_PACKET_CACHE_FLUSH(pBufInfo->bufVirtPtr, pPktInfo->pktSize);
++#endif
++        pPktInfo->pktSize = 0;
++    }
++    else
++        pTxCurrDesc->bufPtr = pBufInfo->bufPhysAddr;
++
++    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 */
++    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);
++            pTxCurrDesc->bufPtr = ethDescVirtToPhy(pQueueCtrl, pTxBuf);
++        }
++        else
++        {
++            /* Flash Buffer */
++#ifdef MV_NETBSD
++            pTxCurrDesc->bufPtr = pBufInfo[bufCount].bufPhysAddr;
++	    ETH_PACKET_CACHE_FLUSH(pBufInfo[bufCount].bufVirtPtr, pBufInfo[bufCount].dataSize);
++#else
++            pTxCurrDesc->bufPtr = ETH_PACKET_CACHE_FLUSH(pBufInfo[bufCount].bufVirtPtr, pBufInfo[bufCount].dataSize);
++#endif
++        }
++
++        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 */
++            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);
++    }
++    /* Set last desc with DMA ownership and interrupt enable. */
++    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 */
++        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);
++    }
++    else
++    {
++        /* Last but not First */
++        pTxCurrDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA       |
++                              ETH_TX_ENABLE_INTERRUPT_MASK  |
++                              ETH_TX_ZERO_PADDING_MASK      |
++                              ETH_TX_LAST_DESC_MASK;
++
++        ETH_DESCR_FLUSH_INV(pPortCtrl, pTxCurrDesc);
++
++        /* 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 */
++        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);
++    }
++    /* 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 = 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*)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   = 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*)pRxCurrDesc->returnInfo;
++            pPktInfo->pFrags->dataSize  = pRxCurrDesc->byteCnt - 4;
++            pPktInfo->status            = commandStatus;
++            pPktInfo->fragIP            = 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, pRxCurrDesc->byteCnt, 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 */
++            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);
++        }
++    }
++}
++
++/*******************************************************************************
++* 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;
++
++    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",
++                    __FUNCTION__, pPortCtrl->portNo, pQueueCtrl->resource,
++                    pQueueCtrl->pCurrentDescr, pQueueCtrl->pUsedDescr);
++        return MV_OUT_OF_RANGE;
++    }
++
++    pRxUsedDesc->bufPtr     = pPktInfo->pFrags->bufPhysAddr;
++    pRxUsedDesc->returnInfo = (MV_ULONG)pPktInfo;
++    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 */
++    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;
++}
++
++
++#endif /* __mvEthGbe_h__ */
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthRegs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthRegs.h
+new file mode 100644
+index 0000000..7b9f052
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthRegs.h
+@@ -0,0 +1,700 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++        this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "ctrlEnv/mvCtrlEnvSpec.h"
++
++/****************************************/
++/*        Ethernet Unit Registers       */
++/****************************************/
++#define ETH_REG_BASE					MV_ETH_REG_BASE
++
++#define ETH_PHY_ADDR_REG(port)              (ETH_REG_BASE(port) + 0x000)
++#define ETH_SMI_REG(port)                   (ETH_REG_BASE(port) + 0x004)
++#define ETH_UNIT_DEF_ADDR_REG(port)         (ETH_REG_BASE(port) + 0x008)
++#define ETH_UNIT_DEF_ID_REG(port)           (ETH_REG_BASE(port) + 0x00c)
++#define ETH_UNIT_RESERVED(port)             (ETH_REG_BASE(port) + 0x014)
++#define ETH_UNIT_INTR_CAUSE_REG(port)       (ETH_REG_BASE(port) + 0x080)
++#define ETH_UNIT_INTR_MASK_REG(port)        (ETH_REG_BASE(port) + 0x084)
++
++
++#define ETH_UNIT_ERROR_ADDR_REG(port)       (ETH_REG_BASE(port) + 0x094)
++#define ETH_UNIT_INT_ADDR_ERROR_REG(port)   (ETH_REG_BASE(port) + 0x098)
++#define ETH_UNIT_CONTROL_REG(port)          (ETH_REG_BASE(port) + 0x0B0)
++
++#define ETH_PORT_CONFIG_REG(port)           (ETH_REG_BASE(port) + 0x400)
++#define ETH_PORT_CONFIG_EXTEND_REG(port)    (ETH_REG_BASE(port) + 0x404)
++#define ETH_MII_SERIAL_PARAM_REG(port)      (ETH_REG_BASE(port) + 0x408)
++#define ETH_GMII_SERIAL_PARAM_REG(port)     (ETH_REG_BASE(port) + 0x40c)
++#define ETH_VLAN_ETHER_TYPE_REG(port)       (ETH_REG_BASE(port) + 0x410)
++#define ETH_MAC_ADDR_LOW_REG(port)          (ETH_REG_BASE(port) + 0x414)
++#define ETH_MAC_ADDR_HIGH_REG(port)         (ETH_REG_BASE(port) + 0x418)
++#define ETH_SDMA_CONFIG_REG(port)           (ETH_REG_BASE(port) + 0x41c)
++#define ETH_DIFF_SERV_PRIO_REG(port, code)  (ETH_REG_BASE(port) + 0x420  + ((code)<<2))
++#define ETH_PORT_SERIAL_CTRL_REG(port)      (ETH_REG_BASE(port) + 0x43c)
++#define ETH_VLAN_TAG_TO_PRIO_REG(port)      (ETH_REG_BASE(port) + 0x440)
++#define ETH_PORT_STATUS_REG(port)           (ETH_REG_BASE(port) + 0x444)
++
++#define ETH_RX_QUEUE_COMMAND_REG(port)      (ETH_REG_BASE(port) + 0x680)
++#define ETH_TX_QUEUE_COMMAND_REG(port)      (ETH_REG_BASE(port) + 0x448)
++
++#define ETH_PORT_SERIAL_CTRL_1_REG(port)    (ETH_REG_BASE(port) + 0x44c)
++#define ETH_PORT_STATUS_1_REG(port)         (ETH_REG_BASE(port) + 0x450)
++#define ETH_PORT_MARVELL_HEADER_REG(port)   (ETH_REG_BASE(port) + 0x454)
++#define ETH_PORT_FIFO_PARAMS_REG(port)      (ETH_REG_BASE(port) + 0x458)
++#define ETH_MAX_TOKEN_BUCKET_SIZE_REG(port) (ETH_REG_BASE(port) + 0x45c)
++#define ETH_INTR_CAUSE_REG(port)            (ETH_REG_BASE(port) + 0x460)
++#define ETH_INTR_CAUSE_EXT_REG(port)        (ETH_REG_BASE(port) + 0x464)
++#define ETH_INTR_MASK_REG(port)             (ETH_REG_BASE(port) + 0x468)
++#define ETH_INTR_MASK_EXT_REG(port)         (ETH_REG_BASE(port) + 0x46c)
++#define ETH_TX_FIFO_URGENT_THRESH_REG(port) (ETH_REG_BASE(port) + 0x474)
++#define ETH_RX_MINIMAL_FRAME_SIZE_REG(port) (ETH_REG_BASE(port) + 0x47c)
++#define ETH_RX_DISCARD_PKTS_CNTR_REG(port)  (ETH_REG_BASE(port) + 0x484)
++#define ETH_RX_OVERRUN_PKTS_CNTR_REG(port)  (ETH_REG_BASE(port) + 0x488)
++#define ETH_INTERNAL_ADDR_ERROR_REG(port)   (ETH_REG_BASE(port) + 0x494)
++#define ETH_TX_FIXED_PRIO_CFG_REG(port)     (ETH_REG_BASE(port) + 0x4dc)
++#define ETH_TX_TOKEN_RATE_CFG_REG(port)     (ETH_REG_BASE(port) + 0x4e0)
++#define ETH_TX_QUEUE_COMMAND1_REG(port)     (ETH_REG_BASE(port) + 0x4e4)
++#define ETH_MAX_TRANSMIT_UNIT_REG(port)     (ETH_REG_BASE(port) + 0x4e8)
++#define ETH_TX_TOKEN_BUCKET_SIZE_REG(port)  (ETH_REG_BASE(port) + 0x4ec)
++#define ETH_TX_TOKEN_BUCKET_COUNT_REG(port) (ETH_REG_BASE(port) + 0x780)
++#define ETH_RX_DESCR_STAT_CMD_REG(port, q)  (ETH_REG_BASE(port) + 0x600 + ((q)<<4))
++#define ETH_RX_BYTE_COUNT_REG(port, q)      (ETH_REG_BASE(port) + 0x604 + ((q)<<4))
++#define ETH_RX_BUF_PTR_REG(port, q)         (ETH_REG_BASE(port) + 0x608 + ((q)<<4))
++#define ETH_RX_CUR_DESC_PTR_REG(port, q)    (ETH_REG_BASE(port) + 0x60c + ((q)<<4))
++#define ETH_TX_CUR_DESC_PTR_REG(port, q)    (ETH_REG_BASE(port) + 0x6c0 + ((q)<<2))
++
++#define ETH_TXQ_TOKEN_COUNT_REG(port, q)    (ETH_REG_BASE(port) + 0x700 + ((q)<<4))
++#define ETH_TXQ_TOKEN_CFG_REG(port, q)      (ETH_REG_BASE(port) + 0x704 + ((q)<<4))
++#define ETH_TXQ_ARBITER_CFG_REG(port, q)    (ETH_REG_BASE(port) + 0x708 + ((q)<<4))
++
++#if (MV_ETH_VERSION >= 4)
++#define ETH_TXQ_CMD_1_REG(port)             (ETH_REG_BASE(port) + 0x4E4)
++#define ETH_EJP_TX_HI_IPG_REG(port)         (ETH_REG_BASE(port) + 0x7A8)
++#define ETH_EJP_TX_LO_IPG_REG(port)         (ETH_REG_BASE(port) + 0x7B8)
++#define ETH_EJP_HI_TKN_LO_PKT_REG(port)     (ETH_REG_BASE(port) + 0x7C0)
++#define ETH_EJP_HI_TKN_ASYNC_PKT_REG(port)  (ETH_REG_BASE(port) + 0x7C4)
++#define ETH_EJP_LO_TKN_ASYNC_PKT_REG(port)  (ETH_REG_BASE(port) + 0x7C8)
++#define ETH_EJP_TX_SPEED_REG(port)          (ETH_REG_BASE(port) + 0x7D0)
++#endif /* MV_ETH_VERSION >= 4 */
++
++#define ETH_MIB_COUNTERS_BASE(port)         (ETH_REG_BASE(port) + 0x1000)
++#define ETH_DA_FILTER_SPEC_MCAST_BASE(port) (ETH_REG_BASE(port) + 0x1400)
++#define ETH_DA_FILTER_OTH_MCAST_BASE(port)  (ETH_REG_BASE(port) + 0x1500)
++#define ETH_DA_FILTER_UCAST_BASE(port)      (ETH_REG_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   */
++/****************************************/
++
++#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)
++
++/***** BITs of Transmit Queue Command (TQC) register *****/
++#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)
++
++#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 Ethernet Port Status reg (PSR) *****/
++#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_ENABLE_RCV_FLOW_CTRL_BIT        3
++#define ETH_ENABLE_RCV_FLOW_CTRL_MASK       (1<<ETH_ENABLE_RCV_FLOW_CTRL_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)
++
++/***** BITs of Ethernet Port Status 1 reg (PS1R) *****/
++#define ETH_AUTO_NEG_DONE_BIT               4
++#define ETH_AUTO_NEG_DONE_MASK              (1<<ETH_AUTO_NEG_DONE_BIT)
++
++#define ETH_SERDES_PLL_LOCKED_BIT           6
++#define ETH_SERDES_PLL_LOCKED_MASK          (1<<ETH_SERDES_PLL_LOCKED_BIT)
++
++/***** 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 Tx/Rx queue command reg (RQCR/TQCR) *****/
++#define ETH_QUEUE_ENABLE_OFFSET             0
++#define ETH_QUEUE_ENABLE_ALL_MASK           (0xFF<<ETH_QUEUE_ENABLE_OFFSET)
++#define ETH_QUEUE_ENABLE_MASK(queue)        (1<<((queue)+ETH_QUEUE_ENABLE_OFFSET))
++
++#define ETH_QUEUE_DISABLE_OFFSET            8
++#define ETH_QUEUE_DISABLE_ALL_MASK          (0xFF<<ETH_QUEUE_DISABLE_OFFSET)
++#define ETH_QUEUE_DISABLE_MASK(queue)       (1<<((queue)+ETH_QUEUE_DISABLE_OFFSET))
++
++
++/***** 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 Port Serial Control reg (PSCR) */
++#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_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_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_RETRANSMIT_FOREVER_BIT          11
++#define ETH_RETRANSMIT_FOREVER_MASK         (1<<ETH_RETRANSMIT_FOREVER_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_DTE_ADVERT_BIT                  14
++#define ETH_DTE_ADVERT_MASK                 (1<<ETH_DTE_ADVERT_BIT)
++
++#define ETH_MII_PHY_MODE_BIT                15
++#define ETH_MII_PHY_MODE_MAC                (0<<ETH_MII_PHY_MODE_BIT)
++#define ETH_MII_PHY_MODE_PHY                (1<<ETH_MII_PHY_MODE_BIT)
++
++#define ETH_MII_SOURCE_SYNCH_BIT            16
++#define ETH_MII_STANDARD_SYNCH              (0<<ETH_MII_SOURCE_SYNCH_BIT)
++#define ETH_MII_400Mbps_SYNCH               (1<<ETH_MII_SOURCE_CLK_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)
++
++/* BITs of Port Serial Control 1 reg (PSC1R) */
++#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)
++
++/* BITs of SDMA Descriptor Command/Status field */
++#if defined(MV_CPU_BE)
++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)
++
++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_REG_BASE(0) + 0x0A0)
++#define ETH_UNIT_PORTS_PADS_CALIB_1_REG     (MV_ETH_REG_BASE(0) + 0x0A4)
++#define ETH_UNIT_PORTS_PADS_CALIB_2_REG     (MV_ETH_REG_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/crypto/ocf/kirkwood/mvHal/mv_hal/eth/mvEth.h b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/mvEth.h
+new file mode 100644
+index 0000000..c42ed1a
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/eth/mvEth.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.
++
++*******************************************************************************/
++
++/*******************************************************************************
++* 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__
++
++/* includes */
++#include "mvTypes.h"
++#include "mv802_3.h"
++#include "ctrlEnv/mvCtrlEnvLib.h"
++#include "ctrlEnv/mvCtrlEnvAddrDec.h"
++#include "eth/gbe/mvEthRegs.h"
++#include "mvSysHwConfig.h"
++
++/* defines  */
++
++#define MV_ETH_EXTRA_FRAGS_NUM      2
++
++
++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     maxRxPktSize;
++    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(void);
++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);
++
++#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);
++
++/******************** 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"
++
++#endif /* __mvEth_h__ */
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.c b/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.c
+new file mode 100644
+index 0000000..889d4d9
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.c
+@@ -0,0 +1,362 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "gpp/mvGpp.h"
++#include "ctrlEnv/mvCtrlEnvLib.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);
++
++/*******************************************************************************
++* 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(mvCtrlRevGet()==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(mvCtrlRevGet()==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;
++
++}
++/*******************************************************************************
++* 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/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.h b/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.h
+new file mode 100644
+index 0000000..526d324
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.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 __INCmvGppH
++#define __INCmvGppH
++
++#include "mvCommon.h"
++#include "mvOs.h"
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++#include "gpp/mvGppRegs.h"
++
++/* 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*/
++
++/* 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);
++
++#endif /* #ifndef __INCmvGppH */
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGppRegs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGppRegs.h
+new file mode 100644
+index 0000000..b6fec34
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGppRegs.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 __INCmvGppRegsH
++#define __INCmvGppRegsH
++
++#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)			((grp == 0) ? 0x10100 : 0x10140)
++#define GPP_DATA_OUT_EN_REG(grp)		((grp == 0) ? 0x10104 : 0x10144)
++#define GPP_BLINK_EN_REG(grp)			((grp == 0) ? 0x10108 : 0x10148)
++#define GPP_DATA_IN_POL_REG(grp)		((grp == 0) ? 0x1010C : 0x1014c)
++#define GPP_DATA_IN_REG(grp)			((grp == 0) ? 0x10110 : 0x10150)
++#define GPP_INT_CAUSE_REG(grp)			((grp == 0) ? 0x10114 : 0x10154)
++#define GPP_INT_MASK_REG(grp)			((grp == 0) ? 0x10118 : 0x10158)
++#define GPP_INT_LVL_REG(grp)			((grp == 0) ? 0x1011c : 0x1015c)
++
++#define GPP_DATA_OUT_SET_REG			0x10120
++#define GPP_DATA_OUT_CLEAR_REG			0x10124
++
++#endif /* #ifndef __INCmvGppRegsH */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.c b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.c
+new file mode 100644
+index 0000000..672d3e3
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.c
+@@ -0,0 +1,669 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "ctrlEnv/sys/mvSysPex.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:
++*
++*
++* 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",
++                        __FUNCTION__, 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", __FUNCTION__, pciIf, pciIfmode);
++            return MV_FAIL;
++        }
++		return mvPexInit(pciIf - MV_PEX_START_IF, pexType);
++
++		#else
++		return MV_OK;
++		#endif
++
++	}
++	else
++	{
++		mvOsPrintf("%s: ERROR!!! Invalid pciIf %d\n", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__, 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",__FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__, 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", __FUNCTION__, pciIf);
++	}
++
++	return 0xffffffff;
++
++}
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.h b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.h
+new file mode 100644
+index 0000000..9c2d160
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/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
++
++#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);
++
++#endif /* #ifndef __INCPCIIFH */
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIfRegs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIfRegs.h
+new file mode 100644
+index 0000000..08d4d2d
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIfRegs.h
+@@ -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.
++
++*******************************************************************************/
++
++#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/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.c b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.c
+new file mode 100644
+index 0000000..f216979
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.c
+@@ -0,0 +1,1006 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "mvPciUtils.h"
++
++#include "ctrlEnv/mvCtrlEnvLib.h"
++
++/* #define MV_DEBUG */
++/* defines  */
++#ifdef MV_DEBUG
++	#define DB(x)	x
++	#define mvOsPrintf printf
++#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=mvPciIfLocalBusNumGet(pciIf);
++    MV_PCI_DEVICE *pPciDevice;
++	MV_PCI_DEVICE *pMainDevice;
++
++	DB(mvOsPrintf("mvPciScan: PCI interface num %d\n", pciIf));
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPexMaxIfGet())
++	{
++		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()))
++	{
++
++			if (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/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.h b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.h
+new file mode 100644
+index 0000000..2ee0b17
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.h
+@@ -0,0 +1,323 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "mvSysHwConfig.h"
++#include "pci-if/mvPciIf.h"
++#include "pci/mvPciRegs.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/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.c b/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.c
+new file mode 100644
+index 0000000..4a08734
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.c
+@@ -0,0 +1,1047 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "pci/mvPci.h"
++
++#include "ctrlEnv/mvCtrlEnvLib.h"
++
++/* defines  */
++#ifdef MV_DEBUG
++	#define DB(x)	x
++#else
++	#define DB(x)
++#endif
++
++
++
++MV_VOID mvPciHalInit(MV_U32 pciIf, MV_PCI_MOD pciIfmod)
++{
++        if (MV_PCI_MOD_HOST == pciIfmod)
++    {
++
++                mvPciLocalBusNumSet(pciIf, PCI_HOST_BUS_NUM(pciIf));
++                mvPciLocalDevNumSet(pciIf, PCI_HOST_DEV_NUM(pciIf));
++
++                /* Local device master Enable */
++                mvPciMasterEnable(pciIf, MV_TRUE);
++
++                /* Local device slave Enable */
++                mvPciSlaveEnable(pciIf, mvPciLocalBusNumGet(pciIf),
++                                                 mvPciLocalDevNumGet(pciIf), MV_TRUE);
++        }
++        /* enable CPU-2-PCI ordering */
++        MV_REG_BIT_SET(PCI_CMD_REG(0), PCR_CPU_TO_PCI_ORDER_EN);
++}
++
++/*******************************************************************************
++* mvPciCommandSet - Set PCI comman register value.
++*
++* DESCRIPTION:
++*       This function sets a given PCI interface with its command register
++*       value.
++*
++* INPUT:
++*       pciIf   - PCI interface number.
++*       command - 32bit value to be written to comamnd register.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       MV_BAD_PARAM if pciIf is not in range otherwise MV_OK
++*
++*******************************************************************************/
++MV_STATUS mvPciCommandSet(MV_U32 pciIf, MV_U32 command)
++{
++    MV_U32 locBusNum, locDevNum, regVal;
++
++    locBusNum =  mvPciLocalBusNumGet(pciIf);
++    locDevNum =  mvPciLocalDevNumGet(pciIf);
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciCommandSet: ERR. Invalid PCI IF num %d\n", pciIf);
++		return MV_BAD_PARAM;
++	}
++
++	/* Set command register */
++	MV_REG_WRITE(PCI_CMD_REG(pciIf), command);
++
++    /* Upodate device max outstanding split tarnsaction */
++    if ((command & PCR_CPU_TO_PCI_ORDER_EN) &&
++        (command & PCR_PCI_TO_CPU_ORDER_EN))
++    {
++        /* Read PCI-X command register */
++        regVal = mvPciConfigRead (pciIf, locBusNum, locDevNum, 0, PCIX_COMMAND);
++
++        /* clear bits 22:20 */
++        regVal &= 0xff8fffff;
++
++        /* set reset value */
++        regVal |= (0x3 << 20);
++
++        /* Write back the value */
++        mvPciConfigWrite (pciIf, locBusNum, locDevNum, 0, PCIX_COMMAND, regVal);
++    }
++
++	return MV_OK;
++
++
++}
++
++
++/*******************************************************************************
++* mvPciModeGet - Get PCI interface mode.
++*
++* DESCRIPTION:
++*       This function returns the given PCI interface mode.
++*
++* INPUT:
++*       pciIf   - PCI interface number.
++*
++* OUTPUT:
++*       pPciMode - Pointer to PCI mode structure.
++*
++* RETURN:
++*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
++*
++*******************************************************************************/
++MV_STATUS mvPciModeGet(MV_U32 pciIf, MV_PCI_MODE *pPciMode)
++{
++	MV_U32 pciMode;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciModeGet: ERR. Invalid PCI interface %d\n", pciIf);
++		return MV_BAD_PARAM;
++	}
++	if (NULL == pPciMode)
++	{
++		mvOsPrintf("mvPciModeGet: ERR. pPciMode = NULL  \n");
++		return MV_BAD_PARAM;
++	}
++
++	/* Read pci mode register */
++	pciMode = MV_REG_READ(PCI_MODE_REG(pciIf));
++
++	switch (pciMode & PMR_PCI_MODE_MASK)
++	{
++		case PMR_PCI_MODE_CONV:
++            pPciMode->pciType  = MV_PCI_CONV;
++
++			if (MV_REG_READ(PCI_DLL_CTRL_REG(pciIf)) & PDC_DLL_EN)
++			{
++				pPciMode->pciSpeed = 66000000; /* 66MHZ */
++			}
++			else
++			{
++				pPciMode->pciSpeed = 33000000; /* 33MHZ */
++			}
++
++			break;
++
++		case PMR_PCI_MODE_PCIX_66MHZ:
++			pPciMode->pciType  = MV_PCIX;
++			pPciMode->pciSpeed = 66000000; /* 66MHZ */
++			break;
++
++		case PMR_PCI_MODE_PCIX_100MHZ:
++			pPciMode->pciType  = MV_PCIX;
++			pPciMode->pciSpeed = 100000000; /* 100MHZ */
++			break;
++
++		case PMR_PCI_MODE_PCIX_133MHZ:
++			pPciMode->pciType  = MV_PCIX;
++			pPciMode->pciSpeed = 133000000; /* 133MHZ */
++			break;
++
++		default:
++			{
++				mvOsPrintf("mvPciModeGet: ERR. Non existing mode !!\n");
++				return MV_ERROR;
++			}
++	}
++
++	switch (pciMode & PMR_PCI_64_MASK)
++	{
++		case PMR_PCI_64_64BIT:
++			pPciMode->pciWidth = MV_PCI_64;
++			break;
++
++		case PMR_PCI_64_32BIT:
++            pPciMode->pciWidth = MV_PCI_32;
++            break;
++
++		default:
++			{
++				mvOsPrintf("mvPciModeGet: ERR. Non existing mode !!\n");
++				return MV_ERROR;
++			}
++	}
++
++	return MV_OK;
++}
++
++/*******************************************************************************
++* mvPciRetrySet - Set PCI retry counters
++*
++* DESCRIPTION:
++*       This function specifies the number of times the PCI controller
++*       retries a transaction before it quits.
++*       Applies to the PCI Master when acting as a requester.
++*       Applies to the PCI slave when acting as a completer (PCI-X mode).
++*       A 0x00 value means a "retry forever".
++*
++* INPUT:
++*       pciIf   - PCI interface number.
++*       counter - Number of times PCI controller retry. Use counter value
++*                 up to PRR_RETRY_CNTR_MAX.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
++*
++*******************************************************************************/
++MV_STATUS mvPciRetrySet(MV_U32 pciIf, MV_U32 counter)
++{
++	MV_U32 pciRetry;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciRetrySet: ERR. Invalid PCI interface %d\n", pciIf);
++		return MV_BAD_PARAM;
++	}
++
++	if (counter >= PRR_RETRY_CNTR_MAX)
++	{
++		mvOsPrintf("mvPciRetrySet: ERR. Invalid counter: %d\n", counter);
++		return MV_BAD_PARAM;
++
++	}
++
++	/* Reading PCI retry register */
++    pciRetry  = MV_REG_READ(PCI_RETRY_REG(pciIf));
++
++	pciRetry &= ~PRR_RETRY_CNTR_MASK;
++
++	pciRetry |= (counter << PRR_RETRY_CNTR_OFFS);
++
++	/* write new value */
++	MV_REG_WRITE(PCI_RETRY_REG(pciIf), pciRetry);
++
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* mvPciDiscardTimerSet - Set PCI discard timer
++*
++* DESCRIPTION:
++*       This function set PCI discard timer.
++*       In conventional PCI mode:
++*       Specifies the number of PCLK cycles the PCI slave keeps a non-accessed
++*       read buffers (non-completed delayed read) before invalidate the buffer.
++*       Set to '0' to disable the timer. The PCI slave waits for delayed
++*       read completion forever.
++*       In PCI-X mode:
++*       Specifies the number of PCLK cycles the PCI master waits for split
++*       completion transaction, before it invalidates the pre-allocated read
++*       buffer.
++*       Set to '0' to disable the timer. The PCI master waits for split
++*       completion forever.
++*       NOTE: Must be set to a number greater than MV_PCI_MAX_DISCARD_CLK,
++*       unless using the "wait for ever" setting 0x0.
++*       NOTE: Must not be updated while there are pending read requests.
++*
++* INPUT:
++*       pciIf      - PCI interface number.
++*       pClkCycles - Number of PCI clock cycles.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
++*
++*******************************************************************************/
++MV_STATUS mvPciDiscardTimerSet(MV_U32 pciIf, MV_U32 pClkCycles)
++{
++	MV_U32 pciDiscardTimer;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciDiscardTimerSet: ERR. Invalid PCI interface %d\n",
++																		pciIf);
++		return MV_BAD_PARAM;
++	}
++
++	if (pClkCycles >= PDTR_TIMER_MIN)
++	{
++		mvOsPrintf("mvPciDiscardTimerSet: ERR. Invalid Clk value: %d\n",
++																   pClkCycles);
++		return MV_BAD_PARAM;
++
++	}
++
++	/* Read  PCI Discard Timer */
++	pciDiscardTimer  = MV_REG_READ(PCI_DISCARD_TIMER_REG(pciIf));
++
++	pciDiscardTimer &= ~PDTR_TIMER_MASK;
++
++    pciDiscardTimer |= (pClkCycles << PDTR_TIMER_OFFS);
++
++	/* Write new value */
++	MV_REG_WRITE(PCI_DISCARD_TIMER_REG(pciIf), pciDiscardTimer);
++
++	return MV_OK;
++
++}
++
++/* PCI Arbiter routines */
++
++/*******************************************************************************
++* mvPciArbEnable - PCI arbiter enable/disable
++*
++* DESCRIPTION:
++*       This fuction enable/disables a given PCI interface arbiter.
++*       NOTE: Arbiter setting can not be changed while in work. It should only
++*             be set once.
++* INPUT:
++*       pciIf  - PCI interface number.
++*       enable - Enable/disable parameter. If enable = MV_TRUE then enable.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_STATUS mvPciArbEnable(MV_U32 pciIf, MV_BOOL enable)
++{
++	MV_U32 regVal;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciArbEnable: ERR. Invalid PCI interface %d\n", pciIf);
++		return MV_ERROR;
++	}
++
++    /* Set PCI Arbiter Control register according to default configuration	*/
++	regVal = MV_REG_READ(PCI_ARBITER_CTRL_REG(pciIf));
++
++	/* Make sure arbiter disabled before changing its values */
++	MV_REG_BIT_RESET(PCI_ARBITER_CTRL_REG(pciIf), PACR_ARB_ENABLE);
++
++	regVal &= ~PCI_ARBITER_CTRL_DEFAULT_MASK;
++
++	regVal |= PCI_ARBITER_CTRL_DEFAULT;		/* Set default configuration	*/
++
++	if (MV_TRUE == enable)
++	{
++		regVal |= PACR_ARB_ENABLE;
++	}
++	else
++	{
++		regVal &= ~PACR_ARB_ENABLE;
++	}
++
++	/* Write to register										            */
++	MV_REG_WRITE(PCI_ARBITER_CTRL_REG(pciIf), regVal);
++
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* mvPciArbParkDis - Disable arbiter parking on agent
++*
++* DESCRIPTION:
++*       This function disables the PCI arbiter from parking on the given agent
++*       list.
++*
++* INPUT:
++*       pciIf        - PCI interface number.
++*       pciAgentMask - When a bit in the mask is set to '1', parking on
++*                      the associated PCI master is disabled. Mask bit
++*                      refers to bit 0 - 6. For example disable parking on PCI
++*                      agent 3 set pciAgentMask 0x4 (bit 3 is set).
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       None.
++*
++*******************************************************************************/
++MV_STATUS mvPciArbParkDis(MV_U32 pciIf, MV_U32 pciAgentMask)
++{
++	MV_U32 pciArbiterCtrl;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciArbParkDis: ERR. Invalid PCI interface %d\n", pciIf);
++		return MV_ERROR;
++	}
++
++	/* Reading Arbiter Control register */
++	pciArbiterCtrl = MV_REG_READ(PCI_ARBITER_CTRL_REG(pciIf));
++
++	/* Arbiter must be disabled before changing parking */
++	MV_REG_BIT_RESET(PCI_ARBITER_CTRL_REG(pciIf), PACR_ARB_ENABLE);
++
++	/* do the change */
++    pciArbiterCtrl &= ~PACR_PARK_DIS_MASK;
++	pciArbiterCtrl |= (pciAgentMask << PACR_PARK_DIS_OFFS);
++
++	/* writing new value ( if th earbiter was enabled before the change		*/
++	/* here it will be reenabled											*/
++	MV_REG_WRITE(PCI_ARBITER_CTRL_REG(pciIf), pciArbiterCtrl);
++
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* mvPciArbBrokDetectSet - Set PCI arbiter broken detection
++*
++* DESCRIPTION:
++*       This function sets the maximum number of cycles that the arbiter
++*       waits for a PCI master to respond to its grant assertion. If a
++*       PCI agent fails to respond within this time, the PCI arbiter aborts
++*       the transaction and performs a new arbitration cycle.
++*       NOTE: Value must be greater than '1' for conventional PCI and
++*       greater than '5' for PCI-X.
++*
++* INPUT:
++*       pciIf      - PCI interface number.
++*       pClkCycles - Number of PCI clock cycles. If equal to '0' the broken
++*                    master detection is disabled.
++*
++* OUTPUT:
++*       None.
++*
++* RETURN:
++*       MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
++*
++*******************************************************************************/
++MV_STATUS mvPciArbBrokDetectSet(MV_U32 pciIf, MV_U32 pClkCycles)
++{
++	MV_U32 pciArbiterCtrl;
++	MV_U32 pciMode;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciArbBrokDetectSet: ERR. Invalid PCI interface %d\n",
++																		pciIf);
++		return MV_BAD_PARAM;
++	}
++
++	/* Checking PCI mode and if pClkCycles is legal value */
++	pciMode = MV_REG_READ(PCI_MODE_REG(pciIf));
++	pciMode &= PMR_PCI_MODE_MASK;
++
++	if (PMR_PCI_MODE_CONV == pciMode)
++	{
++		if (pClkCycles < PACR_BROKEN_VAL_CONV_MIN)
++			return MV_ERROR;
++	}
++	else
++	{
++		if (pClkCycles < PACR_BROKEN_VAL_PCIX_MIN)
++			return MV_ERROR;
++	}
++
++	pClkCycles <<= PACR_BROKEN_VAL_OFFS;
++
++	/* Reading Arbiter Control register */
++	pciArbiterCtrl  = MV_REG_READ(PCI_ARBITER_CTRL_REG(pciIf));
++	pciArbiterCtrl &= ~PACR_BROKEN_VAL_MASK;
++	pciArbiterCtrl |= pClkCycles;
++
++	/* Arbiter must be disabled before changing broken detection */
++	MV_REG_BIT_RESET(PCI_ARBITER_CTRL_REG(pciIf), PACR_ARB_ENABLE);
++
++	/* writing new value ( if th earbiter was enabled before the change	*/
++	/* here it will be reenabled											*/
++
++	MV_REG_WRITE(PCI_ARBITER_CTRL_REG(pciIf), pciArbiterCtrl);
++
++	return MV_OK;
++}
++
++/* 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 mvPciConfigRead (MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_U32 func,
++                        MV_U32 regOff)
++{
++	MV_U32 pciData = 0;
++
++	/* Parameter checking   */
++	if (PCI_DEFAULT_IF != pciIf)
++	{
++		if (pciIf >= mvCtrlPciMaxIfGet())
++		{
++			mvOsPrintf("mvPciConfigRead: ERR. Invalid PCI interface %d\n",pciIf);
++			return 0xFFFFFFFF;
++		}
++	}
++
++	if (dev >= MAX_PCI_DEVICES)
++	{
++		DB(mvOsPrintf("mvPciConfigRead: ERR. device number illigal %d\n", dev));
++		return 0xFFFFFFFF;
++	}
++
++	if (func >= MAX_PCI_FUNCS)
++	{
++		DB(mvOsPrintf("mvPciConfigRead: ERR. function number illigal %d\n", func));
++		return 0xFFFFFFFF;
++	}
++
++	if (bus >= MAX_PCI_BUSSES)
++	{
++		DB(mvOsPrintf("mvPciConfigRead: ERR. bus number illigal %d\n", bus));
++		return MV_ERROR;
++	}
++
++
++	/* Creating PCI address to be passed */
++	pciData |= (bus << PCAR_BUS_NUM_OFFS);
++	pciData |= (dev << PCAR_DEVICE_NUM_OFFS);
++	pciData |= (func << PCAR_FUNC_NUM_OFFS);
++	pciData |= (regOff & PCAR_REG_NUM_MASK);
++
++	pciData |= PCAR_CONFIG_EN;
++
++	/* Write the address to the PCI configuration address register */
++	MV_REG_WRITE(PCI_CONFIG_ADDR_REG(pciIf), pciData);
++
++	/* In order to let the PCI controller absorbed the address of the read	*/
++	/* transaction we perform a validity check that the address was written */
++	if(pciData != MV_REG_READ(PCI_CONFIG_ADDR_REG(pciIf)))
++	{
++		return MV_ERROR;
++	}
++	/* Read the Data returned in the PCI Data register */
++	pciData = MV_REG_READ(PCI_CONFIG_DATA_REG(pciIf));
++
++	return pciData;
++}
++
++/*******************************************************************************
++* 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 mvPciConfigWrite(MV_U32 pciIf, MV_U32 bus, MV_U32 dev,
++                           MV_U32 func, MV_U32 regOff, MV_U32 data)
++{
++	MV_U32 pciData = 0;
++
++	/* Parameter checking   */
++	if (PCI_DEFAULT_IF != pciIf)
++	{
++		if (pciIf >= mvCtrlPciMaxIfGet())
++		{
++			mvOsPrintf("mvPciConfigWrite: ERR. Invalid PCI interface %d\n",
++																		pciIf);
++			return 0xFFFFFFFF;
++		}
++	}
++
++	if (dev >= MAX_PCI_DEVICES)
++	{
++		mvOsPrintf("mvPciConfigWrite: ERR. device number illigal %d\n",dev);
++		return MV_BAD_PARAM;
++	}
++
++	if (func >= MAX_PCI_FUNCS)
++	{
++		mvOsPrintf("mvPciConfigWrite: ERR. function number illigal %d\n", func);
++		return MV_ERROR;
++	}
++
++	if (bus >= MAX_PCI_BUSSES)
++	{
++		mvOsPrintf("mvPciConfigWrite: ERR. bus number illigal %d\n", bus);
++		return MV_ERROR;
++	}
++
++	/* Creating PCI address to be passed */
++	pciData |= (bus << PCAR_BUS_NUM_OFFS);
++	pciData |= (dev << PCAR_DEVICE_NUM_OFFS);
++	pciData |= (func << PCAR_FUNC_NUM_OFFS);
++	pciData |= (regOff & PCAR_REG_NUM_MASK);
++
++	pciData |= PCAR_CONFIG_EN;
++
++	/* Write the address to the PCI configuration address register */
++	MV_REG_WRITE(PCI_CONFIG_ADDR_REG(pciIf), pciData);
++
++	/* In order to let the PCI controller absorbed the address of the read	*/
++	/* transaction we perform a validity check that the address was written */
++	if(pciData != MV_REG_READ(PCI_CONFIG_ADDR_REG(pciIf)))
++	{
++		return MV_ERROR;
++	}
++
++	/* Write the Data passed to the PCI Data register */
++	MV_REG_WRITE(PCI_CONFIG_DATA_REG(pciIf), data);
++
++	return MV_OK;
++}
++
++/*******************************************************************************
++* 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 mvPciMasterEnable(MV_U32 pciIf, MV_BOOL enable)
++{
++	MV_U32 pciCommandStatus;
++	MV_U32 RegOffs;
++	MV_U32 localBus;
++	MV_U32 localDev;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciMasterEnable: ERR. Invalid PCI interface %d\n", pciIf);
++		return MV_ERROR;
++	}
++
++	localBus = mvPciLocalBusNumGet(pciIf);
++	localDev = mvPciLocalDevNumGet(pciIf);
++
++	RegOffs = PCI_STATUS_AND_COMMAND;
++
++	pciCommandStatus = mvPciConfigRead(pciIf, localBus, localDev, 0, RegOffs);
++
++	if (MV_TRUE == enable)
++	{
++		pciCommandStatus |= PSCR_MASTER_EN;
++	}
++	else
++	{
++		pciCommandStatus &= ~PSCR_MASTER_EN;
++	}
++
++	mvPciConfigWrite(pciIf, localBus, localDev, 0, RegOffs, pciCommandStatus);
++
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* 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 mvPciSlaveEnable(MV_U32 pciIf, MV_U32 bus, MV_U32 dev, MV_BOOL enable)
++{
++	MV_U32 pciCommandStatus;
++	MV_U32 RegOffs;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciSlaveEnable: ERR. Invalid PCI interface %d\n", pciIf);
++		return MV_BAD_PARAM;
++	}
++	if (dev >= MAX_PCI_DEVICES)
++	{
++		mvOsPrintf("mvPciLocalDevNumSet: ERR. device number illigal %d\n", dev);
++		return MV_BAD_PARAM;
++
++	}
++
++	RegOffs = PCI_STATUS_AND_COMMAND;
++
++	pciCommandStatus=mvPciConfigRead(pciIf, bus, dev, 0, RegOffs);
++
++    if (MV_TRUE == enable)
++	{
++		pciCommandStatus |= (PSCR_IO_EN | PSCR_MEM_EN);
++	}
++	else
++	{
++		pciCommandStatus &= ~(PSCR_IO_EN | PSCR_MEM_EN);
++	}
++
++	mvPciConfigWrite(pciIf, bus, dev, 0, RegOffs, pciCommandStatus);
++
++	return MV_OK;
++}
++
++/*******************************************************************************
++* 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 mvPciLocalBusNumSet(MV_U32 pciIf, MV_U32 busNum)
++{
++	MV_U32 pciP2PConfig;
++	MV_PCI_MODE pciMode;
++	MV_U32 localBus;
++	MV_U32 localDev;
++
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciLocalBusNumSet: ERR. Invalid PCI interface %d\n",pciIf);
++		return MV_BAD_PARAM;
++	}
++	if (busNum >= MAX_PCI_BUSSES)
++	{
++		mvOsPrintf("mvPciLocalBusNumSet: ERR. bus number illigal %d\n", busNum);
++		return MV_ERROR;
++
++	}
++
++	localBus = mvPciLocalBusNumGet(pciIf);
++	localDev = mvPciLocalDevNumGet(pciIf);
++
++
++	/* PCI interface mode */
++	mvPciModeGet(pciIf, &pciMode);
++
++	/* if PCI type is PCI-X then it is not allowed to change the dev number */
++	if (MV_PCIX == pciMode.pciType)
++	{
++		pciP2PConfig = mvPciConfigRead(pciIf, localBus, localDev, 0, PCIX_STATUS );
++
++		pciP2PConfig &= ~PXS_BN_MASK;
++
++		pciP2PConfig |= (busNum << PXS_BN_OFFS) & PXS_BN_MASK;
++
++		mvPciConfigWrite(pciIf, localBus, localDev, 0, PCIX_STATUS,pciP2PConfig );
++
++	}
++	else
++	{
++		pciP2PConfig  = MV_REG_READ(PCI_P2P_CONFIG_REG(pciIf));
++
++		pciP2PConfig &= ~PPCR_BUS_NUM_MASK;
++
++		pciP2PConfig |= (busNum << PPCR_BUS_NUM_OFFS) & PPCR_BUS_NUM_MASK;
++
++		MV_REG_WRITE(PCI_P2P_CONFIG_REG(pciIf), pciP2PConfig);
++
++	}
++
++
++	return MV_OK;
++}
++
++
++/*******************************************************************************
++* 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 mvPciLocalBusNumGet(MV_U32 pciIf)
++{
++	MV_U32 pciP2PConfig;
++
++	/* Parameter checking   */
++	if (PCI_DEFAULT_IF != pciIf)
++	{
++		if (pciIf >= mvCtrlPciMaxIfGet())
++		{
++			mvOsPrintf("mvPciLocalBusNumGet: ERR. Invalid PCI interface %d\n",
++																		pciIf);
++			return 0xFFFFFFFF;
++		}
++	}
++
++	pciP2PConfig  = MV_REG_READ(PCI_P2P_CONFIG_REG(pciIf));
++	pciP2PConfig &= PPCR_BUS_NUM_MASK;
++	return (pciP2PConfig >> PPCR_BUS_NUM_OFFS);
++}
++
++
++/*******************************************************************************
++* 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 mvPciLocalDevNumSet(MV_U32 pciIf, MV_U32 devNum)
++{
++	MV_U32 pciP2PConfig;
++	MV_PCI_MODE pciMode;
++	MV_U32 localBus;
++	MV_U32 localDev;
++
++	/* Parameter checking   */
++	if (pciIf >= mvCtrlPciMaxIfGet())
++	{
++		mvOsPrintf("mvPciLocalDevNumSet: ERR. Invalid PCI interface %d\n",pciIf);
++		return MV_BAD_PARAM;
++	}
++	if (devNum >= MAX_PCI_DEVICES)
++	{
++		mvOsPrintf("mvPciLocalDevNumSet: ERR. device number illigal %d\n",
++																	   devNum);
++		return MV_BAD_PARAM;
++
++	}
++
++	localBus = mvPciLocalBusNumGet(pciIf);
++	localDev = mvPciLocalDevNumGet(pciIf);
++
++	/* PCI interface mode */
++	mvPciModeGet(pciIf, &pciMode);
++
++	/* if PCI type is PCIX then it is not allowed to change the dev number */
++	if (MV_PCIX == pciMode.pciType)
++	{
++		pciP2PConfig = mvPciConfigRead(pciIf, localBus, localDev, 0, PCIX_STATUS );
++
++		pciP2PConfig &= ~PXS_DN_MASK;
++
++		pciP2PConfig |= (devNum << PXS_DN_OFFS) & PXS_DN_MASK;
++
++		mvPciConfigWrite(pciIf,localBus, localDev, 0, PCIX_STATUS,pciP2PConfig );
++	}
++	else
++	{
++		pciP2PConfig  = MV_REG_READ(PCI_P2P_CONFIG_REG(pciIf));
++
++		pciP2PConfig &= ~PPCR_DEV_NUM_MASK;
++
++		pciP2PConfig |= (devNum << PPCR_DEV_NUM_OFFS) & PPCR_DEV_NUM_MASK;
++
++		MV_REG_WRITE(PCI_P2P_CONFIG_REG(pciIf), pciP2PConfig);
++	}
++
++	return MV_OK;
++}
++
++/*******************************************************************************
++* 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 mvPciLocalDevNumGet(MV_U32 pciIf)
++{
++	MV_U32 pciP2PConfig;
++
++	/* Parameter checking   */
++
++	if (PCI_DEFAULT_IF != pciIf)
++	{
++		if (pciIf >= mvCtrlPciMaxIfGet())
++		{
++			mvOsPrintf("mvPciLocalDevNumGet: ERR. Invalid PCI interface %d\n",
++																		pciIf);
++			return 0xFFFFFFFF;
++		}
++	}
++
++	pciP2PConfig  = MV_REG_READ(PCI_P2P_CONFIG_REG(pciIf));
++
++	pciP2PConfig &= PPCR_DEV_NUM_MASK;
++
++	return (pciP2PConfig >> PPCR_DEV_NUM_OFFS);
++}
++
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.h b/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.h
+new file mode 100644
+index 0000000..4746336
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.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.
++
++*******************************************************************************/
++
++
++#ifndef __INCPCIH
++#define __INCPCIH
++
++#include "mvCommon.h"
++#include "mvOs.h"
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++#include "pci/mvPciRegs.h"
++
++
++/* NOTE not supported in this driver:
++
++ Built In Self Test (BIST)
++ Vital Product Data (VPD)
++ Message Signaled Interrupt (MSI)
++ Power Management
++ Compact PCI Hot Swap
++ Header retarget
++
++Registers not supported:
++1) PCI DLL Status and Control (PCI0 0x1D20, PCI1 0x1DA0)
++2) PCI/MPP Pads Calibration (CI0/MPP[31:16] 0x1D1C, PCI1/MPP[15:0] 0X1D9C)
++*/
++
++/* defines */
++/* The number of supported PCI interfaces depend on Marvell controller			*/
++/* device number. This device number ID is located on the PCI unit			*/
++/* configuration header. This creates a loop where calling PCI					*/
++/* configuration read/write	routine results a call to get PCI configuration */
++/* information etc. This macro defines a default PCI interface. This PCI	*/
++/* interface is sure to exist.												*/
++#define PCI_DEFAULT_IF	0
++
++
++/* typedefs */
++/* The Marvell controller supports both conventional PCI and PCI-X.         */
++/* This enumeration describes the PCI type.                                 */
++typedef enum _mvPciType
++{
++    MV_PCI_CONV,    /* Conventional PCI */
++    MV_PCIX         /* PCI-X            */
++}MV_PCI_TYPE;
++
++typedef enum _mvPciMod
++{
++	MV_PCI_MOD_HOST,
++	MV_PCI_MOD_DEVICE
++}MV_PCI_MOD;
++
++
++/* The Marvell controller supports both PCI width of 32 and 64 bit.         */
++/* This enumerator describes PCI width                                      */
++typedef enum _mvPciWidth
++{
++    MV_PCI_32,  /* PCI width 32bit  */
++    MV_PCI_64   /* PCI width 64bit  */
++}MV_PCI_WIDTH;
++
++/* This structure describes the PCI unit configured type, speed and width.  */
++typedef struct _mvPciMode
++{
++    MV_PCI_TYPE  pciType;    /* PCI type                                    */
++    MV_U32       pciSpeed;   /* Assuming PCI base clock on board is 33MHz   */
++    MV_PCI_WIDTH pciWidth;   /* PCI bus width                               */
++}MV_PCI_MODE;
++
++/* mvPciInit - Initialize PCI interfaces*/
++MV_VOID mvPciHalInit(MV_U32 pciIf, MV_PCI_MOD pciIfmod);
++
++/* mvPciCommandSet - Set PCI comman register value.*/
++MV_STATUS mvPciCommandSet(MV_U32 pciIf, MV_U32 command);
++
++/* mvPciModeGet - Get PCI interface mode.*/
++MV_STATUS mvPciModeGet(MV_U32 pciIf, MV_PCI_MODE *pPciMode);
++
++/* mvPciRetrySet - Set PCI retry counters*/
++MV_STATUS mvPciRetrySet(MV_U32 pciIf, MV_U32 counter);
++
++/* mvPciDiscardTimerSet - Set PCI discard timer*/
++MV_STATUS mvPciDiscardTimerSet(MV_U32 pciIf, MV_U32 pClkCycles);
++
++/* mvPciArbEnable - PCI arbiter enable/disable*/
++MV_STATUS mvPciArbEnable(MV_U32 pciIf, MV_BOOL enable);
++
++/* mvPciArbParkDis - Disable arbiter parking on agent */
++MV_STATUS mvPciArbParkDis(MV_U32 pciIf, MV_U32 pciAgentMask);
++
++/* mvPciArbBrokDetectSet - Set PCI arbiter broken detection */
++MV_STATUS mvPciArbBrokDetectSet(MV_U32 pciIf, MV_U32 pClkCycles);
++
++/* mvPciConfigRead - Read from configuration space */
++MV_U32 mvPciConfigRead (MV_U32 pciIf, MV_U32 bus, MV_U32 dev,
++						MV_U32 func,MV_U32 regOff);
++
++/* mvPciConfigWrite - Write to configuration space */
++MV_STATUS mvPciConfigWrite(MV_U32 pciIf, MV_U32 bus, MV_U32 dev,
++                           MV_U32 func, MV_U32 regOff, MV_U32 data);
++
++/* mvPciMasterEnable - Enable/disale PCI interface master transactions.*/
++MV_STATUS mvPciMasterEnable(MV_U32 pciIf, MV_BOOL enable);
++
++/* mvPciSlaveEnable - Enable/disale PCI interface slave transactions.*/
++MV_STATUS mvPciSlaveEnable(MV_U32 pciIf, MV_U32 bus, MV_U32 dev,MV_BOOL enable);
++
++/* mvPciLocalBusNumSet - Set PCI interface local bus number.*/
++MV_STATUS mvPciLocalBusNumSet(MV_U32 pciIf, MV_U32 busNum);
++
++/* mvPciLocalBusNumGet - Get PCI interface local bus number.*/
++MV_U32 mvPciLocalBusNumGet(MV_U32 pciIf);
++
++/* mvPciLocalDevNumSet - Set PCI interface local device number.*/
++MV_STATUS mvPciLocalDevNumSet(MV_U32 pciIf, MV_U32 devNum);
++
++/* mvPciLocalDevNumGet - Get PCI interface local device number.*/
++MV_U32 mvPciLocalDevNumGet(MV_U32 pciIf);
++
++
++#endif /* #ifndef __INCPCIH */
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPciRegs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPciRegs.h
+new file mode 100644
+index 0000000..89d0ef1
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPciRegs.h
+@@ -0,0 +1,411 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 __INCPCIREGSH
++#define __INCPCIREGSH
++
++
++#include "pci-if/mvPciIfRegs.h"
++/* defines */
++#define MAX_PCI_DEVICES         32
++#define MAX_PCI_FUNCS           8
++#define MAX_PCI_BUSSES          128
++
++/* enumerators */
++
++/* This enumerator described the possible PCI slave targets.		   */
++/* PCI slave targets are designated memory/IO address spaces that the  */
++/* PCI slave targets can access. They are also refered as "targets"    */
++/* this enumeratoe order is determined by the content of :
++		PCI_BASE_ADDR_ENABLE_REG									*/
++
++
++/* registers offsetes defines */
++
++
++
++/*************************/
++/* PCI control registers */
++/*************************/
++/* maen : should add new registers */
++#define PCI_CMD_REG(pciIf)						(0x30c00  + ((pciIf) * 0x80))
++#define PCI_MODE_REG(pciIf)						(0x30d00  + ((pciIf) * 0x80))
++#define PCI_RETRY_REG(pciIf)					(0x30c04  + ((pciIf) * 0x80))
++#define PCI_DISCARD_TIMER_REG(pciIf)			(0x30d04  + ((pciIf) * 0x80))
++#define PCI_ARBITER_CTRL_REG(pciIf)				(0x31d00 + ((pciIf) * 0x80))
++#define PCI_P2P_CONFIG_REG(pciIf)				(0x31d14 + ((pciIf) * 0x80))
++#define PCI_ACCESS_CTRL_BASEL_REG(pciIf, targetWin) \
++							(0x31e00 + ((pciIf) * 0x80) + ((targetWin) * 0x10))
++#define PCI_ACCESS_CTRL_BASEH_REG(pciIf, targetWin) \
++							(0x31e04 + ((pciIf) * 0x80) + ((targetWin) * 0x10))
++#define PCI_ACCESS_CTRL_SIZE_REG(pciIf, targetWin)	\
++							(0x31e08 + ((pciIf) * 0x80) + ((targetWin) * 0x10))
++
++#define PCI_DLL_CTRL_REG(pciIf)					(0x31d20  + ((pciIf) * 0x80))
++
++/* PCI Dll Control (PDC)*/
++#define PDC_DLL_EN					BIT0
++
++
++/* PCI Command Register (PCR) */
++#define PCR_MASTER_BYTE_SWAP_EN     BIT0
++#define PCR_MASTER_WR_COMBINE_EN    BIT4
++#define PCR_MASTER_RD_COMBINE_EN    BIT5
++#define PCR_MASTER_WR_TRIG_WHOLE    BIT6
++#define PCR_MASTER_RD_TRIG_WHOLE    BIT7
++#define PCR_MASTER_MEM_RD_LINE_EN   BIT8
++#define PCR_MASTER_MEM_RD_MULT_EN   BIT9
++#define PCR_MASTER_WORD_SWAP_EN     BIT10
++#define PCR_SLAVE_WORD_SWAP_EN      BIT11
++#define PCR_NS_ACCORDING_RCV_TRANS  BIT14
++#define PCR_MASTER_PCIX_REQ64N_EN   BIT15
++#define PCR_SLAVE_BYTE_SWAP_EN      BIT16
++#define PCR_MASTER_DAC_EN           BIT17
++#define PCR_MASTER_M64_ALLIGN       BIT18
++#define PCR_ERRORS_PROPAGATION_EN   BIT19
++#define PCR_SLAVE_SWAP_ENABLE       BIT20
++#define PCR_MASTER_SWAP_ENABLE      BIT21
++#define PCR_MASTER_INT_SWAP_EN      BIT22
++#define PCR_LOOP_BACK_ENABLE        BIT23
++#define PCR_SLAVE_INTREG_SWAP_OFFS  24
++#define PCR_SLAVE_INTREG_SWAP_MASK  0x3
++#define PCR_SLAVE_INTREG_BYTE_SWAP  \
++                             (MV_BYTE_SWAP << PCR_SLAVE_INT_REG_SWAP_MASK)
++#define PCR_SLAVE_INTREG_NO_SWAP    \
++                             (MV_NO_SWAP   << PCR_SLAVE_INT_REG_SWAP_MASK)
++#define PCR_SLAVE_INTREG_BYTE_WORD  \
++                             (MV_BYTE_WORD_SWAP << PCR_SLAVE_INT_REG_SWAP_MASK)
++#define PCR_SLAVE_INTREG_WORD_SWAP  \
++                             (MV_WORD_SWAP << PCR_SLAVE_INT_REG_SWAP_MASK)
++#define PCR_RESET_REASSERTION_EN    BIT26
++#define PCR_PCI_TO_CPU_REG_ORDER_EN BIT28
++#define PCR_CPU_TO_PCI_ORDER_EN     BIT29
++#define PCR_PCI_TO_CPU_ORDER_EN     BIT30
++
++/* PCI Mode Register (PMR) */
++#define PMR_PCI_ID_OFFS			0  /* PCI Interface ID */
++#define PMR_PCI_ID_MASK			(0x1 << PMR_PCI_ID_OFFS)
++#define PMR_PCI_ID_PCI(pciNum)			((pciNum) << PCI_MODE_PCIID_OFFS)
++
++#define PMR_PCI_64_OFFS				2	/* 64-bit PCI Interface */
++#define PMR_PCI_64_MASK				(0x1 << PMR_PCI_64_OFFS)
++#define PMR_PCI_64_64BIT			(0x1 << PMR_PCI_64_OFFS)
++#define PMR_PCI_64_32BIT			(0x0 << PMR_PCI_64_OFFS)
++
++#define PMR_PCI_MODE_OFFS			4	/* PCI interface mode of operation */
++#define PMR_PCI_MODE_MASK			(0x3 << PMR_PCI_MODE_OFFS)
++#define PMR_PCI_MODE_CONV			(0x0 << PMR_PCI_MODE_OFFS)
++#define PMR_PCI_MODE_PCIX_66MHZ		(0x1 << PMR_PCI_MODE_OFFS)
++#define PMR_PCI_MODE_PCIX_100MHZ	(0x2 << PMR_PCI_MODE_OFFS)
++#define PMR_PCI_MODE_PCIX_133MHZ	(0x3 << PMR_PCI_MODE_OFFS)
++
++#define PMR_EXP_ROM_SUPPORT			BIT8	/* Expansion ROM Active */
++
++#define PMR_PCI_RESET_OFFS			31 /* PCI Interface Reset Indication */
++#define PMR_PCI_RESET_MASK			(0x1 << PMR_PCI_RESET_OFFS)
++#define PMR_PCI_RESET_PCIXRST		(0x0 << PMR_PCI_RESET_OFFS)
++
++
++/* PCI Retry Register (PRR) */
++#define PRR_RETRY_CNTR_OFFS			16 /* Retry Counter */
++#define PRR_RETRY_CNTR_MAX			0xff
++#define PRR_RETRY_CNTR_MASK			(PRR_RETRY_CNTR_MAX << PRR_RETRY_CNTR_OFFS)
++
++
++/* PCI Discard Timer Register (PDTR) */
++#define PDTR_TIMER_OFFS				0	/* Timer */
++#define PDTR_TIMER_MAX				0xffff
++#define PDTR_TIMER_MIN				0x7F
++#define PDTR_TIMER_MASK				(PDTR_TIMER_MAX << PDTR_TIMER_OFFS)
++
++
++/* PCI Arbiter Control Register (PACR) */
++#define PACR_BROKEN_DETECT_EN		BIT1	/* Broken Detection Enable */
++
++#define PACR_BROKEN_VAL_OFFS		3	/* Broken Value */
++#define PACR_BROKEN_VAL_MASK		(0xf << PACR_BROKEN_VAL_OFFS)
++#define PACR_BROKEN_VAL_CONV_MIN	0x2
++#define PACR_BROKEN_VAL_PCIX_MIN	0x6
++
++#define PACR_PARK_DIS_OFFS		14	/* Parking Disable */
++#define PACR_PARK_DIS_MAX_AGENT	0x3f
++#define PACR_PARK_DIS_MASK		(PACR_PARK_DIS_MAX_AGENT<<PACR_PARK_DIS_OFFS)
++#define PACR_PARK_DIS(agent)	((1 << (agent)) << PACR_PARK_DIS_OFFS)
++
++#define PACR_ARB_ENABLE				BIT31	/* Enable Internal Arbiter */
++
++
++/* PCI P2P Configuration Register (PPCR) */
++#define PPCR_2ND_BUS_L_OFFS			0	/* 2nd PCI Interface Bus Range Lower */
++#define PPCR_2ND_BUS_L_MASK			(0xff << PPCR_2ND_BUS_L_OFFS)
++
++#define PPCR_2ND_BUS_H_OFFS			8	/* 2nd PCI Interface Bus Range Upper */
++#define PPCR_2ND_BUS_H_MASK			(0xff << PPCR_2ND_BUS_H_OFFS)
++
++#define PPCR_BUS_NUM_OFFS			16  /* The PCI interface's Bus number */
++#define PPCR_BUS_NUM_MASK			(0xff << PPCR_BUS_NUM_OFFS)
++
++#define PPCR_DEV_NUM_OFFS			24  /* The PCI interface’s Device number */
++#define PPCR_DEV_NUM_MASK			(0xff << PPCR_DEV_NUM_OFFS)
++
++
++/* PCI Access Control Base Low Register (PACBLR) */
++#define PACBLR_EN					BIT0 /* Access control window enable */
++
++#define PACBLR_ACCPROT				BIT4 /* Access Protect */
++#define PACBLR_WRPROT				BIT5 /* Write Protect */
++
++#define PACBLR_PCISWAP_OFFS			6	 /* PCI slave Data Swap Control */
++#define PACBLR_PCISWAP_MASK			(0x3 << PACBLR_PCISWAP_OFFS)
++#define PACBLR_PCISWAP_BYTE			(0x0 << PACBLR_PCISWAP_OFFS)
++#define PACBLR_PCISWAP_NO_SWAP		(0x1 << PACBLR_PCISWAP_OFFS)
++#define PACBLR_PCISWAP_BYTE_WORD	(0x2 << PACBLR_PCISWAP_OFFS)
++#define PACBLR_PCISWAP_WORD			(0x3 << PACBLR_PCISWAP_OFFS)
++
++#define PACBLR_RDMBURST_OFFS		8 /* Read Max Burst */
++#define PACBLR_RDMBURST_MASK		(0x3 << PACBLR_RDMBURST_OFFS)
++#define PACBLR_RDMBURST_32BYTE		(0x0 << PACBLR_RDMBURST_OFFS)
++#define PACBLR_RDMBURST_64BYTE		(0x1 << PACBLR_RDMBURST_OFFS)
++#define PACBLR_RDMBURST_128BYTE		(0x2 << PACBLR_RDMBURST_OFFS)
++
++#define PACBLR_RDSIZE_OFFS			10 /* Typical PCI read transaction Size. */
++#define PACBLR_RDSIZE_MASK			(0x3 << PACBLR_RDSIZE_OFFS)
++#define PACBLR_RDSIZE_32BYTE		(0x0 << PACBLR_RDSIZE_OFFS)
++#define PACBLR_RDSIZE_64BYTE		(0x1 << PACBLR_RDSIZE_OFFS)
++#define PACBLR_RDSIZE_128BYTE		(0x2 << PACBLR_RDSIZE_OFFS)
++#define PACBLR_RDSIZE_256BYTE		(0x3 << PACBLR_RDSIZE_OFFS)
++
++#define PACBLR_BASE_L_OFFS			12	/* Corresponds to address bits [31:12] */
++#define PACBLR_BASE_L_MASK			(0xfffff << PACBLR_BASE_L_OFFS)
++#define PACBLR_BASE_L_ALIGNMENT		(1 << PACBLR_BASE_L_OFFS)
++#define PACBLR_BASE_ALIGN_UP(base)  \
++                             ((base+PACBLR_BASE_L_ALIGNMENT)&PACBLR_BASE_L_MASK)
++#define PACBLR_BASE_ALIGN_DOWN(base)  (base & PACBLR_BASE_L_MASK)
++
++
++/* PCI Access Control Base High Register (PACBHR)	*/
++#define PACBHR_BASE_H_OFFS			0	/* Corresponds to address bits [63:32] */
++#define PACBHR_CTRL_BASE_H_MASK		(0xffffffff << PACBHR_BASE_H_OFFS)
++
++/* PCI Access Control Size Register (PACSR)		*/
++#define PACSR_WRMBURST_OFFS			8 /* Write Max Burst */
++#define PACSR_WRMBURST_MASK			(0x3 << PACSR_WRMBURST_OFFS)
++#define PACSR_WRMBURST_32BYTE		(0x0 << PACSR_WRMBURST_OFFS)
++#define PACSR_WRMBURST_64BYTE		(0x1 << PACSR_WRMBURST_OFFS)
++#define PACSR_WRMBURST_128BYTE		(0x2 << PACSR_WRMBURST_OFFS)
++
++#define PACSR_PCI_ORDERING			BIT11 /* PCI Ordering required */
++
++#define PACSR_SIZE_OFFS				12	/* PCI access window size */
++#define PACSR_SIZE_MASK				(0xfffff << PACSR_SIZE_OFFS)
++#define PACSR_SIZE_ALIGNMENT		(1 << PACSR_SIZE_OFFS)
++#define PACSR_SIZE_ALIGN_UP(size)   \
++                                   ((size+PACSR_SIZE_ALIGNMENT)&PACSR_SIZE_MASK)
++#define PACSR_SIZE_ALIGN_DOWN(size) (size & PACSR_SIZE_MASK)
++
++
++/***************************************/
++/* PCI Configuration Access Registers  */
++/***************************************/
++
++#define PCI_CONFIG_ADDR_REG(pciIf)	(0x30C78 - ((pciIf) * 0x80) )
++#define PCI_CONFIG_DATA_REG(pciIf)	(0x30C7C - ((pciIf) * 0x80) )
++#define PCI_INT_ACK_REG(pciIf)		(0x30C34 + ((pciIf) * 0x80) )
++
++/* PCI Configuration Address Register (PCAR) */
++#define PCAR_REG_NUM_OFFS			2
++#define PCAR_REG_NUM_MASK			(0x3F << PCAR_REG_NUM_OFFS)
++
++#define PCAR_FUNC_NUM_OFFS			8
++#define PCAR_FUNC_NUM_MASK			(0x7 << PCAR_FUNC_NUM_OFFS)
++
++#define PCAR_DEVICE_NUM_OFFS		11
++#define PCAR_DEVICE_NUM_MASK		(0x1F << PCAR_DEVICE_NUM_OFFS)
++
++#define PCAR_BUS_NUM_OFFS			16
++#define PCAR_BUS_NUM_MASK			(0xFF << PCAR_BUS_NUM_OFFS)
++
++#define PCAR_CONFIG_EN				BIT31
++
++
++/***************************************/
++/* PCI Configuration registers */
++/***************************************/
++
++/*********************************************/
++/* PCI Configuration, Function 0, Registers  */
++/*********************************************/
++
++/* Marvell Specific */
++#define PCI_SCS0_BASE_ADDR_LOW						0x010
++#define PCI_SCS0_BASE_ADDR_HIGH						0x014
++#define PCI_SCS1_BASE_ADDR_LOW						0x018
++#define PCI_SCS1_BASE_ADDR_HIGH						0x01C
++#define PCI_INTER_REG_MEM_MAPPED_BASE_ADDR_L		0x020
++#define PCI_INTER_REG_MEM_MAPPED_BASE_ADDR_H		0x024
++
++/* capability list */
++#define PCI_POWER_MNG_CAPABILITY		            0x040
++#define PCI_POWER_MNG_STATUS_CONTROL		        0x044
++#define PCI_VPD_ADDRESS_REG	                        0x048
++#define PCI_VPD_DATA_REG	                        0x04c
++#define PCI_MSI_MESSAGE_CONTROL						0x050
++#define PCI_MSI_MESSAGE_ADDR		                0x054
++#define PCI_MSI_MESSAGE_UPPER_ADDR		            0x058
++#define PCI_MSI_MESSAGE_DATA		                0x05c
++#define PCIX_COMMAND		                        0x060
++#define PCIX_STATUS		                            0x064
++#define PCI_COMPACT_PCI_HOT_SWAP		            0x068
++
++
++/*********************************************/
++/* PCI Configuration, Function 1, Registers  */
++/*********************************************/
++
++#define PCI_SCS2_BASE_ADDR_LOW						0x10
++#define PCI_SCS2_BASE_ADDR_HIGH						0x14
++#define PCI_SCS3_BASE_ADDR_LOW						0x18
++#define PCI_SCS3_BASE_ADDR_HIGH						0x1c
++
++
++/***********************************************/
++/*  PCI Configuration, Function 2, Registers   */
++/***********************************************/
++
++#define PCI_DEVCS0_BASE_ADDR_LOW					0x10
++#define PCI_DEVCS0_BASE_ADDR_HIGH					0x14
++#define PCI_DEVCS1_BASE_ADDR_LOW					0x18
++#define PCI_DEVCS1_BASE_ADDR_HIGH				0x1c
++#define PCI_DEVCS2_BASE_ADDR_LOW					0x20
++#define PCI_DEVCS2_BASE_ADDR_HIGH				0x24
++
++/***********************************************/
++/*  PCI Configuration, Function 3, Registers   */
++/***********************************************/
++
++#define PCI_BOOTCS_BASE_ADDR_LOW					0x18
++#define PCI_BOOTCS_BASE_ADDR_HIGH				0x1c
++
++/***********************************************/
++/*  PCI Configuration, Function 4, Registers   */
++/***********************************************/
++
++#define PCI_P2P_MEM0_BASE_ADDR_LOW					0x10
++#define PCI_P2P_MEM0_BASE_ADDR_HIGH					0x14
++#define PCI_P2P_IO_BASE_ADDR				0x20
++#define PCI_INTER_REGS_IO_MAPPED_BASE_ADDR		   0x24
++
++/* PCIX_STATUS  register fields (PXS) */
++
++#define PXS_FN_OFFS		0	/* Description Number */
++#define PXS_FN_MASK		(0x7 << PXS_FN_OFFS)
++
++#define PXS_DN_OFFS		3	/* Device Number */
++#define PXS_DN_MASK		(0x1f << PXS_DN_OFFS)
++
++#define PXS_BN_OFFS		8	/* Bus Number */
++#define PXS_BN_MASK		(0xff << PXS_BN_OFFS)
++
++
++/* PCI Error Report Register Map */
++#define PCI_SERRN_MASK_REG(pciIf)		(0x30c28  + (pciIf * 0x80))
++#define PCI_CAUSE_REG(pciIf)			(0x31d58 + (pciIf * 0x80))
++#define PCI_MASK_REG(pciIf)				(0x31d5C + (pciIf * 0x80))
++#define PCI_ERROR_ADDR_LOW_REG(pciIf)	(0x31d40 + (pciIf * 0x80))
++#define PCI_ERROR_ADDR_HIGH_REG(pciIf)	(0x31d44 + (pciIf * 0x80))
++#define PCI_ERROR_ATTRIBUTE_REG(pciIf)	(0x31d48 + (pciIf * 0x80))
++#define PCI_ERROR_COMMAND_REG(pciIf)	(0x31d50 + (pciIf * 0x80))
++
++/* PCI Interrupt Cause Register (PICR) */
++#define PICR_ERR_SEL_OFFS           27
++#define PICR_ERR_SEL_MASK           (0x1f << PICR_ERR_SEL_OFFS)
++
++/* PCI Error Command Register (PECR) */
++#define PECR_ERR_CMD_OFFS			0
++#define PECR_ERR_CMD_MASK			(0xf << PECR_ERR_CMD_OFFS)
++#define PECR_DAC					BIT4
++
++
++/* defaults */
++/* Set bits means value is about to change according to new value */
++#define PCI_COMMAND_DEFAULT_MASK                0xffffdff1
++#define PCI_COMMAND_DEFAULT                             \
++                (PCR_MASTER_WR_TRIG_WHOLE   |   \
++         PCR_MASTER_RD_TRIG_WHOLE       |       \
++                 PCR_MASTER_MEM_RD_LINE_EN      |       \
++         PCR_MASTER_MEM_RD_MULT_EN  |   \
++                 PCR_NS_ACCORDING_RCV_TRANS     |       \
++                 PCR_MASTER_PCIX_REQ64N_EN      |       \
++                 PCR_MASTER_DAC_EN                      |       \
++                 PCR_MASTER_M64_ALLIGN          |       \
++                 PCR_ERRORS_PROPAGATION_EN)
++
++
++#define PCI_ARBITER_CTRL_DEFAULT_MASK   0x801fc07a
++#define PCI_ARBITER_CTRL_DEFAULT        \
++        (PACR_BROKEN_VAL_PCIX_MIN << PACR_BROKEN_VAL_OFFS)
++
++
++#endif /* #ifndef __INCPCIREGSH */
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.c b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.c
+new file mode 100644
+index 0000000..068aac2
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.c
+@@ -0,0 +1,1143 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "pex/mvPex.h"
++
++#include "ctrlEnv/mvCtrlEnvLib.h"
++
++/* defines  */
++#ifdef MV_DEBUG
++#define DB(x)	x
++#else
++#define DB(x)
++#endif
++
++MV_STATUS mvPexHalInit(MV_U32 pexIf, MV_PEX_TYPE pexType)
++{
++	MV_PEX_MODE pexMode;
++	MV_U32 regVal;
++	MV_U32	status;
++
++    /* 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      */
++
++    if ((mvCtrlModelGet() != MV_1281_DEV_ID) &&
++	(mvCtrlModelGet() != MV_6281_DEV_ID) &&
++	(mvCtrlModelGet() != MV_6192_DEV_ID) &&
++    (mvCtrlModelGet() != MV_6190_DEV_ID) &&
++	(mvCtrlModelGet() != MV_6180_DEV_ID) &&
++		(mvCtrlModelGet() != MV_6183_DEV_ID) &&
++	(mvCtrlModelGet() != MV_6183L_DEV_ID) &&
++		(mvCtrlModelGet() != MV_78100_DEV_ID) &&
++		(mvCtrlModelGet() != MV_78200_DEV_ID) &&
++	(mvCtrlModelGet() != MV_76100_DEV_ID) &&
++	(mvCtrlModelGet() != MV_78XX0_DEV_ID))
++    {
++
++        /* Read current value of TXAMP */
++        MV_REG_WRITE(0x41b00, 0x80820000);   /* Write the read command   */
++
++        regVal = MV_REG_READ(0x41b00);      /* 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(0x41b00, 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 (mvCtrlModelGet() == MV_1281_DEV_ID)
++        {
++                MV_REG_WRITE(0x41b00, 0x80860000);   /* Write the read command   */
++                regVal = MV_REG_READ(0x41b00);      /* Extract the data         */
++                regVal |= (BIT0 | BIT3);
++                regVal &= ~0x80000000;              /* Set "write" command      */
++                MV_REG_WRITE(0x41b00, 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( 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 */
++		mvPexPowerDown(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);
++        }
++
++        /* now wait 500 ms to be sure the link is valid (spec compliant) */
++        mvOsDelay(500);
++	/* 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;
++
++	/* Parameter checking   */
++	if (PEX_DEFAULT_IF != pexIf)
++	{
++		if (pexIf >= mvCtrlPexMaxIfGet())
++		{
++			mvOsPrintf("mvPexModeGet: ERR. Invalid PEX interface %d\n",pexIf);
++			return MV_ERROR;
++		}
++	}
++
++	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;
++
++	/* Parameter checking   */
++	if (PEX_DEFAULT_IF != pexIf)
++	{
++		if (pexIf >= mvCtrlPexMaxIfGet())
++		{
++			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  */
++	if ( ( (dev != localDev) || (bus != localBus) ) &&
++		(
++		!(MV_5281_DEV_ID == mvCtrlModelGet())&&
++		!((MV_5181_DEV_ID == mvCtrlModelGet())&& (mvCtrlRevGet() >= MV_5181L_A0_REV))&&
++		!(MV_1281_DEV_ID == mvCtrlModelGet())&&
++		!(MV_6183_DEV_ID == mvCtrlModelGet())&&
++		!(MV_6183L_DEV_ID == mvCtrlModelGet())&&
++		!(MV_6281_DEV_ID == mvCtrlModelGet())&&
++		!(MV_6192_DEV_ID == mvCtrlModelGet())&&
++		!(MV_6190_DEV_ID == mvCtrlModelGet())&&
++        !(MV_6180_DEV_ID == mvCtrlModelGet())&&
++		!(MV_78XX0_DEV_ID == mvCtrlModelGet())
++		))
++	{
++
++		/* 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;
++
++	/* Parameter checking   */
++	if (PEX_DEFAULT_IF != pexIf)
++	{
++		if (pexIf >= mvCtrlPexMaxIfGet())
++		{
++			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 >= mvCtrlPexMaxIfGet())
++	{
++		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 >= mvCtrlPexMaxIfGet())
++	{
++		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 >= mvCtrlPexMaxIfGet())
++	{
++		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;
++
++	/* Parameter checking   */
++	if (PEX_DEFAULT_IF != pexIf)
++	{
++		if (pexIf >= mvCtrlPexMaxIfGet())
++		{
++			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;
++
++	/* Parameter checking   */
++	if (pexIf >= mvCtrlPexMaxIfGet())
++	{
++		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 >= mvCtrlPexMaxIfGet())
++		{
++			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 >= mvCtrlPexMaxIfGet())
++	{
++		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 >= mvCtrlPexMaxIfGet())
++	{
++		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 >= mvCtrlPexMaxIfGet())
++	{
++		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 >= mvCtrlPexMaxIfGet())
++	{
++		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;
++}
++
++MV_BOOL mvPexIsPowerUp(MV_U32 pexIf)
++{
++	if(pexIf >= mvCtrlPexMaxIfGet())
++	{
++		mvOsPrintf("mvPexIsPowerUp: ERR. Invalid PEX interface %d\n", pexIf);
++		return MV_FALSE;
++	}
++	return mvCtrlPwrClckGet(PEX_UNIT_ID, pexIf);
++}
++
++
++MV_VOID mvPexPowerDown(MV_U32 pexIf)
++{
++	if ( (mvCtrlModelGet() == MV_78XX0_DEV_ID) ||
++		(mvCtrlModelGet() == MV_76100_DEV_ID) ||
++		(mvCtrlModelGet() == MV_78100_DEV_ID) ||
++		(mvCtrlModelGet() == MV_78200_DEV_ID) )
++	{
++		mvCtrlPwrClckSet(PEX_UNIT_ID, pexIf, MV_FALSE);
++	}
++	else
++	{
++		MV_REG_WRITE((0x41B00 -(pexIf)*0x10000), 0x20800087);
++	}
++}
++
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.h b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.h
+new file mode 100644
+index 0000000..d8f1cdd
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.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 __INCPEXH
++#define __INCPEXH
++
++#include "mvCommon.h"
++#include "mvOs.h"
++#include "pex/mvPexRegs.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;
++
++
++
++/* Global Functions prototypes */
++/* mvPexInit - Initialize PEX interfaces*/
++MV_STATUS mvPexHalInit(MV_U32 pexIf, MV_PEX_TYPE pexType);
++
++/* 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 mvPexPowerDown(MV_U32 pexIf);
++
++/* mvPexPowerUp - Power Up */
++MV_VOID mvPexPowerUp(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);
++
++#endif /* #ifndef __INCPEXH */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPexRegs.h b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPexRegs.h
+new file mode 100644
+index 0000000..8ac1698
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPexRegs.h
+@@ -0,0 +1,751 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 */
++
++/* 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)		((PEX_IF_BASE(pexIf)) + 0x18F8)
++#define PEX_CFG_DATA_REG(pexIf)		((PEX_IF_BASE(pexIf)) + 0x18FC)
++#define PEX_PHY_ACCESS_REG(pexIf)	((PEX_IF_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)		((PEX_IF_BASE(pexIf)) + 0x1900)
++#define PEX_MASK_REG(pexIf)		((PEX_IF_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)				((PEX_IF_BASE(pexIf)) + 0x1A00)
++#define PEX_STATUS_REG(pexIf)				((PEX_IF_BASE(pexIf)) + 0x1A04)
++#define PEX_COMPLT_TMEOUT_REG(pexIf)			((PEX_IF_BASE(pexIf)) + 0x1A10)
++#define PEX_PWR_MNG_EXT_REG(pexIf)			((PEX_IF_BASE(pexIf)) + 0x1A18)
++#define PEX_FLOW_CTRL_REG(pexIf)			((PEX_IF_BASE(pexIf)) + 0x1A20)
++#define PEX_ACK_TMR_4X_REG(pexIf)			((PEX_IF_BASE(pexIf)) + 0x1A30)
++#define PEX_ACK_TMR_1X_REG(pexIf)			((PEX_IF_BASE(pexIf)) + 0x1A40)
++#define PEX_TL_CTRL_REG(pexIf)				((PEX_IF_BASE(pexIf)) + 0x1AB0)
++
++
++#define PEX_RAM_PARITY_CTRL_REG(pexIf)			((PEX_IF_BASE(pexIf)) + 0x1A50)
++/* 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)	((PEX_IF_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 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)*/
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* #ifndef __INCPEXREGSH */
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.c b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.c
+new file mode 100644
+index 0000000..19c871a
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.c
+@@ -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.
++
++*******************************************************************************/
++
++#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/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.h b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.h
+new file mode 100644
+index 0000000..82eb72d
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.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.
++
++*******************************************************************************/
++
++#ifndef __INCVRTBRGPEXH
++#define __INCVRTBRGPEXH
++
++
++/* 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);
++
++
++#endif /* #ifndef __INCPEXH */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.c b/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.c
+new file mode 100644
+index 0000000..6c5bc19
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.c
+@@ -0,0 +1,1522 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "sflash/mvSFlash.h"
++#include "sflash/mvSFlashSpec.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
++
++/* Globals */
++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
++    },
++    /* 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_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
++    },
++    /* 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_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;
++
++	return mvSpiWriteThenRead(cmd, MV_SFLASH_WREN_CMND_LENGTH, NULL, 0, 0);
++}
++
++/*******************************************************************************
++* 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;
++
++	if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_RDSR_CMND_LENGTH, sr,
++                                         MV_SFLASH_RDSR_REPLY_LENGTH,0)) != 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++)
++	{
++        if ((ret = mvStatusRegGet(pFlinfo, &stat)) != MV_OK)
++            return ret;
++
++		if ((stat & MV_SFLASH_STATUS_REG_WIP_MASK) == 0)
++			return MV_OK;
++	}
++
++    DB(mvOsPrintf("%s WARNING: Write Timeout!\n", __FUNCTION__);)
++	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++)
++	{
++        if ((ret = mvStatusRegGet(pFlinfo, &stat)) != MV_OK)
++            return ret;
++
++		if ((stat & MV_SFLASH_STATUS_REG_WIP_MASK) == 0)
++			return MV_OK;
++	}
++
++    DB(mvOsPrintf("%s WARNING: Write Timeout!\n", __FUNCTION__);)
++	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 */
++	if ((ret = mvWriteEnable(pFlinfo)) != MV_OK)
++		return ret;
++
++    /* Write the SR with the new values */
++    cmd[0] = sflash[pFlinfo->index].opcdWRSR;
++	cmd[1] = sr;
++
++	if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_WRSR_CMND_LENGTH, NULL, 0, 0)) != MV_OK)
++		return ret;
++
++    if ((ret = mvWaitOnWipClear(pFlinfo)) != 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_PP_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", __FUNCTION__);)
++        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", __FUNCTION__);)
++		return MV_OUT_OF_RANGE;
++    }
++
++	/* Issue the Write enable command prior the page program command */
++	if ((ret = mvWriteEnable(pFlinfo)) != MV_OK)
++		return ret;
++
++    cmd[0] = sflash[pFlinfo->index].opcdPP;
++	cmd[1] = ((offset >> 16) & 0xFF);
++	cmd[2] = ((offset >> 8) & 0xFF);
++	cmd[3] = (offset & 0xFF);
++
++	if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_PP_CMND_LENGTH, pPageBuff, buffSize)) != MV_OK)
++		return ret;
++
++	if ((ret = mvWaitOnWipClear(pFlinfo)) != 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];
++
++
++
++    /* Use the default RDID opcode to read the IDs */
++    cmdRDID[0] = MV_SFLASH_DEFAULT_RDID_OPCD;   /* unknown model try default */
++	if ((ret = mvSpiWriteThenRead(cmdRDID, MV_SFLASH_RDID_CMND_LENGTH, id, MV_SFLASH_RDID_REPLY_LENGTH, 0)) != MV_OK)
++		return ret;
++
++	*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_BOOL detectFlag = MV_FALSE;
++
++    /* check for NULL pointer */
++    if (pFlinfo == NULL)
++    {
++        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++
++    /* Initialize the SPI interface with low frequency to make sure that the read ID succeeds */
++    if ((ret = mvSpiInit(MV_SFLASH_BASIC_SPI_FREQ)) != MV_OK)
++    {
++        mvOsPrintf("%s ERROR: Failed to initialize the SPI interface!\n", __FUNCTION__);
++        return ret;
++    }
++
++    /* First try to read the Manufacturer and Device IDs */
++    if ((ret = mvSFlashIdGet(pFlinfo, &manf, &dev)) != MV_OK)
++    {
++        mvOsPrintf("%s ERROR: Failed to get the SFlash ID!\n", __FUNCTION__);
++        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", __FUNCTION__);
++        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;
++
++    /* Set the SPI frequency to the MAX allowed for the device for best performance */
++    if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFreq)) != MV_OK)
++    {
++        mvOsPrintf("%s ERROR: Failed to set the SPI frequency!\n", __FUNCTION__);
++        return ret;
++    }
++
++    /* As default lock the SR */
++    if ((ret = mvSFlashStatRegLock(pFlinfo, MV_TRUE)) != 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_SE_CMND_LENGTH];
++
++    MV_U32 secAddr = (secNumber * pFlinfo->sectorSize);
++#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", __FUNCTION__);
++        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", __FUNCTION__);)
++        return MV_BAD_PARAM;
++    }
++
++    /* check that the sector number is valid */
++    if (secNumber >= pFlinfo->sectorNumber)
++    {
++        DB(mvOsPrintf("%s WARNING: Invaild parameter sector number!\n", __FUNCTION__);)
++        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;
++	cmd[1] = ((secAddr >> 16) & 0xFF);
++	cmd[2] = ((secAddr >> 8) & 0xFF);
++	cmd[3] = (secAddr & 0xFF);
++
++	/* Issue the Write enable command prior the sector erase command */
++	if ((ret = mvWriteEnable(pFlinfo)) != MV_OK)
++		return ret;
++
++	if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_SE_CMND_LENGTH, NULL, 0)) != MV_OK)
++		return ret;
++
++	if ((ret = mvWaitOnWipClear(pFlinfo)) != 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", __FUNCTION__);
++        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", __FUNCTION__);)
++        return MV_BAD_PARAM;
++    }
++
++    cmd[0] = sflash[pFlinfo->index].opcdBE;
++
++	/* Issue the Write enable command prior the Bulk erase command */
++	if ((ret = mvWriteEnable(pFlinfo)) != MV_OK)
++		return ret;
++
++    if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_BE_CMND_LENGTH, NULL, 0)) != MV_OK)
++		return ret;
++
++	if ((ret = mvWaitOnChipEraseDone(pFlinfo)) != 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_READ_CMND_LENGTH];
++
++
++    /* check for NULL pointer */
++    if ((pFlinfo == NULL) || (pReadBuff == NULL))
++    {
++        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
++        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", __FUNCTION__);)
++        return MV_BAD_PARAM;
++    }
++
++    cmd[0] = sflash[pFlinfo->index].opcdREAD;
++	cmd[1] = ((offset >> 16) & 0xFF);
++	cmd[2] = ((offset >> 8) & 0xFF);
++	cmd[3] = (offset & 0xFF);
++
++	return mvSpiWriteThenRead(cmd, MV_SFLASH_READ_CMND_LENGTH, pReadBuff, buffSize, 0);
++}
++
++/*******************************************************************************
++* 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_READ_CMND_LENGTH];
++    MV_STATUS ret;
++
++    /* check for NULL pointer */
++    if ((pFlinfo == NULL) || (pReadBuff == NULL))
++    {
++        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
++        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", __FUNCTION__);)
++        return MV_BAD_PARAM;
++    }
++
++    /* Set the SPI frequency to the MAX allowed for fast-read operations */
++    mvOsPrintf("Setting freq to %d.\n",sflash[pFlinfo->index].spiMaxFastFreq);
++    if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFastFreq)) != MV_OK)
++    {
++        mvOsPrintf("%s ERROR: Failed to set the SPI fast frequency!\n", __FUNCTION__);
++        return ret;
++    }
++
++    cmd[0] = sflash[pFlinfo->index].opcdFSTRD;
++    cmd[1] = ((offset >> 16) & 0xFF);
++    cmd[2] = ((offset >> 8) & 0xFF);
++    cmd[3] = (offset & 0xFF);
++
++
++    ret = mvSpiWriteThenRead(cmd, MV_SFLASH_READ_CMND_LENGTH, pReadBuff, buffSize,
++                             sflash[pFlinfo->index].spiFastRdDummyBytes);
++
++    /* Reset the SPI frequency to the MAX allowed for the device for best performance */
++    if ((ret = mvSpiBaudRateSet(sflash[pFlinfo->index].spiMaxFreq)) != MV_OK)
++    {
++        mvOsPrintf("%s ERROR: Failed to set the SPI frequency!\n", __FUNCTION__);
++        return ret;
++    }
++
++    return ret;
++}
++
++
++/*******************************************************************************
++* 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", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++#endif
++
++    if (pFlinfo == NULL)
++    {
++        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
++        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", __FUNCTION__);)
++        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", __FUNCTION__);)
++	    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)
++	{
++		if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, preAllSz)) != 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)
++	{
++		if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, sflash[pFlinfo->index].pageSize)) != 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)
++	{
++		if ((ret = mvSFlashPageWr(pFlinfo, writeOffset, pWriteBuff, data2write)) != 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", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++
++    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash))
++        return mvSFlashWithDefaultsIdGet(pFlinfo, pManId, pDevId);
++    else
++        cmd[0] = sflash[pFlinfo->index].opcdRDID;
++
++	if ((ret = mvSpiWriteThenRead(cmd, MV_SFLASH_RDID_CMND_LENGTH, id, MV_SFLASH_RDID_REPLY_LENGTH, 0)) != 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", __FUNCTION__);
++        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", __FUNCTION__);)
++        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", __FUNCTION__);)
++                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", __FUNCTION__);)
++                return MV_BAD_PARAM;
++        }
++    }
++    /* check if the manufacturer is MXIC then the WP is 4bits */
++    else if (pFlinfo->manufacturerId == MV_MXIC_MANF_ID)
++    {
++        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", __FUNCTION__);)
++                return MV_BAD_PARAM;
++        }
++    }
++    /* check if the manufacturer is SPANSION then the WP is 4bits */
++    else if (pFlinfo->manufacturerId == MV_SPANSION_MANF_ID)
++    {
++        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", __FUNCTION__);)
++                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", __FUNCTION__);)
++                return MV_BAD_PARAM;
++        }
++    }
++    else
++    {
++        DB(mvOsPrintf("%s WARNING: Invaild parameter Manufacturer ID!\n", __FUNCTION__);)
++        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", __FUNCTION__);
++        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", __FUNCTION__);)
++        return MV_BAD_PARAM;
++    }
++
++    if ((ret = mvStatusRegGet(pFlinfo, &reg)) != 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", __FUNCTION__);)
++                return MV_BAD_VALUE;
++        }
++    }
++    /* check if the manufacturer is MXIC then the WP is 4bits */
++    else if (pFlinfo->manufacturerId == MV_MXIC_MANF_ID)
++    {
++        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", __FUNCTION__);)
++                return MV_BAD_VALUE;
++        }
++    }
++    /* Check if the chip is an SPANSION flash; then WP supports only 3 bits */
++    else if (pFlinfo->manufacturerId == MV_SPANSION_MANF_ID)
++    {
++        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", __FUNCTION__);)
++                return MV_BAD_VALUE;
++        }
++    }
++    else
++    {
++        DB(mvOsPrintf("%s WARNING: Invaild parameter Manufacturer ID!\n", __FUNCTION__);)
++        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", __FUNCTION__);
++        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", __FUNCTION__);)
++        return MV_BAD_PARAM;
++    }
++
++    if ((ret = mvStatusRegGet(pFlinfo, &reg)) != 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", __FUNCTION__);
++        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", __FUNCTION__);
++        return 0;
++    }
++
++    /* Protection - check if the model was detected */
++    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash))
++    {
++        DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);)
++        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", __FUNCTION__);)
++        return MV_NOT_SUPPORTED;
++    }
++
++    cmd[0] = sflash[pFlinfo->index].opcdPwrSave;
++
++    if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_DP_CMND_LENGTH, NULL, 0)) != MV_OK)
++		return ret;
++
++	return MV_OK;
++
++}
++
++/*******************************************************************************
++* 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", __FUNCTION__);
++        return 0;
++    }
++
++    /* Protection - check if the model was detected */
++    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash))
++    {
++        DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);)
++        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", __FUNCTION__);)
++        return MV_NOT_SUPPORTED;
++    }
++
++    cmd[0] = sflash[pFlinfo->index].opcdRES;
++
++    if ((ret = mvSpiWriteThenWrite(cmd, MV_SFLASH_RES_CMND_LENGTH, NULL, 0)) != 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", __FUNCTION__);
++        return 0;
++    }
++
++    /* Protection - check if the model was detected */
++    if (pFlinfo->index >= MV_ARRAY_SIZE(sflash))
++    {
++        DB(mvOsPrintf("%s WARNING: Invaild parameter index!\n", __FUNCTION__);)
++        return unknModel;
++    }
++
++    return sflash[pFlinfo->index].deviceModel;
++}
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.h b/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.h
+new file mode 100644
+index 0000000..f441a5c
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.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.
++
++*******************************************************************************/
++
++#ifndef __INCmvSFlashH
++#define __INCmvSFlashH
++
++#include "mvTypes.h"
++
++/* MCAROS */
++#define MV_SFLASH_PAGE_ALLIGN_MASK(pgSz)    (pgSz-1)
++#define MV_ARRAY_SIZE(a)                    ((sizeof(a)) / (sizeof(a[0])))
++
++/* 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_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);
++
++#endif /* __INCmvSFlashH */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlashSpec.h b/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlashSpec.h
+new file mode 100644
+index 0000000..eeb4426
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlashSpec.h
+@@ -0,0 +1,233 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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
++
++/* 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 */
++
++/* 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
++
++
++/* 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_M25P32_SECTOR_NUMBER             64
++#define     MV_M25P64_SECTOR_NUMBER             128
++#define     MV_M25P128_SECTOR_NUMBER            64
++#define		MV_M25P_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_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_MXIC_DP_EXIT_DELAY               30          /* 30 ms */
++
++/* Sector Sizes and population per device model*/
++#define     MV_MX25L6405_SECTOR_SIZE            0x10000 /* 64K */
++#define     MV_MX25L6405_SECTOR_NUMBER          128
++#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 */
++
++/* 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)
++
++#endif /* __INCmvSFlashSpecH */
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.c b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.c
+new file mode 100644
+index 0000000..39e0b72
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.c
+@@ -0,0 +1,576 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "spi/mvSpi.h"
++#include "spi/mvSpiSpec.h"
++
++#include "ctrlEnv/mvCtrlEnvLib.h"
++
++/* #define MV_DEBUG */
++#ifdef MV_DEBUG
++#define DB(x) x
++#define mvOsPrintf printf
++#else
++#define DB(x)
++#endif
++
++
++/*******************************************************************************
++* mvSpi16bitDataTxRx - Transmt and receive data
++*
++* DESCRIPTION:
++*       Tx data and block waiting for data to be transmitted
++*
++********************************************************************************/
++static MV_STATUS mvSpi16bitDataTxRx (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, 0x0);
++
++    /* Transmit data */
++    MV_REG_WRITE(MV_SPI_DATA_OUT_REG, 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))
++        {
++            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));
++		*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));
++		*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));
++    }
++
++    return MV_OK;
++}
++
++
++/*******************************************************************************
++* mvSpi8bitDataTxRx - Transmt and receive data (8bits)
++*
++* DESCRIPTION:
++*       Tx data and block waiting for data to be transmitted
++*
++********************************************************************************/
++static MV_STATUS mvSpi8bitDataTxRx (MV_U8 txData, MV_U8 * 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, 0x0);
++
++    /* Transmit data */
++    MV_REG_WRITE(MV_SPI_DATA_OUT_REG, 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))
++        {
++            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)
++	*pRxData = MV_REG_READ(MV_SPI_DATA_IN_REG);
++
++    return MV_OK;
++}
++
++/*
++#####################################################################################
++#####################################################################################
++*/
++
++/*******************************************************************************
++* 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_U32 serialBaudRate)
++{
++    MV_STATUS ret;
++
++    /* Set the serial clock */
++    if ((ret = mvSpiBaudRateSet(serialBaudRate)) != MV_OK)
++        return ret;
++
++    /* For devices in which the SPI is muxed on the MPP with other interfaces*/
++    mvMPPConfigToSPI();
++
++	/* Configure the default SPI mode to be 16bit */
++	MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, MV_SPI_BYTE_LENGTH_MASK);
++
++	/* Fix ac timing on SPI in 6183, 6183L and 78x00 only */
++	if ( (mvCtrlModelGet() == MV_6183_DEV_ID) ||
++		 (mvCtrlModelGet() == MV_6183L_DEV_ID) ||
++		(mvCtrlModelGet() == MV_78100_DEV_ID) ||
++		(mvCtrlModelGet() == MV_78200_DEV_ID) ||
++		(mvCtrlModelGet() == MV_76100_DEV_ID))
++	    MV_REG_BIT_SET(MV_SPI_IF_CONFIG_REG, BIT14);
++
++    /* Verify that the CS is deasserted */
++    mvSpiCsDeassert();
++
++    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.
++*
++*
++*******************************************************************************/
++MV_STATUS mvSpiBaudRateSet (MV_U32 serialBaudRate)
++{
++    MV_U8 i;
++	/* MV_U8 preScale[32] = {1, 1, 2, 3, 4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
++						  2, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
++	*/
++	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 = mvBoardTclkGet(); /*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", __FUNCTION__);
++		return MV_OUT_OF_RANGE;
++    }
++
++	/* configure the Prescale */
++	tempReg = MV_REG_READ(MV_SPI_IF_CONFIG_REG);
++	tempReg = ((tempReg & ~MV_SPI_CLK_PRESCALE_MASK) | (bestPrescaleIndx + 0x12));
++	MV_REG_WRITE(MV_SPI_IF_CONFIG_REG, tempReg);
++
++    return MV_OK;
++}
++
++/*******************************************************************************
++* 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_VOID)
++{
++    /* For devices in which the SPI is muxed on the MPP with other interfaces*/
++    mvMPPConfigToSPI();
++    mvOsUDelay(1);
++    MV_REG_BIT_SET(MV_SPI_IF_CTRL_REG, 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_VOID)
++{
++	MV_REG_BIT_RESET(MV_SPI_IF_CTRL_REG, MV_SPI_CS_ENABLE_MASK);
++
++    /* For devices in which the SPI is muxed on the MPP with other interfaces*/
++    mvMPPConfigToDefault();
++}
++
++/*******************************************************************************
++* 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* 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", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++
++    /* Check that the buffer pointer and the buffer size are 16bit aligned */
++    if ((((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, 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 */
++		if ((ret = mvSpi16bitDataTxRx(MV_SPI_DUMMY_WRITE_16BITS, rxPtr)) != 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, MV_SPI_BYTE_LENGTH_MASK);
++
++	/* TX/RX in 8bit chanks */
++	while (bytesLeft > 0)
++	{
++		/* Transmitted and wait for the transfer to be completed */
++		if ((ret = mvSpi8bitDataTxRx(MV_SPI_DUMMY_WRITE_8BITS, pRxBuff)) != 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* 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", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++
++    /* Check that the buffer pointer and the buffer size are 16bit aligned */
++    if ((((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, 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 */
++		if ((ret = mvSpi16bitDataTxRx(*txPtr, NULL)) != 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, MV_SPI_BYTE_LENGTH_MASK);
++
++	/* TX/RX in 8bit chanks */
++	while (bytesLeft > 0)
++	{
++		/* Transmitted and wait for the transfer to be completed */
++		if ((ret = mvSpi8bitDataTxRx(*pTxBuff, NULL)) != 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* 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", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++
++    /* Check that the buffer pointer and the buffer size are 16bit aligned */
++    if ((((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, 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 */
++		if ((ret = mvSpi16bitDataTxRx(*txPtr, rxPtr)) != 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, MV_SPI_BYTE_LENGTH_MASK);
++
++	/* TX/RX in 8bit chanks */
++	while (bytesLeft > 0)
++	{
++		/* Transmitted and wait for the transfer to be completed */
++		if ( (ret = mvSpi8bitDataTxRx(*pTxBuff, pRxBuff) ) != MV_OK)
++			return ret;
++		pRxBuff++;
++		pTxBuff++;
++		bytesLeft--;
++	}
++    }
++
++	return MV_OK;
++}
++
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.h b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.h
+new file mode 100644
+index 0000000..74859f0
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.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 __INCmvSpihH
++#define __INCmvSpihH
++
++#include "mvCommon.h"
++#include "mvOs.h"
++#include "ctrlEnv/mvCtrlEnvSpec.h"
++
++/* Function Prototypes */
++/* Init */
++MV_STATUS   mvSpiInit		(MV_U32 serialBaudRate);
++
++/* Set the Frequency of the Spi clock */
++MV_STATUS   mvSpiBaudRateSet(MV_U32 serialBaudRate);
++
++/* Assert the SPI chip select */
++MV_VOID     mvSpiCsAssert   (MV_VOID);
++
++/* De-assert the SPI chip select */
++MV_VOID     mvSpiCsDeassert (MV_VOID);
++
++/* Simultanuous Read and write */
++MV_STATUS	mvSpiReadWrite	(MV_U8* pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize);
++
++/* serialize a buffer on the TX line - Rx is ignored */
++MV_STATUS	mvSpiWrite	(MV_U8* pTxBuff, MV_U32 buffSize);
++
++/* read from the RX line by writing dummy values to the TX line */
++MV_STATUS	mvSpiRead	(MV_U8* pRxBuff, MV_U32 buffSize);
++
++#endif /* __INCmvSpihH */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.c b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.c
+new file mode 100644
+index 0000000..a5d5a64
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.c
+@@ -0,0 +1,249 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "spi/mvSpi.h"
++#include "spi/mvSpiSpec.h"
++
++/*#define MV_DEBUG*/
++#ifdef MV_DEBUG
++#define DB(x) x
++#else
++#define DB(x)
++#endif
++
++
++/*******************************************************************************
++* 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* 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", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++
++	/* First assert the chip select */
++	mvSpiCsAssert();
++
++    ret = mvSpiReadWrite(pRxBuff, pTxBuff, buffSize);
++
++	/* Finally deassert the chip select */
++	mvSpiCsDeassert();
++
++	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* 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", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++#endif
++
++    if (pCmndBuff == NULL)
++    {
++        mvOsPrintf("%s ERROR: Null pointer parameter!\n", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++
++	/* First assert the chip select */
++	mvSpiCsAssert();
++
++    /* first write the command */
++    if ((cmndSize) && (pCmndBuff != NULL))
++    {
++        if ((tempRet = mvSpiWrite(pCmndBuff, cmndSize)) != MV_OK)
++            ret = tempRet;
++    }
++
++    /* Then write the data buffer */
++#ifndef CONFIG_MARVELL
++    if (txDataSize)
++#else
++    if ((txDataSize) && (pTxDataBuff != NULL))
++#endif
++    {
++        if ((tempRet = mvSpiWrite(pTxDataBuff, txDataSize)) != MV_OK)
++            ret = tempRet;
++    }
++
++	/* Finally deassert the chip select */
++	mvSpiCsDeassert();
++
++	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* 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", __FUNCTION__);
++        return MV_BAD_PARAM;
++    }
++
++	/* First assert the chip select */
++	mvSpiCsAssert();
++
++    /* first write the command */
++    if ((cmndSize) && (pCmndBuff != NULL))
++    {
++        if ((tempRet = mvSpiWrite(pCmndBuff, cmndSize)) != MV_OK)
++            ret = tempRet;
++    }
++
++    /* Read dummy bytes before real data.   */
++    while(dummyBytesToRead)
++    {
++        mvSpiRead(&dummyByte,1);
++        dummyBytesToRead--;
++    }
++
++    /* Then write the data buffer */
++    if ((rxDataSize) && (pRxDataBuff != NULL))
++    {
++        if ((tempRet = mvSpiRead(pRxDataBuff, rxDataSize)) != MV_OK)
++            ret = tempRet;
++    }
++
++	/* Finally deassert the chip select */
++	mvSpiCsDeassert();
++
++	return ret;
++}
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.h b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.h
+new file mode 100644
+index 0000000..329e26b
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.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.
++
++*******************************************************************************/
++
++#ifndef __INCmvSpiCmndhH
++#define __INCmvSpiCmndhH
++
++#include "mvTypes.h"
++
++/* Function Prototypes */
++
++/* Simultanuous Read and write */
++MV_STATUS	mvSpiReadAndWrite	(MV_U8* pRxBuff, MV_U8* pTxBuff, MV_U32 buffSize);
++
++/* write command - write a command and then write data */
++MV_STATUS	mvSpiWriteThenWrite (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* pCmndBuff, MV_U32 cmndSize, MV_U8* pRxDataBuff,
++                              MV_U32 rxDataSize,MV_U32 dummyBytesToRead);
++
++#endif /* __INCmvSpiCmndhH */
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiSpec.h b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiSpec.h
+new file mode 100644
+index 0000000..658159a
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiSpec.h
+@@ -0,0 +1,98 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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
++
++/* 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_CTRLR_OFST					0x10600
++#define		MV_SPI_IF_CTRL_REG					(MV_SPI_CTRLR_OFST + 0x00)
++#define		MV_SPI_IF_CONFIG_REG				(MV_SPI_CTRLR_OFST + 0x04)
++#define		MV_SPI_DATA_OUT_REG					(MV_SPI_CTRLR_OFST + 0x08)
++#define		MV_SPI_DATA_IN_REG					(MV_SPI_CTRLR_OFST + 0x0c)
++#define		MV_SPI_INT_CAUSE_REG				(MV_SPI_CTRLR_OFST + 0x10)
++#define		MV_SPI_INT_CAUSE_MASK_REG			(MV_SPI_CTRLR_OFST + 0x14)
++
++/* 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)
++
++/* 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_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)
++
++#endif /* __INCmvSpiSpecH */
++
+diff --git a/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.c b/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.c
+new file mode 100644
+index 0000000..0bf8b75
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.c
+@@ -0,0 +1,1023 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 "mvTwsi.h"
++#include "mvTwsiSpec.h"
++#include "cpu/mvCpu.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,"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,"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(TWSI_CPU_MAIN_INT_CAUSE_REG);
++	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(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,"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,"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,"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,"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,"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,"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,"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/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.h b/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.h
+new file mode 100644
+index 0000000..bd5b6d0
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.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 __INCmvTwsiH
++#define __INCmvTwsiH
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++/* need to update this includes */
++#include "twsi/mvTwsiSpec.h"
++#include "ctrlEnv/mvCtrlEnvLib.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 frequancy, 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/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsiSpec.h b/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsiSpec.h
+new file mode 100644
+index 0000000..d0c2b9e
+--- /dev/null
++++ b/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsiSpec.h
+@@ -0,0 +1,160 @@
++/*******************************************************************************
++Copyright (C) Marvell International Ltd. and its affiliates
++
++This software file (the "File") is owned and distributed by Marvell
++International Ltd. and/or its affiliates ("Marvell") under the following
++alternative licensing terms.  Once you have made an election to distribute the
++File under one of the following license alternatives, please (i) delete this
++introductory statement regarding license alternatives, (ii) delete the two
++license alternatives that you have not elected to use and (iii) preserve the
++Marvell copyright notice above.
++
++********************************************************************************
++Marvell Commercial License Option
++
++If you received this File from Marvell and you have entered into a commercial
++license agreement (a "Commercial License") with Marvell, the File is licensed
++to you under the terms of the applicable Commercial License.
++
++********************************************************************************
++Marvell GPL License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File in accordance with the terms and conditions of the General
++Public License Version 2, June 1991 (the "GPL License"), a copy of which is
++available along with the File in the license.txt file or by writing to the Free
++Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
++on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
++
++THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
++WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
++DISCLAIMED.  The GPL License provides additional details about this warranty
++disclaimer.
++********************************************************************************
++Marvell BSD License Option
++
++If you received this File from Marvell, you may opt to use, redistribute and/or
++modify this File under the following licensing terms.
++Redistribution and use in source and binary forms, with or without modification,
++are permitted provided that the following conditions are met:
++
++    *   Redistributions of source code must retain the above copyright notice,
++	    this list of conditions and the following disclaimer.
++
++    *   Redistributions in binary form must reproduce the above copyright
++        notice, this list of conditions and the following disclaimer in the
++        documentation and/or other materials provided with the distribution.
++
++    *   Neither the name of Marvell nor the names of its contributors may be
++        used to endorse or promote products derived from this software without
++        specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
++ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(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 */
++
++/* defines */
++#define TWSI_SLAVE_ADDR_REG(chanNum)	(TWSI_SLAVE_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)	(TWSI_SLAVE_BASE(chanNum) + 0x10)
++#define TWSI_EXTENDED_SLAVE_OFFS	0
++#define TWSI_EXTENDED_SLAVE_MASK	(0xFF << TWSI_EXTENDED_SLAVE_OFFS)
++
++
++#define TWSI_DATA_REG(chanNum)		(TWSI_SLAVE_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)	(TWSI_SLAVE_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)	(TWSI_SLAVE_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)	(TWSI_SLAVE_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/crypto/ocf/ocf-bench.c b/crypto/ocf/ocf-bench.c
+new file mode 100644
+index 0000000..d325231
+--- /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-2010 David McCullough <david_mccullough@mcafee.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@mcafee.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 100644
+index 0000000..212f971
+--- /dev/null
++++ b/crypto/ocf/ocf-compat.h
+@@ -0,0 +1,294 @@
++#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@mcafee.com>
++ * Copyright (C) 2010 David McCullough <david_mccullough@mcafee.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
++
++#ifndef htole32
++#define htole32(x)	cpu_to_le32(x)
++#endif
++#ifndef htobe32
++#define htobe32(x)	cpu_to_be32(x)
++#endif
++#ifndef htole16
++#define htole16(x)	cpu_to_le16(x)
++#endif
++#ifndef htobe16
++#define htobe16(x)	cpu_to_be16(x)
++#endif
++
++/* older kernels don't have these */
++
++#include <asm/irq.h>
++#if !defined(IRQ_NONE) && !defined(IRQ_RETVAL)
++#define IRQ_NONE
++#define IRQ_HANDLED
++#define IRQ_WAKE_THREAD
++#define IRQ_RETVAL
++#define irqreturn_t void
++typedef irqreturn_t (*irq_handler_t)(int irq, void *arg, struct pt_regs *regs);
++#endif
++#ifndef IRQF_SHARED
++#define IRQF_SHARED	SA_SHIRQ
++#endif
++
++#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
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,5)
++#include <linux/err.h>
++#endif
++#ifndef IS_ERR_VALUE
++#define IS_ERR_VALUE(x) ((unsigned long)(x) >= (unsigned long)-MAX_ERRNO)
++#endif
++#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 <linux/mm.h>
++#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;
++}
++
++#define sg_init_table(sg, n)
++
++#endif
++
++#ifndef late_initcall
++#define late_initcall(init) module_init(init)
++#endif
++
++#endif /* __KERNEL__ */
++
++/****************************************************************************/
++#endif /* _BSD_COMPAT_H_ */
+diff --git a/crypto/ocf/ocfnull/Makefile b/crypto/ocf/ocfnull/Makefile
+new file mode 100644
+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 100644
+index 0000000..a6b76cd
+--- /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@mcafee.com>
++ * Copyright (C) 2006-2010 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@mcafee.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 100644
+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 100644
+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 100644
+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 100644
+index 0000000..38dad13
+--- /dev/null
++++ b/crypto/ocf/random.c
+@@ -0,0 +1,322 @@
++/*
++ * 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@mcafee.com>
++ * Copyright (C) 2006-2010 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
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
++#include <linux/sched.h>
++#define	kill_proc(p,s,v)	send_sig(s,find_task_by_vpid(p),0)
++#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(randomproc, SIGKILL, 1);
++	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 100644
+index 0000000..b31e1a6
+--- /dev/null
++++ b/crypto/ocf/rndtest.c
+@@ -0,0 +1,300 @@
++/*	$OpenBSD$	*/
++
++/*
++ * OCF/Linux port done by David McCullough <david_mccullough@mcafee.com>
++ * Copyright (C) 2006-2010 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 100644
+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 100644
+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 100644
+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 100644
+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 100644
+index 0000000..7e65101
+--- /dev/null
++++ b/crypto/ocf/safe/safe.c
+@@ -0,0 +1,2288 @@
++/*-
++ * Linux port done by David McCullough <david_mccullough@mcafee.com>
++ * Copyright (C) 2004-2010 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@mcafee.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 100644
+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 100644
+index 0000000..9039a5d
+--- /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-2010 David McCullough <david_mccullough@mcafee.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 100644
+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 100644
+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 100644
+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 100644
+index 0000000..9404634
+--- /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@mcafee.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 100644
+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 100644
+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 100644
+index 0000000..03a6249
+--- /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@mcafee.com>
++ * Copyright (C) 2006-2010 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/drivers/char/random.c b/drivers/char/random.c
+index 8258982..d382084 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -129,6 +129,9 @@
+  *                                unsigned int value);
+  *	void add_interrupt_randomness(int irq);
+  *
++ *      void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
++ *      int random_input_wait(void);
++ *
+  * add_input_randomness() uses the input layer interrupt timing, as well as
+  * the event type information from the hardware.
+  *
+@@ -140,6 +143,13 @@
+  * a better measure, since the timing of the disk interrupts are more
+  * unpredictable.
+  *
++ * random_input_words() just provides a raw block of entropy to the input
++ * pool, such as from a hardware entropy generator.
++ *
++ * random_input_wait() suspends the caller until such time as the
++ * entropy pool falls below the write threshold, and returns a count of how
++ * much entropy (in bits) is needed to sustain the pool.
++ *
+  * All of these routines try to estimate how many bits of randomness a
+  * particular randomness source.  They do this by keeping track of the
+  * first and second order deltas of the event timings.
+@@ -714,6 +724,61 @@ void add_disk_randomness(struct gendisk *disk)
+ }
+ #endif
+
++/*
++ * random_input_words - add bulk entropy to pool
++ *
++ * @buf: buffer to add
++ * @wordcount: number of __u32 words to add
++ * @ent_count: total amount of entropy (in bits) to credit
++ *
++ * this provides bulk input of entropy to the input pool
++ *
++ */
++void random_input_words(__u32 *buf, size_t wordcount, int ent_count)
++{
++	mix_pool_bytes(&input_pool, buf, wordcount*4);
++
++	credit_entropy_bits(&input_pool, ent_count);
++
++	DEBUG_ENT("crediting %d bits => %d\n",
++		  ent_count, input_pool.entropy_count);
++	/*
++	 * Wake up waiting processes if we have enough
++	 * entropy.
++	 */
++	if (input_pool.entropy_count >= random_read_wakeup_thresh)
++		wake_up_interruptible(&random_read_wait);
++}
++EXPORT_SYMBOL(random_input_words);
++
++/*
++ * random_input_wait - wait until random needs entropy
++ *
++ * this function sleeps until the /dev/random subsystem actually
++ * needs more entropy, and then return the amount of entropy
++ * that it would be nice to have added to the system.
++ */
++int random_input_wait(void)
++{
++	int count;
++
++	wait_event_interruptible(random_write_wait,
++			 input_pool.entropy_count < random_write_wakeup_thresh);
++
++	count = random_write_wakeup_thresh - input_pool.entropy_count;
++
++        /* likely we got woken up due to a signal */
++	if (count <= 0) count = random_read_wakeup_thresh;
++
++	DEBUG_ENT("requesting %d bits from input_wait()er %d<%d\n",
++		  count,
++		  input_pool.entropy_count, random_write_wakeup_thresh);
++
++	return count;
++}
++EXPORT_SYMBOL(random_input_wait);
++
++
+ #define EXTRACT_SIZE 10
+
+ /*********************************************************************
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index 2cf93ec..1b6d2bb 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -141,6 +141,7 @@ SYSCALL_DEFINE1(dup, unsigned int, fildes)
+	}
+	return ret;
+ }
++EXPORT_SYMBOL(sys_dup);
+
+ #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
+
+diff --git a/include/crypto/cryptodev.h b/include/crypto/cryptodev.h
+new file mode 100644
+index 0000000..6032317
+--- /dev/null
++++ b/include/crypto/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@mcafee.com>
++ * Copyright (C) 2006-2010 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/include/linux/miscdevice.h b/include/linux/miscdevice.h
+index adaf3c1..e961a9a 100644
+--- a/include/linux/miscdevice.h
++++ b/include/linux/miscdevice.h
+@@ -12,6 +12,7 @@
+ #define APOLLO_MOUSE_MINOR	7
+ #define PC110PAD_MINOR		9
+ /*#define ADB_MOUSE_MINOR	10	FIXME OBSOLETE */
++#define CRYPTODEV_MINOR		70	/* /dev/crypto */
+ #define WATCHDOG_MINOR		130	/* Watchdog timer     */
+ #define TEMP_MINOR		131	/* Temperature Sensor */
+ #define RTC_MINOR		135
+diff --git a/include/linux/random.h b/include/linux/random.h
+index 25d02fe..b59ec10 100644
+--- a/include/linux/random.h
++++ b/include/linux/random.h
+@@ -9,6 +9,7 @@
+
+ #include <linux/types.h>
+ #include <linux/ioctl.h>
++#include <linux/types.h> /* for __u32 in user space */
+ #include <linux/irqnr.h>
+
+ /* ioctl()'s for the random number generator */
+@@ -34,6 +35,30 @@
+ /* Clear the entropy pool and associated counters.  (Superuser only.) */
+ #define RNDCLEARPOOL	_IO( 'R', 0x06 )
+
++#ifdef CONFIG_FIPS_RNG
++
++/* Size of seed value - equal to AES blocksize */
++#define AES_BLOCK_SIZE_BYTES	16
++#define SEED_SIZE_BYTES			AES_BLOCK_SIZE_BYTES
++/* Size of AES key */
++#define KEY_SIZE_BYTES		16
++
++/* ioctl() structure used by FIPS 140-2 Tests */
++struct rand_fips_test {
++	unsigned char key[KEY_SIZE_BYTES];			/* Input */
++	unsigned char datetime[SEED_SIZE_BYTES];	/* Input */
++	unsigned char seed[SEED_SIZE_BYTES];		/* Input */
++	unsigned char result[SEED_SIZE_BYTES];		/* Output */
++};
++
++/* FIPS 140-2 RNG Variable Seed Test. (Superuser only.) */
++#define RNDFIPSVST	_IOWR('R', 0x10, struct rand_fips_test)
++
++/* FIPS 140-2 RNG Monte Carlo Test. (Superuser only.) */
++#define RNDFIPSMCT	_IOWR('R', 0x11, struct rand_fips_test)
++
++#endif /* #ifdef CONFIG_FIPS_RNG */
++
+ struct rand_pool_info {
+	int	entropy_count;
+	int	buf_size;
+@@ -50,6 +75,10 @@ extern void add_input_randomness(unsigned int type, unsigned int code,
+				 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/kernel/pid.c b/kernel/pid.c
+index d3f722d..e041b52 100644
+--- a/kernel/pid.c
++++ b/kernel/pid.c
+@@ -387,6 +387,7 @@ struct task_struct *find_task_by_vpid(pid_t vnr)
+ {
+	return find_task_by_pid_ns(vnr, current->nsproxy->pid_ns);
+ }
++EXPORT_SYMBOL(find_task_by_vpid);
+
+ struct pid *get_task_pid(struct task_struct *task, enum pid_type type)
+ {
+--
+1.7.0.4
diff --git a/recipes/linux/linux-omap-psp-2.6.32/am37x-evm/defconfig b/recipes/linux/linux-omap-psp-2.6.32/am37x-evm/defconfig
index 8f1868d..2578116 100644
--- a/recipes/linux/linux-omap-psp-2.6.32/am37x-evm/defconfig
+++ b/recipes/linux/linux-omap-psp-2.6.32/am37x-evm/defconfig
@@ -2004,6 +2004,27 @@ CONFIG_CRYPTO_HW=y
 CONFIG_BINARY_PRINTF=y
 
 #
+# OCF Configuration
+#
+CONFIG_OCF_OCF=y
+CONFIG_OCF_RANDOMHARVEST=y
+CONFIG_OCF_FIPS=y
+CONFIG_OCF_CRYPTODEV=m
+CONFIG_OCF_CRYPTOSOFT=m
+# 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_CRYPTOCTEON is not set
+# CONFIG_OCF_KIRKWOOD is not set
+# CONFIG_OCF_C7108 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
diff --git a/recipes/linux/linux-omap-psp_2.6.32.bb b/recipes/linux/linux-omap-psp_2.6.32.bb
index e1d444c..82dc77d 100644
--- a/recipes/linux/linux-omap-psp_2.6.32.bb
+++ b/recipes/linux/linux-omap-psp_2.6.32.bb
@@ -140,6 +140,8 @@ SRC_URI = "git://arago-project.org/git/projects/linux-omap3.git;protocol=http;br
 SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
 "
 
+SRC_URI_append_am37x-evm = " file://0001-linux-omap3-PSP-3.0.1.6-kernel-with-OCF-Linux.patch"
+
 SRC_URI_append_omap3-touchbook = " \
                                   file://0001-ARM-OMAP-add-spi-platform-devices.patch \
                                   file://0002-MMA7455L-accelerometer-driver.patch \
-- 
1.7.0.4




^ permalink raw reply related	[flat|nested] 5+ messages in thread
* Re: [PATCH 1/3] linux-omap-psp: add OCF support
@ 2011-01-05 21:21 Maupin, Chase
  0 siblings, 0 replies; 5+ messages in thread
From: Maupin, Chase @ 2011-01-05 21:21 UTC (permalink / raw)
  To: openembedded-devel@lists.openembedded.org

All,

BTW, I hope I didn't do a bad thing by sending this big of a patch to the list.  The large patch came from http://sourceforge.net/projects/ocf-linux/files/ and is a single patch from the project site directly.  I didn't realize that when it got embedded in the e-mail it would become 6MB in size since the original patch was only 3MB in size (Not sure why that happened).

Sorry again if this has caused any isses and if there is a better way to submit this patch please let me know so I can do it right.

Chase



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-01-06  8:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-01-05 20:39 [PATCH 1/3] linux-omap-psp: add OCF support Chase Maupin
2011-01-05 20:39 ` [PATCH 2/3] kernel class: stage ocf directory Chase Maupin
2011-01-05 20:39 ` [PATCH 3/3] ti-ocf-crypto-module: add crypto module for hw accel Chase Maupin
2011-01-06  8:00 ` [PATCH 1/3] linux-omap-psp: add OCF support Koen Kooi
  -- strict thread matches above, loose matches on Subject: below --
2011-01-05 21:21 Maupin, Chase

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.