From d2b854419501d2e069c176eff058d41530f27a52 Mon Sep 17 00:00:00 2001 From: Angell Fear Date: Sat, 16 Oct 2010 00:02:07 +0600 Subject: [PATCH] fb fix, ts fix, flash ttfs experemental --- Start_WM/test6.ncb | Bin 0 -> 9333760 bytes Start_WM/test6.sln | 30 + Start_WM/test6.suo | Bin 0 -> 29696 bytes Start_WM/test6/inc/GF.h | 43 + Start_WM/test6/inc/GF3D.h | 39 + Start_WM/test6/inc/GFAudio.h | 168 + Start_WM/test6/inc/GFBDev.h | 189 + Start_WM/test6/inc/GFBitmap.h | 45 + Start_WM/test6/inc/GFCamera.h | 367 + Start_WM/test6/inc/GFCameraScr.h | 40 + Start_WM/test6/inc/GFDef.h | 254 + Start_WM/test6/inc/GFDefScr.h | 81 + Start_WM/test6/inc/GFDiag.h | 442 + Start_WM/test6/inc/GFDispCmdData.h | 1740 ++++ Start_WM/test6/inc/GFDx.h | 1847 ++++ Start_WM/test6/inc/GFEPP.h | 89 + Start_WM/test6/inc/GFFDev.h | 321 + Start_WM/test6/inc/GFGx.h | 1927 ++++ Start_WM/test6/inc/GFGxError.h | 46 + Start_WM/test6/inc/GFI2C.h | 314 + Start_WM/test6/inc/GFI2S.h | 49 + Start_WM/test6/inc/GFINTx.h | 114 + Start_WM/test6/inc/GFIsp.h | 1654 +++ Start_WM/test6/inc/GFIspError.h | 37 + Start_WM/test6/inc/GFJxDec.h | 508 + Start_WM/test6/inc/GFJxEnc.h | 1306 +++ Start_WM/test6/inc/GFMinimalIsp.h | 29 + Start_WM/test6/inc/GFMmProc.h | 1766 ++++ Start_WM/test6/inc/GFMxDec.h | 727 ++ Start_WM/test6/inc/GFMxDecH264.h | 1536 +++ Start_WM/test6/inc/GFMxDecRV9.h | 853 ++ Start_WM/test6/inc/GFMxDecVC1.h | 732 ++ Start_WM/test6/inc/GFMxDemTS.h | 725 ++ Start_WM/test6/inc/GFMxEnc.h | 795 ++ Start_WM/test6/inc/GFMxEncH264.h | 788 ++ Start_WM/test6/inc/GFOSx.h | 39 + Start_WM/test6/inc/GFOption.h | 140 + Start_WM/test6/inc/GFRm.h | 2039 ++++ Start_WM/test6/inc/GFRmError.h | 68 + Start_WM/test6/inc/GFRmHelp.h | 515 + Start_WM/test6/inc/GFRmHelp.inl | 626 ++ Start_WM/test6/inc/GFRmIx.h | 654 ++ Start_WM/test6/inc/GFRmOEM.h | 551 + Start_WM/test6/inc/GFRmRDMA.h | 411 + Start_WM/test6/inc/GFRmScr.h | 59 + Start_WM/test6/inc/GFTrace.h | 304 + Start_WM/test6/inc/GFTypes.h | 65 + Start_WM/test6/inc/GFVersion.h | 24 + Start_WM/test6/inc/GFVx.h | 3028 ++++++ Start_WM/test6/inc/GFVxError.h | 42 + Start_WM/test6/inc/GFVxScr.h | 311 + Start_WM/test6/inc/cpuopsys.h | 309 + Start_WM/test6/inc/gfrm_clock_ids.h | 22 + Start_WM/test6/inc/gfrm_module_ids.h | 56 + Start_WM/test6/inc/nvboard.h | 619 ++ Start_WM/test6/inc/nvcommon.h | 153 + Start_WM/test6/inc/nverror.h | 50 + Start_WM/test6/inc/nverrval.h | 277 + Start_WM/test6/inc/nvime.h | 849 ++ Start_WM/test6/inc/nvirq.h | 144 + Start_WM/test6/inc/nvtypes.h | 258 + Start_WM/test6/inc/vssver2.scc | Bin 0 -> 1261 bytes Start_WM/test6/lib/Release/libgfsdk.lib | Bin 0 -> 95704 bytes Start_WM/test6/stdafx.cpp | 8 + Start_WM/test6/stdafx.h | 56 + Start_WM/test6/test6.cpp | 127 + Start_WM/test6/test6.vcproj | 453 + kernel-2.6.33/.config | 26 +- kernel-2.6.33/arch/arm/configs/g900_defconfig | 130 +- kernel-2.6.33/arch/arm/mach-pxa/g900/Kconfig | 13 + kernel-2.6.33/arch/arm/mach-pxa/g900/Makefile | 4 +- kernel-2.6.33/arch/arm/mach-pxa/g900/docg3.c | 356 + kernel-2.6.33/arch/arm/mach-pxa/g900/g900.c | 47 +- .../arch/arm/mach-pxa/g900/g900_core.c | 159 + .../arch/arm/mach-pxa/g900/g900_flash.c | 363 + .../arch/arm/mach-pxa/g900/g900_pm.c | 77 + .../arch/arm/mach-pxa/g900/g900_udc.c | 260 + .../arch/arm/mach-pxa/g900/gf5500/inc/GF.h | 43 + .../arch/arm/mach-pxa/g900/gf5500/inc/GF3D.h | 39 + .../arm/mach-pxa/g900/gf5500/inc/GFAudio.h | 168 + .../arm/mach-pxa/g900/gf5500/inc/GFBDev.h | 189 + .../arm/mach-pxa/g900/gf5500/inc/GFBitmap.h | 45 + .../arm/mach-pxa/g900/gf5500/inc/GFCamera.h | 367 + .../mach-pxa/g900/gf5500/inc/GFCameraScr.h | 40 + .../arch/arm/mach-pxa/g900/gf5500/inc/GFDef.h | 254 + .../arm/mach-pxa/g900/gf5500/inc/GFDefScr.h | 81 + .../arm/mach-pxa/g900/gf5500/inc/GFDiag.h | 442 + .../mach-pxa/g900/gf5500/inc/GFDispCmdData.h | 1740 ++++ .../arch/arm/mach-pxa/g900/gf5500/inc/GFDx.h | 1847 ++++ .../arch/arm/mach-pxa/g900/gf5500/inc/GFEPP.h | 89 + .../arm/mach-pxa/g900/gf5500/inc/GFFDev.h | 321 + .../arch/arm/mach-pxa/g900/gf5500/inc/GFGx.h | 1927 ++++ .../arm/mach-pxa/g900/gf5500/inc/GFGxError.h | 46 + .../arch/arm/mach-pxa/g900/gf5500/inc/GFI2C.h | 314 + .../arch/arm/mach-pxa/g900/gf5500/inc/GFI2S.h | 49 + .../arm/mach-pxa/g900/gf5500/inc/GFINTx.h | 114 + .../arch/arm/mach-pxa/g900/gf5500/inc/GFIsp.h | 1654 +++ .../arm/mach-pxa/g900/gf5500/inc/GFIspError.h | 37 + .../arm/mach-pxa/g900/gf5500/inc/GFJxDec.h | 508 + .../arm/mach-pxa/g900/gf5500/inc/GFJxEnc.h | 1306 +++ .../mach-pxa/g900/gf5500/inc/GFMinimalIsp.h | 29 + .../arm/mach-pxa/g900/gf5500/inc/GFMmProc.h | 1766 ++++ .../arm/mach-pxa/g900/gf5500/inc/GFMxDec.h | 727 ++ .../mach-pxa/g900/gf5500/inc/GFMxDecH264.h | 1536 +++ .../arm/mach-pxa/g900/gf5500/inc/GFMxDecRV9.h | 853 ++ .../arm/mach-pxa/g900/gf5500/inc/GFMxDecVC1.h | 732 ++ .../arm/mach-pxa/g900/gf5500/inc/GFMxDemTS.h | 725 ++ .../arm/mach-pxa/g900/gf5500/inc/GFMxEnc.h | 795 ++ .../mach-pxa/g900/gf5500/inc/GFMxEncH264.h | 788 ++ .../arch/arm/mach-pxa/g900/gf5500/inc/GFOSx.h | 39 + .../arm/mach-pxa/g900/gf5500/inc/GFOption.h | 140 + .../arch/arm/mach-pxa/g900/gf5500/inc/GFRm.h | 2039 ++++ .../arm/mach-pxa/g900/gf5500/inc/GFRmError.h | 68 + .../arm/mach-pxa/g900/gf5500/inc/GFRmHelp.h | 515 + .../arm/mach-pxa/g900/gf5500/inc/GFRmHelp.inl | 626 ++ .../arm/mach-pxa/g900/gf5500/inc/GFRmIx.h | 654 ++ .../arm/mach-pxa/g900/gf5500/inc/GFRmOEM.h | 551 + .../arm/mach-pxa/g900/gf5500/inc/GFRmRDMA.h | 411 + .../arm/mach-pxa/g900/gf5500/inc/GFRmScr.h | 59 + .../arm/mach-pxa/g900/gf5500/inc/GFTrace.h | 304 + .../arm/mach-pxa/g900/gf5500/inc/GFTypes.h | 65 + .../arm/mach-pxa/g900/gf5500/inc/GFVersion.h | 24 + .../arch/arm/mach-pxa/g900/gf5500/inc/GFVx.h | 3028 ++++++ .../arm/mach-pxa/g900/gf5500/inc/GFVxError.h | 42 + .../arm/mach-pxa/g900/gf5500/inc/GFVxScr.h | 311 + .../arm/mach-pxa/g900/gf5500/inc/cpuopsys.h | 309 + .../mach-pxa/g900/gf5500/inc/gfrm_clock_ids.h | 22 + .../g900/gf5500/inc/gfrm_module_ids.h | 56 + .../arm/mach-pxa/g900/gf5500/inc/nvboard.h | 619 ++ .../arm/mach-pxa/g900/gf5500/inc/nvcommon.h | 153 + .../arm/mach-pxa/g900/gf5500/inc/nverror.h | 50 + .../arm/mach-pxa/g900/gf5500/inc/nverrval.h | 277 + .../arch/arm/mach-pxa/g900/gf5500/inc/nvime.h | 849 ++ .../arch/arm/mach-pxa/g900/gf5500/inc/nvirq.h | 144 + .../arm/mach-pxa/g900/gf5500/inc/nvtypes.h | 258 + .../arm/mach-pxa/g900/gf5500/inc/vssver2.scc | Bin 0 -> 1261 bytes ...re Developer Kit (SDK) Developer Guide.doc | Bin 0 -> 1500160 bytes ...s Developer Guide (Master with Hidden).doc | Bin 0 -> 364544 bytes .../arch/arm/mach-pxa/g900/ttfs/LICENSE.TXT | 412 + .../arch/arm/mach-pxa/g900/ttfs/Makefile | 31 + .../arch/arm/mach-pxa/g900/ttfs/Makefile-m | 31 + .../arm/mach-pxa/g900/ttfs/Makefile-omap2420 | 137 + .../arm/mach-pxa/g900/ttfs/Makefile-pxa27x | 177 + .../arch/arm/mach-pxa/g900/ttfs/Makefile-y | 31 + .../arch/arm/mach-pxa/g900/ttfs/README.TXT | 1109 ++ .../arch/arm/mach-pxa/g900/ttfs/VERSIONS.TXT | 215 + .../arch/arm/mach-pxa/g900/ttfs/_common.h | 124 + .../arch/arm/mach-pxa/g900/ttfs/_dochapi.h | 2621 +++++ .../arch/arm/mach-pxa/g900/ttfs/_docsys.h | 205 + .../arch/arm/mach-pxa/g900/ttfs/_fltl.h | 172 + .../arch/arm/mach-pxa/g900/ttfs/_tffsioct.h | 79 + .../arch/arm/mach-pxa/g900/ttfs/bddefs.h | 108 + .../arch/arm/mach-pxa/g900/ttfs/bdkemul.h | 135 + .../arch/arm/mach-pxa/g900/ttfs/blockdev.h | 1439 +++ .../arch/arm/mach-pxa/g900/ttfs/defs.c | 341 + .../arch/arm/mach-pxa/g900/ttfs/defs.h | 238 + .../arch/arm/mach-pxa/g900/ttfs/docbdk.h | 550 + .../arch/arm/mach-pxa/g900/ttfs/docdrv.c | 452 + .../mach-pxa/g900/ttfs/doch-firmware/Makefile | 72 + .../g900/ttfs/doch-firmware/doch-firmware.c | 206 + .../arch/arm/mach-pxa/g900/ttfs/doch_api.c | 9149 +++++++++++++++++ .../arch/arm/mach-pxa/g900/ttfs/doch_api.h | 130 + .../arch/arm/mach-pxa/g900/ttfs/doch_ata.c | 3599 +++++++ .../arch/arm/mach-pxa/g900/ttfs/doch_ata.h | 731 ++ .../arch/arm/mach-pxa/g900/ttfs/doch_func.h | 171 + .../arch/arm/mach-pxa/g900/ttfs/doch_sys.h | 120 + .../arch/arm/mach-pxa/g900/ttfs/dochstub.c | 121 + .../arch/arm/mach-pxa/g900/ttfs/dochstub.h | 72 + .../arch/arm/mach-pxa/g900/ttfs/dochtl.c | 642 ++ .../arch/arm/mach-pxa/g900/ttfs/dochtl.h | 84 + .../arch/arm/mach-pxa/g900/ttfs/docsys.c | 1304 +++ .../arch/arm/mach-pxa/g900/ttfs/docsys.h | 88 + .../arch/arm/mach-pxa/g900/ttfs/dosformt.h | 443 + .../arch/arm/mach-pxa/g900/ttfs/extfiltr.c | 717 ++ .../arch/arm/mach-pxa/g900/ttfs/extfiltr.h | 43 + .../arch/arm/mach-pxa/g900/ttfs/fatfilt.c | 1949 ++++ .../arch/arm/mach-pxa/g900/ttfs/fatfilt.h | 185 + .../arch/arm/mach-pxa/g900/ttfs/flbase.c | 89 + .../arch/arm/mach-pxa/g900/ttfs/flbase.h | 267 + .../arch/arm/mach-pxa/g900/ttfs/flbuffer.h | 76 + .../arch/arm/mach-pxa/g900/ttfs/flchkdef.h | 1512 +++ .../arch/arm/mach-pxa/g900/ttfs/flcommon.h | 616 ++ .../arch/arm/mach-pxa/g900/ttfs/flcustom.c | 106 + .../arch/arm/mach-pxa/g900/ttfs/flcustom.h | 386 + .../arch/arm/mach-pxa/g900/ttfs/flioctl.c | 612 ++ .../arch/arm/mach-pxa/g900/ttfs/flioctl.h | 490 + .../arch/arm/mach-pxa/g900/ttfs/flstdcmp.h | 95 + .../arch/arm/mach-pxa/g900/ttfs/flstruct.h | 847 ++ .../arch/arm/mach-pxa/g900/ttfs/flsysfun.h | 239 + .../arch/arm/mach-pxa/g900/ttfs/flsystem.c | 720 ++ .../arch/arm/mach-pxa/g900/ttfs/flsystem.h | 173 + .../arch/arm/mach-pxa/g900/ttfs/flsystyp.h | 96 + .../arch/arm/mach-pxa/g900/ttfs/fltl.h | 122 + .../arch/arm/mach-pxa/g900/ttfs/geometry.c | 132 + .../arch/arm/mach-pxa/g900/ttfs/hal_nor.c | 464 + .../arch/arm/mach-pxa/g900/ttfs/hal_nor.h | 91 + .../arch/arm/mach-pxa/g900/ttfs/hib.h | 272 + .../mach-pxa/g900/ttfs/ioctl_example/Makefile | 72 + .../g900/ttfs/ioctl_example/ioctl-example.c | 791 ++ .../arch/arm/mach-pxa/g900/ttfs/part_inf.h | 227 + .../arch/arm/mach-pxa/g900/ttfs/tffs-pm26.c | 184 + .../arch/arm/mach-pxa/g900/ttfs/tffs2lnx.c | 1756 ++++ .../arch/arm/mach-pxa/g900/ttfs/tffs2lnx.h | 59 + .../arch/arm/mach-pxa/g900/ttfs/tffs_api.c | 5359 ++++++++++ .../arch/arm/mach-pxa/g900/ttfs/tffs_api.h | 224 + .../arch/arm/mach-pxa/g900/ttfs/tffsarch.c | 2101 ++++ .../arch/arm/mach-pxa/g900/ttfs/tffsarch.h | 174 + .../arch/arm/mach-pxa/g900/ttfs/tffsdrv.h | 312 + .../arch/arm/mach-pxa/g900/ttfs/tffsdrv26.c | 1902 ++++ .../arch/arm/mach-pxa/g900/ttfs/tffsioct.h | 55 + .../arch/arm/mach-pxa/g900/ttfs/trace32.c | 48 + .../drivers/input/touchscreen/ak4183.c | 17 +- kernel-2.6.33/drivers/video/Kconfig | 12 - kernel-2.6.33/drivers/video/Makefile | 1 - kernel-2.6.33/drivers/video/g900fb.c | 539 +- ramfs-android/default.prop | 1 - ramfs-android/init | 37 +- ramfs-android/init.rc | 8 +- ramfs-android/init_1 | Bin 106576 -> 107412 bytes ramfs-android/sbin/adbd | Bin 113288 -> 138352 bytes 220 files changed, 113734 insertions(+), 460 deletions(-) create mode 100755 Start_WM/test6.ncb create mode 100755 Start_WM/test6.sln create mode 100755 Start_WM/test6.suo create mode 100755 Start_WM/test6/inc/GF.h create mode 100755 Start_WM/test6/inc/GF3D.h create mode 100755 Start_WM/test6/inc/GFAudio.h create mode 100755 Start_WM/test6/inc/GFBDev.h create mode 100755 Start_WM/test6/inc/GFBitmap.h create mode 100755 Start_WM/test6/inc/GFCamera.h create mode 100755 Start_WM/test6/inc/GFCameraScr.h create mode 100755 Start_WM/test6/inc/GFDef.h create mode 100755 Start_WM/test6/inc/GFDefScr.h create mode 100755 Start_WM/test6/inc/GFDiag.h create mode 100755 Start_WM/test6/inc/GFDispCmdData.h create mode 100755 Start_WM/test6/inc/GFDx.h create mode 100755 Start_WM/test6/inc/GFEPP.h create mode 100755 Start_WM/test6/inc/GFFDev.h create mode 100755 Start_WM/test6/inc/GFGx.h create mode 100755 Start_WM/test6/inc/GFGxError.h create mode 100755 Start_WM/test6/inc/GFI2C.h create mode 100755 Start_WM/test6/inc/GFI2S.h create mode 100755 Start_WM/test6/inc/GFINTx.h create mode 100755 Start_WM/test6/inc/GFIsp.h create mode 100755 Start_WM/test6/inc/GFIspError.h create mode 100755 Start_WM/test6/inc/GFJxDec.h create mode 100755 Start_WM/test6/inc/GFJxEnc.h create mode 100755 Start_WM/test6/inc/GFMinimalIsp.h create mode 100755 Start_WM/test6/inc/GFMmProc.h create mode 100755 Start_WM/test6/inc/GFMxDec.h create mode 100755 Start_WM/test6/inc/GFMxDecH264.h create mode 100755 Start_WM/test6/inc/GFMxDecRV9.h create mode 100755 Start_WM/test6/inc/GFMxDecVC1.h create mode 100755 Start_WM/test6/inc/GFMxDemTS.h create mode 100755 Start_WM/test6/inc/GFMxEnc.h create mode 100755 Start_WM/test6/inc/GFMxEncH264.h create mode 100755 Start_WM/test6/inc/GFOSx.h create mode 100755 Start_WM/test6/inc/GFOption.h create mode 100755 Start_WM/test6/inc/GFRm.h create mode 100755 Start_WM/test6/inc/GFRmError.h create mode 100755 Start_WM/test6/inc/GFRmHelp.h create mode 100755 Start_WM/test6/inc/GFRmHelp.inl create mode 100755 Start_WM/test6/inc/GFRmIx.h create mode 100755 Start_WM/test6/inc/GFRmOEM.h create mode 100755 Start_WM/test6/inc/GFRmRDMA.h create mode 100755 Start_WM/test6/inc/GFRmScr.h create mode 100755 Start_WM/test6/inc/GFTrace.h create mode 100755 Start_WM/test6/inc/GFTypes.h create mode 100755 Start_WM/test6/inc/GFVersion.h create mode 100755 Start_WM/test6/inc/GFVx.h create mode 100755 Start_WM/test6/inc/GFVxError.h create mode 100755 Start_WM/test6/inc/GFVxScr.h create mode 100755 Start_WM/test6/inc/cpuopsys.h create mode 100755 Start_WM/test6/inc/gfrm_clock_ids.h create mode 100755 Start_WM/test6/inc/gfrm_module_ids.h create mode 100755 Start_WM/test6/inc/nvboard.h create mode 100755 Start_WM/test6/inc/nvcommon.h create mode 100755 Start_WM/test6/inc/nverror.h create mode 100755 Start_WM/test6/inc/nverrval.h create mode 100755 Start_WM/test6/inc/nvime.h create mode 100755 Start_WM/test6/inc/nvirq.h create mode 100755 Start_WM/test6/inc/nvtypes.h create mode 100755 Start_WM/test6/inc/vssver2.scc create mode 100755 Start_WM/test6/lib/Release/libgfsdk.lib create mode 100755 Start_WM/test6/stdafx.cpp create mode 100755 Start_WM/test6/stdafx.h create mode 100755 Start_WM/test6/test6.cpp create mode 100755 Start_WM/test6/test6.vcproj create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/docg3.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/g900_core.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/g900_flash.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/g900_pm.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/g900_udc.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GF.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GF3D.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFAudio.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFBDev.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFBitmap.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFCamera.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFCameraScr.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDef.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDefScr.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDiag.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDispCmdData.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDx.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFEPP.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFFDev.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFGx.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFGxError.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFI2C.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFI2S.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFINTx.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFIsp.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFIspError.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFJxDec.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFJxEnc.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMinimalIsp.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMmProc.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDec.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecH264.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecRV9.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecVC1.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDemTS.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxEnc.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxEncH264.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFOSx.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFOption.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRm.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmError.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmHelp.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmHelp.inl create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmIx.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmOEM.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmRDMA.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmScr.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFTrace.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFTypes.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVersion.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVx.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVxError.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVxScr.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/cpuopsys.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/gfrm_clock_ids.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/gfrm_module_ids.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvboard.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvcommon.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nverror.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nverrval.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvime.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvirq.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvtypes.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/vssver2.scc create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Documentation/DOC Driver 1 1 Block Device (BD) Software Developer Kit (SDK) Developer Guide.doc create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Documentation/DOC Driver 1.1 Extended Functions Developer Guide (Master with Hidden).doc create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/LICENSE.TXT create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-m create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-omap2420 create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-pxa27x create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-y create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/README.TXT create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/VERSIONS.TXT create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_common.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_dochapi.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_docsys.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_fltl.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_tffsioct.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/bddefs.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/bdkemul.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/blockdev.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/defs.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/defs.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docbdk.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docdrv.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch-firmware/Makefile create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch-firmware/doch-firmware.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_api.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_api.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_ata.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_ata.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_func.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_sys.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochstub.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochstub.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochtl.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochtl.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docsys.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docsys.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dosformt.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/extfiltr.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/extfiltr.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fatfilt.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fatfilt.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbase.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbase.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbuffer.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flchkdef.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flcommon.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flcustom.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flcustom.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flioctl.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flioctl.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flstdcmp.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flstruct.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsysfun.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystem.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystem.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystyp.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fltl.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/geometry.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hal_nor.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hal_nor.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hib.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/ioctl_example/Makefile create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/ioctl_example/ioctl-example.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/part_inf.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs-pm26.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs2lnx.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs2lnx.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs_api.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs_api.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsarch.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsarch.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsdrv.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsdrv26.c create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsioct.h create mode 100755 kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/trace32.c diff --git a/Start_WM/test6.ncb b/Start_WM/test6.ncb new file mode 100755 index 0000000000000000000000000000000000000000..47e9a10226e4165ae5fef4a8ec5e8ec7a4c089aa GIT binary patch literal 9333760 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%0AK@?bkqg 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�Q`8L8+SL`Mu2ZH~SL_m-WIW#ZveE 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
)`$|>Cqs}+uw=r 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 z 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�= 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%0AmU8$Mq6H1=7}S@531r?W>pqv4H(&tRYFoCz-{ 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

  • d z-dE3UU|geS7|oRMhQ>8QhtYruZ)99!kkEl7ys`1nkNWgS#q>k-oNxv`=+cBYP54Pg zULszP5om{Sz9{R;!V7@@t{xbo$xlsgZ{Ne@?7cV8qiXn#CiKw#rSDwypJ2i zxp%_b8}Ers&OF_OcS!hx4=VgA5pV6fn)}iip00$mqwz4#dRoFe8SiF$`<;>S&c?f= zd83~y;a!Y}aoqPOysPn`k9;BFn;6&bCA2jXzNvBTtHL;mFGGAPoZXBEedksQS2$YR zh*;#%gl}d%j6t*ZMyIIvo0@QiBj>$}yhOY$vbo$JAN@z` zSSEdJTN@Eb>m%V?8P~otv_y;klx}Uj9hyzX2Nb#W&$s8v;!j3@&}Lfye0y3|N=F|h zTNmsEP zD_6MNqi0unui3B}n!}*4XEfZu)YEUs^*_?nH|AOs3?sTsPv44juB-2WeG|;47)A=M zrnB$CZ>?vR>+ZM4-W$Wn7+N}+8{nRNo%s=%RKL9e`cvt+TXOD?k&b*cXPJZJ?~^%8 z|NR>oLf0?m_p*5H_uR_A-0f?)`w5fx4YWm1yER7sY|r_5Dy{LHkH9>Dc?lz3uAV1< zqj~s((PJz}5vjt`u*QH~ACqoA}IcSA;VP>WD%xVj6Y9%2TDb0GA zHn|pdwTlO^SIr=14{J~GC5%qfuHfqZmD{bT`=^lNp7EwaTc95&Jd(hT3agVrVBLltDT}2Ak^-bL)@t#t*D%$pN zx9=04v%OnChG#3MGC_Cj?j&s#upNR7bB@zo3-NJQO3HSj$-lB)<|Jv$cBQ+l;{Gg# zZBM8AT4CQGouA4^xxB#5iTB)K^|n}Fr<^O>Fe?jW8*WmeY^RtWLvmGT@-ci<^*>O-KgkpxamI>-o~tF^03=7#_vQoKl*-?>v~1-vyExS<+dMb@oM)# z4E<(KGMk<--Svwh)z?)^L-e!??Rj%oUZE4Y+m)RV{4Fum_D9Xlw?lb z)6;4r*>-TZ#Jdl6mz0IOFK`W`yRDt1d$~KrNq&&+D0U4C?v8S~w)$jRP`QTs8q-kg z-EOAjkv_VZY9uSkkJj$EinP`(#_SZFE^}|4YKyFTrG0> zx<)s+hB3V^uv$~k-k7@bMV_W-_rQ-ctsSTPPBHDYY*)L{F+82z)KTG`M!Q@KeVJ1W zM($=hwf*I*Qk`_qvX{~Bl}xB7v_nGd? zze?)=*XsYre+jb>(JRD#GM;8lL&g^*ygGTFUKCGfygM)9HH|O#kHU{kcx~hN_;UF8 zgiFq+@5kQ`-#+2eyU>ES{XaHOcnjl;{H3^WnsBu@kxp$r_o@k3`+E+=xY|{uAwLH9>nD6ym>X<<6qIE$e5xZi}7%=@%QQd=Y11?rSaEo9Ppxq z-(>t58;?6B;kO!p+{Uf$mhd}_hjk+QCHx-a+N&LDHsR&QZ$r|eeUfL=S{ zD~xLgXvVbsqxfD=8()M5oIbmRKX3eenVIkpjB6ii z#?2)BW8;U}IMl8Q|IGLddS#JB68@F($+Se!PySF0|BuGUph;vzM8ZAaTM{0PGk0ym zs~aC;dWG{7u6bjUj+LKgCtT~cYahO?`QI(!nhz&wQ~JBX-&g2$N;Usan#~6MKk&B- zUaoc388hHN=DcUZwXQmvE!NqhA3xzr->hxR`mH=S;mwS%@~b#EO?Y$TANUVAua)o? z#^3kvbN=SnVt85_*BY{nZb*15?_^wSMWGW&cxU5UM~e9* z3GZV371rNk+z{n_HA1KHohpwQx8Psq{6@kzG5(T&iF19@L+*Z4<3UgPYcV~PcQf9K zxlrgM60Z5CNOT;mO_y-ZH)Ta94y5^nYrZLO#6i0>;hN{_Tr&=8nS^g)JdAUlnsAlB zYKf|UV%LOkWxNriP#KR0&-G^vs^KrJ%dd4oKEbU0Ugp|h^m{Ppd)hd&Pr$Bgv*Wch zIp2tR6tfZ|x1V5ipRTojfAwp<`JG?WeTVY<>`LtK|K|5+T>lkQ_X9L=nAE>AeqS8f z3!D#X9m4$;_H|bUx6L{0n$~a6?^QSzmMx>3JnRSjo8M_z&Z^}0Eq?zR*`^;B<8UYJ zimNG{^XDrrO$uRW$~n4c@T$-kH0OMXrJB!uZ?&Wkbmv%bJyIZSJR8p70ybLuV+lddoL z7uOV~kGWpuv(@j#<# z*YsEAgszQ9uH}A;Fa8~#-}5@x)ZXp*6&i8OUYG+hCt?<2ZpA!?c@y&^X2Y);C6DQY z8Ht&UISO+I<_gT+m}fB>r<{(h{sfkfjn+77ja`=BcmWC&tv;kawGRB($lzVjH%&tO zb|_k$;~8su9^-^BNAGkiW6HEX&(n-}dXEvIKQk<=7UQv+`%a9;>d8FF?QJ#1aejY4 z%^&QK@U#7i{&e;SxX54bZ}fNjhy34J_g1=T=|&!5@IOvpfkP-JbBUu1;V%Wfs(C*O2$F;46QMsR*;D}sOGK4r|M*5@qvDy+s_ zjTw$>`5MgM*DAN#4?rv3<~sp2_APxE)?DbpP6~aPi#p7Y@VojwSwnP`-`kJ&6Z}4Y zlAr9S`x*XFe;B(!o$OCxkE^qYv2)ln>jL)Qy4YXB>d066oBa}hi@((`WzVns{4&=5 zUE!bcE08r+=bg>_-DU6b8R2VU&)tIArh2C2c*XJK?pLq2jqIEGfB5TT-0Ry(rV)RG zb@wGF$^JHORM)C1ZRF02PntuF&L;+MW)$j+#LcISl&j8rH)c$(ByQb#y8F&cx|jWW zx6-TSBwspvwP8gUA;GD=EV|rljVZOHdonU{A!`O~&Hh<;daWq+pG?ad6TcRr=t4hN zfAqq;k*;nbuGKzLn4fXKdC63=zr{nNye4?H~sfsdI#ATBXvvnp*x=T8qKLz zO#^bJ^5houC`rpdkes*!xo~&hSgQ~1OZcaf0}m(n&9T0aGf9L>bsGgtrVr0 zRctE$mdAKfEQQ!mTy!BGLM)85cRrOjR4U8gOs!SD&kWQ5=y@m6%F#TBKPt1;j@2EL z-R{_wGiFh?o=ACmG3DqDl%3MJ$i)s`Z6Eo$(tqnUOMZuaaKnd_B^l*2>Pm zw^Cg3n=75=-+lE`TWewcC(AVH&=g;L_#eI6(Xzisy{k69>>o22TY5izoiZ;?rRY7h zAEkAY{TKIvmnKp6GiXPvbuIfl_^6h@>>v7ndd>fkFE4ntQ$=6#UwY|^L?5zNw&+`w zW@GrGzgN;qgCRGYyRW>oBC?NgpL=O+WIw@u>u2Mm?$wuC$@kHhS(oo2EuWsWt(U%1 zwj;eXAG)uj`_j+Eu2%0Rq>+K7jM01}X?%43Xja5OJNm1V=?%&wl|JiH=G+2TYJ7=O zX)Q{fTcYoWdg(WG_bUIJSO1w@<>k8Cy1Lekmap_vvY+q1_e-O1FOzp`kZYIXTY+nb zQA*A6(y+)ST9qtc9V89!armS@|1#3jgj?osx2(9lTlD*JfquaU%#%CgRs@BJv*M^dKupj_RR(lnH$r%--|vU3S# zrgTucw+~q+Fhr0Nd*-#X#)LnC$C^S^b%^-a}F*pB}-6Rxmn z3UO3nXQO}O$) zfwtp3&Z85q{8_LSg3&7!{V!GiEFe3b$az*)@!T28p9SVWs()?QA}>|`EYOnLjq|1n zSGd^u(d4(r30ED&4xJpV`;zcF3BTJ{Jhw!=I=vrqe^?AZD;AU~-&dy|8_IcJ!s{6i z<1Oz=xY};jkqUO;{8qy28xP|-7Z;yv>*`fU&K$t?vl6cItU3~Cf6m9iRjzAXdf;JP z^pwQC%EjumA9`>enQ-a3t0UQV;{3N_{V_tkmTP0YcXZDx40BW-*NWqr+a$cH@lbEA zlkjH7L%sD~^k4ooHy-M(R}fu_zUNqXuVYz}Q+C8e_W=hLsvAvseiNlaH%y zX5&s*QeS+7(HK;XCDrd*--X{|x!DY+>-s$i`!LL2m}!_fm@hE3z7KBN#`BH$FfS1M zg`B4}qkhAl>IZY(pz15>4y7Lyn~Xb|vS@DNEOQh^?^=_U-ZXNmm+MO`9YBe8pY0H; zQeD55%2h`9w|tCuh$eon_^#G zwrQ5`WIM(w$H~^CV%%yYS|p8lXN9LPxmbBXF4|e?CEIT7&J)=FRw9dC>6GVW>&T99 z!M2}kLb_Dwr_;7R*e&CiTr6^TM%z3$o8&0=5VB@iNqZ1s{xRBjKufE#R4(?iTp`=h zPUXF9mpYa33h7+z?+`n(_u)%?5<|1S`-J-y27Rf6EJx_h1DxtG+3s^k5XZW2TiV`x z;)lNA7HHi15YH;vUoPG2e5nin>4 z!)sKO-*NoUjW#}^SHeR*f3?-yEfZdg5NJjB%lN-R!h?J}kFma#3u_hqSG`C3+Un=G z60Z76qkB)`|Kka7V7x5M8%sFF2!FF|{j8DjSe})t9#HB~`L}1aB5x)f`32Q0c!_u| zTFP=Sp4Vf6hxtSM@LsCNH7~HaxexPrj!bw9<6$1p{DikO9_B^el<-!@dr=C}r;zYa zZ-o6t-br|X(SuMI*I6=bNKHnun))rY^dt?KuCE@Q%iVJkqmf2#?nJRXtM|U*yjOxSlKj z#Ty_iYkbqf=$;jq$~qel^Hg3-co*YgUQ3r+!GF2$YCOz?IV9nm7!UJimPW4dXk17G zo~q}*3(vzN-iXqEl&-H6{BMT)ZpOoWpxqMQ-FT1(&xu_AOZU|XU*yld3E$j!m~XTy z;gX9Q(StRKbJKN;-*F4$Vg0i13E$FqsL$^#re|AswGri=?kh|9*5^1DtTBSkA8b6#?>s)?LyU)garR5N@=0rIl^L7|MgKL9WvKC>XXpW6m*3*b zC#~bSj(LxSMsFxztK6J(=?9jGchM)-kHZfLGire9JHyJ*ZKVsrZ0n#Hd*dnvmb*yx!(=@ z;h5tvi!iTX@-?+2Uw*;w2{)oYJb%r#y=t*UXSxy&F9>vyoO$M{~OfZR-s-D@u1>!-O^_Z`hRKKK zPNj-$t*ktft&M9Kec0Y)8?iE1Gk%k^+~V0m7TdpnJDNgR#n$o=yZ{of~!qq;l<322W2!FqMMSPY@4_e1PPDM*or2${HKLw{S21OisAkzxC0LxlM>$2_$`H7;0GuE zw=#Zh;aYe}k?$hj*j;J-y%l4SdU@Kc$lU8@o#j zm%^JST)e3ugOmTsQ$#?gOP>@8D!qouo`Z~^Z7C%l941%(ChX$kLW zd|_cB{KAB*J=@YmeBBPkaH>7q(VbN|3*Mvn zUe=!N=#DKM3-6e4wP!oJvO*br$jSnmggr69>!l`!gAUDYTzaim6 zj1Mlbt+IO|;c6ETazhG3;8~~eT=_H9_|U>oc(a77T|CI`P}l+9H{m-N-?6YGeD8!0 zGrn_SXZVo`-_iIkgqg@*8Z8dt<;iTKX0j`5k% zpF?@>c;od7^>BY_!Y3HtxUez&$%OA?yndlR{MUrJnFy@M*?>%218C*$GD}fsoF{9xnnWlZ^TRW=Fl zEBA*Oe?Maijcb+gLydosF{Q$_DL%LKFyn7#ESKYIBz#uFUujs3XYoDUYvz92=>J(f z_i*DYGnOE5QxkrK@i#J-{BaK!{V6@t_)FO<@M{x}q6Yt;&t8PjOZd^oAI~0#AD{4J z68>9*VtXO*>$B@|Kd631_)BM-`wg-U;9DfTEaCGuu5e!>zMsp?{rT~|7V^Gxj91C3 z;LlA7Kh}8FtSbERgdbAIZo-c@UOlT0|0Urk7+)(}3tn&2@O|~%6OGr%YQVcE z{3PRRXKTZ^OZdsgYi2d!`zQPqP<~{50e1X6wS2Cw#8)^|JNg zZzcS6###q@p-Q8XQA|Ib(>V0YxM-W%z$S*IL_m zrF!oB_YD8n@AW+Q`M$2R*M9G{*Phm1<8@sd<0l?}Rro1riKBhu@!7(EgQh9`n|geX z@YArSfCjI}=L$aqZFRKMa$bAClI97wcFLV%JdylK%o`s;{L?O-R9x45;nwarOJ#e# zdwh{_S_WZ!Cf2S_ zdQ#}tlE+sFFRTl*obmVv!b|Fs;Lm$}rSMX^6!=n)e<-|?t^~f#;~xpHtSf{6 z=JAh(SJ73#<8QO~ljr$~@M^jmcsY-+5?)i+1aIu|RN-}W9q_!IgG@QWVbEIe5!gXgar zyRI$5M`|cFsoEajDtv;5GOp_4@h^o>)|0`X^!PU6FX$J*=X!j*@acLw_*#$e5dMmO z1^fq(?-V{;&jt@~kDcc(;dAsH@G>6XEqtz?3*N-zUkRV5=YjY3_#WY}>DRy~czmz$ z1$qJaVvp|=zECd&-|g|Qg)h>Jz|VSozi`{W%2zFR{s)9F){7Cpy2rl}o}yF0yLtSe z@b~n4;Nv|0t?>8t``}AFen|L-`a|%|9{*1G$NFRNUp)T3@U?m^c!uh+^ZY^hr}|Uy z^VwtN(vQNE0!|#9%@*T_h0{t7?~%ukczi{SCz3CPbsgiEa>q><=;Wiq?e{nvd;BNi zze6t$_JFZ;l71F$zsK3n2WA0 zf}b^K!Mnu98B+P(_!L#blmKty@m#`-o8sW(WBtU`+`><2xCKx-Z@Tu}Q}YOaC3pqP z3pd7iKH<~EFV+c<)4vV!18l@#>E`jG!Y2k3vE1Qt`jbgf6U2|!n;xehm=yI4EKt#& z@;Lpsq^Pm5sfS&o$LU`sMU4(dV_C@K^p}#NM#4r6y1E{xpOX|dO#E^E7HiL>))GD> z7=q;?kJk}CK>Ts-^7x&?X)OysQ68@^{1I5vBL925k??-7aYaAE<4uJ35x-t9di-wT zywH6yza-p#&*4#z&k{aDjX?Un zJpQt9`(4|%9)Cr+)uX%J&Zg z!tWPYoQKaKPQsY_S_QW6sRQ;&27BcJNGV%z`7k9r+!zXNh7q%Nc$q(0;>NE1j4NFt;q z1T#<=oz>9f*BG7D@D>NF5lAOUXGj-FS4cNVcSsM&y^#ALJs}uD#1q!g@`dLaNL$E* zkUo&UkbaN>kVhc{A%h{0Lxw<}fQ*8ShCBrs0~rsQ0GSAx1epSv3Yi6Y8S)C`Rmg0} z9LQYAJji^=Ymfzy*C7ibZ$aLMEQTzByaRa`vJ~M2I{=UnaswniBr_ySPy>?yO(5BeLbo5wzth3&1AhHCSBHYlg0%S!Z6yqd zpT+(kVEqt;VagR3E^!$;rjS;UK@c8`+u!~bOTvwtr%E62(ODeyxkEV0+|e10g2WRAgnMsl^s$M(iqYW z@)#sK&+C`b_Yru$(Q|$V@n=BZfpo_4D4!zCYl+tPV*LapvQ@i&$+UcS6>)QiMwNxs zggj6fbAecnhonGGK!P}Xp9|N*eC2h*XOj)vqw~BS;pp6>CAUS}qhm+gxXv*1BqfT= zW%S&lxLh_s`pqHtyJK?y;RyS}efdnrfiqvch~=9Q|J6X;9eh(eV6_9`TJIed8Z$S(^CO~7D%OhC-6*4|8@(TtAa-_4%#%{?tnQEhd zPyrq~JhlkoA0ga!6w71YdR9!l-Ux}dH$)t=W*!@fF!$v#yQ8Cj;JWq3>FxIWvD|@k z9p#qXXPMjfDV7^tI5+OgE*H+6!S378El0Q|EMrg?Hh&m>>%MSUB8;RO`XhM} zBMx4ZGoVL9KWrs}vhZm4?+}jeXT;ubV$R@dkXK*7q?QAZf1}}#eORus=lVck+(^UZ z;01U|v0|XL$ryD){@54e8hc>*f@o&`h^}WMp>`l+P$zJa;aCvYWCSQ=kBw{Wr)3Ym z$z#_zI=WDQgZpv=w$;W_?!-7%?EmWpZ9Hn*bTjXucf>R}c6Un6$Z6L&vv(}WjTD(i ze_aL|Q~v)M7+c{JI-zGct+D5zs~5?P_O#aLceeTCI0@G{Ix;c%4x=?(qmEQv(;a(r zjT&?lOcQqn9Os^(Ij+NP9L*_is1?dJ>WHp3t#aEn&Zrd7QBRTnnIeg1%l5%*StK93 ztK)p*iJ+!C8b{kl>PXu|Q5VI@$L>z`gx*k3!+tH#Kzg&mm`>>FVujz@ihg4%29j6k z^^D&szkbQ@pD+c^$5hrQksedHJ-|11o%GFXkHHb*k2N)s8K3&cKN)^eobfBE24N&8 zF@V7ssnAqSH5?)48pnl`g2C=;IotR{FxXuSb+wXA-){VR6u$V2nUYTWJf<_a#`(t| z1CD!ejiVi%gEH<;bB;W#UgYi>NBHMzYD6%9?1DbUkJ|qq>FTb8CT=7@x~r#FUUjp~ zogL?de+h1JXGhJpMrPR{Xwx8F^cCPmF)O|ZPtS#=G3xd_M&zd9O?n}SX0Lw_vg%0k zxm2h(*UrtLmlZJuZ9M6BwO&d^13<8xGvb@_U4?_-Fgf1JGW6o z=Yoz#f@{m0#kcFuFzSu>g&j{M(Ma`=7@>>gt6VlE>PFn4+q(P78Jx+QBTFo6I$?b7 ziQq|$D*buMkw2aV$NNSGkzR5Nw5cPBbYl+cMkbP{JJPxaVZn$$-T7?p3OGxCCdk%=n&&8=Fs5!xh{EAN zg`aTGfb$${^&f@o)lge_rlFP*ukDcLub#{K)HvU3ID*V=95+61)-|@Z!8w;1LG1zm2U21*tkX9Vkz% z^uovn)8KeU7a4cq8b@33{M_iw5H$+@Z!6Kr)l2AEM{?A?XVi^26&!W76*cQ}nWLy@ zS)wdMFF2A%+?jGNxss-CB9B?h@W+vVu5rBoqS@!luPX2_7|A|&k2xd%X|T^7jrx5# z4d(~AH)jPdn0=_9nAdAd%@oy8v1K&Mw-debNane7aW_L)#gi0WD_Y!$=chS#Xz$gxX+?!8yve^yjVwqeklereSYe zk5aFCu=xP5l`swJn0yvIh_m25y&4oU zkv!L0#IxA<~l~b$dw;kt%^+a-}OBEdD49+*WEc9S;_``$t{6P*XRNdr~9upyr4r z*EmkuO=WRyR*shTQdw}Pd34@sdzYjC9Jl9QCD0lz5lnYakaOyDGkcjbUzkU)2vH`3R%GydU(TR8D<_ zlo*3EanbM6F!~|EU!cXSXFjw(3ZwlI^C;UG^BMnh+c-zfY8rUk#2c8wCy6Hy$fTEGyHw($~M|MtunOT<2G9C zWew}QHQEj42tRdeoW-sh#@%I~HuG;J^_$wed|dNaALS&|;w;Qg^=UU+#$m)lyy{L1 zikrU+)qjv)P%thjUa#qym!7XXW8SSR=H$9zzOFmw@_L{>!k_I;ah9+*W)S;G9nCfh zb2R5N*;e9Q=Ww)CY};rwJViexaekP zwe7hju3Z;fMswQFp=B3I1y=$kLn|p+KkV`gZOGm*i(QYdF}{%0IEXZoI-3@u}sql$<8ao(0|%op8) zR9Bx+M{sR0!j&=9kUSjJaqkQDXQ4ss^8Y}?pF+LNqi#lvKavsXXOImrPnbwJOU9$w zR@@s%gE1z<;w%z=>yRwHE@&d**9~)ll|zteC(U^;e1i!iS zr@nJW-QV3cYHLl`zqvK)I4#l%?tT@91x8_$fcKGSL=VMP#Of}?YVuhaouMoHnx3_6)F=( ztN6sLqVIkOdhd6kzG2z)uhu8JHaEv(BH@=NF({56)Oy^NWdWSRnKUM&iHE&US@U0^ zoD1b$ussH9Byf#-2pxkq?p@(miM|PTyEW=k{~EM$Iggs;mxJ9dchSD>PV<6mpV4Zo zlNtV;%?;G`{V2$EKRw?um!-o9)Jzdb$*KmMnz za_4?_7?1VNuzc3!Ci&>MdQrr1t~fJNi7x9^N{b{>*H-SW!yHT=2~h3l(s0 z$(I3t{Q5K|XK)Q=;eTT$=9KFP&t5C(|2=kpoGo|w{f;^E6_4mY^)-2B)ZRR+?sp|} zDd>8a(ntQW+`AuTKi@#=7P7ro4WkkN6yA&b&lUpxPf$yfSAGn$&d&r3_4Uhs?#gMy z@O?m=UY;8*c^@*r{^Qy7OR_n02SzY7eOtBBj1dc2D@?cLb&JcALsi?EElr2j5NZxBq6J|NPCMKF4W zf!sfp;;f1JPE%{oj#)p4HWI(S!rv5W*G40eb}Z5_^Z)>ZDE9#80Bq3dXc zdZoN#YLf=xc$fdnh5U`LW7~}MV3Gr+?Ek5LPY&cJmZMvOUHF!r|38Pz=d{_%taG63 z%0@3cI7{<>+6}*|9I{LaPHh|x%^&pJ@Ga8Zb~E_T`5O< z`KG3$dq(tPa?sG97xTyux^NiDfEMQ^#-YE_<8)UxH8 z?KM;9nQPQ^ekFL(tFbwWUAu?9?WcmS z?s{o=@`9#4G1EN)YvCiB-XB;3JP6+!GcbP}```HEz|GIzAoH_1Wq!7d%+LO7LTz^* zg*xt6Oron1Xp!;0rUw;nTVVM6&|N33ThnM-%X3>1!ymsO&$Y+pH~LSxje4})Rv4o| zg@e$gavHXSr-RVlEn1>x(xJP4+8OoGqump>vv&^_vZ+jjPmqb`mw(Kq2azv%v~}`3 z>(0cE`9~V7voLlN39UaE-?kbC{poo`mVTcFi*+Pt-BY3M_#c|Snz%PTG-V0T{^MCu z_nz_iE|)O0JmA_@*c)6mT`>N`ygMKIdXZGZd9ZiH(U_>O$(H)RTBi>urhEfDH{B4v zi}PX1Y}rH-X>aC*&SoUkVC7!aTkWm#xVmO*up8f5_5ahdfbnQgaMsMsYs=Ce@GjBA z&`N~IT8my-B-GGmo~?==-d*U~#r}Wqase%tGw2?O!*rjPUoCv|g=+<5ZkpC4T%!%i z^P-#1weB*)waKND4))XO^e1S!a+}R()WYW)+pzru`n2I1J={z&)F|f~Tk{=)$WHYL z#ylb!>+&Tn`Ksx(u3V#^k@_aByT`QV_`{6FJ!V=ZpfOP*96Q`z2|Xx%WU{)q$<9rz zaidN2x^b_0+?|8%t4FpIlhMPDZzxjFGCs7~3d?S*>cAJ!*hCVcPKx!0!o+ca6mS>kF7Wc?+|F@1gAY z5Mx^#^-lCqcB7B77r%oT3ps)|CDam4V2p`F8#S#-2VW5x&n*E-aFt#)Y9-KaccdFGGo7xPoUteLq zKYv&dPlUby|JcRiK|^r@FVjBI%NU~D}S z+A%SP9eIhY&v!z{BocZ?V2pG4rq{V3@Hoae z6YT}o0SoaaM$*%r4Sm)fHT2EMV-*VdYwpTb`dzxq&>tDM*)p2m3%Qm7J_|F1&0QV& z20X$?(i}Yz#z>ETMcH7FtH)_u`McOQ@%i+S_N4#69gf0tWcw+SIqq)SwjTZcFx~uy zzh~Sz(ic+)lipnoJqvCz>9^P#koM0H=&5yVUvMbK;j*Kj!I2J)FWa#+W}B=)z&2T7 z{qM3TT^&R#^D6q%Kh_2uJFkOd{j0I^|I^z!7M~91VaMWQ|2Zm8Zb#)a>fKqc+54ln z!#{p60GeqY4~5rP4X}L6<9u=o_8fQO|4fhbS@S!mweWwm$1@4P6&`uffAx60@SEWq zR;jKY&mp`le5*k(9h}F5ol6qm1I(x3hf!3I-{kS1z^QeG_=)7u_LcY-!J(ds@Klb%Y z`pcdLheyIh~2)^P7vjKV>lX zQ59d2r~})Y=)1*5;N_Y3nUwP_ILm&W8Af zS%wO${BGYO@`TBXi{E2Eedb+mX)IsFv-|P6Xs}%Hgh?GkhV#Np*c{CCFh)_yVGNZO zPoICC2dRT?{#e4lGY|5=J3i-Cvf@1avHZUabFKx2@&CeH%L}`&eNS#R62hO&_swGV zW{%r@pXM>E&4~BP@v^v+$b&7el_NBx#b2(tT*zDlJxH6H z!-?Q6Jzhol)8W(Lx5RiN`K@ZS@Kq>J_#ReAd!?%IG2s}*-{En#r*2ha!?EB$d%T+P zap5@dahU{; z_YM1kKM_kOsjl!2VF&O>Jzh_EyRaR2Uys)p-X?4V-qYg^gtrP?fp_$HL*a>GB6v}c zqxpgJzdO7eJZ+38lGnvJAbAsa{>^b+Xb^#O-V^h9;4GKHTUvg*_-7g9#b-OcuBwhX zQna%@j%h&f8et9a$sTViycT9Ul$z)9yM@<*1_$0d@aVXf-w`$iU+=|lCh;4F4Z(MN zyt(j3VI%M#JbsVxCSenB9lH-nErgep?*v@9JC;upg%`sNI_3~!yd`-9SYMK#a_M)( zeQPPaAV!$*okWkf63)IYX1-e5e9QQ)g%=Hrf^UwcpVUUU^}qifINK9=e;;WpJj5UT zv3i^>uLjD52K-qsoh0ELO@{5P$J+}(X-_#2znEXZJ9`|a4oLr)IR@Us=6di*}&)XPPC#^XJOPczfNSHyTCd1Lq=C(q`d<0E*E_X~ek{EU|e zXTAk*N!|p0#-B(0)-FCQ{gZnM=ZFSuI6eM=@Tq1h_;N3ObcT@5^ODY+vGYlKP`LG< zJ~qY^$(yN>&{M`7lS>C)1(N#+A8kg1e-F;{1aC>+LOq3%56s}VviTF<2gHAF3pLh^ z1;5SX4@-RNzoO6RaSXj6ou|#y;8Psuar+5>M$&&gcAnxtw}l#EMj(E#7*Biz@mr}U zgwJ#7j6gd5g%34D5kJ-A1B4GV!@$4w_@lyyo8jOcW9cUi6mI>q-yY+MJPna)JLuDeFJYf2=UuPUx@zMZwF`nI2Q3A6E6CZs;9>X3m;?#A^ud4 zKQ7$*e@}Is#~mV^RtnHrkDX@{I%PQS!{%Y|JTaa~-d)`*{7aV(yhJ2FDZD4F?NAh^=UMG^@r;>yxyL4W}c|IkaBXcMx!I{s&Tax!u z9WhG)%Lx~M2I7wq-q~~pKkxCe!n>F*;APs{`@s0)gm*Pv!8cTgT5+Y$d}kIxcb#Z&>0i}6JACt$TgzR0By&n(F= z3#WdbQmesvUEnRrhp9^DHt-)^{1u4*itt;^E#TSO+v_ENRd{7n8N9Z~XA8g8+zQ^u zaUOS$@Y^K)b9Y^PACu+^FDHKX*Ti@td9o@d{7IJ%JjW!@6VADB*rJ2;{J~q2k5VPY z|Ne(Aek$V67hc+wM*N>W{+e*k528QY!Cn{BUm(1!q_aGBK1r_&r-lN*i5ENng~AJ& zLf|tz{)X@ZrT}>F7*8Z0qizyj)*bhA9Cwj$>u0|{IIj!5CHXj&8}kRapDzA-#D7zG zUh(5U%j0he&u8)>{$?-zw}o>a0{y1g`6MkCp4DUp&l%&1E((9pr2`K|$t#3gzyBjW{(*4&eS&$hbdpvIKd;Xt{mCBxQ21Gm&ws07 zF`h_1Rh<$(-KBpJ$Nfn7X?+^;mwEhS;b$;gj&U}ReRjT zC#@5HSiVD0*5jWF|3SWIkSoR$$)~Gtg;#Uw!|PM>XTrbJ-y!{G9{*f8tt(KT$I?mq zLb&}7LE!QA!uRX_h<~zCEI*Ua#4Ij(cb7gqOC@g*zEAH1AL#Lo!l`Qu|CO^wb9^Wc_hu#4`J(f<=m%`WS zb>Po>e4Fq!dJTADjJG0xRed6Sxa07UHFCS~)p|AJ_x1P=;i)dzTvg!+lqXFS|a=h$KmN~-pf98^rDp`C|2|@Y*hZR-Dfd!so%-4E2u3e-uvN74TQ& z@x#KcKkKv}KO&sA;TQ*w9XIKy@L75m_{W})65?<1_|L*; z>Y3mxJbq003_Sz~ z?(vhtr|2o*cX|9*;q*~~{zy%G|C!Dy;m_&kz;E&5|0eud{Ve!WFaBxalk_C;$sRu= ze4?HR{-no$7fx?5u%NDg?YSqN6+T=K2k#Q&t;koY$A!;xyadkkobX|K7~((g@$Y?DHJbpp=lln>UfgZmooZ7r-S9|;q;Y0Kg@b&d#=XptZ15JPTYdwBhcs*SYe5%K< z2(P2-fKT-JRpGUCE$|i|=LGF4MIAqkyA_KaHxOP`R|PNS#n-}1>(bzvJ#K{O(Rsid zp!1Xl$78+To{k*OcOJs~=)V+4xMDn#N19a{1UUste?`?rjP9xlYuVuZ* z(+a2NKl;laPbb`dujQi0ZxEgpo@g+i5<6~Edf_+7_hvfAcp^FKLg6=dw&zm==R<$l z_cI7^q0LsQO_9lhR5kIdxNsy z(OK>Bc;VCnMY$I{|0Md$-k|JvTx!O6BKbD;yL{i}fJ>)7u8V%Ow~5{r$}5l4kM=fo zJ~)qMmM-=_F#e6g?e}R)di*Bg_WLyTJ)TpzSl6m99;e^!ZHkut@RjFr`rY29?DuId z-FYpaB;^rKopI=gdmJjch~GY-f97vIPXEN)RJ))Zmb*QkUwE6K4VHWEh^1dZxb=s- zDaI4YcVJ|qKl1kr?mQE59|{WZ2M?#H-#lJOxb>f#8cQdsu<$gY=6Cr*<-q@A0C-X={vnK9){WG2yhDLVGF36Uo2A$QJogmri@6UtGBLt9!-c zC4}FHu_yHBV(BE66y8;J1s@pWiR63XGnPDCSDQ~dBmGjsJHv}C-WQLT7EWtZjIYMh zNh%|}J;wepuM*>l95465b4B))=4k zc!Kcen0tbE9FNm)`yqV!?jG(F*cu=T1EJTa6*Xj z7LQjIJ|r9hel9jolzO}H$HT|L4|^P@>o}jm;b8DR9 z)8oLE$KeSC_j9Zs3x3qK2N?e@;iL6v@Gm^xMEEE@3jBSKHx)iozWWmIaX2tS`aR^k zHFtZwnegtqJJLz#@#ez2=q}*ZJ${ey&bl*r;PDp1JLnGJWj&rKyuEG@ej!%xr?wQ{ zR<{MuA5x8UBk%$2$tYQ{M^R z+v8n?*Oc!Pwe@&c;Wcy(#J>YPGaehCOE=-vN5%Yz$GZ!sr7h-3WA#hwy~1fdk8vlw zr%^ih32%sRfg=BSyr=LIsswli$G%C>;QE4IRAke5(=^wWP@afk_VC(k`Iy}QUFpAQV3EQQUp>IQVdcYQUX#EQVLQU zQU+2MQVvocQUOvCax zA*~>-A#EUSA?+YZkWP@!kS>t^5X?HNL6Aow10jz?FvEvYV(Vl4Ni2s#k|84@qab4- zVeg24oTBO~_&hM&aQZ=gckXn%1kUEe%Aa_FQLK;9CLK;CDL+*k!fi#7*gtUUR zg|vfofOLd(fpmrRfZPkY57HBIKcqM0K}esVD+ZD&g)y-CFqV`7kjEjzAq9HFi#?X) z&p;+Zo`Xzk#9My|`&`6&fDhqjfE0w3hD_QMsG|!|r$HEInvvY}5_FXirv~I~QG2X?7zjR5 z0Ao2wi$ed^jj+8Vqz_~`WD;c7|3DUFo9|=&GpwKR7$*g|Jv)|FA(>vpH{l>H8=|yv z+qnH+7k&iGX^;bm<4d$3uV*2)FLm*`??xB?3QH9qJD)r*ToKD8k8>Yh3Sjr1fC?+y5IJ_0*d75xW~Zw9;m`vd#`X5SNF8S(z`J-ZA0^If?kB4ciA} z5YkUGBN~Od-@Ed`lEZ5?lVm`Wl zNyhhKEaLFpDuZ-iM3~Qk_i&LHPW8gOyzohcqx`{Tv~T(wEsxftcdj6KBM5b>BWZ#4 z9*zycawz0o$gl7j9>sYN>+2xV`VJS?$Y*IFOexCtOjs6%l!jD-aJ@RD zuD9L<;TCQ^I#wABP__k&);l1)6OF8GunCVtTd9wE7`l>U(C?uqa5SRSeIeVC3^mdm z`DSRT-i9_j>Nd3lGdbJP{wFPIzG$h1)`4Gym5*E73HVAyyOrCY)T3O?+-4O0JF0;=3m%bePmU0hKB1|T&CubHTKo*>X=&wXL%MAYbranW#wo~c&Be0|BDmaYhLqdiOd0yIn5r(xW2IyZV@ysk>nVZ0}# zZZ-M-@H=;fk138{lf9%lQ^e42o!cGjGwCIg4Gedplg?0F+{Z)hIlUT;8KUHv2Vm(u z#?k4)$8PU6>SOn0YT(ImzJ~j!YHIi~^oyZxDbKkLG))KJ7D)IzSQxS`PktL(@OKQt zF%hQ!x;a4tbS0_5$NlG-JK&jtq1V+dxSli!-GkO<7mS0@=P^gBx%F919b$$?hqv5? z9sxq*I9`RXtfYhG+wx#V@IkOL_z<41J`O$!3hN@e2y}-YgkIM$!+9OE_lBI+FhMNAQ z2g7@9Ug5&TQuk`tJc8|Q_!7Xepu1JI?z6+3eXpx_r0}lx)eO( z?&DUpx!L#Q{pkqblc(JMVegf5S4{m4O)YhXCWc4vv(Mzspgr;!_iBUhuC#yBKEKWS z5#$8YrRIIZxd`qxOmh~Vq4S!0&pgjtpw*lh7DfKcjO%Spo!5MA+PnNvIN0aTVo@-yuDzmthBJ#iMvBgeff}B}uHfh33ao%g zf0LdsDXrnBx%>H)q5eAQ6VP&>hO=R~cd#*-hJ1Jf!ug?{avL;++CXb;Ff=5eH^bcX z2{m;EnD!}6D+-48gtS{>=ty|Ql~tAWjmQ_g=J$ftu;9PPm91Cs<)UHcbKHBzuM&KY z)c9s!)&`mvSxn!sq01-P;)bE-Vytb!2kxC&Yd8`_mcxAMj#NZ{;Bs^eL%m6E?PtEk zz2eaq28-c0=GYf;a*aPjdx5&SjPsJAwlzZ~!;yGb89E-^?sD_WfI1*#p`lhhL+wJ^ zBQbO;eDn!>*KX7|=`-$3D(XjFIzI;wy0T%h>Ey0;rC5t_?_FUhSI&KdGQNZ>g`3H! zFt_)VaT12=YHH>&)XbD{*Y=R1H4WJ}A?=YEIu_<~@9PG`xplHN`dPPc6GQ!Lva5z8 zpA0pXv1W$4%Pc)Z>ooNo82VOINqc=+b!k_o(Jw6LhPn56O>G5+KG3DzyZ)@&6wtRR>E$4A zOMB1qnwQ*luQr^?<#losz;Qh8b*EnH&NEeQ zcJV$noHgLq_KNxq3@y`nU5>~He_fk#_B>MKpn1?D;M^GR?3Ey`=6EP;s%{tsr5_LK z3vmDWnwnG$UD32vU?_dK+1=^60WCn8MkPFZ&Ly#=X@i-i_CeR6O}N|TsiOLBoCS}Z zJ17hfB;#DY+uKmjfN9Rt)QDl|OI;gJg=vmOO|;v!JWkQ)XZ1BSwuazb z`5xwi7Ua$FYjO{?mit3P|5mpFS>I++_E(-%{mZ-oou)8O{YU)KX@{ zdFSh4Zrq-0U3VrOgSzetv&PW|i}91g0==!Zc5{pzc2@UdCas@nvT*A=nzknlh2gF4 zKGuUx4J{H$zYWW|b6I5Ga-mODIhV^Gh2O3M*o$|Et;l;qTEKC?%^__#8TvV-^(sSW z!dEaU!qCp(S68F{s*bqp8Z5J!ykqTy?!ghq&<8g&9!7$0IZfv&R=P!+SaCV=AH7P%o?xd!|OPDPs@qQkW%fuDiD%iH-&L z9;&HjBgfG>+>^N(R#pvM&9uc_#+~E67=sa9YW6VhtC}`I44pKz0%qv9@UnY@#|Al2 z-tcLCA)bGzkHQ$w>Car5lTJ5q?^QO_z}1ig4DFj4?|j$*SHxou#i()vq{@6a34R@C z2038iG}K+iB~#IrTop8RPq^=J%~>SwyAg9o4P3dmDWJ{-X?AE(aDI_-Td1n;&d$bY zGPQe1XK3nkGIUYXVuzuLhBloHZ40Zq`~XkFm|W#m?!}jwjt5mSWyKihf+fheEcdFy z<6oViZqR#_?X4>GR(rb==YEsyj!mD?)ZE~{@j4kHrdbm+ER8j1g1B}!=70KV>KpPJ z_QNL(Z8W*Z`tYO@{se8R``FM(c&4Z-Zo{jF^s^o1JW zo{Z7dqT<$B`n0QyJDSsY+B`DvKCNxJ{i|?*OYuaH%m9HuKKy_rg&3Ay-yR2_AB7_q9POJXNN3UM+Ob^q}eDN}smsE<-&sZhu_U!j9$kH1i_7?7Rf) zJ$|KUo}niJ#yA;Lr;4G{np*h`6*8repE=TSE37M8o38L*`m~`h1aAF3T+ZV7UXf~cUCk?$a;y71%}Rs@46OqKAm6paBq1}!#P;q<<^*a?WynA z)J0_c7d5S|7`oTc&jdrc;%0WR&v%s0<7(K4IV7-Ra5tDKMuy?iSj<|f~U?y=6myrYsD4N zyWI6P4_dqH+Z<5Clj+UYv_)iSq@lGjk5>+!25Y%}1_!m=5k3sYy8O3Tt#SEuo#D(l z^Pep>XlKB*(imC}GOZD?JEWB^#-Ebui8s;dAa7q#s@A|8!=crNkHl?~79~Quea+ecAh_*SxPVrgqBp*V5un=RsLmP1ix2tO>q))*LOf zb&cVz)QXrZ-b7MpkAvD`kDBk*c> z3~%a5^Bepxp2s(&F2UlrBt}14!E(GEtkCi-hAOGcH*hsf#*UUAErGhZ1<3TlS`p3xz**pyMwJiVtxYK zGwJlMj$Lo4&%kplu1csmt`(69-&CNU4Ebl!j+x`iZ4COxwTsS3JU%eB4Pjx&QdD90 z1}zV$=gO^hG&PqQdS26Zk7+hVF3LX4-uGvM^lqPbg8C>E`Ft;9Ja(v|W-#}gps7p9 z&{M%B_vG@yX8lQ&9+DgIMZpunldhCH7SQ6Gv5%N4NRRgiGvat}(gxJM;+DE%waPPj z7nr!Zc2S{2nB%_i~8xYbk)Z$=GY13F86kz2=wi(Oswa`36^`Q;2g zb=SX6)pz%LNI<(T9;=9SrWS|>7xx^c zX~W4-bwlqs41E_y->sbxR&!^**|cyuwRJ#kZN{sn>5qV+pA0=PF?1np;p)2s0lh4d zoeQhE{4_Bzt`1xfypHYm+~&du*YEJm#g;~0jB*+HSjY*#Q3fhp+<%Xu-Yl=8UC=F{ z?EvX?P46%aeHqe^5ktqr*IkZ!N4@TH!L0$U3AuLxl=0nNN*kb+(%q#rMbobo_rDl+ zcV~YvnBh`7Z@RlYwkn|A2;;r3skzM1?*V-WF?1+wM%bL6pijD% zSu(VIPP!+zN1w#mv1P{E=ZZO#@A+9b_B0t;-Kv&3*UVK3j9tM*OvPSJxW0$JAS6`ZY8y-mr zWU{%p>yLm|=e)A+s8Me~$;t3I)bZKeUX={}A~D^sLw=)^p-Sox)G$24VHHB>{%v;! zhs-+1_e%R>oohW6(zHe5o=Y^f6?u$g=qSGGo+tF%LDIv%;vklbFz56i`yb5r{5Q4# z@$GX?;CZdY{O9%dIoAH?ul6}mb3pvR+UHpNA8ViE+ZS2;pTF7{otAX|YF}jSfBtG; z^t;5j_C^0)?0?d=NFV8euEy!%uMmEisc3&aFANP#j0E0)Jujk)fFHXjy_DkAOAWBj zo^=8I-{Nt;ahQ3-4|8T7=Q|9`Li{i~;Bl63n5)1KV^tn!O^ERt{LmxxINx8+dvoTy zk;l^t&nEWZw*R^RFYkXQnF0N=-L>~& zHL?u;?0fP{(zW+I$-d|ODh_5kzf7~z+| z*;~P^Rx-;4>OVh?WhRtI5$AiR;rU14tAaO^3avi41VJ)TiGznKGnhOu;#I8&Vt+FKp5oD$tPeWl$TMjnEE_XGGD2v(kQEXS$pN_$auXz%YC1Dc z^@O}N-O6KLIAY^GHWT5GUEH@2ratF!tk=99^Y)PHki1@aDdN+VZJvF{Lb?~EJ5a|%rvO;}AiYXPvC<&hfx7Sstx-j=L#2=qhJ=L_l-I`tQC-+H@dsf5kbCZ+;+_vjn#Nll_nHKib*_+4i9CKiYEp z{{P2bs4ebwJIH?zd!dbgssF3O8VYkcZLgJ=uAZMMe&)A(oOuQ#4){U4z~i<(KOJ*J zm>cjo>uq|3gNnLZ>v7wje*rqZn1k~;-*3!Y;RnqgkK6VqV(BMgKZOj zc*-7UeNH<%6ryU1$8!s}c83!@&Uzm9QuyKNcs#H0`uK7I+8rKe{ja5df*!ob+0UdM zUtKKcpfq#mnaXwnzOH~DM(sV$b^&eD_G3BJe4pBfWp|Gk5zcQn zqQ3TcQQ_Owb}VanyoB&nm5SvJ9xo+)1!m5WuVVQvwT$q$FuR7iRF9Vx{wA#XP_ufx zyl~rI9`128GjP4Oecj*Vm4uIzdAuebzeRX5tQAr7c>Gr358*4a&>Zl172(#eKo*aq zxr5_cKLMe~s|&a7p#o{0e(a{(sNKZ-JH=h2>QgzcbQim>vOG945i>0v^}EbEACt-!)BFbJL9uN zZ`jhF$1IFLQ=<30K1$1Jc*FUhZ9JyARA!J@TwC^Y=THOfFV+i8leNKj2=m&auL<&< zWEsB;HmAIn(_ZN2?sn$04{|MKMm{?>yj^v0XVy}^3(dZF72g1+It2NiQrWep4`F7L zxtB+0o~`V{d=FS_@XQCJ)s~FA^CN`+N<%S_*aJSVmIA zYo7a`cM#uIw!=HBA7IDC7UM2;Q!ATFBJvb#B&O0C^$>+664w`^9HOwr$@QgbjmT|S zXAPKw@{YOy)CO30-P&h}!=s+SZynBxN8K;&R6bAU!)35L{?QAueBmA}RanL`%#w}m z0ESunpLF3_$RW*fgpA<+Ir!o7I4bvh4Zn#lybm=-roNc-1m_dyu~@qCiE~tdB_m5s zw!J6(8!=eM@fa-G_P8+bGuuq$Y$>r7&S%2Acf$Q=ox*e9j(7A2%zhk2&i2Es8+pg; zA(v5DXK{TWbSx;W3%PzkT@YdKhU=9vGfi3bxV_`ailr^LB%q9?uyp5{@v7O=WSDo2 zwJzh;#a*WC_wIC5)A3oaLtOr+rXBa)iC=wJLalWNV9WXeZV6+8a6;CExYyrBPP!9IDelE`+Ts9*b=%_BfeFBAz(Y zK7{W^@*J*Tk6HxOqG1`x|4-wb`A&Q-?I|9iA>M6D)UIoV9_I6C(eXd)b{>^^lkIng z*=py=M_Zf)^H*%#zG6@jN!Rr_<71W*Urd92kH=B%;IDX49K3|bc|J-N3JQVe_IRA| zyaD|pW%M|Yk6t^zkqLVP+_C6`7EoDyF8u+>zE5gJ&%?Lez^ZAd86}Td!F^u5d3Fd9C5bi`F$(42l;kI zob7o$Df}=F3eNN9b7y-VtqA;V8;I?of0C%3^mp62EozgnUE)i1WFp$KF)tOz_(V}x zgFJ@!*x*|6Xi(=wBUJ~~LCJxPT?+Y*tr+IEa;O7Ws|i?RUSf$f0y<@fRXL=_6dsd& z#l3PMH%&u4(kkj!S5r2^SWYcRi_1M@+_HH0zCjGey0sc$Bvbpz+VQhOwx-x4<2>DmR12iYr?W=N4yJtyB?ikWhU1{8Rj{3{UmsH| zuU$iWxBtVcw+oF@LtJRAT8R*^W-_iOb8y=2RaZ@Q$4`=SfiXDx7Y0*Ze6~fh2P}Jd zY_=9yeluJYr8di2hO?lA?TsbRx{Q< z??|gPzBja5i!9f;ZM?R&YYfxBF0I!XkJf9E1sk`~=OAs^7^c5+TCp*_8a6VtV`G?l z4zy%rX>TprV)ks@z5({Pv}j}aW7ycxrcJ9ynsBCD>Vef*;LrA%N+FaR+Za15=0PH@ zn|M{kQO*ZGcRg_cUk~ z$1r{F(k_nSFSWId&0It>z-jId0>Z^JqKAFlVi3J;(5I{AfSNa3*+BpamVnzd&P@HgpVA%O&!` zW-ZfVwshRSTw7~8-VJL_7qhA3c7DAuzPr`4qUXHxVf+Yt^joyGtz#_e#?ZQsXHV<8 z$ij{-m%m!r{gu$>j_Dl5k5+d~hgNry^Y8FrE1#lG5jljwBBQQFn;t#%45-fFS6ld>oaD-7BBsx5`R9t5Gs}G#rOGQFMctJ zKM(ywjM#YbeLlg9UtHqPh2=5kgS_}Y@9D)aA@S#6)Dx{fFTT%fdGSk1{Ml+YmgT(o zKF{mLFD3C`#kU?%PI~cuey)4${+E{cub|HeTOjZ_EScYYzTJyoM&iGWUMA*Gz4$(V z$BSQ9;&T*Kso7q9pHKGUmy`G}q2;R72rs_R`+M;@-xM!nYnT`F;`_Xn7r%nUxAVyL zy!bw^>cy`p@$LL_885!i^Lz1cmiTtwIkOkv=h};3N#fi2=ri47_uuD7!P6if%g+Rf zZ|AA^dGUR|)r)_N#JBU;YrObAf7gp&S>juLx>vmTKA+^p=X_kejCdped+~kV*NcCf z#ODkR+NoZApSSYjb6zhVen_9gvVj-h=L@{@p{m4x7QGtOUtWBlm-EuUUE*6k!Ter) zpJ(>sSCjY?)kG{Wca1$SpZ^LTJ+JB#-_C~~^5Xk^w-=xDkMS7u7?0(8FTT&;_u|)- z_|K?ku$<$?_xX!n{8|#<&cl}T?ptl)RuAEgSb3g$hwyhXYK(d+mQL!O!UtlU8PDD0 zb%k3!$A>&#Pxt_Msl`aP$LkBX{^sxYcmv_qfBYRDZz$aQn@{j~BjJ59x`WXKk2eFcn z)vw&<@q2{dk1;{m33|MRaI4pm;_*b`)^GiEkGB-wL-oLNsK;9g?+$G?v`anSTDaBg zsPFMM!r7CAw+)ZC6>k03XZLtJ;nvUnh0d}2lO((oW-DOH>GAf$tv=~Sk9QDm^+1<< zyrXcdH~N~#nQlDvn|Peb9`7vN`m-PE@h-xx|N93#-c`8um*3Xo-Go~`miiv&eT>JP z2k-069=}&O=PHrkJbs^W>;GPPyr*!h_j0^b?7lG{#A76k`S%--_Y!XPSU&MM^I1IR zviUyk@;LKlywgir@9{pu>!>_xeaBH`+&f{+jw{|NZczlU)Yqzq*<1Cls;m15LmKkIH>(r&fv!JiSek%Pov8T@Q zF<&HY=8HafGWwT0o`-h`}! zd;>WL$@)s1Dha6#X#;r(G79o4WF=%fSjnoNH@q}$Rx;XkdGicAU{E_LaNP)Q$rvhKrTRTpBty1gsgy^ zgWNI?*8*7#`3X{dKGKA|4A}$8{u=Ik1|vSP2O^vdnFu*?0keqsSilT~3y%uaO1IpH zWwy^S2L}iJ-0vV7x;Yob7Iaqf6M7Kc1K z*68avkN4?yjB(Q}{PX@i?rmVyS#OQy5EmZimT$V{a<|;$mIvLE&#`bEW*E@f3GiMt zR^wc#iIiPr6{Oe7(CgAaX6OyYmXblJ8p_KtisiK3pDjs-CQ09nq1lSPXNDFk<5F)Z zB{*3_#WpoVQ>9jAsEhP_8CoDUNj8KMQLnUySIoB1%1MH@bqCDbcY?-C7u3hyP>1)x zyc%1X+-rhje~Y16iX#IIEmAWuM#In#qC?I!Sw^t@VA+yiY_wP^6;y@f#}ciu^q{!c zOc@JdXr;=4tIduO%fg~4CyObTq9sxCmO*LFA4_wq8(&GWF4u_N0U8wJ(LP`r-4$C{ z4E0eQD`V(8Ddia|quAbO=sCrn8bdQ=?2n;SinTXWY>T!OTQm%JM?3Okm-@ZZ4rknn z>at7yq)Owqc9PZzDnQ|z&jO;)VC7%H#WD`aT8 z)I$uFQmfs*?G@XoWc{w`@5f`FlA8L=H%st)SF!(SQyAd(Yoj=ZME1TqeUBYiEu;#m zW#dDX%l7i(L@Y#^@d9apd3&j7i4a(#6lF>VcHj3Rufq!|F z*fX|I+1fzdEJvxN*cRiROoDzA+jk6iL~EO4MLfzv#Zg&?j!V0Np_^4Rcm1st`&MKV z6?>HoO;PMOGxVa2kT5hyaZHDy`O>Oles1<}yd!MM@r+udUCq`c!|jm^*%M%D5B-1a z-F2MQX7@M#WM$S}X5DA8;!-H?Qk+E=cbCQ8-QC@_xKp%9fuaQprKN=eg;Lz5@cW#T zgq(ZtWtsaczvubmVPA*LymNBp%9TteHi<&}M)Yd5LPtgD)dFRvUibBU+$BOvr@9v_RMSIa*BR^*UE+Y@9l ziW|mZ-~6X-IvS>!LR+&meYG%;Y0r^#tU~*8q_q6e{t{^?g^r-mt2qiC+o4zU6*@{t zuU7N%V|sN#d7{s|2g+Q13hO9zw2AsIRA{?}UPUT&B!ynh=3_|oYJswOvbL5jt!&1{ zJY@3s8+eO<|Ni?8&9&{W1nks#1905qpyt|k;G>Jqsa(7M#8T|zb7u7XVrUn%acAw0 z7APkLUjg_xQ=N?p4HxdpPWSo2buz-e*vG4r;KhW~8WC6E;JyJk9xgnTy|>yQ{xZcJ zZzOv++))VE3kk<22L5%xy$P}Y7f#!?xIzT?Ai~+0PACUm)W35kcJ2D5y=^`|CnuS< zk8$r6+(!YQ7Rtvv%BSOOIO2}`v0*=5IBjR+2)ybJ4>CO^7yC4<<*+^6@nbnDbUcTa zmV9$9JIVDn|9MPVR(H zZ(rS=|Hbp-$vU|D0qq}v8Hg>`LA0OlgkL7ne#tdBE&DkBKdCah&cgk$!vY^voxMFD zA9#s;!)d?H8Ef+tbX~icPW#2!LgVM)<)HfO^M&?{o$;;Q9NmU3&G}M?UE9z78`EXX z7usKS*7qNe38(#HXFkt}{W8%G5A`Un(i4Gui-7& zwd?1*38(#BS6uN)#}Qizr~O=4JU0oObpNt`(EQ)m51Rk``a$!5Uq5KBtsl&Nng}cx zk%&;Nm*Ua2Arh6fc!t6j#4*Hq#HZf>g??`kK2|fQ2wsy{N4FW`7`|BNpt}Ka5%Cb= z6k_HZ>j99KmQUkhP8x8hU7#_quy1$q4t|D7C~ek#Y9t}%E`wh`SO2-=?BubYu` z0`F=3L*uZmt#_&3HxWj?sSMd(M!D1`7oz|5T0Y~tz9RVG$m)U$GOlKCS$&#Nv*)h1IIKA9P){9==<~;Ct=!88y*v7L?TtTL~em_CI}R zP&-ekE3H4QmMsT3=EwU5(L7&+U$@(I{x0Ou5amwMCJl&rfehqt3_i$yv3tX9*UCpC@iF*nc<5sMu z)=-o1S4*vpKWfu@Ja-!6?tvZE?zrk=q&h*Js?JjX{~8Z{H`DZw#WfBTbd{Go-qVs| zE;HIIx_=^?1WR{W-e&KJ))<7p(P#}iBfE|7q)7Kt+=Dal`;;Si66o*vyN8wtP^0l3 z602szRdzY?mmBSp4=q!G@3&kSOIcC0Q8~VgVq3JtNR{rfGzP6P34hcg|7XTZzb&Tr zp?k4XOu^@h+9w)!iKh8C3e#o0qU+FTd7;mLJF%?x6|b}4b3mUBx~l$&{(n7vU2zsm zQ9J$hk64yGuq;w;JldwAs{K#Dg9(A9V2ffDmiAT38npLbBx<5 zR0{g;kHLHT#t*!+1$STCl2-vD`@$m@dnvKMQEeE6Kp z*W>l|O9OoF$D_Sy{?d9USk?Y7iq9C$CtBJmwkK%IKr8G&g{j*AwEaXm1#oy?SI;rpmuD9`9XK|OI@!ltbe^qLfo9T8lDh8=v|O!SCxRcIxe$`g<((`~3Q}oKPyM z6dCopRK@zW0@{w|(GaZ3rlHIS_@3#Y_EuBBr@L_nBaeQ$wp`hP>-l5U9BLu8jXGML zsHUy7k3`c5nhvljqmc1k_TlKJJNXxp4wx<0o8pkMn`Y33>j>bWIbMNq)=5-W4i}i39 zeEOgEPpN-zv>iRYgI?1aq~Us*neaT*7ATX3>&Bl4?f>QaJWTz)o%;O|Jume(PwMxj z^?6$Z-p$Kx?Z5l@{3W3LqE5w}N;v)Z|Njlk0@as( z6PecE3tz21bXGd8zZZTM{_Zk<18Z;hg}+uVUFDh9UymTI|8P9zKCQnO!PwEtfG54V4#C~bU+crHjdKL)0PaFtqSU{L!}A|MvTTKmMof$IJV-pj!B+osa$Zcns0^MvCq{w+ydffoaXYscs2CoY0F5uStdXC}^pmlLiXhntc( z9iC12SDZgCaU$GPxPBZiaSZ&fYED-P&L5gM9DY`KY4$;hgW=nSW3vGN`X%;7f$;{I766N2|i9ZUDtpsXA{f9 zy9gh`UMR5`ysmIM{)sKv#INARg->G7nwSfoS@=x$#KbIcf8h(*qY~rcFF$-dj+nB7 zJvcD}epNVKM}Q?fF#vu@_;z;ZL{IoC;rrO%*&N`Lg&$^rVS8i4To!(U{h{qCyoK;{ z?00PU;Z=oSX8+xG3tmL{HTIuv*Wg)%-(>&M_7gl%_+RX&Z0F$b-ka_4i2bPT1pGJQ zFW3**4#N)$f5*Pdwimu!IQ?!HzYDYNfR7UH%D&FF5#B{O9T&xsd)pd#J>h}u3vEl` zMTOJvk#P>uHXj}*JdS;mZ93dVI38t#f1_;^;P?J9r#A=tVA}}z55jY^53mh{uM>_N zPUBx6TVMEe;rL+({&lnUg7+6*g1v*SGrY0zGVE<^?cgPZS72{$YYDdrugu=q))ej{ zT)S~&JzE3#vv=ln)#ChQTQd9?;q}<-*y_NK3UAC_+g2OCMR*JLTDDs76~f!FC)twV z(}Z_quVJeJA11sjdv#lNcu(QI*sIy9!5azh$6m!&1ztkk*(=y8z;6hr^Hx}2*~-ID3a9g2_y)0+gYOW&fW54(EPR3RCG4eb zrQw5wuVgP}D+O;Zd>wm9TS@rW!Z)#(u$6#k6~2Q#udM*wTljwVFKoHskKdTndxYI) z%LM;X_$l@XTO54fYvkiSo$or$zCU3>EZSY9AMaxej z#}nxjHp7eQULU_}Imf;!VH5n`tB>WU{KUREVL5!K@L$>IBrJdr75)eN)P$MvO2YqS zpO7#K9wPic`^bc`@Eb49@jhiAlrRk5?1kA5&)8!VV&N6x`gA2fXOBvVf;&*YHoYlt z*}W3{;D0-e88~f(?&G5T$qdxBJ z8{#*>XHmXhA7Azb@k`*Xga@+Ej-LxJDLjmQO8g9Xl<+9_@$nPkAD)`!C$Nu*9|QkQ zcn0<%@k8PJglA>%8$S>}Pk0XYp7FileTC;^Pl@jaPZnN?y-j=v`1Z$U`xIt>ANM{E z-^*~LeTuNZje864V0v|OXXQD2X>7;R`RHEwy-`v2mvJwV-&A-p_E&MQ;KPI$XMY{{ z8ooey3HCQ}Z{QiJp89+#$9^;J4%|g}74~1^uEX;^GN-F5`_#Cp@Fx$=a%!;;jvEgD zQ8*szgmLwY8vx%TyfJ(CxZdz7!ke?F#C3sp7T%V>`mfY!ZQo+$zC^( z?z812ygz%5xZ3c4?wiv!fc;MFomkY9Tx*}s1KEFz{S7`r_#pOcvDe_qaAQ3~Zc#4B z{tWM@`&g`J2D4v@y#g;`mXk7){dnvtcxK__*$>4Yg$D_r%DyLdKm5brAM2Sin|*8S zPIxnNRa;NaVQ&=M2p%c&7qM50tpmqwnOcHz|xx($1a+SSAOc{75;lHyNiYW@OBK$Uc-k1XL zY{DP2XNt)M_Z0q;JuW5@e)msvybg}E`~=5D!-w8B>*>h8IC?S8r#6Kf>k}vT1CVNdie+8C9XZHEg^O0XcxP^UQ^gMVz;V$fRqvyhH!d=BT-F zdIIuq2=`{67(Eg0<)p1wDc^^EQuHKvA>qF4lcOiY^I*Kjdcco;SoAQsk8pqXq0vL( z_ivi>D}cR!bbt66;eqUZqx-@)2@hiL9o-u~RX9$eV|sf=_k{Nlj>`|=-J`q1>k7wd zd3e|8uJ9tlL)kk=cZS=9)BXQ^l}^!};11-9w*1GiH;iryzxIde8QE(_*Msj9o{hb7 zbanWA;d$B1M1Kt*AiN-Z(dd%!hQdp-=Zh``FDkq|d-mwu@Mz)m!*E~47X1bM-3_yz zb=ae#;LwHB_Mp2F6ZQ=Uow>o*SQX{G!ypg^fp2G6kiM?i2O?YqNDeSePYEk*ZJG0l0 zstw;EybF7ss5xhYyjlO0KI|o<%EB`UAH-fLsuPe*4%yDdX9*M&*LLlI!0u6WA|BUc!ZSyRVt~)7TG3eh;4_d=~ru$b<0a!WXdb zjQkd!SNIb4Es@*cR^hAI*F|oGzxvf2?^^a%k*nbsg>PbC9Jw66N%%JQd65g?GlcJ9 zpB_0I-beTW_KA^G;Pr$bWgite4qj0BarR-6!{O1w&#?E891M35{v&&@$Ug8^SIu_5 z!2UMkZ3K>2kn5lKpV{w5+=r{ee`UWFaT|W~XEXl~_G=M0;75i3$$ll`D%_o1pTBq5 zCqztu@48}^^MJiy#31;1;ZN9mM)Zbfy=<2Al-)bR8-D#Kvz*uL@92_vWv}pe?61OK zhvRx(;SNspxqBS`9NtT~3;VtB2k=_Lz1VMt-+|{A?#KRH_;t9ia4Y-e@L%A6Uoz_% z!G1pcBK)NAIQEm_XW*-aXJ9`P{yjX$MYA0;veyc)1&@Ur+XI={YlPQ;2MEv1UM;*D z{Nja=`PIoIm2&Js&f53mKUn`{VXqKg0r@$Ff5HBB_}B1S!n3kh46g|9Bs?2?rSMAd zF~YO6R}QZXUnV>UdzJ7i@B_kgvR4hS3O{DnKRFkBnea03esE)X&d;7Vya2q8@FMKl z!gIlM2`|N-Av_D*LwE)DnD7Mn%^%J3tFniNN5a1qUYp%7JQ!a8yg9$>u&)bShZ7AI z;l}(*W?vn)8eT+rUG|k>E8#JwS0|5Amat#d+s8+B7+jBiS=ch~(dIMENb*r-V&Gei`Ad*e8cghUXOCntf8(BzTxvesUZ3abe@& z%g&nZNuE_1!Tv$_IE=R~``ECt$iFVU9s8KDG4S)k+p~`j8x21syaW5Fuu<@h!aK5$ z3>yibraO+OC3j*U8a5PO7H)iwy0do)>j94v-j}^ySSR?qGiLr^_U2)&;a7wYXKxhN z1ini+ei(yxs1sHnK1=vS_8MU|;eCWpXRjDm6<$yHeD;!I<>9fX&ClHe_Di9ca3TM> zrXSlsc_I6cp+CZZIc3&=Is2i|qwsygSF`U8-49ec)6S4+=znNLS3;T+Y74Uq>$6Goso#MqlJ!CfAOSm8Vq>w3a z%lBse{n;~xWP-msW|kkoo*0q{-wwxHE;aEIKOk$tWRF{r`DJ7Gs3@Ozi)j6Un{&A`)%uA@DajG zv;S`W1K#0?**<01yIZ@%8^VqGTb8|xwF|tm>D9?|DIM73^zXZR_`WO0-pSet`Nf2n zXHT)Fz#9v%z~0%~8D7vVKly9+cGhE$;;eJZiH zw6;Y49O0GOTUlGd_X)4U-rCw4p0~}%@{_BwH?=l}KQPCeT#dc4wK4o>;q*YWyh=lB zL-<+YHQ4K0>%$KTPhziYtqb2Oye4}cYaMtq)2owzsgz;=8TI$aa@$UIVE;-fXRU?& zxB7IoM?2I){#Qx`YXx|`i+FBFd08YolJ0ia}du3~7_zK~5*sEBpz#j@v zX0K|k3eW3mmQ$C#nzb6dm+*S*)veXx2ZYyWuVJkLSKQ2U8n7o>li8DJxbQaY*{#{(i-qInizq*b zH3$4#;qBOST64nB3vbV!%bE**Uw8-h+}7N1#Y1Zcs%J;`Jk~t$0O6h3zqEcy<(t!+ zoWdSt4T7&Qy*ha<#fv?MUd}j_-Vy2U!n?5hT7BUygm-24v--jN3Gc@4Z}o@I z6W*OYz#0JGD!d1KpfwP_$gF2_Pj*+UD?GR9N#qTc55eTqb)Sas&0g#-Ru}ka;l0@{ zRtvnJ@ILI$R%dt@;eFYitWNM|!uzp1S{>mvh4*K7usXmi2p_<%T2*)<;RD(66G3>Q z?zG)Ii2YsgyI|bU=8*ZlHiG?L@I&|!;bYiu2j78bC)bZ}jAdUMyc8Y_H@>IFu`dc< zMCBhe%b&tNF?cHcr0^N+V}i%QHw&M~J~VhFe3o$Bt^)IAVDKRLAmPi|dj|%c%^cwlsh3{s66Z8iDRQMkDw?S{=Zl2obm&*B;{aw&I zc%nJpgus;cU z0{>a~LH5T%kKsQEKg9kh=n?!|;oq@840;IPDEu({gP;fS*}Bv6e1!e4pugbt;CRd1 zjVIZ!1pNvxCj1Qhg`i9DMBx|NPX(QWdkDYGemv*|{K-DE{A=uof{wy33%|j>H)ub6 zm+(96+khmYCI29k;BGpL&q8)Spu`_^=K_VA!6_-Wz3?14cc@QuQQ*}a1N;M0Xiuv>!M;k|{& zv4043gf|hMk^NQRJ6srCPWTt>PXnLBa|zGI{&(Obc)0Mq>~{k1!vEQ0PFF$p>w&l6 z*Myf~zY=&2eo%Nh_Va<4;7f&9VLuUg2EKT=`MIdd{$=2o@VjF9sm7isFb}*Q{`-13a(ry6n+`F>rt3joCv2Bj68qndRUki1`>07zDo{9E$+lGtd{lOL!-COQ0Kk zq44hP9|9cV!-V%{e-rQy8~&|?4`hED@Dg5L_)zu-0gvEc2p`SKtBzLPyuz!&f(!m;Yb{E7=m zgpU-CO#paQKs3C?HnV-OX#-#FzZyFnwc&V6pX+37Qo&dFuYku=zTQ4K1OlJ#KO62P z9Ea%O6aA;apKLYrap)aB%6}aElJG0+L;Q!s_Y41xy|4d3_)6h_u=nuq1s^T^E_)~c zuJE?PAF;RcZx635`~`bs|K{+V!r!vj^=|+V6pl;UQU4nLwc#%?GmLh?A$fRZ|Elnd z!m$YhFYEs`e2ee^_9FhJ;0uI@vVZAc5I#zH1bc4(Jn*i<2ZD;RD#W_-=v6m|mT{r?Q^C zmi|2(@8B?aAp1t&jmU2+d=UF4-%ap=!UwZ&_T3EkY-ZMT2>UwUb@03E&G|KoeXj39 z_*voO*k}08g6|YQg?*y$RQN*S)7i)Rj)RX9K9_x%?j5uD`TBZk3;P?N_dfW(5Wa)`xz9^@ znDD*q4}6}$U4$QEzvFWcet(@={`c(HeQv?e3qQ^Nv(Gj7Zs8Z$fAskYzF7Fr>_7ON zg^w5hJNprz|6o7pa|qsC_+9qhKKtNRgx_c1=CcEySNK!*^*)>7VZz_Aukcw5 zcNR`J!|16j^jQjjxYle3C-yl$^WZ-TcW0mKGZVf~xG(!SpGoleHRk;FW53{i0YB^t zgB$bLpZ%QoIr#0>A3ce@k8+CLQ_nBs;4p;lE7V6h>wOma|LFPTf$V3z&%mDu4`M&< zeH#9=S$=Xb`w8z8@VTZZk@r`QvY*iXYm{$gKkj`T`MZUOuz&CUJ$#MuQ1)Zq$Kcb= z@{_~Zzw`bMUfuL0^1;eJ_7S>Q#dyQn4|yL#eh=Xh><7IM!rKUsWIy120A5dc6#IVf z{qPF9)AxQf`yTH-aA(u2laEu@vrpC6OSP~bi(%jBy%G7VgvYXP^4$XZU{Mt=Ql315TC*@4)`t>osoV_GY;` zT^-q{cuj%dha2mMPV5uCCc@WJzCOL(*#~$HfsYa1m%XP~U-^KG*CVe7zGvaa=jaReTpqdLC+C0kB=Sj0R(4N4e>%Q*va;v&$cg+H zdOmqJ_8cBL;J1WlXV31D9sZN>9PHUVvcZp-<4w-Vp4lTaJfrDJ^JmTP`T6}Ehp*E+FByGO$dz>VcOg+0PO z0{(oqS$+?84|gB<8R31{E$*)HCBg@>e{gezcN0FG{k7XWbSnxU%l^de1-kLVC$azS z_7Gh~_zd=2Zg%f8cXFS-FU%=V}Evy`lEv_5!0-E9AT?3vwYJ+uyP zOc#|qO9^$O_1RG2-?In01*6+k_-S@8H$QZX3ICDZ#mybvaN$?j6*nhzpHDN#OYJpF zdFM*&?_Y#d`_59HyS|1W5`LTgkt=;a%oqMQ`(4-j@SegSvEOvP4bL*wY@f&MyP2r}gqIrJ+k>_;KL_*lWAggRc-iguS{;61?*`l%ubo zhq7<6;Ep3z|$>B77|SLLKSTNB*=Jg2 z!e0oVz&^`@Rkjl7qwW7v{zUfK7JTI>nT1bcpJTySrgF-huH?z=Q!Q9kDc=d7!akX& zcard_?4vECkv~@WH1?5}k?=i9l;YTrX#`3(6{jT#}Owdj^ zdh_w&{p`1$Z^JuLzP^4t!hX^D3ZR_u6YOW4&%-y4GRr^7KE|1@LshatbV@YC$WorlBQ2tUIg)>t z25z*&U3O>u!*-78N#v^)m3^M>5snT+{$h7>rt5+y3ctth=uFoa4-!t>wW}2eX9sv= zv;5@y?C+i4@)^O8bv){&Zd9i&(uCEW@urG9?>(gW5#&o@9 zpXW3W{_`-i92MK~tCg`%biMpe;ZE!$okqcD38(#m)yg2JVep>9z1aIX^@rCL9>Crm z&p*d{Rd^_SM?Bjc$AyGPv$t}h-zzu@r~RMRN)spgea4?d&HB^++iIn*6aBvAgmBsq zT&*NI(eG(C2ð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%0DSgDd;;Zm-VUBCo=@^b%1uxqz_@grClNl1(^0P7 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 z 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%0DeHPmY?Y-|i( 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 f~cY_R?qZ7PSVuqbw>n<|W=yv;XchuF>yhMt1 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

    67w_3G!^!D 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%0DrPnA^OV%^n#;j^=YF~1bB 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­>fj(YvY5}_j%=df_lb>sPFd5^$KN- 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 z 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�_gjsFs(*iK8w$NpW}TVWOo)C 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

      Bf%O7Y|#Nf?T) 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 BAsB9yy0z^2_mF$x#M92pIGU*xTPm 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

      1Rnd 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

      q@j4*T1-Hup=ugydFk&dVGnAC}l zmT3z!Z_1a)-bX{Ph92*yMj_(tr0P7`EhAOt)HQC2yC!Ox)l>H0CMKbGezzQLtLBCK z3t0PFgdhW^-=ajbM=Z}P~7QmQSI@y^JU2z^MNQBKYv z(Q&h*6B4x6M$d4v(XoMYx zT>bqS{Z8Xv?VGCZ(uq^b+x9|pHhsB$jd;;fiIq7UDQ zx+Ug4Y*1?i%SCiCvyr(Lim%6%kxsTIs_wV4U$fI+m4YPA&)5#8&~0Zuuf5MDe|2|C z%_koDh#cCWlxrQ*rG-Ow{jJlvTwmwaifdeNrB>r%&MV#SW0~WkqXoRD2#-d2biXUa zS~CqyQFic0iN9lgpx*mk#1~Rl-9LVqtWw*1&?Sk|cqK!7WVbO@A4yOYnU^_F^?Ro3 zy?s?ZuBuI^{bw=9f_2!zzSE)xrycU)stVU33>`f9kD&58Uq-kJm+-f71mAebO5=Rz zlqcBb*{MKZ`#=4=1>x=tRQX%w(e+}5$TUv8W;vr~8QGNb6zB@=?LNRMyYNP6YdyVN^-4vX3!YZXx` zjeZ>{&uhBm7&@WI^yrSB`;2Gr3Ob~BU9VJnh`-G2obA!iiHu6eE5sa=A){U^BBy8n ze=!rdP4S#b;#H@Ua3)mz3xSHiVcuUuG8~WQ+Vm3W7YWE0ss4dLeomPB&@2x z;6&-oS;E#$X8@~SDP^g-x-0vZf1Jbr>Bn4 z?Pi7VKSMoxdtCS9*ytJ!+B(`Lw|8MHy+f6=DSlQ4*F?7$Pd#5g08D2}WQoj+olT7F z`A9z3*2m{e#F$a@XQZ$;k4r|I7%-J0KEqz)&$ql&TD5b@oV^}-1g0vC#V8+gfo1GZ zH{2hFUHOMOnM$R z!gSxv`878F*0}ed=O?<&w^e~f`^G8))H=14A z$&cc!=2#*l(J$ zN+aEOoAtY__k@=-*jBHs|6Y%Gz#VH5#E_j_f_M6T(J2T<#eh#d*oK{-x?R*{bsQI)dN{ZAo6(de|GB2 zTycVZW(wwqB;d1t5BA7S`n{csgXeqd^<5`+PSN$39L$G7gRiJCMPjM3+vN^EuD~G~ zwAZb|%m6!K(U|&PiBrKTekrXx$S|7gbc-JF$OnIw->e%{xvqlY{)9|tI66o>y-(y@ zmkTz!Wok2*1U%5?{R6C*L0iyWRtLvgDOm5LZ03*QUMYm0(AgY6)YXx_M(94Yl6{OtrI91tVZEI2Oqa`g zW?kb>)Ny|>^ff>D&VAk5`j#y;qfS3{AyqGv!<_Qxb}L17{WKN-Kjzrm(8nbMm;1J> z5$Z`t_3jnr)OF4rmCwJ?MHm#@o7~~taP~NPs(a)N zyplzIUaEB^Q9Hf9a~J>#|}MSj=RvY%yY`%0agfg z{WK#`D%&uRzE9P^hUl*i%J`>C;yqXSYll4FPR2P~7Oh4Pm#T2oI&a%fwP)8~z-&*~ zZNK{`Rh|{5{^|;tc!T2K(sg0{?}Z%IqN){H+h6h{il~b^CXq$YV4=>forrVV6j_j)r7}j-kJiI zuYrlXt+K%*8BA<&7&5F0>{VOM;(VO84*4d&ZysZ6G6x>U%~$I)bYjg#VvE3#dNOv88X_Sa~(B4KjP=o5S`yQGXYy z$l0*TR359J@XDyvDvWcROA;f;v}ks7>zBIrVU9R4jlRIT9+_4bb4Z+p*aPhFNYeaH zDGG+TFS75u4Fe=_IC^!~itAmmp_r`e=7*Z9&rCkb`DpABIxPv7#b=$8ZiH%!{4>D; zz<*8VGasKVZ<}E2gFY%rs$f|#UgsdiE3b5f_ddK2pMlSv@&ei9MSO1MvCZd3=*n}| zyW%KCn^%HU$gdfy}j{E`07Uaa6mf2j4j}l?op(i9-ek>G8RL zhwi&pKK^F@X_rEU8A0FqX}el?OSBA->7(>mwZdE1^4(ONNB=O7AValNjiNfg_WMW1 zyCvsgRaX-l>M>q5rVjrxGkCePoKJ*JL_O9%i$YC3mG$4aE->fX-TMNthvLln?(Drz zI3*?e-yieoInf^H@obm$!N*yzPaw%QCQ*lfWA^&*YQ^gQCt0 zzllqJqz}J|=aG8xol*;Vwn2V{bf4*N%VfWvnkOr2?h&oW+2iAnjr3Zl^_MO))ZO)q zgJeC}6#rg0S-9_(D&Um*aw*O@A-Q+{f!=6WM;BKjfD38YyeRn7wM zR2%%gIBLEMf>8r0%BcA68=mxGOoj{ZR} zW6+r`UOA2q%AoUC(eWT}x2StPRgP^XJ<{HkuNcqTMVgNb{o$1t2e2){FI*Vq8Zp-` zd$Dm%bxyar5w9v(fi~>tPA_vv3G`?N6?x-#4dUG39Q*$RhFsDg9eSe%9)1PfHeX~yC0onOL)5?tTyuL)abGu}?DbtvIFzPsM1D|TAu1)+T zdkM}`ER7FsG5iXyF*)fuu++GR=>CSB#}DsZ5Ca4gYU*bFp@twr5a^4sCYTf z%Gl$f-0Gc%Ps2C-9s-|YP^p4os*tA}G=0kFi{v)fn~9Be+0_&Fk?<3CiiIBG4tpev z?zn=bb7z12#(Ct@QqIN5Z9P%f7U+5nDtl0sF^D;~A2xHpp&wa}-NK}Vs;z$+iT_LZ z$}iCkeE3hegTMD`9w~)fKBBwIYYb!{ktx|*ciCx3M6 z{2OtD*w_6U3tQ5W$S7;zi?j#(mILq?E5M!Q36$bvyi(=>wo9jcY5VhtJ?XV9s=p+_HtEApoa^u{c53jo|XLxpEm_s7);k>CryV`oErJ+B#Y zobV}4e+tA-%Ok^HIb~A^l~O%$m5;)sPu~bJjJ3JgdzXB>n*EhIFV!im`_XIg35O=B zHtLA}BLn!tjtzBxG15pl5WA6Ks@`gYJ9C+Oud}ZlQaF^eW9h%MtFac26v@p({>yi| zuW!BNmc<>T@6XT2I;H<<;|>2#yKM5|Q&$|4Hj*sgh+VwAsxK#4HFtk-qwt2ewsHpW z1cL`xeP{$@Hejdj>lsZuhsVfyzAuaJ3mn#VY@iIv+z$WpvGq7G?lq@hm*3`*%IuHw zoA!XleS>nGRM)Fbky(LzHmIP9K{9@C#OCKqR1q_GiCXUgxtaeb-JkOnvI&kMK?CLdSwRpAB-$qTVJ> z$@sr+WsvNjtDZbsq^>itKRW*ejK84sW}J1ajt_+d>;7(hEAu5UdWk2$u(WYhP2K{)BN}um+$*`0F%Pd*q3WOa$m;%1X<*_KFXrSdviJT{ zyp4+6Kbk#2b>z6g`F;D1ky_gGQSYg@sP9&#{ABNNkxI#25_cSDtdCT6Ua(7m44H>M z>o55D!M=0K@6+rlVEa;1kByh))1o0ia`wwzHQvI({uf3M{9R+@TGW~2C2~jXUGuVj z{||wsYk>@MH*%-Z@HcZtvA_Rb=f74)kECS|$sZ6XPy6Bv-KM{e@io{RWc&NkhZSJY z^Aep}RZ~`KrN8QauynYm*N|dhD(w{agYNTT`*q*5hcSLXoT~a%$@nU7wnN}UB)Hwmo<(!WjykNF1Fg-%7AWZ9sah1Ong`DCipOl&|}L;=hk@6 za2l)g`5qnlV00YcZ-t*{=)9ioFYOo$H#Q)@If2}pF_Z^CK=#rpt7jy!HM&`aUq{tt#88W)Api6(`niTPLt8j%#mhqrODdk~lfPk8_e%sx)#j zcJ77am z8YDSi;)|Sl)*?qxpq%ODltav=7L7rlX3_e;)cv}>ee211UTJ55M1XNSkH4LM;F>dL zQf+%2-Oz|-YA!UwC1u{9va$s=1<1OwJ-r%NYj@&K$4ZG8fzSN(b--^$!C7+gmwjp)zMK!ut*5e1MOM9dZ+y`;h*ehxv;`j)E(^`~eIgc8Hsd zbqQXsU{kLg{@^eDI;sA*>#}cO?aqFosLfwML2=51qq-gHf@O%=FzPrjotX2~(&=zU zE`Mgtx|&Vpw;}%D?KEYKZ-23##SK(_`zMT-^Q=MSQoambV{R?;PCPWO7&x$5xB)E zlhBj7!8tFigAPA9P*%sIFSqbYqXr?;_ItN{n99D$Ci6DZD&CUwy#G{r>&Beqe}X+V zbHwC{PH{{F+qoMILLH}6j0-;$;U~wLr!Kd4%FPc>S$#EF(v|b=Q%0HxhdX5rI==?y zILKZJe}mw&E+kTIG8UbnK`)!>KHDp8pxlIa9%{CEA=Zh)oSQOyANGIP0QhxB_S;H_ z|D1sB%YDL6cD=)9uDQQVI>g>}psv^ApYYAL3*6irY(ro8%P~K<6#9{~*tTG!NPXS& zcT2Y=VA%Fxw-1iOphCu6%Kq>8nn39VUeBQA8<49|_6TG$d0D&dw6Ag0{*)8EV|28$ zB6>U%17|(YJHjh#z~|R6eGVG;^V!C(6|NC`!CVEsvLp>>a=P{0wr>zPt`)k^Tj8zi zyxOW<9%O&z-*B!)GBw_wl8!}36R9$cG4*uTed}7n#7Y-W?Uo{70sYuFT2z*PQ{for zkX+!5j>T%OFUY>$pb4fN?c98SSp}ZLqCc>avuFyqREyr3`|9w5w9_{kzqE|L!`??u@URu-s{N;Ik%6t!2_{R{L zj-EC;iZMX-yUQlN#R!w+qsl`}m(F*Qj{))xd*}pLoRSB9*|MLbrWgJwSW2H4DbGCJ zrx53AGS3*4`aZrKSR2!pb;ys{z%E+K**Gn9e?M7P_p8qlY+p;8sXsG^={7lYhBK+Z z)^Tpv_2oNv(7!C2fj)30xSD?^221!K_-wllKYLyEZzIgtEji~B`>0CDn&+HGkJdCi{Ovt(Z@4oYwtv zbyc_YMAvPn=^eo9fTxeK4F8(&_0S8$&Z~%z?=RX-D<-*v}e&fZ{tk+ zxyS+j)bUS&y|&XXWY}SU=(gVw94wpB4_dU1HqOX={_-pAG^)BJCc6CXPXpwgjc;E2 zO4mo7MJn#rDmqOgttZ&S2E}p7NpM!ruubfJ&p2~9L<+HQz6S>5aeHvB4MmcpV~T-( z=|KdT+`;s%l}^E*ximo!v~ai1mzBQ~?SkbtzGDpPXX*_npvyXW!y`+}1WC)2sxNu> ztNvDfxbAmGoXasdn~5>{YYzC}j4IFBQ-#RsP|hA53BF_)`c@leVI3H@l`VYxr;$#h z8mf*9jqt5stLd3$mP*9ef&e!QLt@)Yvl7ed(bb@o>2S|^*8%lCv3May5->t z_@6yq`NQRqIc>o0F4psDQh130LsV+*3vfOk^YHn4Y7XgLIr=$g%3_h>Lv$J$VybW( zdSknHPv19E&Fcx0(_nV$#RgkjL6xT`Ypz9uSzE50<(#}a`dwFX@Ra->a-Xh2QryI{ zS>dhgFnIqj(RpO43qGm-l)eai9Q;)s9)i6t?H{+YZr2>x%!PsX=y4JoQg9LF;Tiuy zZl8lSdmb{FRW1DFH*DY9pj-Wcvk2RmIMB8C*ncg>W(7O1_~>j$o3hX&W51jyBd-%9 z*%(iHr1IGM8`Ve4p5u(jv;h(y`;=Aa!gAxA>Lq(ugHqXeftuSK(x4hXittf8v`nyE zK%TILIjDtAU-mf?U#qjI_)GUAzhs~OB`QBZKsMTBkw!RoHMeZQkHO2C_%vm&F z>}4_ZShVh*WB+NVsge56ZSZ-;W;tZ_-vN@ToazHjTKUdvOXjq?>b*R1rH$AdjT(f!_TV#d<3P8zf|t2y5y7cl4& z{DVOW{l8pyp94htS_XbE`DJiB%dta$fxQ%R#~f#vvl)wZQw7M`cfNIHL|=exy>TGE zHj#T7v=-f?LABr!Q=m8c`4s+2SbzKKp(00%B73~4!Zl-z)$Xq9wN2vBQUB-b2y@aY zvuyu!)BG`KIp?rDoDzhO)vN4RP9O4ZlgQ!i|7VL!F5C9k)kg=&AlBKs?DZqlyhXli z%#!c%H}(l%T3}4GgX8NB7P=t#fUvhBPd5chZua?qW5b#K1vYY&`Fs^!XE_u3w#PO0 zls#wbipf0Mmk(-GO+Pd8HLwx$D0AV-Baw5d|Nn3Uo4wM3(uqAv0Q$iWKOpyB3+DVj zez*oOcd#ZTLk@DdxLZnrFVCMsz2nsdJ(ug$@Ff9`;{Oe0qK{^O#JkW_85GbL94c$& zuf5!|X$rU;=KDtQ#1_px4YsUWpsYh5^gfV!E(ET1y>Gi*`okd$J3D0n^&cy%TRNP> ze)nb6@#I{f-g(U2qXv}2ej|CH3}KvBV2@lFJgq?!;em?4`&)FCy-MH7ZpoGp`>}3% z-nX7dzB=I}>{R^^m#oj_6#x9}9ee0{9kv}i-7btvgj0XkKTxQ;nnV zpQv}obA!J+%Lwq`zrLHff1(8QQ>0mc)<9h5G1Un!4nlq4?)DZLn8{ z;A@oNEs$w^iJpP|wXyPz36!epJt+4~%qso@{7jR*n>?uV3y)7Ky ze6>{gAG%-{n_kz8J#^}5)?nj#w*AN);D3^=M{kueL>`Yp9`OKQ71UML{MbAUaLMNR z@Th6fiO+UQou3_&{XBeH8r^rxfRR|)-;12xU*3JxV`pS>m4n2c{G<{X9)k{=Hn`qu zs^W6m{JX2rB8OJ#IvRVxA&<*;BV|b{*U%K zB-ge;Ie-m{-$VS^4nbyuj=u+3$?|zUa%&Z5Vh_V#0?%(E7k{6Rcr)=$zkHKQZ43Zh_->MweVV~tt?b+}!=g1rnk|$yGiQ4{B46I*S@Z1jvHF4t_(mRD)hQRd5*K-3j81OxTj7!1eOUt;>jstWqT-Giue zZT-y?_?ChAVz%j?VuCRpUs1oOEIRl&=6JU5PEO#J0?3W_j???Rl3P_9r*G{iIhUz& zrd_MngT##Qq8)Yp&gC7i4tc~)zpK;;Tc1*#hum0?A?rQKvyx}#yJN-Gv(nU;L3Pp5 zoC;9=W}nUeSv^HI1b#2uN{9S$$hzZuEix)r)dE@O9Gy=UOMQofv&pt6Sh@wPyc%~`V!Ql(=^*);Io+aEM}s7I zG#I;;0n!0VH=VeKTp^@8nhLiNpLLHM(@U} zd!><&w}98P({ZrFvrNB4nTvR3x{2Sk!X&8Un-A;0alMxmd0hTLDFd!=8*@fa*3xr5 zRX>X}Q^l*!24?5osBLRcCxo%v7;IaRzgmZkXLC=hz7+Of=<=)l5-8`#IK`ROBMo-C zW#Dfv*$q}<9Q*R=PUIJ@RJw0k+24w9B`;577x+{#AYI!1u(*Ju8(*052Rll5LR9WjHSFbg~A;%{N%1Fj-g1UfJlS<*T{W^r~` z0NA+U^>ms~O6fGLw2W&%m+A`}`s+Dl&Tut0(tPEXNASa8W57}(hnNnZIF>p*icJ4Y zbP0J!Mr?LRP!}Z!bM8P=Jx=~!sOo>r67cTGLTiEpd4ny)?2f+U#80y(Qo?IcF4y0esVQdi2VG$4sZR+mqDd>$izyH8maSb zg|V)4=jc9U+`IXss^huH)ys9)-(KaROxWdli3f z0B5kVr?e>J9X)>-_c9#U<8kHJ!Q!>)GlpIQpJ`%mjx-ICjFY?)G8#L2biiToK0p2h zW({7*qVZ?Z0fSkv$bX0R3q5bVKqsZX{W|5i5L#YR8&8bb2~9 zkrRznIa=BHCclrWoxU1{9O-~t^0BtZ!iF;s*bIXr@R49pfrY+(Wb#tCB&!}Qr?4Y9 z*fVN-rN4{bjk)i4><{d;Ypkx<)RpW{;3JX*$g{M%Zmw zujAv(YM6fCEA(XVGPh6`BtjF zn+{A+WSTrtm&16rIFc{$`6t!8TkiLr<9`6pJ1z}AZc_V69Q65#GO2KvZo4HNeAUyu z4jBM$#Gte7&~sE&?`er_dMCCGS&;ShJ>iiu8Od{PRaa+{x#Z{6s=jx!N3+w5Zn{1% zz}x<5;`VA)5NTXaKdYY0H=l1e1xY{V?7m>umtj9p279$7<8;c&kLlmWuVnv#S6=3u zhHnV`|BvJBzuLa_W`#NaOwY^KJ^S@_uy47(pBE@^=)1Mo1dGF^*NOqLUGg_L)2)Zy z(!E!Z?9Aqt(%^?Hm{@`%U}KY*vL_?`%;s3%{w8YP=Z{tMo{N2=oid;G?N=ou*yG~LG$5XghTH+rHQR;`-BI z*}{2L>lv2@jY39Z(Sl-N15F)%#c%PCoY*UAI{V3%N0j$l6)tg86}oRp_Jh-OKl%n< z_a*yRJ54C%Clg=ldbFNpoa@`3)_vm|%6{5TfmQSv&N(kwoKO7Z8T+;!xg1hAoyY}j z8>YPC%#xfsFC|{!&mC-Bo~h`|+N;!Zw8sXgimF$8`o`~uTd+kh<0pYPTyovE4>Fz= zwfTLRvA|E(4L0ujQg-y*cDgVCynZ##3LL7&NzIeG49$Mf^Su%0^iKW1NrWmx5Ip>7 z)*6fMvcI`?%q>4n3zV+dlO(vOo=l60FUG~{_vC~QdEZw3j%o8LGYTH}Z7lTm%nb#S z;N!c$Z~a>DFs|urcp>Ber-Z&^+qh>@nnEG+E>fRN#2F#QOgzaI>=jN8^x~^t)y?W< z*z@1=$PL!BIT!t~h1U7#f&Yf0Hs3`N=twP^hh0TG@H%xnt2#XPtE!hQrfl5`x7zft zl815IwT|u!)v>wjW8%oIuS;0$n;BMaPcct-|Om9Wn1;pA*JJexqgi_iZVwP zXFqT!K$X26I?C0>!Kj#hrrJc(93Citw$t@B@k8`!<_gk%&`5jD7i71i@YiTj7xw=t zSG%M(Yi}!XN&d`%k5k~g0RBXRvPweWqfWKv}Lcl+m5x+X3`j2h{t@Yzmb7C%{|`QSq(sZZ+9I&%ypXFZ+kQ*tfpbWiY~A z!4~m4Jf=Z)k(Eq7haE6{-$dqvErWE};rLjZt!e;b|9195f3~Yc(9Mi&f?Rr zwv+elGq5Ml5+dQ>;1j$9YZx-GWSpsY?q@$)QW2lqi=8rYxF0rOPAP$0qUE}%b1Bs% z9nu9$vwrl^k2>#0-t4q#hstC1@Bm5wk6RkzvttalI3Jk1EVo}d_WH&TLI<)QyOA%^ zgB89{p5j--p!wH*>&Q2h`u82O}4; zG0;anW_%h)nlQzQDTQ39Rpjv8vpS52`Xe0s}PWmik?1 z3K&y-)7=Lb7-Cx=jriM^N52+YX&cwV$i5@1Vfb*EqQZv4 z_b0FQ3UhJoP?0sm9i@P{u<7@Db6Lel8r*HhfGX(7C7}Z|J z|H742eLVqlmAoYW=W42Vm&ON_Jr-5M0c*o@nQv&pl8)!oIpgynt9YlL~i`4Q<$d*rWw@cRJn<-ei& z@ZPcdsW6&q(tcwDkR_QWE*T=VivJE(LFS-zDQa1xpER)ar00e zS(HxK^A2o7uiA9g2Sf2^0QMp_HboWLXI*A)oj)f?{%IclxR^Xmm%(_)kE;1Uzs^5{ zZoeBZRKA*`>ow?jN4LDTo!?U}F20yvbMDep~dHqIKYJjW%)Lw)Nqa@t?|Z!|&PJLqfrsr=c)wM)+VzN3B1VLjg&q~-?We^q4H zdndT0WE+Rnj>ECFN3b(!2gWt6Q{Ez@?9s?yPUpe4eXrZUcYJm9 z{V}@q+p&MUfsEavTJZXDZmD-w-KF~1@wI_63K{g>cxoILEvv@JulM~VIqRuGy)QbX z+9;87U}B@AEMSi};#;m-RTcj0N9r9XZz4b4g03f>YKLXd{N&{e-~8{W?I-6}Iix-q ztX~TIOW&`(GHtq3=2hU_@9W4+@_FSfyvwMZtlL*qIuVyS^YzCdDR|4kH92J1BkV5O zdw#r%UE74HZ9X0Ufd*w~@4TRm`n@S3_9BDSc-c@FUl}Go!?`qAY8F>@F{~kd$n5fA zf2y+Izt6d!Q?Z@6%bDFBI9p}~eyHx~In1h`ryJOh?!*3L7jj|b-4m@_3^T%%0f7@`?HCXYC>%2|qCzwy_AWu6}7JdevAoU`rjLWI&dm{VcRD;#; zyq{ds#-n~$C?6=VO}{fnI;C7r`DL@t(~>Pg;$}|vdjQ`&9sTArd`O^|Oc?By#mH=r zy~aODVTW9K>*UN4e3$MElH*=I7vx(UAf3=BcHXVh%pa`BI<@G$>9B_956M#9ZSqqmoCRCs*J{>hNTJe~-Dxiu|6Y_;&je z{fu79qPCZGUM8_l%!omquT|wL3_lXVoO-{E8=f3o4{O-1&iI@hpzG)PA=M6Nr>k@l zEmM88LMFFV9TS9I40}oBnrCByb2Q|R71@ulH(Fz2MXY>$G_lo(qLE`+VIttQEc&oV z)z^0;@W*yRm%(^`>83|s;IpMqbNJ>{;KOZpKB-Q6B&;aDuNJcJ8S5L*i2FJ_{0Dm3 zSeenY&`xJk`i{93MclIdtwVlmVeDx*V+f48L65=E)yRa+%M$u8c$E?G^>!*g$o^0N zK9Ai@babtJba#F4ttsY`M?c}`!K{|QO#j5yI16C|zN<>E0ke$n2Rn^1?F)>1Ik6)h z3wGj{cHk7Y2Fc;dx_(Qq^3A_J4g2r#nt?L!5c|--ReKoEM%O~eay>|z#nkE9<7_v_ zP`i}A<0BnOG(grnnf7YYI7q5J)Oq-+a)7ik_aR1F<&l$A$G^h#fdHpyy zRgH~B*?rrsQ)Oh__?U@~Ql4Wj1kd^lIE3;KM3zkTNH_eQM@Kzl>#_I4N2iQrKf7j@ zzg#K8`K(2lud$J^s7Z5&Br4`F8#ltop;Nt)QjHbsx&1n9rcT#>|AwiYOfWzd7_;*Y}th>UZO&ZYk^Mk&7|mqrn@0H^3no*wgn7aGHvMVwJokMPH(CQ7o`MSfoHL>HXx}17bzjqdXFgwrYY%O!$3#4DR z&ghhq=*2F8lS%j#y%oIU=@Cxp!(OA@9rH#1a@p8h*L~_Es{Fa|zZe}gE9#J5=A3Ih zPi@M!hR;-MSkbLIugx{`#aqiTCKqDl^FY~!=jgsSIDn~R)mtJ_7V2rqI-)$xtHoE47T zvFGLhxy7E|pr>bi;|z`lzm$M6+dFlL3_S1KM|)xqQn!v?FO2l=qR*~+${}q{TUz6u zovznWeRoEATf1}pzee3BAHsUAi@gC$O z1|`Hc-=MCYR6kqY!7ZnY`pZ(VX?Cg&_VPe0&i^?sl7{kjXcHoTf=?<1A8|VvpT6uL z?mbX(s^8V`tQbkhoQg9S_n3R{%1?E9?eDVx?wHOYeb-|Ln#wEj%K6D+_W%DzjajEG z`nx~4Dbp|1d~8|mwEq+5%m?99D4we45BP6b{z=8{G7DR=$*M2EAEx`XJ^n3IUiITl ze;EO9YEi804tY_ZJx)Gdf4gdc9c~I9)W%yS`rauWkPTYY>!|vb1DW)fC^xoI=|uIP z#raiv-lbBZgRrYUi+_k!Hojm+THpGuJkKL<*U*mCd)we3$-7d&=`l7Vd8^~c)0{K( z6YNIW6Is*(d#vbaC_4A`HcZo?uUwKml3yS%`U^W1D53H<7CR_|Qgvs4R|tRFcR8QV zrpL6$`Rcj-U)0}Q;e&EvuN@stgNI&PQ|15EO*L+EgA4nVQvEKCEW@J0qSGh?wxuxq zlR+`F;dAOw&J{KH=vMf=L7X$o-ZKaG4;#QEeidIm`8hs3Ywg zs|z*+Yw$rjTIV5h+{pjG>kVewv>P&>C9A3O-1c68JSm9|rZ>L*u|qMa6X%%+RPe~d zp?W-BGUxX#v+xsP;=|%2A8-~^^Zw_E=GVsGLeCB8QT5RuoJG4Ps@yf=s{XSzCU(}VoN}#@b zc3$P%h}Y}?A?+>Tq&R~9@7mklyW874+#yJC4NlMy+&yS;2_Aw=&=8zJ@Zj!Fa1RnZ z!GaS)NP-8KVDGo-nWty>j^ug%Z+$*@voq7()85rpzpCyLB1Qj+kjQzu+}r+Tj1;lz z(D}Wm_>@!hlD4Yo(5*YeT*Rj0YxZNkh#z|!exhFMa;F&=C9lyf!~w4vAK7KLpL9M| z+~4bY#amg=Dc5`AM=6GNdmHO(Fg?f@DXTZ=y6GKh(hCl!?w24Jf0ju1|3yvlzlANz z@(b805VUjE+^&`8-kR_wnNtq{Hb}NvApNlF5UPAyT!r zu8W9n*!q1=fvu{D)0)#uC|S$szh&^vMY9(G<;Kzk39Bdn!tZOzBJZA*b0#?oAAau{`IFc{pc=@o*t_ z6y?ANA~K{I$Qu;BH(1XpkM486CF903jXhZ@o!>09hoWPt-d_IaU!{TQ6SL}g_QQPO zSx!}TOI~nWdt&+VTZ|8yRM-h78D@7CwF&X|J2hV z`E*}ti5?)BO83-t(mL?4*bcw$tIO_VKDfLjLayOEwn`Glrlm`F zrh5SY2Tp3RGgMBn$IEvM9}t6(!;q*^Ec11~uuQWj04O~3U@?CMvXFUbk?$uOmRb{^6xZsjEUzA`7(=FN`7kk zgY%s$A8Y?@WW%gsL5&;bQvzE9D-s$gGELem3PT*-T{G6R!;ZgY&(MntpYk zIr9Vj*Wa!bDfzI`T9wKx9%OpM;&LYKcOLPfds&4Hs?n@a*$+0wrXN#-=VJbESHZM> zw~hL3wJykgg7~99SzG!KW?U4HlzGgf36YoBRK~&`ZU@&A^#gv!k=O3!?4(u0@lCo2 zJJIWInfk;IjZNtpJw~cy$Cwms+rLp>c#UV4Z@&5$%vh-UqmGrfkFJYSC(XD!Oxv93 zWa@5JZjU5CAN@PeW6&vl^D=sF3L>+d{D662bf^@*s?$yX59e93?*11oO{c>*&Eb+i zJ4A}F2mbNyAvY-+B8M|Yh!;7nqK=<%rrQwC`I^GHYCo8~t9SL5MT&QmUnZu*#;_Rj zwjYrBuQlHu4aV1|;-3Y^wV$_J#~JNe!SR7Xt7G}I&BY#0(F=6HPU=(`K5>U%8kf`c zJqxVTYj}J`Jw8C54F;n0IdsHdxaC$9eCJer`efy7J>{Spday+2=W#!g%OP%joN%7; z=YDAwgkAsZ6zMk(lfqzrV%5}RZQ+JUsf`ZAriYd+U<~~#_XLmh`3M<-bq;|YX8l^7 z&(4eV_Y39F_s_tMK3EIhAU(RozJX;_ac`~Bed5=(*t}=g-|SFS$5rnaaGpSYY_k-# z${8h>*T*~`sQ2#=Q2#~#48pwRt!&yxz29BXj2m@t(|J`F7R{XmR;(I!XQ|PvX3`Ho zU>=@p@zm-`*`a#=9tVD3(Ui2N&fY%YUq9OA;VeC$6a{w{u^e1>7L%WajDMSo#RY%I zp53O{V5wrF5BuvnUSP>Ej_fz%Dz+b4cj8c~iu}{2xxSeDV|HsV>jG=8=;D0()DbiH zEu4alheH;yueGk9Dxv7XzBJ)f+?w#x|3&fAgh``>*wcUJm5-i8FIydK2C6vZzxNXA za#cjGuzsN~L%LM@I%>{;eeJ*B54L!96|yBbf;>G#r9FPaS|W=KZO1u@$XRp2ul*M3 zl9uSfzrtr`POz^-3r0z=>Rx&HAo@3^G46a8Zu!a}v%Uw1^jKJnFTtkU^kEaP)Wf%l zO-(17HKv*$Jk%i5H|#L>wFCO-1Eux*H-iG(#t!oVGUhVa64>(OO5yJ!H!Zr|Pj1d$31pl)>-7t`NBet}#!1{d`qZtB+ZG zXqAUi2lca*4lJ*F-gZ2AD|ARFYDda6@E$2Hd+YSF9&s#;xwZkd}Y$q)KOZ~pm%+#g2SF{Qq>loOg>bWE3<4hso?>*9Zpj*af z=3Lw=_&9a+4;8*ud{g)8UQw@Q=nwmOr5e~VMUAWLel(Q4{WePXjo;C~T+VCy*PD#^ zofqVL&pgsFLAZRo*Ckuex@96dqtmQ~k;B5}x0xQPT8uGLpZs{(dr$I8lGWH-f`L#p z16z>amg0X98K+IZ;-~B?Jkzi2fmXHi$(Wg@4?npYE_=XkHvT+Z(%`#QQGfht_Kg4T zeqyJqu9++O<$^yHTWxIqmpR|yGsb7W6Zl5o4M$&DAt!Rr;elhNej<~1J6^U5_;R;! zK=!k#5-zR5F;#wT;)k`@Wl&*yf3MS7hVDdB#vAOT$Lsfpt@(c*vW+F!SSVVWB|=8b z2Q!I2HYU3LL4^47nn@nxg;2m776PI&2)s$&A<_4+1U8oV^| zj%)`pfuL@0mt1-dNCtNOnI%iuvMRYzxh1+*nkK0ex zn&F@|*h4G&_b+0;de zDdx8dKbm${v<6w=iG@+}@VH0%h6jdO@CP;{p%D_tv7b|Mo`dyM6sy47%iDidcY3AF z8=ouz&ygQ_;q|!a99SP~qsLhbPT~zR{Hrb8avXm2^7}4nf?Yx-`1_TNw>Q_(_pCJY z=c_R;`2t-=Fx}Y~BBSwx9}Yh__ItNvFXs|BxW~VahD+B0x}Lfo&~@7+hI;$rbcFOo zem1gXq?DOTAEKVK?bG$}`VaH9FVC9a6_9y2X(jSLMGLaHq!)a$O%1T+8E)ZJ>}Ln+ z`6WlC5J}t&OwDYMob!N7VQwg8`9`eLKCr%3ymnjlv(g*E^t{BECi}xL!Pz)zbxP`M z24`0t@ynG4(d(%IIP6uH{g@rE_+``2R-V&k8va^eQ)C63hYaX<_Wwsd2KRi|gnf)` zXO%#>bP{+X>QSVHW>9@GkxW!>3R!&h~(u)-x68#Wc0;+C~>bRIrn z-xHq8D_7d!V*`w*lcK;JIH|;5(|@)c)bm*12YRk;O&|O(I#(}B{0s2MY1yNWMJMty z$Y+pBV=MU!rr+Rm6;&S^E@`jm-;3M$Wot2y%>IlyADq|c4x6j$yV*PA!)UhUvr5IS z!CuHo>$jRdubz9q)$fPjkKUJ^@t*z7{sKIs+YdUyGEaQt(S@BiSI zgUHECv^9Nykzo2)1AEqWqzpV^bfy4ty5YM?RD2bzq)Uyl0Wo%Tl+rSK9mt zeisbkloag$kq;&W3uRM_lRhb2N%uMR?Dja5#&*l!|JlV6(!3}*Hu$56lIFdgMxU{q zDfoeYJ``C(dFF!qmm=lrH}CEz*IM49ogPVsZ@IgVIhXAUek(Vl3+u<(C14#|mDc0) z_95NRe8@qU=Jv~b6~bkI-w4?T<|EEM)6RDK&g+@&=z!*;qX4&&A!xs`#T&@GsCc7? zp^wAgMd~qb*?boaC1a?1tSEWZ8@q;7e);DDd}o$0DL)d~{Rpp2I3FUf+2cCN#d!&D z-qX(>{Hp6N&oJHI2hm~JbPt_z{0rD`?d9C)bfGeIWz0O>p~RfUgs-v*tjCJBP4r3c z3Zc>kpD5?g_+{4(GY;*v8(6YF`(9mRIrP)}zSC`9d9+*N31=0v_H9b-l62=h(yJ<1 zg$CH5FTj>;qVoM|_Mj@AO6bA5-w2f()X&kDE_n*(O3~ayoQbwCLWWuPIQr>-|6g0s zFW1(Xx!8_Tcurt_yaYe=F8Xm5`pdcOWwM$6|Dd%lFZ=6vQM;eOCe72~X7$nSaww^;m+9!ecO}wg z+ni26dpbQrVttK2sJ%Kb11FgNr@nD+iAR29f1R&xU>{cR`aRU?&&Sp-m|9#8l@24! zykWoppkVa5v+e=TFMjHgd*H<~v(Je|{{{3@Vuk`#2d2?R3%!D7=)f9Oo^My^YwEsirDbt2w>_d{_)2vIB zY_M=xxdtE;S%qCTGFU}@GMRR0W9^C5^Sh-Y#REo3(d6W&E$a;eFAFYmZA7@_3X=a0 zKNwiQZzEg(ejTUFG5(>R6B^;WwF){n?-Km%91NFRIZSPU`{rG{d>w{lnhxk*3RPAfhcrP6?HP*p*Q9KLl;Cvt2+#|m+ zcTO7~IA&6VwJc`&6j+=ZnFUzg`r+nV`#YNQdoOY>2s+fl*a}TTS8P+_1*Tuv&+Kcu z9HyN1v#*eGKIvTU&0?7}b9Y&#Zq6WR6eyvRR8gXGoC zz|kwZhs^H=`;@LP@V8}QC}oF=VKc5jvvB%r;Ej^b!mo07U9TDQ>iXHa6uY1*ewmA&z^2a^h}3QoIR5Q- z&TF}<_+m<9%CV}mTl^U!B-3rv55AqJ)2W3lzHX7g@sV;PeuAs}rPCghhMoRxaCR|K z1MFxOt)5`YIP^!KlHE1u^vB}z>`!+g50xV^nRb8aiM5)RP^tBnpwv$ zS39u(s_^NtPmZdnzy180Pu9%!$amELztN3$V1$slJE>lr!2Ye?6|?q~>URO;$xZQv z_bJ)?1`K#gut17#k23i^cp3~*2(lP3dM8eiKKz)XFAluDy#1G&{bg&$z{0ya{;PUE zX{fJZb8oO>Opi%juBw*?=`wA#X|@iZ*I`Sl($7B3BPGEW z9zE!m*o@T#7Ite^L$^H2fK0Ec&R3}+dTh7&D09UEZ^d zr2~%jvRZZBS396v{9szl{Wf-raH)95D`%F6OMLwPr)PdtG;oechIiO_=n(qU1W?h%;n2($X%8_+bC*(Eb!Y$*z*kf3x8q=$UbEBa~dIQ z{!G{3Q0AIoDmE^9`AcpGFTY-7*!3Y^|$%pE7#!s6y4x?)MpSZCTXR!!)o~#aJ7w{ENQq<5ezsfedgaI?voe*wQ#%!sNpWoby{5 zKLzL6k0SRdoX#afeP9pJf!*!omfAV7CF%v%vIo6GW6`BmO? zMe1^vn}vMZq3=!JJXDJMLM7HG5puISwsfWa@(H$2?T(r{?Ys@&e#oqCTI+*ka) zWeq30TfqJC^Uxc3>!i>7x!h%>|9j zyFs0F|9(^`N<34LVPR`C9i7^KFeQ>0a6+TZe|;uIFgQn>hTxa)dK@3N(&#hs3o?1IUy^;#dX4PyMEpoexylY1 zc-{5^xGC^L@6`tv$k|CV@xk4%WT=c@2c7{rU#l_TfJT}1Au)QdCoRFHSTfqKoH6x- zg+Ws(kA8sv@+jT^!t!wLG_uhD3+2G3=lpB-G~gT7^k;4S=ilQGNE0Hfu{W7DD_okj z7Kt3gIZEZCP_C}S$d+JUx7D2;*r`*O`o*GEwT8y5~Dd!BnJF|9d2qr zd|FQCtfJkz&N4gZvcBJi$?Uj(nL&Auj04Blmb04Bk393}zS9o9Y%q0&zdg>JIDZ;@ zcu$D@GQubQ+lNX#bghb(uzwGxD%P2m&gW@QdSoy%k9GJvXc~^LoN+Y}-O18|%suG* z6}3dZIBvF2HjIsuEBK^YQ942aAdHt7Fnu;WNh7^>7QHyHn!(8rh27x z-p5}Kkt?V5_s;z8m$?1(b30s2*FBDO)cfoB**J)ve$1RGY0MZd@Ks=YT*pt%=_)=+ z{FzQIb$R`bZLf5=$LLwoeT@${?Br}J+%QDK*spAejN*)5w?rkv4-mTf*yyW=r{#P* z&Wg=|&)$ro9vRb{dHqwDECaukt9#(wo`-R(Xyc3!^qhKL>U7ytc|J+#2?TzrQg8Zy0GL1St zO?q~o)pf+o2)R^EB&2|jTh5XL{QQggW*=~Ht*1sG7tVBMG5&7N^vWLiy5Lcrdn$T_@6l_I%NqPf-&bY5Ef0=sBfRmeikfejT`{oERmhFgd{P73gqSF# ze3aZz>XMLFE*a2K$L-(r-Q_!7#_$(&99ZU-$ak{O)^mR*`sttjJyPcDP$_Z8l=ZN+ zw^#Z2U}>lvLQWM-qa65^mdX9H5L-$`)z0fSUNB$h@!AfLv~z_?nRb2|(=k%c_r`Zh zr%)-EQK$LC&-%M(JEE_}7hojw;G||@awwlmejkNg6&+fx8KF|Lh)*KRg~`LQ9!ZzW z4^GP?ZO|JGWG^wUhEI;Z(cjg%Kre;7{A0_mGK{f!3%Oa{dm-}K?hq*h4>%z!x;5-l z6`f|R+w_G)hpe9MV;`OGv8fw7T-q8g*$~In@%;|qP-D4eE|>+Iew&ZKr#_)FYJo}L zewXPd)9>wP_OKLkU7PI4JK=QVf0=fV@^U+%4orn)vqn+F95meXjF*;0MmH>SOv=k_y=3 zEI=2D{`T^ez_h=z{EvRj-acg!{LDVm-$=d>d)MHmzn!)*R@yv7keUoco!%Y%zA6HEkD%V(R6nQ_^?b56xXJ(Xo`$!tkh(6a&-Wl^; zq+{s+3l2ta;~r-tEB1xypXv+GMuf}X2lcl` zWYqOEI)7k&^~F}nreutbJFJzlKewO6eEkjCP~PT@e+$R0LX8HeWK&cXUC;LYjaFd! z^7$p*pV*s$d#c4*EG>~Q=4TGEsb|J08GlR9VV|OdSM(Qp{uGbHq%QKsj}wK6n|ZHU zQs%C!y3U*C4y^kr*!KMwRb>B{92{WrvAWN%2lsUYUxxRJdu2B^+Kmo!W-7e?Y3%DS zfnoX>nap_h_KKEIfNy30-YVQB_1qqbpHO$Q=gcFDE~vdUXGOkZQW)o>^B1MGF3^c3vCKxED~g(Gvw5=YP5@f$`-@fvRF_)}niw8N_F zSTMCV9cJt}=}cyD|JK@RKc9LGKltFD+~6~cvOiRGVXI5(ObU~96GR4_iJo^mu6^zL z8UE1VRihC$dREPaC$5@JOZ6_*<AK85K3rCw<-Ee|*!B+M9H2oi znKwz#6FJM9`c99$Z!}nCMR^}$XVu#!6*7m&9dyepieqmAKK4C)RoYbAv1Z@cuG9M* zd47@^_$`44T3H;q5w?L&ItW(&y%A=Psf#Y;<#V?*c;D33bqg1~1T0~DaO$Zu`NdCP zS<1e*(o1|IbY$%P18;<_RY`P9?2)qU+Z8>{>z8MPqL*iSQ~FY2_OFvTF9r-_^%4JGxfLEsMV_wxs_Vc`LtPVBfY-eR9tOSo zuqs|DIv#uI&Vg&BGramedaV9-k+FVhfZRq=QNC5P34Q{1MW2^{pABzC|KD*mRK`?{ zp6|B_SpS-_m(0jMW(4)JEQoLU5&mGP;!CYI9D`hXe@>s|Vn0}7hyHFZY;pJX2RqqP zq+7dCIfoo<3j2k0tgnjZf{zTQBFA((q~**> z_Hs4An8Zat^ZlxDxn9@J`MO>y(jZ)}CDZAoW&Qgv8oMJzq6&nH2VVo9GS~gHH!x0x zf;xo)$ON3U5IsyVRqv0l(F9RaI%xda;UZ{TMc{0P497o-qO8d5 zvRL!%yHea!+Pry$d@lAVFK0M|!2)C061$T^PxY8Jq4cjA_)xjtF8C?FU$D0w0&ZuT zKU4|Wcy7&9l%~_WU5Hn z^2RHRI)+O@uyGspdD3D>jIV&7OR;}w79rn(!|qy0 z_rn8LyOp1*znLtd{)YO0w7kiOx-WA)RFbdOWBUN()TSh0onxX}7UpYDJKb*!_4Ue- zTgagb;?wgB&TD+)kwM@U_Eiszy#pSr0r;j!ur&`Dr$1iR@p~exOqm!T)9b;*z6gw? z?&>3hvMKQbGY6?>U!>4!*zeVK^CtYwR>yy2L||BFnBd=^hv{@;m*5=8cKB!eE3p0S z@Qt1XK2PQitjj#CgZ(OCmv|#o=53@t)|O2#E z8)_g+k9E!dqP`Y`H&XOo&oIgHy-zZabxH62*r~R`roMfo+=X}lFX~!VkE63!1Lwf8 zp>BCqjkyiH#VYKtR^j`vdS$|}mKHz<)2AdDT4qhq3#=q{bqLh1R=g1hU5KNb3HRnCXli(b@=&9+TNtbOPh&Ib3a zi#c68Y^`MYfD>wAtR;IrDZw_qfqj)1*i3lC@EDC}=VxOBZ2e}x@n8~t?A+Q7bVhxJbjmtX%heb_e$Oxg$b zTakmDp`$2%O3ob4fov3AMlfY*>latJe%@-J?icq`=sX-d87{HeFTAOW?H}`9#nx^~ z-rlrnL-sq*-^a%fK2p5++ISZo%nja>{fwe|4vh0Huyc>UrQYx%F|?Wfc7n%xY)(JS zndR)`x~BEWz@ib7Wo5Wz0w3|LxKFZJJ^)I6h)g_4FWP#iPUrqJuQVEoKJ2J2i=DTP z>`@hMtf2E_Kd)HZl*@h=)Ab`{*@KS7Jbo&j(0#GYhbCshrSviM;gwqG`bpWAbFq4v zd7#Hm6IT7|(hD8zZRA4eHU6j@z1@F7c4<>H^uHUCfvm{`pNB0i!S(Svm08lEczpsb@CLDHhn4>Uo*z4&7GTSSoFJH@dg=KgGkVVx;9LHU z{;<}l$KJqv4jG}-Z3B;JQ~f^rS<@Tf!S-{GDn1iVgSG364bf!uz*oQU$tv`5T_Ui{ zD+KSbkTWb^_~Ds!`8v;nZwHIo=b3K5-oN=J%O%bynBzfb7mgot+Wk1##jD6JI)JBS z@9w?F86fD)6qT8yb5gXfF8`yOx@;kqjcS&`U}Db01L4c1IXaL_nLLsQ{O=caz{sS> ze{<3h8H7A`d~VaGIz|0|g~NVAJvn>ZlwIBb#2FKcK4Bd%1IFVoFj|UUmIxKUweNoW z!1}ie9;;<%d~SR6_`TBByxoaRI1_ry@|nR8_yWJ9LdAkF^0EKSTm>9nY@htONvGjn ztMf1koaG(#Yc_qK#3w1I>ihfOnDMdvA$ysMF8O{w=T(g|;Z?lSU^;@SzyRIGli8~% z8vPhs>7Ro`{qOEOW(t)`Pa*){XvB3cpUju*Si&yjQ_a#az>`G<8#o`R@EDKKTi| z{!z%JYopsN@-u!8NpHj|Y@>Z%>C4)Z8=3b5us0>MFsHZSocJ&CQ`W_rBanZm1fSrf z>4#1J)${LfMjyM&(a#ibquX!9db3Wd@aryNV}!oQrZnvRzhU0Zf7300V@Fs1o|#Af zaqPcSj`T{qNukmYENxBp%ePx#_k_&$`|kKnOk~pQyi(5_zo6g!DT8@#f6u;_>!*Kx zf7dOi8CNa9aSf{Mm&}y+$RLvk6>1o`n9Zp;CmK9*cle!6pL=CG^Y34NpIl=tOg=JF zZq@S0^~?ANt8KnnA34aR!ua`E7+7a2%_8IVH+~$AtRL?B^Tw3X{YqBc(Uz7byA}-Rcqi ztJOt58cd0>-KsN9hs*oEo?ohg4RO*>*y_Ig(j`TZ7kvX($);9=BP9$yxs%o~=90m$ z9~=c90{Oxm^x`+&oRfzr>3q4tPPAaXNe!lE?-hI>A92awli9bRYahvcJr3M#M&t@# z7DlIAH&UJsWd1~+zsD0LHL(S?X-O&Fr+eX#e(s70sk1av613IzH6V^13fUWTM@)2M zrcZ`|$NDA)-Y2D{2l}g|Dc=+e7hexKc&G8YjY|aC4fRdwkzc_w+$!alb70pMoqOe% z(-9`$+ZXHH^p1gN&~KQtkLYzt-M_#G*`%Jj58krmIN8CqOt8kb9mjc{hz?~`cwl=v z-#202aVNkhYS(ay7>=K#HRkPa@ZLqy%l#W|5?%g=#RxT6hYU|2fzAy~5%SwK=*SSe-10g zVQ;n#U#5M+WI`IBBpIpa9A|jv?~E(LrAR5xnmo zIR~*1_yJkb<*(V3exT=*xh+kOQWy8gG3GFvHtk~_*s1%;bc;Xqf$O>l4;oCFXX$6J zcjKQi5$7s6bn7bYqPRn9q=)-lsO?X;OoG;n^aWy z$Eq{+cs%;IsgJo1UnzDv_Vra?*0Uwpx@TfN#MW;f`~K>d|5`hYy3X#3ztUIcn|;7l zD@rz1*Hi2|`aUzZg$4e`*WySsA3v=GK6sA4--izBtGk?`T*%bx<7FP{!WuT_0dl+4 z(fgG8&NqXZvj>40w8po3_J5(f5%@_-Y|{4Z50w_kgO3&oli?ZsG9Fp)3UHFKmU^Xb zdE~xxqmS7X@R_SSx#SK!(AnN#@6$!e%p|6sRerW1Kln1aTfXZQDKpka$b=h|GpWvL zhw*{!SpghcpUKz>6fw_hfNSu;J8Z|M$NvF)5A-XeAL@Sho;5#}1^cI{<$Y7f`V0F1 z`(5<=_(SnWf{&ANJ+Vt1haT9{o2XD_DW9hxwtUDX71g%nhRrUTKE8f4K2RE%I!lP` zr0Pw*W}PKk$NJ%N7x@1hu*Qq5vqu8oU{8qOHk+oE z3YE``hsi!iQYXL;ADZEpHH{;sA@yX_HS)9)T+3fB<&7C`>e&w88Qx9N ziu1ah>6+^>Y0;V1Ebo?Cevi~o7%ol6hD(JK=&Do2JZ|HI5ATMqL{Z(*dJL-HalSM4 zr|xYU+1V#^;WrdzEN?%><_Nnvo6doaiHWLVL+d+;?(<}b9AM8;b|Bcq>FkXx8I2t$ zv1JGL3qHhmB6~bh4%t%;e8{y4lZ&bS(zCc*x=k^4XUDUzRat{(z%~a3FJksgR2j}jjd)0I~ZgzHb zS^^aN(DZ8+eir)qnCP|-y&pb5rXzQ$gFlJwV|CeUR0s^;2szqs)uPvnO4H9?Y!UiK zMfvZcAFt|@G)exwyl(?L{`LOJ^hfph)e3ZYe{kkNOH(h7;Q#Zp9k#RgGjTTKT&BMq zQL>~3WoQkbU)LwaJGvxKZc`7{tiE7JK7;<~Q)Ca-*9Vr>es5oQ(DxJ-Z)fJ%6-pSlTZ`B~^9Pr)py(@_(U|V*<J1foi<3*WyqBXWe>zL3 zgU@t_T=xt3mWDa?*jw8^O6E`SN%-H`iJ>n$4JPwxZC(Dy_+6|tm^1HRg0pH6*skWQ z`d80u5pv^UxHLhZ@R&8=I`;D2R))ym&2+rjolTvp7|DJx_vHrYG<>o3*eJ#NvlYA1 z)Oo_>=ha}~F5u7W4YsrBUpi*?NOfd1TiAE*XD&#~{(s}~Fu6iM38vYbOh50AUk4}E zy@~&_5zZ(2cZ!z!8WD7MS8&KY86(BL-=u%`savWaG-XoZ({z(%6k|4?4;4__iciXf1|(%D4L8v6es0cX8O*SLv9JV z21ah1F2l&?I%EX0%O$@q(Pf`c8#(DC zWHk*KYLgt;VEcW+%Mnrmn~q^CP2SbJiAQvsCIw4$*0Jv`Hjy)dKgI_od#3gU@YRMs z_z+mP>#0p$w96gX&i1#|br|x%5bTnENB?xKCi1!+k#geaz;9>1=#uV@P20?g6CuSv zjgmWMBW3g}pKJyDzjGW|{=RN$S1VkSz_Z@@3Y;}|o=zIX{18kdK8TXZ@b!`W{dL>C zZPD5+Ybwm1 zdtsz>pw6DrCqipRNH2$MOMN3B>w%(1;OlO@?~`fu@rB=0=V=`E-y414z%FltMEjR4 z$c{z@=!$LH3uGU)@Qu42J%mlukc}zInAhanez)*y;ImNl>%r6#eCq2^^u*tBKIDN= z$yX?_UY+3!Jqqjx_PhKYJW?D!wGBE5MU!&qF*F+A!$;io)qcn;k%b;ZCRSoVgk;8! zwf1(Mm-^@Qwc6@%S&A%M(P?xe1uuaC^?M~x57Qsguotz-#~QR29MVU~A8UY@RFpff zeml=$x1yiu|1ZE#D5}Q%^d&aEih5v&*tU-O#@mN6{M)}Yur5`Q=GZCjMNe4}8A=)S z{D+46rP@Mx)-S-e-{Jg#;(8tEb(M3(@lo@#t>JNE_=IdcgujV4taouErDH3%*IV{B{R zIybecV`uu?EL(W>?2ks#`@yL1eX`}N2)W)KZ2ys%(+F|Qr_Qw1@6Biay$xP8Gw&yY z3I8wZ35G_|KICG_2YY0$wb#EIH+uiRzdmr@a;EKVr^DAqMuC~i|4^ByUP+rPQXW`3 z?xw#W2Oe$edF%rn_`P~M%1CrtrHi`cnWfwO2bo~nTj288voD7C*}67T>Q2Evy%Rot z`hjU%;gM(f)U&Cz#qa+PZpWr{*wS2|87b>BM$dl~^G#>`-zZAa%Z?FvEoJ$Zx^@|y z>OtMVJF{cDrJfcngc90Rz8yI=+*@juwx?Pab=Mp{ew@(!-B7X|9vs zeAM(kJHI3Fb(8408H?4xBROeT3wU_e&EIS2em0{NYo}!^Ut~J=?e)B}X<}f$5>4~U zw+<|hO79`^mI|-&$A(_qCO`GO8DG-5IpcODGQl^GIAiO9&SMn)?f*heQuyTj4dmdZ zz$mnXzXn_FY0f;$e(4-(e}_KKNn1_@)~$M1xvtd?{N4~GpRMvU>$8Jb>088bH+N$3reIhIc2_wG8)URCiiljv>o^20a!+7x@fPUzJXrKK$!>-Sn~ z_OjC&n*QE(A^3yu!X-!D2szMEmuYlw{CdVSX^%pm5fhF3+9RK4!d5(1l&sByuj9SQ zovMdO1irOyr9n?W8Ghlq8GFUonLMcUei;@bd2Hjj{J8?+oyO5QZ9ll~k-5zgV>$XUdCQ|-DMslsGDYG3m z_dq_5UD?Y>uH8osz=>oS!ie%uh<|MocM z7!}964A}sD#2oN{zp+**ssl#4&qCypS+MIIsPhx@#?)ukd13N+YG8kU8`1HvIQ)d7 zTgbYGAQ!0kk?yaZOMuO*>Xr80ks&_9e<8jW23T{U$KsE!?{p-@&*D)&`G7TKIrC1` z3i@41Fd_7x?TKBI`VZ4iKeTbn&Kvj^>}C2~U`qI0z2uTEtp7`p4GjUmt*FFBlZLv# z15P|Hb*L!U9OQ!;v43eEA*H}3EQh}?1ivtj0%+>;Z-xW@XJ@R!DG$jObyof zW31I3E_)=4gSYO!JzRQV=k(X1NLhoPW54AexMv%1IZN?}atD7MJMf!do^g*))6&R6 z8#1OpU~Z~W8CfXyW^<6s^#=R5X$!ar_Fp}cMas(h_?hSn))n4)Wnt{+TKeT|SI!6- zh@D|tr1vC3&jR+AH_L`gF2n@dc3+*)$6|fTA95&eyco_NzDG>CrDQV}G<~0OuUJ zbzKj%xj;~x;x9>c*xUt&r>>v{(p6Ighb%0P0{Z~z`nE;Y;FCr z_^ys$9KGH&u#Fv;p-<^+)+`l1V=&APwAjOy6V9h7Lj+77RKV$D9 zk2)SH6&86VZX57Y$Z8bzS+1{dZ}@i<49zbw*dPDTdvJA+8{zwoJ<$IPHOmn$Pe1g@ zls19&8=TfI?8AboRVA04&&nCSCv{yt*!u1|wc|E9$lBjfx9`ru;gTEt#&~qhiZ++E zLosesdL+kP-M&j#VLShasp}hkby;H%(a*}Y)Ax7Io4#+S)M-`BeX)FyY~Kza(={df zq?qV>TCbd};g*v1Ox{$u&8=NhErCxa=7)FqI#PCnUD|;RYAEaL;s)4}VWVQxR>ycd zkFLw6f$epf{u-m}raiicv|+3dtZ7%RJ%2~+zha{9Erc@^7$X)Is_n&4d5(SUy6c?D zzubXjQm~_XUY$pD;7B&tni%Nh0M05ZpIcuSx?wf0nUn`oyI+X(- zF&@^Y`tiGx0VyRn-tkdmroweMiv6<{&f!8H11h9DcwPI46F8O{cXJUu*^0TbHrqbawn)tSdIv8sw9K*8XMQD||fT z3ua}!Fp2w{9RfZ6G32c9Lfs=nCF?eiTtFYt8=b~Vhuua$uyVDNnKb;`h zhu|BjhgZ%nBhQ1GbJ3{=)2(9IxuQF<>3oL3`BptIjee&Td$44=bh!2zJ+i0=y3gO- z;-xS6z;b4O9wNCS@KJ2pA^sWLz5)ky$(;mY(DMQFH$mos@rM?{XCe)E%nJ}k1lT-up0}&_}8MJ)x4nl zR*he11Amy*a_PK%j-0}#5v+wL7=wA2>+%l&Jg`6RxA0qWtohiE7q@C){r2Ca`(fsx zVRASR`Um8HQ>i1HLK}LeIP%ua@S%;9v0v!{wyCm9TtA2;U{8?=O!&)V;GfxV6lL#e zQ_;hbvN66_(k-^1{QGs_cAtEf)ReD#oS5gyb(1_2RuDgAiLE-pUhb#QBITp9p^~S! zS?_wm>(pVLiit*4H{Vh3pHw#GRrg<~#7D_2(;uo|=Dg88rfe$A+R^xOxEG2)ZlApW zzRv6E&&@ok!Z>La_|bLD+r9~U51Iw)5o&Gd>8C@d+`*v>Zm_J|2S#9mZBx{lA>w*1^;A>6vL2F-N z%k&291^bOk`0u;;qt(t?%{M0V^ErNFW+K1%H`>`Ouw9*DIOFpqHW-~>GMBkbyT%mu(w`pjA_JL^ZD^MT z9w{Az9o0`~(4UNskdyd37#N?k4AI|yOIg=6Wv$4-+11z~zdp}dKu>(qu9N9kN!a5i zN{1}u8RuzOc#tNmL*$_)cZgjU?7O8Cwe!~eIdWfQ>57)!)@j}6{DIZ~!nfOT8^Vt$ zDwoQXxzJPg_$dSXTg|v8k9OSPYfq$<1E;5V)qIJp#+psiT?e?EJ)D$vG9^ljfzw zrV9*|O|MSsvD4<9PNOe8-w3e(|3$NztCm~x&>5pmyJU388HUf%V=%?5!2GGS=ibrt z$AG7tJ&Vq-YFhkSr7&~KMfSKWz*|0#2%LWw%ron%Gmn+&N4JZ4WHWQ2O>2-d1k;28 zI+N9AZefz`yxc{O z8B7^I2LlBzU@g8~6y>zaT^`(9I`rUIr}?DRA$W(`Zn=V8bh^UWK#;d>;MvcYW(`Ug z*yfRUqt|&2{9-7&dWHOka~@9aNQn>b@x-T5tt^3znbojwkG>=)Y zDzZMdXd4{D+z(~E4?Sbl54fJ>N*O4dEZ$6e!KkRmf0OVa(-}x#DjNHbcpe~ z+Uu3BdpP$qk4f|GOY7eQ?2zxQK>ms>Xe-#8QR6uS-0}}#hijPGE6K6x%v;MXwPNcs zKEl4CO;X+8x-(8<6@c&jJ3?abHDhmpJ3^X)34CbrJlT$gOQ~wuaXi8{mp%JZ?8PsC zh;MSzZ#yJh#y5!GHnBIGzN+$57MVsVOJ8Z{FZdeA;&IkqGvh&pDf3*1T%6S-yB+@2 z?D*wNhfA{0IQMT|r2I2HdVg-THG2N+xb`(1IbWPPChk}<^`XLqW{#5F-J|m;?JRzL zQXTz`-q;E%T92=qH`ug1Xr}w`iN=BRiVCv_KA{?G*b3&J!`LY_YwD67Th)0@V5MdS z=6PIddghF{w3BoYRaL$G2@zFW@B^kE?Ug~R#A?}eE8v*VCvxs zIQtQ!8B^fJfBrgppB#uRCf*++gd&soatU;zG$+N0-xFON%ZbaczNpKt~Y_8-Z*hDo0)_~Zkl zGTFk%C#V`Y4wvlJDUU*5ttbzAm9c*WwsV;#@b4C0{LA=eY=4^C)Qyg9{(oA=%wZ`$ z)qQFb^Qoc(|Cls3mPapzet9}_1Vu}_qvzk^mSJI>A5kV;vRM3^dN=A9eAG>HNfh(G zlal?zez?DmKd>h2%n9^5&*)!=LgW=Z&@|2uQPi_B_5}&?8*h#C3YDYx(PPg;<#0Fl zsHd@WRXmD=<_6h|Bsi%1{5-~3D|nM%5}Gmm2p)9j^T7Bm*M!O^&2>II(;wSo6EM~7 zmL{@?zFQLG z_sXXJ9nd|$(COq~tLw*`%q4fNGqy&r)#b3m%Piflvyi=C25;;^Ke)w(ZqHix2EVW8 z#b42}zKfF939QF*tr)wOelf?45b1e6OxlrGC#6I8SGm1TJ8Mrp9`_E8k^^7`6wRKm zL*Kb=)`tXXbsy1hkd$)hn|@lG@IPsK7it#%({I{+4W2YSD*JF&+^|FAR$UEz{q zVKUF!7pin~RS1#%><>aOn6@|$?^BC9{47qmgs;NaJ@Uevaq*3H!Q|%vZdZkUGT_~PeJOYxCpFF( zxDHkO48MH-=yOI}%jW8nVd3(`A1MQfRx_xMSJ%^NHQsN&G2{>YiE?)Izfo$Bshj5| zebUXcLyWUn*U8^K-Li|dIdT-b=%=R4cA704Madw?zO4Qc&bX`?A&C>=J9492CbLgp z4A!Z@VdRC#`Rij#dA1($H4;xoF{%W6WnutTAe*pYMmj z@s*{WNq6ly^SkR*uUsjNO&Iuxs*6mUq)6tGG|Z2Rh8@R7?=09t{MrtLul)Z@)3G~I zGz>coDtzmm$Z%PZ$|no21csl! zGJ2W;>2Z_qSI#4tr^BtO?veZZ&?A9;`Fp%B>u=A%F?}5-v*wxcx9yrP^VAeR`DeRM z@jCboMaRKJ-TyXRMp}F2sU=JvE^X5NYuItqFJ|oF%+IIr_pdllX*2knJ)Bbz5+=8> z$E*UL?7t`k{N;`g^bIg=ik7yEl!N)rH&?-TTwA5fvdNO;p1g)$W)*8U-<>@hzqD4p zbzm%Zdx+2f^E#jT@x!WUVqbJdqs`n|93F8!es-_*MDB}CQ!qUOi*vSLh_o*WKMDV$ z=#MNR(m#qlXIGyrfX_Y?7tG-t{hee9O}njhVECU61|I-FY*YFqrVZ?8|CeiXFc=kC zSN?IxJbq^X(kFc+=k>yuPlm^y5hmsM?q^?t^~f47-jkdWkc0DDdh7Z<#=bCY8n}{C zfo;>9y?KU8y1ove|9Rsz`IhN!*_%}7{S~sWJFJa=!VABjSC_vO_**CC`B8_BxQUPc z^JYHy8JXp)hkog`0Y3~w;Du_YGO>L~KT+3{ zO8+MIZ+}iPW%i?ItcOlLB#T!Du&)>i@8qOZ>~nkGV2!u%{}+<8w*i-!>Xw;%RQTJL zU)|U@LM76|>V8+rCH0Xv()o?m?CtK?FzvKWCKUU*ylwHZ(?WmwS$ftS?CLJ=)pgzF zjINXA_>0_!FQFk8?(NG+o$mqgY))#~Eiiv+zr%0-OkMX0cVR!ky7LQq&Ys~q+#fvx z%Rj-gyHaVM9bwwr`Hd?+uO!7^j+2U8Jm(|i{x((Z3;q_FqM{9~qyI*=(XIDJUz?V` zT5DL$-z{L-CoOz0N)9cJko2`hPQ4H**)$5fHJ`NkHB!C@Z+c@^q@h=) zy|FJlj8BW~_yc9V+(};zdBYpJNf@sgyxNNX_E zmypwTM)y$&9wbroQ2DfOVE<7mu0|F(?I+z{Pgx6W`s`?6on^rHN$)K>kMpvba4P)! zjIp2Crxan{Ei}jKlR^EduVrs;r$04*q-3+!SM@9#dL`e;aH&?$C#_dSil6aXVPBa1 zvx_|*y4|d|1M?HBQs7+l0DpMnm+Su6U>=w?WT8%4c$zx7iM$-#T*u71zK(Zx%VFgG zTV7*xvP;L^&{;~cGw64{E9&~XnIQyUv$_tqXVz&>uNPRC&OA?CsORfMhfG-t_>sFNaY={w!1z0K zh3mnUDC%$F5+_f?jyzZ3nsf_Yz@+=|K{-Pt(cl_P<3G9DiBXl}#(7(KkRVxB`(8jrv-j<~0OX*%G*d1bthJxlg*nY|`( zT+~?OVNF+5_Sdgz#;Wci+{>Hp;G=FYc}Ix0XicmRR%XwcAEL# z>`~Sjb_DvRpyP(0lkscwZ*-EnwP{7kFe&A8i5ENU(r%shkVNofaj?(06<8iSj(r`v z-i$r_S)wDl@9f6Ev7(G8qK8q>Un4(DH57k<{Q}292mC#Dfme87VU>$nelGi3bzY>L z9(P-x<1dozm5b+=#tt9ORTi7^sJ?Rs8x}<;zVpdq#zXN3rc9e0c9fmdMM}sfm$a`Q z*xyv#z3|jh+w_a%;4y6SSv;wIudcoooH@__+J_xL_QNKude<|)`mZS~vZ=}$1K<0; zHTCrueb%O#@PRMzjdL<7XUti?jtay!?>jH{%BdA1pJ!+Pif-}0C=Gm1(GxyNxYi{f zOf_ZOP%E%K>~vBr=Bx;ObJe`$mJ2lk)8B2agLc?Oj`{y^Tl|S%jF3IGy^=G^8V|^2 zDlWlhvN(IQf*z^IK7LVh=7MzLQnz-f6o*Gl-vvK0$k~oWg~<$X&ug*2chXJ#@#bG0 zE>$n%cMTk^lftnjn{Vw0?B{V=GuwgT=?mUbQ90%TMe#X%?dET~&x}2(>;5VGvDw%j zBuDqZg1P(5LDMEGPR1_+=hW8dH&S97k`|r1lRmqq>os9HGiHCC##x;YknMdOxJJ%Q zpzkvykFlxK%)mXtsoR0|{_S|M!@a|$z$ctXY3)z#xau13eDuEj4E?L3p7lc{`9%D+ z-7sa@{~ow?us6vvz76s}|GXAY{XY-*QQvF&$u9b2Fy%jO`jmQC_Z2=F%euvH;k=yT z^VKos>|*ipt5WC?nV7R1m5rW$C(Cz11Lk~1Q_HZYPpjK>Kr)@Tyzm1X^M}Zn*hPI1 z#9!;w(G#6=$&#F=Eb94&J)CI`p6Ojw9b21J*vf5A>5&YpO#P|wTM9(4bM<`IUYC?( zk9N*shtTDFQ*IST5y?s={+)u4*g6N>Is7#47~+vfk98mHk`KSv*vh7vjh~d*UJ1cA zA<1aYGWrxBWmcW&l-~V6WR!W=YMWbro@esx8Ewkb;cQ?ZRk7}Z?`r!sKH$+mDSCwr zX=Z7S>ba#^ zs}Pxm{m|-&P}ywlu_kl@vjQgI^t}iijIbP$j#{HFWd{5u<$eKl9wKImxA767m z_B}o4#0F0tOt)+u4t7AZKllA1yb0 zNmcfX-_jOoN`Ny4GpHzQ)xbHznO4c%x=*KP&$pmu;CI`i{~TqVrQ?ia|IU_G|N8Td zuKTLVb-nz9j3_3WfN%ILNljUN%03(FYWee1zyGRZ=H3ns%y0G1rj?WQ^91bS)3UE# z(B0&_8Tz3;t)t}f8=aRaZ8^s!1#2oYO+^jq|2F-!N~co>9;q6qqi zn1_3$(eLz;yMg0s!K%P{e#%gDKQjz@*A4bTHB8;8v=6>uuZCR1riq&ac@r6~`^>`$ zCX5O@skuwiqZ_R7!qlI7UiTMtSRIfBhP&jbD^#uyjXv+*LznzPdax<*vxOI$_E+)u zw#DBja?hs6LM7W+&K#&@%Anqtn;IfZ@XJ#CXZ$W!M4#fYHBj#}RZ{=|ovt1U%yV$) zw(PM^;~)4%hY-nm%`F2Hn(^%nyLTWw`FPVWhF3Oq)aH=+t>R?1+R~0c>2J6jdRdoa`dy2ImIn0R6_!}ZW1up6Gtp*GDO(tyf2ZYLF>bhS_WC^U1 zPKpa(5fdd&Wb$99x>x@C)h#oE+FHdM{H1Q+W8m_VvyLemURI*YQBF^f5^fo{Y z|BkNWJl${LnXh_fHa;|BeQol!g*AOsL$@qF=aD+>dxn8UQuG;f<#um`ESlt(D$JMh z@L@9ntk`30aDKdQ;@h8_Feer~W;kk4%wN@VE3ydDBNH=FxeJ zO036OD~k^Zt*zT65+5SV@EiZXr4KEB-Wfjoe9q8KWzslX(=XMBan2b!x8b4TlJKD} z)2Z}<{k$By!xh_gy))AYro%$&%^%><-#w) z*UBHtY6kh7?F zkwwk?wg+t84)}xv@YQ?&0MqcTjvZ;8XQb|$vlo9gBZ{-G!sR7;5+G8tFIAM>Z0DBS zL(wrKzsi7KEY^Me^3)EI$xHFa)7>Kpr$(RShxK&HC+E%g55ixZLN`&eh_3VEzXr{% ze7_a`pL<&}#9iO(_x;i7ee;LTtNK3!T}&|b0q3xNU-b0yZ9&&P0Dm-}=omY$>i)dp zYT&p(V(nk+B7-;_W$OQj|Bte>0JGv)+Hmde*(1AW@jwW{2@u@fAy{yi5Zv7Z!QCMc z+}#O5g1ZwScz}ci2~M!!`oB%j+@7<$z`gqm@WUF)A27aR|!_vLFjt2EI z-}s}U*p;*@EAmxwugnB9c(AA*V`tVf z*JJ|EgKQ+DwI7d~n-IfKzkm5BQQJ(V4`VN&XtkyHeg7kxe-$lVvwf@Ti4b|*(I+Ka zgv!oA#D4c-J6=wgZB7^L3oUv7smsK#E@s-&eqJ4`!>7+$ZR+lFG?-U{NB`%My~LH6 zN4@?QQ$I5;zqzLpT}EEkx`#`eq8n;u`B*-|=Rap3GBk!?D&`84-|-!F>U@w4#6C0` zWvjmdf6zY#OSiwlb$y}7%O7BX2cYX#bY*SSG4TF|^>4>eeKH#v-S?e{r%60g7cz&} zd(kP@V!z<9HOVI)y$ifSbal2I0ZSp7~s)iH(@1^-T=o_B;P zpPk>rr}mjXwm$BY`)PtDA+|nYM?+*+g++{HgrxAX&(oa`6uP-!9=&V7y-%E%D1dWPihu>3ALoNsrOt5}d$%ll=l0ekBhc z(si4B4S8nuNauR?U46{i#{6z%$r29t zOTd*XS~A?U<0sY}Gti+YZBAP**+Kkok`?Np>!Uon!={#fN{!;7QYLPgv`ZiOEn6p= zG4XP>en-OO#1q@>k}QntQa`_cz3e#~SjR2E*e$+{T_gIj(qna=*}LnuyaXRHc!GW| zy8ky;n6`G_@A=lWQ%!5U%=!gA_~J0uSkuo=P1EnY*Ul@|(UU70jqjvMmYrRJ8akiR z-{^E%vAwT*RKL^P86Nf%GhWrR@4(vjtb*S<_7gc;<7WteJ9BnmFJ3J0n}<4VF+N4l znDBP69EPvXQAXtwmCCah9)T^37yl)VOXzYsQ^jbAkN!d-a>Naf#J;i^`oe~-!4;&{ zW5$`*KF`ivv#E{g3+j5kyZU=Gmq4#{He3#T8%)eiuN1H1lR4~tPFPqDJCE~mgXHcR zGpA+8-_&;lvDJ?sA{)TVbf*vcz`l)OKdvaVNU=qAU1XXFDw7F#+?W>mQ4`$yyeb51RE#`nv6<<&wxXYZIy9Lx#$&gzW4*O&M(nxpecP}a1y zdOFn&{3~bi%YAUxE$3q6ahLUzb;73esr-4^C< zr#oe>eYZ;lNtwa=z5jrp+uVeB#Lt5y?=QN(o=gkOw`y+Ul}-(l^2ouRRDO~E?XlJ< z`(A6S4ej6R=%Q`6zYCMWRN00U=yQ;h#iC9BN`+n+>}7$(rhZiVZS%bHE8|en=c`OV zeSaa+zdPq#@?{Lu|9UiL?Om-CUC&H>-T7utsjv_~0G)`tjvdUTrr1X0(RF>UGq&@m z!Xz$x!-C-BzG>x?%h`!l&b*LjT!ifWDM+p~14G=0Slr^0HoHS5+2~N2`Hd;e19bK_ zEqE1JSL%8fWHFJcMX(#+il#r@y{hwg1jfusr6od+Qm(hGb#Kz)V*|T@7cH?DoE9c` z#<-={W%O0;O&vBPhL@t#TlG<$2cuiCsRwZ<;?c~9;n{6!J19uLT1Pxv)*_pd)&U#J zx|4oIhpXQepyZw?kHNMKr zhk$GH%7L5_va%EL{|11c1E1qfL(C@99GV4xoC*I2)L-Xzx(~Y6;%Ba9gna&sF5mK; z9tmac-S!H1$GlV6rEj4VC0ah!2Jy zu~TvIDXgiF*>APLzGWhN`3BiSWWrM7WTi(({DOEM$$b((r_TE+$9@HUvLCs!qF+au zwQ)Wek8Q|d$D%|3^`~$t(O;K6Z3nj$xP(ptJK$Wb1rhVn>7~=-w&4I|5$rdjqe+AD zdxAdX-p{75+UX`0GW}3p`?(GF=zcKk>}5M5_iKvmv(GX8+za$j|3;1QC2%v6&3uvX z1N;A(;f8NNQY-M?D(`<%fLFvmp(1ucHDe*`d9M5N`HlbfW@N{fzOwHoY*$<^Ie%HV zyL#%c56EntIi9|x%lRA($>x=M9M)+FuQ@1OUb=N&3t6{HRPxK*8Rp4b)*7j<%mOnS znMQ>L$&;_FJPuAW-}i#Ox1z9v*cO5jRdf;iqTek&d)%d_%$Y6B z!IWAbF6+T&R=t3mv#Dz&{F!}y71;bi=n@KH@0#>-IC?N_MA)bIeitI=k@XF09xB&= z^vD)$<@bZ%S==&6Mp6gI8u;YW8B?yw=b|5D>OB?vV;4|W_kkua0@IEB1)270(kNI*4KDL|xjtw3*Q>l=X{u`~k%f9FDz!Wtd z`r8HzbpOiE`ZN?7`bPZLq}Y$Yq$b!MRS1?I)tS?f(bQ=iA)hi{K)<2vtU z*NB~q@1ifhcFUA&E~&c&d!K$$^RmliAK$LjA)T)U*kNwfeSH8fmbv=6?MI9IEdW|z4 zTP5a- z;hM_2fAod_cT&k+W}cqQp6KH=x~(?U4419o9s0jQKQ`4T+mGq*{nBdZd&uYP65<-vpYrkgaYaeUlG_MJA)p57&E72c!GB?Vcz>F!hs{_BByDR%1umktxgbGf!R08d#PUU?!aOjy-;p zM)>>fqWjRFfwyG~yzP8zKiMQda}&PooK&_FI<>0$z3(!4Wl%JDtf^perlG$mPI>FL z*L|ml#pBs|rRf)#uex3zza1^Ngvlq216Ns}49#om?O12CwyLyC(&~98?Z;r2ZtL^! z*w>E*8@YR;UoJF)cSD|PQ|l-2mZkXaNnnPQa?qj*A;gyf8^13{xU@}%o#&srt?m2j zxWd|-wPCK=F+WrWqkkOeuqSh-y#Q|1rbor`H*WPEb?reV^9{dybiHi9sgEJa(18+f z-KLT?gJl|+)C*f(vhx|St`hFuBb5Z&XdU<8pi$O?`!p%?#77?=#`wp?KkvvL5=p zy2NC(c%}YH&}CHeNJR&R_0V0@zc&s-pSRB^y^4Z4tmBo#*c2;@xC9@Fd|~4Q;{Jhi zT8`h+`&;nI(=J4+9|#pM*rJr^)an#8d0iR9_k0p0!@hW*g;eOO>o?&+J+?wW)7RDi zi^D`p6gBlXO&(OrLb7n|XuyXulFq2Dx0hHXf_=iKoI`m<@o0nXu-;Tf?bYl*-83*nLpT;{fi;6uCWu`t;XlbLM;TK?Ek6y?tBybH0?OEz+_l$_E}pQRyJ^uw;WDKhSmG zkoG%xMBi`d;N^E+4VR+ee!7E2x}GR--08Ol{vUKm|1QXykuNd2LqXOuHcZa{j4T!2 zAv5EvGW9VSJ@S%9#MYxvj%2QW!`kpAa;(0{L~1ZUXJZV_K_926rnO(JI4`hW-zM`) zw_C`;s_D7j6-i#O^=I}y9kKUASNXa&^7@p>lUc`C#${i{zH#f1#H{|rBjq~k=PQ6e zPwvv=8WEBBz={kw5h~>^`*Bs4#A)?dxHB$T2D6t}^bFo5n6cNl6tbshW?p!I)B3j; zx%>K)`q`hb_p>R+c72`>-DZ~0_0`$yO&&An>A8Pg3DcHaf?aX~-O7bk!E(Bxem+w% zT$Nle1bv>zcufVb^%KL4Q zd{kKX*IW}!xv#U{{4Z3lhhH-Gz#m^pQzs2#2ENys&uG3o_o={ds*k=UL0|K}aK>dS z*7?X(7ujpxH+t;mJMNKI*ag@$X@`D)hKgWOk!}AsTG@v9QL|i9^p2^+$j=npiG9yo z=Ht}*oyYs=wv3!k{l4bVrF}d?e_tWS!H4MMCsFHYI~aoH*WD7)2fs({Bcw(Rza%^W z=A)2HHn1Mt80VJBVEs=v3X?J4fnP*k`^!k=3=ez~V>h;!=nFd{3;*Fsh_q}LA!pC{ zWF30@maV+964}>OeBRaqw@|28sEl3Wk{{5uhA#`8tLDX^46A}9+ihg3EAju_Figf* z4;4Rly^6|R&}*~(T?-xt%botLBVT&u5<0{`_Skp8#4zuUKsI7i|5K)qObY?yK)>6# z3g3U|Dso%Af(C@tJPVlHhI?t!VoGAeY&1I%%WVE31EY$zAk>DY`lD z;LD&|)cUqlG`gwtS%)5@0diJF+py2G$zKl4ja&aNksbE>7`W3f%)94T)^l*m`oS_k zonI=o)K4C3t;>6NB-jn~xZRezWivcha?1S!GO8Nr(O;qOv*|}lu4$5DqSmd_^{&r{ZO6K&sjqf@zK;`Jq|6eNGQ`c$NPfh=^ z^T>-HI|Tky(J=b8lZN*C@Ob`eY>=e=-78OooCaXZn;K(8c|>HduYmDgSGRfg}W_e;V0Jp!+KQ`OcefG z3Kk^(3p&$%U5TZJzU0DpU^9@H6=v_5yQ-c~GU9K>NqI}?I&xm?c{*xeXmuFBviO0AN;N}V>y9bYhFf8>^fyz& zTFRM_gQi>h9>=BsoTfy+ng-rzE;7w?bxj}mPl9MpO76uc#^?AUa`5;n*~m3+xyQY| z=piRe1wRx?Uz}hCF=s#5Wjh1zVJUO4qVw?s>#b5h>|2iq%Q5)y1+U&Gkr>~CqaNs& z-D$w9O^U!TA-==euPPdu*OYtRYMs|F$Vmq|bQp&Y>3r<}OTh{Zu=a8GHFdm(kTe-% zVOW+Bi3hI~{!3t8I@7B2BgnTO!{YI{tS75RWBbecrD!_q)b;$}X02F22S3)|_!1fU(myo^rGVnqV^)qQph|INQhJRy|Q1N!u?^Mrb zdTjC!WpzoAqpY<6$keNje&5yhxIV2NvSAJytJuR76Le|p}hw*3Fgt=->RQ@e3GRN!a@LMcG zXL2D#7M3>Sz?ru?4_c$knKYMf=XZ?7_V6)dkjeebK1or%3fLBoF>U^+DZbl&GkFe6 z5+v1%gvi|0esmMWm97h(1RcQdU;szv)&2JNM?UEXpD`z%ey$>8Ls1+2hADDc{eR(d z^PU*UCT+@}T$k@UGTxY}Sj(D)%5&rkA8!nnDe!2D>W8{y5_8KE^xTT-(ubDpe}DR) ze^2Ol3uoXX!W$u(hA^&D>-Uu+hE+eXgog`VNBn> ztnFV?xre?2}artXA~eP!}}`V-rbl`uQz-(e zMWi()o275~sbQ#`yrRp|6<$VB9%RQ;uuY!+4}A^!#A2{4(NTx9W^ByE50#=8*uN^O z0p|8CdDv94w|y4!G>-r-d0(_h-$-=X`B-MttqZ#8p6+ zo0hfgf1y2FO}a~WOdCZYcYHiJYTs|u2$}D6^Ne~&s5M`!^UoaZup11VqANw+(!52G zWJsjP{OJt%?m@m{Q}wTP+oi*Xr4_o27pdIxV1T|~Iha_FJN5Zx_^i!6!X>;mK1I=s zC>nUclw~}A-u9rIm=H(5=l-wy-rwLBZ90@m`MisenB~lPeVf!PMUzIz@k9Fim(0}j zOru)(qqKBRqbliZeL7)}jjsqr7uOS;6d6T*e3>i)FPt76LV{nS&TIC&)p6!j_>O_$ z(ym*u9OCEToZ{ZRbdz=_I`JU(I zPJ(mr@r(&4?fAwe7pt1@O$cwKXe{!z)YxwN$AN(b_t^_s?3JVX+a@gxlUMU2m}Q~Zc*7v7=lFnmrhuU{dq_AGd|f!B1Z@7tI%+0PCC6Ccwt0?V)N z-9X-4&zg%O62MEN-wCmB0`c#gdGT^XFw}gLP4~{~@A;;b89SHvnlTx(7jZ@BhDz8O zw`_FSLLagCUOONAxV*4e=2q~?u}Wbw=vVU|b-zCI&Swkll=|2Z`Ruuuy6>nfODtV+ zfv))1=?}kzEm?QR-btm2)yjO2`t77C*hj=>&dd%b_J`Ew&VCCwX|9;F2JCYqQ)2en zii#(Pf1R!Cqe}U3DKZZEFg#KciaZm&YUpW~T-ofGS9f$h<{GJwk@Hi(pICNVA6s+! zV|eVd@Pd(PI(g1So>(tb=atctbCydQB;UmGOYh}_{ngGV5B^$uAN5Eq#)G25+fCX@$jsN3 z*6lgnvi0;_@=8wn%V_MIk`#`2y9!Snsbo|JjrJ=pZu z;99zGoGXK$L$`ic&BZ=x!k%i>Rs2Q%qu;apv>rqEzly#ujl`#>qOVh;56P#W$?+85 z3hTgm7IVpf_NLFiPw4n}tH1e{guRKs`kSt&2G|WaDSHglHZL-ou|8#?dES{`olm{u zmqg5q50|p;Z!+Jl?rmAA{)=26XzFkO1%1u_pK6eKkGl5A;@{%1f4!C3%qzu`gv!Sr zY=xKUva7UzM8a~bYn_pQD4KIHYMDnN^Hp@dM6i6?K(|F%FdUKTZ}7)WU!vO~PReuk zg)^&pWEge599}rXmohGs#5AO+HM_KEc`i%UJzpCSx=~I3G zOgmkMH75ewu=Ysvt(EGVx$Dj%o!g9Vfqi!dW8}WYb6!SY?4;Et^*fFu=UECq_-s~m zlZVaof0Q$A70(__sKV-b$-jo>F+I>1%FBd!4TZnzdJB)yG_&Izv>&eoJgnZ z{qm>ykDm-bR~roIFYry-{PH|A{#O!)OPVu561Rg-u6@OKy$zFJk_C>XLoGehC^3En z%bPZIetXM_>}e;3NRc!l^2xWz80HY~k$w7d_D;Lmiz&Kj*;@qhRzD zy~gIorXv~gpWayazu8|CUjkXkKg1Wj(Ay)s@ek0A7*}x4ashnot9!)CX^wmz-ovIi zr}SCr8y?9u%)V-l*NcV8&Z$;Au)m2}G+a(2!#Ft@J6`6mvB+W+C3o1&J&K{z?~NBE z|D?vYeZ5C!(6^iXi=L+>K1dV|e65e~e?R|0l)Nj{t`zpBhFU|hczWPy7vmV_52VSmDge*Ahk`!+9o|f26*wh$Xo(I?x z*z{dlo#!^>jQWIBp6uOVyi^2PJFk|L)4RAA-Os#euKJ)~>;do=}2b<{M zu7${A`117KJ@V8GkAeQQ4Yn!qu%+tDm~J%6^v|u}AQd$p6D;dqv#09M{P4Z*OMNW7 zm|X_@*dIN3p-A`kV6$)21Z4V(HWxrPiLKI*wBhm&`Q*9#$iJB56#Y~QKXT{>J0Q#b z8w^b6d&m%0gIWI*e{QU?mk;1OJ%dXMVb}C18T>7L&a8^yI?e`MFpH$!Dme%kLPTGJhMp1wCl{U?1z3p(zD?cKa&K^mZuhMiH zsGq5mAz1nq^2yKG@?=UvTnTI5zh01dU>Wc=j$W{QS@zG}@hg?yjKN-|bh~*sh05%| zu@kKjb)4H}v5y<7n*L;8`!UFr`R*TH*%=3!HQ4wB@B=}}7#m=hqv-e+@L9-aqoeD{ z(wvm|v6+|b>nW}I_DLa=w&^#-E5cT@lpp^IBg5rMYhAwEeqE*?zye-R8vQ$OST-^H z-kAK-XEHp>>LoglN91i&PsjXkUsFd9x{{>*;PGYmLuQ*D49;74xhv@S z@^59IG!I{i1Hj0^BTf7rAL#hcJyV-Fq)$z5X)V0v2=H=`E$oZA3w|N4?mJH^=((Xv zUZ2eP6Fvt1D&IPnd^a^*=2(7Y*MJpi!nog8#;h4Cudh3Jr7XCp%gv&$FB_hCWC=2{ zA6l5VuHqd|DvumI>2aNB3v7`Ub;h@ilNwLQXK54D-_*S^wF1kbu07evTAIrxuF}MO zEJB=!yx_s}M&D*CeFxTsUl)N7JE69 zRdIZUV{193V5oHOh3`i8PI=!UV`HD&I0-Q|tu?x?B}a&vCQLT55ATLf}TF>i|pv(L0u

      -pp=YqX-2Tfy5RFVCFNEBkx-WN&fP|J40*$iEady04$D z**#RoY{RcK`jo^LFa18j|M;)kK$CE0!oYXgcP==v)W`Fi@38MXk6+F6%TO=@Q^5+P zXs7FbPkM#9)@_y;y?JNRZF6FRSDsV1owkO_A}}*Cp2CAK(Pdb6T|Yatp+{= z9#}S&ZqhUKdubwMbvl>S!A9meW7($s*qNNAADy1(ktvp*z`kc6|N2_@lP&m(-rrNV zU1|$UKI03IEbed0xrn(*(MM^~N1g<$crZwAY{l=!5OkEITr&Ft>*Iawc0bX%KfBF( zH3=*|_@>?#|ImJ8U_I)T*q8Ru^JHJJ5l3H}cdGl-@HrbDrE8$)hpQdT8luvz;9EbL zAGNOfSbTw<*91$}rhf0k&h#jIul|;OVJFsQ{}s0k>l!Q*!M7}T#FMHf_!nSb{I}(U z>rDkSzqvXEmL>1*Q2A+%X;byC?y*VJCGeWMUIYHHOIDMYx@OZSMX`knHuX@eY^ap3 z6fP(5JE~{|cFi`Guz19iVB7sS{NM}VwXqNTBXfw{n~ne6Rc^_=0Y4<@x8~rBB{%g@ zV3ki2qzaNS>_#I~>lw%ym$_vI`K1_x9N3b%CdO{+!30w#_1sYA?dWJ1)-oF+)*8{iAH9H^sxEmSF z;9;SX15AHxbn!Nwj-k(TO)+C@h)_Gzc%Mf*(WRNoGnyhGnR_+^F#;a5{#|8H-crs zakqqbA!eGT`%fDhgkHtGr(9m$hJC>iY_;%v_IuQ^{$yRpRl!3ls*L?cvsJnskCf8a zod07m4@XCtEZJqt*zmXbZuoDMA6ZAuS?Dkv^R;>=5k9vRO~TgZhj`{)?LV+TXqJL-AE>OdagLTCJ9 zGlx3qIQ9WIhw3XOu??s+%`G*0nm$zZu1Vd0R?a1k3W6*G0<)Dc$QasSUxxJttKw|CNuwzy>8C4ldgPx z{avm8(b>D{#}(%iml6H_w5H7Kqk?2J>vwI&+*JH6PZ@5CQTjaCJqfIrh4dRI?dyY{ zA&>5V&lj7yt<{j|+fO}vWpFr{S5t3AUogh3y>-Q9DxQdG1+M2 z(x0=hei(J$S80ClsN20Qe9o!X#GpOvm%^oWc`Bh#n2i3%rZy=}U$(EQ<1ysvM;e2V zLRO>bb%m(untz7l!2muFPJ!1pe$Vb&Lw+cM_B zeRI%Hv2Xt&lV8@N+fejiV0SLGo(|an7oNt+wQ~F{rDF$V5huz&|PN^GD0Tv8bNQhYo8# zJW4I?<~U?6ndCs+3_=g?DIh+yCju|lfu4q{?g}Pchle7 z1q0Y~Oq1~F+^gVU0BRJL3jCn=R zdh4S)?+<=4J$zRAj5>V+YcF5x7oT(<1DE~cU5`JZbzV7QVfQby4s$uz;3Pqk*$HIL^es?b9so946 zCF>F5*1>mu=l4n7q7kwuBtpiY!2jSk;N=Ph$)iX(&Y9rH)4jldXEL*_7(z|N^Ju{C#q@4k%h*>&Jbv2VEj7je$gM$P*s zf33ea<452w*;oC8tyq4>slO6_jKPi<24nx_S?p6k3X&uRJd!+1m@I*(@PlzIIwY_j z)Ejm+z~9LU(?0fFQwN#)S%!QxZgz0eZ9?R8hit1Sa{4NBOrDF^BBRI(mbp9eGY^8L zi_mkS%5&*1o%7Of%{)`JF8gHG#dVCSui5vExbaPd%*~|d*{om~ zDrdr%(LhtyOwCkI{~H~J=TH<6nUJC#%w!yfEuKV(7kP5(H>9;G64kD_IH^z%hx z6B|!HJQwKHf&Z6%uFISk{7nhgh?Za>rv-bNjbqI>+UYzG%rh_R z>$ODPdm63rplXm`vk5BqVo#j!-{IPAsxnB-865ewxe66C4r$c0WY~4P8 zgL&D4Y)#RX>+cV8;R}5neZnh?*pIm*qOY^O2i&q19~o_a)Zd%rf*zkgAs;@qC`2Aq zVZOYA{h5Ua-DTN}tK3f)!H){_&j6oSnrDhyZe0R+kY%PFdlFyq^evIaJJGu|ftPNL zOeeipx>D!C3J2_%xBfzpa3guBO!^64D9H5V4rjg8nfabSs+%=My>r3qsO@2wrO0u8 z?{CK*RNX6mgLQ)SaBe2IluN{Xa)teQF}IYqunsECg41EtLx?Q-L8Jh7s7q1>zE`Dr zgdAAW_JQvY0spp7Ar=7sNB%?b8;W`#j@s8&VPF2FuNk9f@b6_)&PaT9YjmF?jd2V0{LQ1mUjdPU)uOuGDUroGhlHjDA$n_XYaJ=)~iAiYmKmfma}d47pq@%10@ z%}ZM-3UCb#vr){e$G)uP(V( z+$Z^;pce&0Qv+VlNtLeYGFI4S%Acx5u=uM4N!eBZeSYllg?azn7GPk}yT@2!@>1`L zSQ9m$)ZiZ4R7Fp}5V>}QsR1mPzEeLzorCB<0Xk8cj5jj;Lodm}!{**Dw(j}&Jje&*MTq#lhQ z7*~Y!rA}<>kOV)fzxgGHJQyUb{R4U=+J!E)UE za68%0FSB$T-f1putFev7m&HED<!+R9`(Q$ zgLyGJ`n7e?X-8~>sE&g*Z`&3*v}r(!(pdt9M%7Q^h$>&-mThc&g- zFJ}A>pA#fPMqv>Pz^*58Ft~KgjV*G}z zkAy)Toyhb%`}tw$i9bY_EIjAJHRwnmq6?2S=R2P(X!%U(wqBRF0y1rHL#cXH~ImeOLsy8>sqBRogq}7fzeBo zllZ$uO@FJ4d^&supboU8So7@^$3GEaq$0xIL?;?z%B<4nYlKe~^kzj@ z>G@`6!l-3Y=|a}2|L6pE<2U6gaa#Tek*U3OI}900TmyK-X&Dt4IPjXfpS=_|@o~fC9P9rYVuwbige!HveN!+V(O)fjhs}5aa5Srl z--bWIpDdg7$j|wZ{bWRMHUvDCqG0&E_f!Nwr(>`q>*JLZ*!3jEUQN-hFQfLo`;WjI zv)53x1zU@&Ro|b!|JRAVo1*-g-yfs{Hmhsqhsg8V@E6$5ZDZ^xI)IP0^rP`9bHLQk ziYmc!k8&tl^nr0d5F@)i2e*yyOL?$>jVo%RK|_~rkY?^M@oP&P%i8KZUDV;fVA zz5h*pEg^P$tEit#mh7=R^|YMu!lq*%GI8|$zcBWPVlVU2 zcAvZi8}&2t$!ovp?;F6i$W-cud5?W>DE@C>eIHnM`<{I)Xz@bocR{f8>#-?&x;IFE zuZ>T_LF{?*Mo2aIDVsJpWZ~-C$x`N?ohCK~1CNV0Ir4On|oY+?AOY4M4d2mNVJBP|}^ynku<*Ks>4rRRl7-HJ- z5Ll1g3Ek2Iy^f-kjy+|>+Q9iaK`-;Ix6z@Ee&Uw)ZHd!s?a{Zb4U??!iDjl59$4j> z<2C*x519H@*A(r9PmPZH-zAoMO}{+OhrckeEb)+o9;x0zf5)aD0?VM%w_<3uWDk}rtw)ksIE@DR)gAQK)l3`dE6f>NLL?#n zsS_k7=F~BCR-gD}596pPeLV~Q&N93Skr@|t|DOMksZ;g*A0NQ;se8}6qo-}}me9Y| zFXRvGwcBZ9n%Vwuh$0_wRKV9F_cNfj4=cugc zZ)^&;^uSx_dqG{J@56T5_7B3P8T*Yt-i6Dj=yGlHZ#3WZizQ=I_txwTlb7fbYIXc^kB_((rcP-b3-sODfRc3!wx+<%8>+2PC0XD6?Pd;$~{4UV;2isG5|hcBXY3I zMbU{)50R38hsk7Og7PDjB+~-;KA^GUM#_^UmO z9m!B)WYM3}VEGiS2%SlY`jl?23;FDt;u-_`i9-|8} zA<=~#8XH&!yF9J>hsZ}Oh;cg;f2f_J_MsD&+)Ab2gZ{7D#UMFHJd{4@voD})u7R%O z*cYrtnSJt0kx-d{J^#h;bv~CCc_m>#ef|i!s*~b02$wZr>J;6?Mtdx{ZTDxUuY8VP z;6qe!L13SVoNgaBMvd^*5xaM=Z1I{rRk}GDbw7AkQ@7Q_gt~kSPlU?u{KS^{0*qI6 z-8XtthSvOTY(qS)VY*FJ9p`S$oJVnsP*bn4#J1HqD;^<>!!;_n>y$htA6-q#<{ zb?}lkOwp<%2 zX-!{WWnTY2r~IqH1c6bRol<{;^Bs}T3o<4fQm%{LW zib{kA_NB#OoI5^3FM{r<{sL3xKDTv0dK*XQub#cy!z-zfuPUn2AD!Em#3g{gKN35z z&#C(zki(pr=8;|Kr)SkR- zwwxRI4HeHIlluZ+9D?uHZ_szlP)}h`yTd2m@F2;F{AFq@(^gl|sTTSNJk?5UMVEjH z<@*;TF!%M-l%udNSEr^?$7Y@(AyN_ENYP@}?@wsYMfB_G$$c^bnP;sO;gT$UuyhOF~1*w@`QpNBa^0{g2bNzIg+EPFJssG5-5rJ)t#eV5?6g)s$ z_?LJQG6+nTqRyX&NqTsx5@qn6%35pFqc--LK4w8zY*WT=QTwF2mm#g5lU`xBS$2+{ zI`DWIIr`D3tTFKY^;?BV%HDyK%3sLIV+_LYE11jdd+1wZ;Lp3`M{jemq}||>-uP#o z?7*L>+!r~p*2loAHDev_X8C+6#5$&^k1JdX?ZqEZ=5UE%B1@JOe@1V;vfYwDemC9J z=QQS8o1Vb)L?$o(RZ?Q}UmP9iu!-6 zL)VrDna;VN!NYbY)(0}Q9q2$dWHj~T0$*@5zF$gXZ*5cd`EL0d{iIFZv5kvcMBhIY z9$0TTMw;<-ArJnyvgrO$>Y@2AJD)?P{Sv3Hd5?YFJ|_55&uu;5=qvN+Uw<_RPtpZn zpodKRs=Ldw*-z0YZs_{Haoa2NkZE2tk=@O~0*l#{)$qm)-Snts3-q3aP=yG8D z_W&FCF?;gdmhLt*qfhEZ!_yr9A7$>P!ab4?e-!t&_$3oqq2a`xw5i>~AX#yXIcB@Q3?ysb)S|Q<3r@ zpPw@>M5@#dmA2GlI{2@L&5_fA)yT~pf2&})Y$9&MO@|KTGjJG+>emOy+5-Q@=j}I| zV=Tv>x8)|{pHIOj(_GWo3{QKm965svyrzutB$J^{u81 zcDjB?{SrLJT<^HkeDjm6A(HV6)BlGzcFUH8raaT>n`_Wf9(snKfHbE5?7W@FGwdlA z9P-O07nqm+_%8#)ADPyci25Co)2QF>^rqja-?8D>R?Ul=pSow$N7KR3{23(Q&BpKN zRP(*+{@=*)$5Ph~@QXDX-y)s5hs(KcW*n$AuRaBXJ=4tn@xM3qQWL$XO=sZYK143$ ze*Z=#zy~LxKF=LRMh{*fGEM#V-@j3%@5~z1<1xNVf=xTw`NW7Y{cBY(pCldv9{=kg zDZ0ih-A{!{=K1WG(OJ*PNSu*Z#J`D!ObA(rr#~`xe2yqu9^WG?o9OSz&)T4itDoycCIqc4&L%UEo7o3iIqG}z*&?6jv@gKR2XB3R1j z()owMrzrY$zPYb{`_h{7so&4Qz}vJ6K4vnQ;~3cG|J+iiD~`U(Nt242^#9}x%=^S} z{X127U|rkK?-jq?#5ZJQN`d@2J6KYi*0aAjd51L*KIS`g;+tFRzLXTanoSceo%GaX zKIwYH!&XdU~NQ+uhl2@&3ZTwX{c$?hkz8$1G;- zJ?QF@d*FmWM8z7T%R3S*7w(`t*=@e5qr=v<4m#xqm%I``yIX$6mM$`-OliiK^Ipq# z$WVVIrVaR^^Bv7MIMal)|2PW9_yqfyjo9ku%I_lHHhQid#7o9rpkzFqcS5C{ff_ai z3wINrGD$tsCVteis5CW45JO}aGD)yETdPONd@!neI+*%R3Evl)t|9Bqk~>7wp?llj z82uA+gR1ed$%rs@sh&xMtY`{y<59or@;rItlT7F^Y$}A!S!BBPvA$9W8=mRd_$XRk zir8KFvj3r*sh1m7^cZ+#CP~M>=qQQt)=t!rz5`ERQ-HHu(LLOkFM)m3pb{&bw^KcQ(fdoBaq8EX^^Go zQP)<@)BP(BK3FHmcS*ycI_>Tu$fCY>OSTpvk`ue8ULSeo&zB;}thRLKXP+PWDonb7 z7kwEY`>Z%V`F*+h)&=W`n`GJQQ~+OfaCtiEtlHZ#XC&uzM zJ$bxtpU+pbp8gpuIgp>FfiFK)8#@AI+C!~++kq@5I(qSyN76=`dsMpgLws_-II_+I z`l;@W4@EV`v2VZ*>J@c5v=jS7uV41S3-tH6WhA)ZUf|Q)Pu2CiYjBYCI}|uRBiJ8a zFJr!2<=KY){ab7AmFcRU1HS)Te^<3dBIVHwI|-8xsoEn*Qsd9D%nhCX&GEoIRr=ix ziCymx+$$yd3~V>}=;$bM^Qd_^(>+8!b6^#6ko{mY7C7%jfBsE>{S7IO!arg=9V0oh zNM=QScUmx%imI}XMPOgDbPscJCF~%O9p7Z`{0@1}5HLbHy&m~(OVlx_o;|?+*gXs0 zgfSX1%`0=3N5~ROz7v0y8N({=G}_Q6H~JYxOXCs;03BZH3ZYVrc#I#S=E%zT*K^6} zq2W?`T-5p+=Gaf#c^vN=ec#L01&pT6Gq?3gibkQbXSSI$?B~^S3V5-f&@BuG_mKuY zN!IVp_%48a%cdS{1HZN1SEl`cN@vp9>7B=}W1_$RrC0aoklFY^XoBzlf^ON4oGW$` zGmofzDkC%MGdgfijTeuYc7K`r9FZ0OuJ!%Iw$bGu@38++d1OIO-nnmJe{bfnv7C1- zMBaYlmNQvgl9GMghp12`Q;vfxOuALynR>II&1Cg~Qmw%}mkN_&&54u3zH;(iF#Yfh zHvO~&-hW--H{18r@#jeT?COb_YgZ6+?tyO8Bp2WzP6o?ee0aD^688+7;_4637vZm} zC76S3J51T~;7{gL@Ur7d;}0p=^ohp!{FzZ!By%kAXvpYS71kwKjtsmBx@eo4p|iE= zX${LJw5Ua4NiC*84a&vO~foEU^Sdn z7dh_9J;=ynn>u?0My2_eU}$!Gq&9XBXMd)jX7R}DFYzQuxhgT4zK6VJ%srp53}rB5R-z=kX`&0pq{^_I_rRqVMU(>eNX z@nQP?v7V!sfHztbjP1x>>a8d^=Dwya?Pq&V36mV?3;p?Zo80*|zdX8$zPSPZ zgy7%Z=;x{r4E#3lQ*;at4A3OTZboo5)3dqc(Q==h8W|?r|FGX=j>{99`psPx**Ws4 z__?Eg&sKczC>jkfnF4<cuxl6q$Q0QST13BS)^ZTLdBN#}kdrCiu*GWI_jhkwD##9uiUE|oR~ z)`k5}b?i`)wf-Mn*T>QlhZtS$%N6>Yo6Rxf=Cx%zoOcM=ordrkDHu0vLgn?C5Lt$9 zCfRXfcBc!IgUOIP^IUdo&OaU+IDXC@(ZADpb$|YSlrDRwYsj*YJxxia>oKH&dAGB? zx6r%3M8{YlZ;&iG4KJMCBi<2aOn++GQ#+rz-8h_>0s2Z-##)+dL9*pDd}ZU~taego z%Bbf%CxpoS+4}nQ)c6tu2lwV0z6`zqN47$jy&brhpWw%%qa;Jj)i{S;@=qNwMUTMA zupcNjBur9I#2-95i-h;#Rp7t>xlZgeczT;MO!iB|WZ@FF2AySb`>H<1bjZ~L@91CM zE(XiMPJVfS9OmIMk7QtcN2VIsnbl)nR`fA`(xXsck9^M@o_bo8J5er_++{AM8Vt^J zdyuq$6fTt$d*l#uoot`$`ckRp_QK{4*~W287H&V;;M2f4R9%0@I`ZQ~(;pH%HuPqyqXeK_H(HF!7lhHi~aVi+gb@m2H_ZZZ74*X3qCZ{jNmlS>w zj_nMUah3IZejKXnr6YcQqoZ>5^wq`eB^B*1Dl%#lxR)Fe(jg02;79s;>K$QH87y@{ zWUCFoK|WL2v`1$4yaQ%=WkEZa+?axIsXgdBPXx;jFb@Nelg$`!`he27ui&1idPa{*7MI1Fg=ReEKID#+`Qu~b{TGmJyf>yW{p(&&jbf)Q=BDkne;6&O!9c8aYOungqVEn zH1=^IF~t>Cif7ge^}8e3oceq9J@s4B>{CA3**EaLqxb6HZ61b5qssVIK@ZmG2c15s zwpRvPSbP^4#`Tx<^{-Ci^BJtktzCYZge@JPSIdR!lG z3+@Fh&P1zE+V54zP;g#P;Tivp9(Q$1;Y<2m32N$k+fxIYZQ*IwwYAKJ8@|Cd2V6tQPsrq~eTmBF zpGQ7P6e~==ON`9{I=fuWbnaJE2>xw+QlGd2?Hzl*o9XlzSrF=xWv!hh0W(?N)K|es zyvtlLBL94<%eIpJ#_vV{z5UK~HF*WTCF-y7)3Il9*ylt}F$#Y;Hl28;=Y-+dyk7eq zKZ0Y-9JU0$$4T$znEBw=4BZaue)}w58Ss&A-_`ka+a<5=mCdird+w!m=7gU1wZ514 z#}Ijyz$c?xyTk*}c9H$}M3+zE!lTVh%Uqcs9q(S#2kl%M9`(uQMBo_T`6N7Bn2ZBU zy#;=>8}sG}=Iv%>UD6dl_fCq(7*|w06LOjX`aHV-MP8WiwC~Si&v4?P>BEX&|l4@3j6q%#@^w@H`Pv`p0FY7~m@>c`K9dVxq zgD2j$&a}h(j2!=VTQ+IxQjQur4|TpNy*{sC$*9ydMIWcu#~257Jw9}d(WM9UH*{m4 z;G}Kab@}taXSHkz_5kd!lTzK&_v0dinC>?95-YAbccyoqPl_Eb?k;ZmGa6jxPD|&g z(rb`N5~5(x9wcep?P6B%HXCkrVLyyThh##)i73rDczPcVV~`0N1w%A10j*_mz$7rmbT)YBi49mjNUs;w_BAv zE_n+t{om+I%l}g3bO#5U@!ozC>(>DM+)Vv&pGa~)R4!w0()V<@T=BT1Tv%Xxs{H3T z`czmSlUJT9x<3{}XEYigGKm;(Va&zBU?WSfK~AU09HiNOK`)AZbf6GdulP}?(7#cMv~X5 z^hMd1e3g=UH3oikZlR}sW%b=|?9(dyrkOkEFv_$1vRnU(VEbV(miCZON_* zgzIwo!97&KPB6_%{Nx`Bk+kd^Kd-LmJ~#7d(xSxO&8mOTU_1})pw9~*^2k#5CRgD9 ze8>c1v4;vy87}wO8!FmeBuK9BGks89tJzA|K{c*7&Zn+uYVx&DF2@X&-seMQSRpXJ z%pbE0fXxA?-TxZ#gdKf!D|Un5?;-vhI<-ZaL>gox&dyVOa1{xW>&3lNfOT=v%rHq5 z$IRc0V(Iq|WB*$>W|(-H|Asd*eV|fDYy``DCCr*bTBmYJf`|yY7{e5A?2OGfnL&GBK-aJ;EI^~{Wn5t0NPmQ8Mphgk%kYQjmdt5>n>NB=Uf2)?Vf zcx4r`x^DfkL&cZb@ARQX@X|@q%dJo2mwGYH*jM>&M!s|!yu)5_MmGIjOTR0qEB-+{ z>F>U4`AKNmBt*)jbW7ETUg`H`gnW$s#3$J8{Irf3T`h=nGBQ|}@5WCVwm>(oBAa3@ zJJ1X)8MuNI*x)~G6)Nc)gv#4)5#qLFYRj{lZ`;(?E(LZ__#9DmtEd@!_T5z(7=yg4 z)KSxxnzjbEZLCPLkbizR`IT?$78kO+$W*tq>H9me zPxu)fj{c6Hn{oXDUe6s4OSH4D1nx~jsM$Gq1ja%XPQ#buK9rm}MHo*?3 z8h*R5`>Ps+y~ng*SqKihb9VfH(S|$95F@BZ)HYBhxClRGldp5IjIYgH!5VS@w)uw5 z$wK8D^g;WxdgR;Bb?WM+0{h`W{K!VYFBUyXtS0oFt5f@B$U$@l?Lwsky0ALLd)PgY z*aq-2ikiT`M@JF(FtF*)C*T~v2RCvwM9#8Sd}8@6zKZOvA^qat=*`h!DS=&btgZSz zzhPTn3;j~Zs;2Gj=YPcC%^GZ)Y$}HTq>nlVOEc`%3upIBk!$9e3Sdls!4Jpu7N!mC z=j>ziGafmJJ%*F~u|nnB6(*nQ;K3EuX^T#=h+c;pme)^=v~WzmHs}M94Ngg-`*2@y zpyLkXC!D?Sn||yycH_f32%iwx@y%u*c@cTq3;xnta_XHzjCkt21U?qGM-#h4z0GCq z5%rs~16dkaZgqXkBVFzzZ#?pq2mhDsfsQ@Z>#MqdrzSp0qsf1FE03h!K>U->R4VL5 z;^;QJj&57gn2Y*%Qu>=BKYR5gtKm=Zvw0s`Tg$y*od=om+i;IZI-;L$zrfVv`v)Wa z+tpm>8?PiW9LwW3u&_^ZmC)~q0d7OlcyuC)VjX;cc>iznrxB7UMv#029$?J&=-;sj zeZ;T*^)vH}gR@4LmJ2(b1|NB)3VL!ynJNX=Vc&~EQlyUQU)xif`@=`-ywv||!*!ij zD2s3F?)Z^-qUV8PGkww+o-)FkD}T9R#)x^E_yLDKvf1sIQhD{ezQE?C-ZkXg1=&A< zVf|+WdheZ~5{_)4c$iDpf`hOr%`Gs#E#cD`3jk% zy@3~oSFkAq_De63)!8(p5jrROb&Mm-tq)vMp%D13Wu`4vx<9g*`E`AV2>F|L=YHan zOLOq`HOMD(g1nOZuTZ&^Rew*yqwJl)(&a#Bvh{$zmi>CT3|VN(v1b)F( zo$(k4K2yE3@Mk8i`uz#|Nt^P-@krI0_=PP_e8y=J@_IDuTr!WmDy>u8dF_%m$?(sB zE}E+!%83F&7IFDNz;k#m|7e6{9u$k%;E{$HAeAUyfN9nfR+YA4@$hjkvGSiyM z`xNy!hd;6fUYW$+H}heygd%I(ycu5}75uUpjOeKZrd=ZElbJp74c3PPYxMiZWC%eX ziVfs8uT)Kkjb^1_$;&=$Ep>bPvj}<6-7PWUA%1256UWkTr+HxV|9ls`bq8!++XS|q zdT#{#_y*XaHUB6~%H(s&M;lBZSNAte*7KS=w`nu;M_Ksuf(^m8pfj3;{=L!&^a$V! zr&#k~Hufo1clc%4Y5H;#Y{k*vW%V2h7kE!o*Jo#;-@-1tO%gB*Mci^I#H>{puzyZJ!7Zyg zg-Hf$kCPTZLOsD5MMn?L!lPCtjtu(x=xA|f{oG0Lnzh+yZgR-7YV{71M2ux89b_JJ zQk(oyzsGssKA(-w*rtT9MY^JMz4@)F-TgIri5O}JR5%j@#w?g{a^OPk6>Y4C!5Fmq%FLs zq5?;C*^8jl3CBOrqb45YLHO%q-fp#$IOym#oHTB*e$I`}icOnmgi5}1E*a0BurBk& zYQ|A?l-s(#E?!`shtlgl^p&;uPE#MBmF>X=@czntcWg@*VCR{6Z@9c381)@LfZt10 z*e!*=4wWbEB4pPW_%6p58DLTguoU82T;(iE)-q$!`3$fbX}rXYVRdg`74tpncUTK-`6~vN zOI=rV`h-uGVp}sIguNShzQ`1-g072l<@9mlpMmukIep~cp+D%d6~T^KQR(KywnR3f z=+F6q<$izB`d4)xan!-OD_Q~GT~U<-9x3C|W55f}P|;9u?)~90&ah@|ZOb0B418`P zVkN`#RR04xLxe|;Z$vlw$SX6FnSS(5cI>p?`Q_zLA1*^7`l(IrV(GFxTVbx*_ngNs z|NQs+Ds4QlPi4T)B*0HZ&P=90AF*d|Pz?-TS)W`8hYvw+cKbGdF-n4WwRD|F8K<9q z8Y0z@qqIg2;-m+;@#jSw4i9n3XDK}r=K)x;$071$rJf_|H*==e=jX94Z9mhL!A>!k zeSUxT&WaxY05-$zkx`xX`{_tRSoR-DvyGxJn{tj*fRP?`QO5%;#6H1PuXj=Kvq1I*vOf{&0fSN zPSJYo+->?l(*8Qos^W|L$JaUco^wy!t4OyXNJ0JBgPkiI86mGdLHXl!=ylid_(`$3SrC*Pzlfwyf-Gk- zIO0N_4|W7uTLa`pn{}>&aj-cBUmY7&p&!o5tMhn`y<5sYeo1Hf5>er20$^!vq>C3?CaPr)})4c#u$->Lg78C-H0p5&LO*tqw@zn=&HVc5Oo zMYg&7vhFk6*`p{r$$6k-O6Yz%2Y&pQ*4RPc4VOIK(G%}}6C}n@@!Y!K{Ix;XQ&Rfn z|4OCfV?WD&)kz~+Te~jTb(HF{UnU^ij!xx~CFd&UZjIMqJT?R9i8xTqcYq|O#8JE_;Pi9B)#zW?|aVe%n1+=@CO4^@-l6& zHr9x3`gy}_$mrqq=Z^G9Hl8~vH}YDWo`YAkDSvY?Dyen7uUKs2WG-gH+hPB2*98kr znN`^R=#3MB)p1hBszF(V?Beeq^wUdm@zZcJOd>Kx%G3-&Nj*^4$2$0oyCsn!So$(& z8tQ*H`pwuD=IJ%+dwp+x-`wJJR-V8PeOKuBO$^4{_j>M7&$6?&-TjRIFcd6c4^uzR z@alg$%l5I`_|U#FVHy5U&@tQ8h_1Mgz3rt>kZXV+RkWl?>|?W0{@Cj}LtFgw-}cM* zeZf9qbGtqkJx;ZJ0Xe|h*=1Bv<|F%PALWw~$IUnx(%d8SYMDBieMaYdBzv!Xo7^(< zcQg0y$5v~6M$V1Jp7i`^-KSK(KdTQ$sU5gG_K?f!i`30w`iXk)q%EsL>#k3dfE00? zw47nj9SnUw=S!XM>g>T9B8MJwJzQ2I3y){XWv41$`T~Al?&<#8a2R%rU?|Iu=gi5Y z=vG^Cw(gp6$#oNqZc@(pISRJ4pig#{r4G=)Jlcuhhl8Q*rt)(id3q_rU%Kg$<~f5> z@DM&-o|$^F^L+AiQ;%QQ;aqIu+)5N7{mR)P^wr-@*FoG^aOr>K_uvCezt11ZJ_`)m z@GAkSwFukilB^5!be&XPjNg_=$dQl{bZ0-`su_02m0j{qwDl|W%l~~BzmP{V<&2V2 z=q?Xf@|{AJ%^djGay`%dS1N6q;B(886&C@Y^a=9G17P3IoM8>VhJ2GT`RQnUro1%$ z;QBv0#dc?z8yC7H-|lef3I=O-LCyt*KbZSd%r;p7Kb4QYYj+D{H2HQwreuzi(;anM z7t48N@J-zh^b_+t&%%<<-xAt}2OM)jf_LyuTvgZg{eNR0e`^z&`lyIsy+UC8*Z!{O zjBD`THnjySySpf|=O4kweFe6?5i*n<9=VBL>=d~5jzy_6i@%&fzaG{wN>Z)U_0yTT z-lhxXbpOAS5PUW|*}r~8uZNw}vYMPHIR-y4XIygb9QukJP$5wNba z1G4&Mxa?*k+6jiIE_Tm}ePD0aVE@OSAz7c$xoG)srmWG^Rrd$_n!4U)`G(B;oqqNV z{JNsL^r?gJiU-=@N3%4%8TyNKQ%(OWVEKM|6PO?GRgWh(h(>4Ghy9`{{f@ zK0{xz>Gy!lVtpG*`@Y17OqZSD3-5=^vY=__t?UnMI{XUxdIx>~0K1PzOYJx2x~6eJ z9-vE7G)+WIi$k`U7lutsk@le>$zSB zH{fR`JLBZayMC!&hjlzb%zia`wSG3O4|c8Ay54F+P&(re?%4%wY4_-~+I^$z=`{N7 z8sMlD6&QqV(E*3;jU1Q|?oCs;ph`-}%tT*mN|l{`P@B;4dw?mHkd#FM&~ekuJ2%=^}Zy4F8j? zyZy$Sx>e!VD|tpVD%&ee>M(!Jd=)O;IAg=6AMni(ovJzH?dsi$XQqGKVH4!RX9e=^ zubDRmdDoVf9@+4kb6>hg$=u!GHT%I6fd#PXQ61)rv#HnL*g7-EHAk165u5x(rSUO%K~~hqLOux&KROKogBO>) z9bOldoefO?vcn}?qWiNi6?UiSR&Dwmj7OJ5ddzLYPUtavz2pv`Bpces{MI+jA7w2b z%1$S@g_pa!%8Xz8T`6?89hu*|6lc#&+rCFX-_$o|eNSs@`sfP_BT+tnxb)nQy~Ahv z-KkN!9KSm-De5}~Exfq;e-HWkLv(;PWkzR_A(yF>4(PRP8jTN&ROsfNl$W*Nrncpx zq!zN$e;T91lz^le>XoPH$wu{a$)!au*?Ua4>2WX$pOi9V#Eu`^HLNQ5Iru@FHX^&- zGRY+aMubV>_t~41)uVm=@?~PqGijjYGHz*B$R$rVq9ev%pG}(?YyU-=*)KY&^GNVc z@CjRXyQG4}vy?dQlhw<8^7KYLU-{Y6SJ>%gb?`hVTX`i*ZT;qj zHLsUFj_%%)LGRxen$Mc|LdUm?`RP5K*SYxZ{s({mTiB1TY7meW7FIBwrDL?eZ(m=d z^ZPFyRsYxuFREFD&>R_1$c&`+*G7Bg!}P_m<^`>AD=G)146pnwUZzS)Dd zV_SuQOuFKh#ybP@0dmP7u6m>+`A@OTjN$IDT`~qd;SV4Cr6Bn6i>*XzTYHVG@R!@! z2TYDdrl7tNow}q8ZL8?-W4kZ4Q$JmD8rc@|z%a`vVdV$9!opwp<<-x+o(iMCQq(iK zzR%N9xBJJeG12MXR(!dGv8mA)tWz>t;D^V4I_3VP07FGay1 zz87?TwHo7+PdNJ~XL-{POBeUb#!Q?UhCWNtvlRFvtBwuH64o+g<&Wa)xZZVUj-350 zwA~Bf>!Zj7zq}a7IpNrZTm;`fC!;CTVPxv{;&B!Z`l2q=!=-5*)_8nMC>qamn>w-1 z9j|KQspq4>c71}ZZz12WG1jzA6>RA{Y|~}`f%*TXg)!`cj=?7Xb8s`%_W*D%(dqHF z(0Tk-2c3^Ixx!`MR?c?*(WIl|e)F|g+R@H&GINecq{&CW=A6S#doD%h?}9`$u%=-*brxKi%5TIMY-A zw}54ejZ%U6v#B-vh9P~tQoO%z?^nnMj!zFrUwDocsRGhxjey+=myBI}QjERJ>&zzq zBfv|oqRzfei9O1ua4A4N42tKIMa7Y2-ogH~fJZ!wOrJ?pDN^!h*Zt|y0q~dw!(>4$ zvXn>gxv^0mc-sG!(v3rwBKV+h8Z*x9M;@tAH&UL!e>Y5G#zbA_+mT_R?XSMqHAT!c zMsGCFIyJ&3bhGKtb{=2V(RG@TdBCO@X?1;!f=5&IV8$07JLPa^SKjt zOmxIgb=|N3Qn%la@9AqYhu?wB;AL#8Q4n6&vuG?W=uzsw*Xy0LL{LJJ-J$0?p_mu{L4W8_k z++cr4x%IP2`0`Qo7yagbB|ScW>jplM{ezQ!$fv&_F~hXkU~3I?hO_@?W^Nk%Gx~7L zUN3%aU4NPPhRFu7lheW0ciMoh3|E_WPzU>Z>$bUvtm}0g)89{g8<1sv!=;SHZ`g5i zTiE_4%xNo^>H6Hy`m@&3`Al`pb+z%uJqDYK6*(eg&MNHwW@D@TAhet+-FhSOZ-o7% zqK4>B(`533|4U!wPj()Fd@weI1S2FRdVq2E5UJRtE||36q8koTFlGWq@Do})sc zHvk{n5Isb^d0?N=6Wa7mBlF*WrmlM*no{H-j7f2>R4Qtz5a z^4AZSighC-G3&~~-(r@_`3?0y^*ZXKuGUi=U9uU<(_$Wjr!AMH|q0 z-%c1V@yA8T``9e5OX89;`1W#AIqcK6P1E1sie4ls_`rc1@fGuoGZcP6=7N1%_bED# z`{Pxn$hl$ia2s-mrluWL zx^as~N_g(jFI-M-=05di&_i&f-C|!eM=(zee*m_PHT)QJLiJvH&KMl2%T{zPK4^-D zw$Cm2L?=zc#-m{m&c(<>AAW4w{?6nmsc*^toZ+4SeYvo$&THy1-zWH1VBCFG1^E&6 zn>{&eaT>3DlrT(YV$1T;BvYS{EnA!J8T>K_A54$4GM2#BDC#{jD93tmRv!4}QQ$=@ zk2m!;v1d@eKxP=73Sl=AopzmkSzzqJ z8f>TruQtsmo6d)RXEO4xZ@>WE%8tz(yluk_9(ii*3+!*-NuuYU%B(#$6+DJLWntvU zi~Z83duW<7K8%oek=54Vd0u4rJuErm0l(G1M&g&rVGH$+1GaLM-?UX znD(*XMZd1GsI6xHcf-qvgtB1*pAHiIpgC~X+Qgc z^_-cw6+iENbe@h}H1Sq`XxdoCFSs8aVRifyBP0Hz4SKh``0k|s6`eyCTNIo|J8Pe& zp2e%q+&&{Tja9o$e^y~iRSF$PnUE27y=&&10~y>htf*OARUAd#=3>)vBupN|mw$Fb z=Rv>GzZt>o_Qwa7qAToa@__|fl``~O8f#m41p`qtEN6Gw$f ziZ1%UXwF@ohmZE?c>Ahj=eSeX!B?yY(JA#!zYN@`!#4ATmMdje{rq&laA}5*c||AM z>M*IEN61geVvbMy^1*AbmMxY)k8!(~WmZ0xbabWPNApo@J)lN_e*Qq!l~ z;`jHz=qv09I>KA5vv4LVY=d;Bug4a5K~nr4zz-!Xug6TI`J87qg)^v-!6~X=H?$n3 z7rLcnwkUb`H{`V!7$3->kMB46T-+e^dy~?G(Qimyb%?|l7VCLj>{iEzrWsqlqCZPE z-YbE<_&A0)?2FDMZ!hrQb3L*V{Zg|-*sj7?y^RL{V&;QqS=>_OtoihtHnlz!DE-eraU&f9nZ9p{l3xf_-*~(%oDrv za+W0aOleD?M@IIssjZoVT448OQ%`K(6s;*8TBd`&JW>W9WVs_kpWE>!rADXW;0qt_ z@yp95x-H603axV$=g=Mf?mYXc>J#;UZ@hpELXN%RH3Q;U(%R!gEQSOmY*8?+0e_O{ca+B!KEMI^CHnVfOV*n2)*c$ zfc%iwj$y9do13=U5B|0F7d~m1MfbDXTg}{KV#NNhC3-*iq0luXQUOwoT^RSM&5Y<6yg>C?)z^MMc}Ad+6ttd;4R4N4;OR6uH3apk%Cry}czVgI8%yKU6WpYIDZVX3nz1CLLY~z(^OKvi?+$>y-Gn^6U^C9Uj%&)S z(iqSbf2hnuH6oDP&N2OGC)k-$$Ry5H4u}hz$Xu46(5#=kCA_bSiT(_oz@Lk~vYLF& zSb)x+`D*-69+`>0;?Q{PDHmgRo60YLmG(+6c&Kiy6~_|s9k9d)x*+Fgy7+zAq{Hk_L=2aGe_gQ^J9E?Pbdl&e4H7R zDy^|qL+e64JNlCzTi>uxEO{Dv05(^OdOL7MNuD9sNFRpJT~p6*0$D#T;s0zJLq0d1 z3X>cu!M17o1W+@`v2@7LG4>XHK=Lf2iAh`#hg5wId(>io`VfK013XPs9E z&z+zDjGr?>bpI(h(~Q1&m-BKK-_&VzTMf46Bld0$&6tSOEVK=W;J@f?G$pYKTd${1 z<0^jF-bVK>>9Xv@hez7k_&u7#S+Fa0f87mEwa!RWFBv`fe)NQXdr@+jCT4_i6Qj>j1``v035 zV&*LY@^vRgSa`dO04r)H08_Eb^v^nAM-`2ksq>a}saK|gOMSi#-%MBWd5KT(G8wUb z8sw4rbIlAiKPn*635#C{G*pl>f?n!h?IYak}X7CbO26$vM?b*!Qm)c<$AY)ZD`&EQI zv1D)RJ_Xpv_4sc23|U`?{(h+jzCh8}Pr{@HIu4t%tcJe_A2$yfWy5^fA{2`~pJ6A> zx~AgxS;;wT1MF1v^&jN>x6nDa#^+9S`u(8!rh4}tI7>xKem8aX{aSq26!*w_2Mq!z7v#x%LHXwCw#Vp$DaHRdlH9Fr$xw+@}sZ%d>{U@ zkw^7M9vTWELph%=cW6EAh!37My{Uta8G~{Y zy^T#NQh>Q#X5Z;+g&LemUOncx-e>80r-2RhAPbAS34VJmzJjcAQ(z+b!hXj|UozH) zA*Z(K_;&nfv7fSO-a?N|%Lg8!19rRMkrWLcW9EX44Rx7USyR)n_L*V!Xx~vvtHflVt)~g5j^YYXnjDv-FpzsT?TlRbwPApoD;Mo zv<~{-Rp(TivVs)`hw{ogzO4 zB~f!dKUDcahbaNhx}_x>n`3=1=bnIEwRD(6)BepQ6qz#VKfx{Kh-}i0Y1=PyTuL8vY};%S@ENw z)JN{^q`Sz5Ut_Dk2HSz=d3};RO83n%mQPA&*!lAUvWfjcX)p}S@z;42eC)Z_><7>f zD$0T`dOEV0XFFXIc`P7Jn&9UJ`?1;CBc%)L`nr0~)I$G1s~g%@p>M(R_l-GEsW1;8 za1PHGoMAA*#E)Rk3Ll4$d9cvEA20`j_58-=lRFRG*h~4P_!f`UE*_K)maJzlIzUB} zv%I;;L--3t6)m1l{ck{;@78kTLmxlQ5Al`DI=(bDI2XrWQH66-`)Kx4&UZO1{_1QY zue=%%F5A4}a*(m0=<`F)kotdvD)^^hEIKL6BcGfe?v?}Ne3G&Pw!Y}(XB5|YfA>B7 zK3(@ng7WxcbjTu9{4tAlABeaECaG&^e{iNB+y7bkNBLjr8S>qG=-L#uNfP><8Wz@K zeMPgjs&J=MMMy7rI(G`Me9>I@t5lW^QIxgTt8lSV0KOt=8D0LXe`5doWtenX5+Pv) z7{>|y(hfb?bZ~+x!6qj9C3K8U#4p(LsyeQncHule+0YZ;Iw!Ezxva~b8J;fH&-lzl z=3C{0F5A_yCSF!#dLNh5`F@9WY0&!6@*PC3e+xOuQhZ*&hrZ_v%MM0;vmp8?n{HWU z&C}kRk1KOFI&zNbH(kgZBV-^va?wUQPXY8E5$IBzqJvG`jWbRxo=l~+#?q(T>2|{J z)QbViJ^;VHe0zCPzszi{>!Mf#d^mUUO3G=GQh2`UYn#ATy&KN+O`IQ4K2kQ|C-cvL zBV;6dqq*$oCW5W8sX}JtmB?*2uhMzDm_xtGYuO~(;oi6W5!m$~YeT>E-x_ zD&m*)(R^^LIAI%fz8l~N?wzab|0=lTQ|$aRmkE=p;6V!{!(M4G0d=sqedho3b7fYX zBm=fc&0;1z%z9MiqbLcMG(2&u{hWdNtsYmik?lEY>m6M`ZLWjmY|Yu$*fftzf?T2`=%88KWKE3&`{Fe#!r?k9plIAA%=santz)Y@N_yE9g?yPgrmK z;E_3hbJ)a483*oUSIy9J^m!B-*Ljz98gd@&F@r_@k{#a2E2i%~d*zoF4@{n&@znqQ zjIr3LDQRA*Z_@cJo~{o&?1paoU!Z2pb>(uuFd3cAC10fo%0|ona?(Rno|g$tx^{Z8 zT~}B-k4&?}M$OpXS!(P5Nh; z3`75vWmW76~)3mQk=&Ns|S?uv%PSx$6vL#sF9%0f8T#`R3 zAhnU%)Wlvd5_wYgMxlM^uGP1490{HKd$Dhy9ZjdybcIg;xQDrAe55=C-yF%s&vu^T!>Sh-t_Jzi4jysUIH(XB_gl{_LF< zdBC#{v~YILwEydW>uCIGU55@v#ap*PfA_4o4Cmp}E58TR+ZoCQ?<7@Qw` zyP|H$(-r0J1mBhteBoaaGV3+|U6|YE&(iO1qL29|TeuW==;ZX9n7?(?hRFqooYxLf zr;$&_{)Q|9U7(_M==2qJ&Sb`MdFDAM?XR!v^2sApAI|so|H7&5fB$dSFK=*0tR)9X zGa4-Ol9=Cnv6r)V*eB;lC-mtq&f4>^|7(Mf;#Xl(?<~G%x9I zIz{2zBsQwW+VL*Dd>*iXWzor>8{wB@*0}n)vZDz*)iLQ6cd^Cg6MBgWIx4a?;bh zrXJQKGkI;DHJhMyX#8{IO*^(->XVYmO#W1QLuq$K?@ULgvO>4l?SuN|lY(Ho6;1bhz|^rHV!zrCKXd)Z=(cLU zBV79Y7%6e$n7)#IPV8gq=VF}aYhj*rsxg0;A%8#di(dvrlRG3Y8!pGfIKv$~$TG;h zZ5mw#8xPjGAz-ni(ir!BgLuhI90JN$oi>Jj8z5cY!C zz4CBXgdF&ha~SKHG8SDJ+D$?6sh0a3&c~$%YF6rCbBa2R&Jg@6% z>MDA|9h>Sr!Is2E$-4SvK^=4&DNMV4c_wtcM~}BGp`M!$-!N|mS+XAW ze?*t%q-u;Go7R65 zA(z;zoNZ^uS-P@eQukS;99n6I68WWQP_o=GYtEmk-SXuyUH^M6yNffHoZ(D~(7N3C zk&ZXKfls2+hqhUA@P~@#gN?YJ1AlGf+?l;)E1LeJLTsfTl3TWqwXq#(;LyEI9%Rx@wgSvBa-YSEg0h6Nj{z5B zQ+(umzwC*S?)Z1ewlwCvrNRxg>=SB5>F>XrpEHSA<0@7_7x0lzDNbtidZz=jGb{MB zfyf)+T`u+1^}6wf?(47PxaD~X^Nks^(Y?(NlNspH3n%6rgV&s!2Tpy-0lz$7uE$gb zWG1It2P7959QUVot{vCKrksl^>wZxoTz{`ZTwTsvGxhV74tZLyqLK2=e$JaO=tzsd zAC$!2sf2zuYgK4{&!A5!dZp?E9(+IfvgsFZP_q7I#&k=s8CRcJvX_+C^!us!X&MJl z8l6U1_JHbnUt}z?(X+kgdA;)JL>+#+Vhf*SrC+Y4@JZ1HoB?j(BvrVKXLbI1d)N;l zH*?ZNx5?X(i=5NjSJ%T62cNwE89pzn>++{X_w!46-L5yAgv%_}LPecM2HF~dsr*vCvR_95h6VFGVy9SnE!JsIK>c>5Nk4>MTC*HiP4WhR&7Eax<#dEdhRw_3}9l*DF3QT*Hrn}k1r&iY>c{^;1VtNRbFF{J)y zN^ice?iDRXuP_K%h@x58@igoOwmT<&wUNU&bB9ZtQRr9Bcx7gB?C4md7ok)62sw0R zFC~bi4hN6l}(D|#Ybm8}G`hRm%xCp7L`j*^oaft@^H!JZ^z7ip zYH`NOkkDt#lEvg3=8d3FJ@-q`Yv7r7a<0-bpS1itOm=1u$hB);If`$7MT3zeY>Fl) zw!by~Z~dJP@O9g;&pQtGAqDo}ih98hyp2+`7f^I6VNhz{*JE_}xS)*s*eC8k&72ZF z{vW+`yte4uzv-pFoypoa6)GE$UAN!<&1Zl3@U5rgxaWB#h))egBP>~4^lz#A%(HYD z=exOQbzS-#%1_ALDqOlA8;=wHyE)yH4Ky#kzdm@FvAXW=uuDgI*q2l-!L`b_Ia zddxT6jr|o5mvd?sQG$TXYalvE{Yt z=WFZ>z+iQ(>61#S!X)w5(EjA=REd_HvCZH+Qx%lQrG|5c4mJ-d3FI=y-aoqShQpUyby z|7P%*ik{>Rtut?P`bZ(p1!^9Yedtd{fa6wly{Eobw&pkWtYS{{y?s?Ve-GUCMfjZ9 zsG7C5_|efRO6m<0FLtIj4RBzN?Pu!R3%?>2i^7MjF;8z&r!|v^B%5ZQm2J#fL|`ox zb+GiX_S@4%qCg&pd1n4jcKvsE>8oUKPcLvJZCa$Rhi! z#b&oKGDFKBo}IqBR={R_#Mao`RK0({yUuq?Yg`_y>6ezsJ4ZF~$#4rZp~C$at;uf2 zdh~FUEWZ1|L0#7VzM$M+VnQu^5|HxL@ltfw3Cj57BDl$O7Vl|?sv1o%t)5>&pa0!Y z_&fjyY17aDn6dO;GCgi1u<_~s$R$&OaG8Y*)_g0{^t9vqws7 zhfl&TOwm^4`@bTS{H4543eYEa?FFX=w&2&z5%QHKtNm;&xKqbmRHmTr!;$}n&Kq_f z)pgNfJ!a#$@J(*n-?oUwUR{N~l!3Ji{@@F+b~#?++o?mCYWO^UNejEj9HaL8BkW%`FyA$@=CYv{ zE~G73wOwE^Z0a{rkDa!2%ow`p7!$Y4dZZcWQ!08E$K<^Qx{&C!8QuD?O*linbm*I3 zye?_LSqB+@0hiNT$6K=vKFz`;hKAO6+pBQ~LpjD2V^mS*(wtuq!I^KtaCvu@TUK)J zLY`APKc6wycUb*T#}56S?vGhdMX^&1A8yL5V)Vo|!=}5I{KCGsui-Bu<#j`sJkF)_ z)iaaM!<4L1G70_K7x05u@JZC|PrY{7@zgaf`L?M>VXy<>Uu#w5?985S`PQS`b~W*366Q8}m1! zcR?1ZC`k(swm~|d9gd;H!N-E4i{Kp=*HgC3U}mvdSg|ZzUa-zQ1xu*tD*GRs^1$CT zOl10v{k-EI0W;u}>R^*vH`MPJ7xc*8Wijhq#hGX6iPC~OaMFz(=3B!*({azTPoIt+ zb1XWTFP?_UqWGMN;QegKn=lOKYi=AGfgiR) z_^H8fNZtzg82(-7^Y$?_Ztb*UyVgq`CLg2gjl}jZ!#(%|FwRYCah6{eFw=kQG>)^! z>}2_iT0JLbDrGGBf7N<^>GfK_KXTZ#tuw|+_K73e`(L8ZwZ>QNx_#{JI&m)d#V~Ot z#x67#zFx&Y`xxH%cjkE)^YwKwpfd$tOprA|FLJIO#gJc$~TO*F)@-2Zgq| zori1I{=vRi*AJ%o<+Gmf{MGUIir>Fd*qPh zK)C!h*ew-L!;{a8kR;-hLtxey*XR7lTVe9`bDxat65y;W-G|nK5qcZNPvnvh1~MNs z>`O)^m<)j&Si^^hq3aaf<4e(eL6dvqS6ar>#sGH^Oh^ zcgWvVh~vHWcak7Sa8lr&9s5xr04fxGWkAdQ!@WVr}y#q97Ww%t*`4p5xQ4J z?Z8pkRQ*G*{M1>0V`?U!G^vihjs5G~NulLD^GE0$c@24TZS;uC*k8?VL?1hfzvzc% zE*WLn6(t|7(|Oz#8D&oWzZEjiEzMlA)6&aS2j}iSZ{n)Fbr`C2l;EL?w9%-1K3z#H@Plc-e)~t`ISmZWD59> zY}f)suG4ih8JTSI^6=CB^c*+{oclQoXR2f9-%WWUj$DvYT)!?7gQEvLBn>yYrbF;RPBv@Ee^Qvfi!L`OEbsYa{rk?D&Iu z2h3@7I>{dXLOb0TXPwh!-!(TnKZK0kRO^*}xpwMFN0t1{*W?9*It;p5@bAr9B5*mE3Rf9T1t&CB@g6aTjTtRu<7^!gO7h3 z-CAw>SB}UI8-+TTH{!ZAd#YVa3ny1%~oB!(H zdkK(1d!l6K9pxp$`I@9GG`j! z-}6bopykAai=1n`ieLaazr*|q{KT{lYwR*o3+oNC0`lJN*&o-SO zsKcuJ!E>=+tHu0xROhL6G3@U@H17+)%USK|&=-z@xA+x5l-G5hCU&7+kQI-d$a#bg zUfuqN^Ew_3n3LM?i@iVDVGiW7|8c(4>InHa9eeb_VbbO#eW?#NJU@aFVZR*F+$Sq7 zox6zvwzLuFBi8lH59K4JB{q09v2*GFGyZo!X}|NIYwGK8}V-$uIw zQ8FJH-7?EhwF>tx^SzT&Gw*)A8~!4`EO26xsjNkYr#gou^sxJG=mn(Feo^o;K zA3jm0-!biKf8+B^U>dOPyV}qriC2M<8>#zy>-nMSsqo9k>-9+e{}KIrbV`)pD~;=O z4ptlZ3HEo%+X}WqW?Vf_9rODwqS-~LG>bIQDJLm|Y_@2GycZvt3H*HW8^~n3(qHd+ zW%69kpypd)B}KkF!Tc~EpGsf2W$ahrV1JJgS6zJAUI@qwa5^uRMM)Suq)iWy-Mhf^ zwY;F~$9}G^KYVJ!IiK7A|4FOcv+Gaz^<{6Q$iEOjaA5DhitmyrYn+vwVCu?_>-`9S z*VwD3jAq|xzgO3j3w^Q?JWJ=rq2v9Z&V~m&!hG{n^3Z%H?x)+MFxb8H)Rm&_=s#?_ zVxrrRLavqT!|Qyh`~2p)G5da5 zMf*EuzbFyGoIC^j4U3Q7LmNN**z~0f#Uf?!48KHRYmonQzZ~uj4z7V$?pyZg|F3yl z)%X8WQL!Yv=a6oz%X7_Gk0qGgTWa3tLRQ*ng&9MY>xE&1ZPvkr3u5+7XPWu&@8zWK z$U5#jFx)GU$$k5;Y5zXa<|h?*anDF;71xEIOZE(-Oy1PH60gjC|0I4n@_KVV$}6?L;M~JzZb`dBkHO>pb?C~iO&?KDsw~pua0>IJ zlWrUg%7q7}{+;hSHw;ZgVW+LGE3uuL2F~mu7_yD;L`Y?1Ev_)X%yb3hq&i3o3d4@=`lT?* z^d4s|6^J=j6FTf2Hi6TO%bca?#p*W~`J8obaw=WE>&T_9l<-QbKSJA9g**q}^k3wj zia)gm*j`qMlz$FWXXmhko(W!ZgXtHODuH7k!(>zi%GHU@tK`NG{Y5DeCz?|bDK z^2@oLN74|Ut9T83%pS)!+@Vue-|xQ7&Qw?zEnl1PQH#E!Gj=|T{>DzxrfJ}e z?tC1S0buS^W`S=2`#$7juefRR6Dc`64!rU>aB{hu==zw?Tza~Xt}m6wgRDBGTL&X$ zU9H&rSqAuLML$>5<80G2-H(&}Yr=N``%(${!zPzk{9rU%{^^wz!_@e5$r?)-0Y`9;=k!1H|J!U zvg@b%_ebWGByA!j#SGInUl!5tCY*|WPWmH){qQt=XQQinDLPD-V3YYJZPuaAow&4M?%-8?_+0Wj!fgOT*t%e!*TLM0DA;)O&$|Z3(nlLNR zf<_h~wn>xr=zc$}f&&z#>e`n&`bOTxC#3pX(`7=J@@NE#UifI=+%no?T{de^9 zKz;nFcJs^4pLM=2x^?@$#-3VHy|t#k-ouvWTpnZ&H94;%n@1v9d)q(27ezz2oM)Y| zX;hIg852#XTo60uriDz|?XZ)+*LnY@hf6MIj*vRNLd$(SQhz@y<8Rg^zw}KKl=sO) z&aL<<{UKa>AtyVG-O^W2@Jj^FOi@p4uWUMie0U&ht&^taij=*dnmWsKD?)O^%jM|7 zImiXEr$IKfGcsK6(ATS>qg|7ja|v6ZJGA_kIMZ_ef5~3;+M)<)Tp3It_^Hg+yraSt zWy~t7c=pXD#?O&_$nf4nMuh&T1?x$4`U1Zo(J7lHd|B={DQMtAZX` z(XqRsb*!FENvD3<$0M`9kNtkz8u)zr+|;9bm!+Or3)FpIOOBHh3|yRoE(vSrlJee0eFDShPvg(Mb0Qkr|zVMJ@oxkY^6pv3Cc3o z7n_nHXHe7gsxn_s(7lGH@L`MsI9K1gQzyNc5=8a_uo%fG;k znOtXMmQ{sOwBPDe>VI=^T{Q||XFnBRKYPvhT*xJD>h}mABbl(j1Y_~}e7|&IkCOp^ zW6zK|iYV- zmRnLI8~NdsPin&twwu6t;QJ$_{ZaI#?5kG6%Wr?GQ=ZD4{Wo9A-DWeCbX`+;P<1`fD|rCZt=9GbB304wxz!=-bTkdy*6~7AM*|8(86ao z&!)?iz_GUE`U~EYeMgfZKAcZ;CKY>`<@f^1(Lkp$se)JfIrf0hu~RCV%`f*Yp7T?D ziYj_m51*su@K0G^_mjcMuX{Uu#!UHIhr5Cv*-0bu+1KClnlQyUw%XrDNzzK#9nCU*qr(!PbbKFQA)6zmIXu{yYtGcs5#}=ewycFo z2@Mf?_uKghS$>^;GMM`!rP0M>!&$^SWBvy6?mao8q?7_~+=2el_`4-?+Wg z^qoJDnVpB%oU#*}c59rK@`l!{GhgpBP7?j%m2B8tzw^NKoo?tKGo>_jsp9lxe;&AM z`mCK!vtsy-Dx~ik9L2ugZ}Jx}8umqnI(x}2JyLn3SQ#)mX~4JS2$xaKLhEZ{OMDm( z!bT8GhLe1wby+f7GF9h0^?x|Fz9Sw5aUUVEsH(@p1`KPmP}XO z`}30z_G}xm?Qqg#ht1`teWCTD!c~E<%$rZwU)nsOakIngbXy8e>NGZgCCvD1v`l}Y zeq){2rRyTmp`c4cj%w55x}3{d#V>tYaQ@|I`n&CsSI1*4WWDVXUrEm7yas0Q1^%MZ zot}d~oE(8p>nJ)Dcy2|9S)YpjVA5>42OVcO{Jy|P-^4!u3i|I%rK4mP{^q_Lqrb6e zm9F<RY{E#oS#I zy^*4#?B$;&(DCLBMLu(xvxKPsIAwGh2H@waQ8knAgzT{t9oz4gd&sp?m3VV2)8S*% zgNg2lPB0nsO>=a1t}pewdbQb`!G|U$ojm#RkMxc;C$j#yYrCW$cv71lvpza${T0)1 z3UjVl;r=?`uhO#K{Nt0#t@Qgre`7O+oVj%K(6Zj@=96%EOPfx7z`E+e{;VbA$Ffs9 zh2PWm=uB+7i4C!$qwrESkS{zchFl?YKrVT`(%K>0vBRIq3AO~@&q;ptm1D3GPQ6b* z|M3$uCzUCp^VkV|$D|n%vNNA9a|!lIZ=;6rTid}+JLz389f~rcZ{CQEstkOiO?Q%l zd&Gutb}YQ>zm`67%(uGCo#Fo!b^Kn(UjD-Ld;KKl@2%U+kG4&2_;8$#QXn%CZ zH~^n(Q&^a3Py3m=w#UbwO=#VVX$d8`<=R0Law7I8M2+R{dK&E_1K_2M<#=3p@!y+ZwqM+nw-9EdWvql;Q<#+u2^ zCzC#bSEODQ?RgQ9?@OAzv;bG6=$FzFvWhgO&h2%Ne}2U3>q7n|Ge<1ijFqNr)q>56NBIh@>!_lR1KwO@O(&Q9J19y@ zJ@QH5npbwQe%~G2))FFOf@ZVwmRrULqYgoTOGTKaU?J%F&eCWV`AN&dX=(5;(TkEC@Gu?YfgrPVq?Pa`>Ws$(fbkx@GAt^kJ-(b$_HDw&{8pnkG{2rq*M?j=LM)vBqxv z*dF#tc5HbR)n91FOya42`J_LXYV4vv&lr${=u+~rKO6Cuxl_gO-X3231U^&8s=NQD zzcWP1%V>35yP*F5IE&}IHbwWv%a$x8o8_0KchS(fMSZEqd|fY9IImPuYu22;iNfSL z{^BQrx_myq9O)C)SLmGlj4Uc_g+~T3Hb;$Q zPdPs*ok!z4898|A05*EeN6Cr@rELS|)JpV!WF(c*>j&wR4Z-=l(Us2XC-NI|)z~Pz z#h>206x!}8YWY-py<})r^#L7_yjY1I@TEywD@3>mw)XsOx;hZQ2KB_k%K=H-YZJ zro`{D@9D+4*UjuFq1Q{yb+J*V9$wk{mEluVnA>$cu?2neY}h!Rw;}N2V_wHh^D28S zC$*(teGT^UZ^rr^WPv@=^}3&VB->yUH*H~LG2fc9sQ8T;59J*)J3Gy)KApFu*mvv` z^Q{sabr~{(EmO3Ixk}NUoTe|fsi^1n&&ma5LwOypqS`n>70R0YOk@9c%3=5QCV=B- z+ONnAbL;+^KafNbexxh%|0)JH#|Feqj<6Hk%{F(g! zLj!y2*muCWrt5<}NG{WN-j?oH$k7_k0^^^?BcDt*q4JMFcULl8ezNp^>P?T~QF8vO zTZ+RwU&UX_CHCHmo-%(b>SF1A)}!xGbo~TpG9Ap#|4Qv|!GlmQl9Y2q7&9K^ zrLoaIu&kHR%PVSAG+f@9$6girRr9ButugEEV|o1`Wbzx$n%}f`1Q>)ciF_CS(dxr# z)??p@rHAj*!y6>9XgubP4Mqp2KnO_&Q_eHMgOWRb5b{L4iz}uO;lA{LxXdCPAy3;XV*3x}Tg>C1MSrwx0Iwxa28XkLD z?X=&)KA|=JCLcQA_OI|~RxMJdA#=J2KB5=6)?^QTaz15*j6r|);ZpSY8(ngn{laX< zN_Z`k_Iz+Zy#tZ*K^m|hNg^fC-6x-cF}R&RAo&MINW8n?wOo<13Ez}m@inAqC-MkI z)oPgaZs;D9=9`!N%>GgT+p}EP^VuzW{M_#6mWGeOrKI&qePl8_#`@*`Pr>k5{z>il zzgCBx?co~8@DvgK7!lH$wb((a)Agzdt2tM&I1 zmC<>2rWf1)GnryOJxAY7jxEX;ReTbU{`P$VkNoXIA3$A}{z$h&y+0$xlM=r>towuR zfjt4sq3AGsNt>$Ulc+~&-M{MNue+HmTpEMNd*Z-Pb$`bt$-ei%L+ZAy0Ny4#wOou( zad1N0C!0R)3^VjsmsD&WCWDWP_`vLjN0aH5$za;-0_)uQ^16_O znX~`?KRc_At3t(@Y5qr#mA}0kTR8KyWD9uq1k7Ehbe~GKMAv!dI8jo4kA61Er^{S* zPK3Nd7Tw*_RlY{1oS!+@rg6xCH{J!)1Ri4NLmk(Cmz#AccT1m~!9Jl}0`@>b>iB%P zc+zr)EEuQlWqoqs9k)Dc5Fypr8y}4Cm)g6r%bOoM9#neI@zXyLeY>Y3K1`3eB>{GC z%fUd{)CT#clU5CI$qIb=6q(I(`2{}WSc}_Wt5^fwl1)de`D8kCY;vz|ujada@=t|u zIfraLAsA{!KR4Iyw~F)!uqRxe#eCCFM_tR+)!*-hp4LhJFg*`ApItzYu4r*+a(#)0X1L+qPd!ka0YGYC0f zDbCa>$$l9bSz7kp8|Z@-8~Y?#!O(G*-=V{J6FJ&X8}>t2k(p$#sONycm?vv|$5~cK zeey1S#ikCM{8Fr~ZjUVJPUf)RicV{6Oyj8txmeL7S@C_P=tx6d=Vfo`7%37UuSNEI zHYNHypI>UR_fHZTGd&$z|NdOxc^C8lNpx$gZ@48AER3S$!%UsOj%VsOQCECYK4Uzv z|BX%^kA}-qY>rkThicP6=Q(;9`+jpJ&Y=Pqqi7Sh0b3YfBk%)qma~gqbOpDM9waKG zZZ9u7+iYj?dwfLXaw&Ke;*n8_MC0&MVoc#JRS={YG0a)5u=1te`Ria83*ul$4xVT*eK?Y}ecer;e2#3Yu7u07wX_}M;59a+H#nm;J39M$ zmdtX;`w=pzK<`E^^of6jzElUujhifo*1*p_p<;oqJX z)Ad;@GAQ5Tm$Xd)pIFGgoOB*p!h{a!u>W*P*|oZTN{WuB!gcCn`oceyVeCKVo9cbF z43Uy%v6;{RLY}-mu1m_5KtBU^>P8e8aBvY%vH8E&IJD2!TW``@T0^Ii9-rolT3q8S zZE$Cb8hnqBh7I_&sqB^O4LGkDY(VjTk+PzXj&pYewuQ{;6)JkAe_|a!@p|1CayK*i zf0LNwrw;ZJyJmy&+8Ww#9@Y)br;2inI_-jAws=`Q@-;G_NgH*#GixIg>8}$lk}+KB zlx3|r?2+I`on}7P%!Tvy`_$MyzO?oN>Pgu)rrvaj*nf}08|RM&dk{Tz9CQw4B;&;ZE!M~;*oZ;2~k5lS4I5SgUM}c1*3nt2@(~DUPe=>7J z7jPUKi|KL=MXxaUDd+jJ_n3m*_*xttYjZ_>-B*c}7Wh)IDIdH{bSjLFv+T9dHEFXo zCLL_xPDB5atJhyz%)65Gh%$+hO{VZV1 z`W`m->ix;remQkQKWn;I_m>|FsW+OcgFC3h9M{@f6CTfqSw1_geLdO>J@mRTsWB6* zRC<@3kBX42se|&$()H%VclwMB0`PO{o3sWz0 z<|P>Y%hbasx8V=EL`Yruqpa=mnb3uK3t4N=#_Vs~nY^Xn;FEXQ2Yva{w6PR1ZE!Jp zXnn4W^vDP2;3;?LyrewGIhkWUlERYPs#e@;!OXpE^p8q%w2IC}bx+AL29MC(b{_-+XGWHvNpwyj?!{k`Hxyfk~_v34?Ny z{<7szXdOS@q`&p@eI3?L!@ibisndPji1T}nnD57FX4=&bYhU~4bhNMi&~ZHs7UY*Y z_yP!vlEZ$m1@H^s!|#0;a7!3#K#l>}9*%_vhkx3E&)c>qkbm_G&9_Q!!hO?6)%_S` zbRQuPo>bT+Jw)fP271;u9nBn6dJn!Z?|{=Dq|05CIqHi9rtI5l;(P26__)$we>mrI z>156@LtdmPCueCWx>XH(V%p>7A0p!?#mrasdDyRG57gnQPsWcl?@u4sbIC{WWR1F* zZ@x*?`uUu_z1Q-EGCK*_qXyXJJ}~^#4%Uk3RAf@jw8D^gDJlzpXj3(8he;5`TIjFk28lfSkUx#r@W#3A?q{Z^OT8CU(k$zDxStFQ4%NPD`O?*@Lr zIds>NS$y{9Rg9kwi|}{&p6*Av!@-n1@yXxpTW$I!rKvCbnYyNBpT1`(G8Ez*t)#zO z1$}Lw4mxi7!G4LqMwdB9eK1VyFJq(QUr{y!X;H7lh3^9gWL(t*!Xl6_Vvh;_VDbVo%n@B2AN`>Nwb~9H=6yO z@4;Q#)Eb=cSD)#;{kknoPCE2P;Y)R&pG}=5pQ!7hOeXaE$bA*9-KDSJ55hmgIxuA` zbof(XtOt*bkZYAAq%Sf@n=T!q-ezG3jc!iS&H|=fc9@#08JFls|H4n zQ?$pgMpp|zuflFxf$ar)tmw4vIQ4*>DK?r3?oCnpmZtvH{g3Q%9z1f%tqJ&LgCE+; zm|Nb~FW>d|$xGyDO-B0U<1~KRb1WcD@fVqdv6<;vq*U(-MjJh4Z!k-LAQv8weoN7* zE&4leZescAI3iM3x=kLtbu;UJ_BEknZbG;&?~}g6whLWYn|YjZH5(lZ_66S} zrytlOAdeP=$*IqM^37zwT&>BsvBk`nGfWC12ixWglM@BN299va-+%e!-aq&PZtRhM zajXny(7^4jm!H3GYVAHOqWYdbneMQhWUIqJ;=el{eD*_YJ2-TT23 zvaeN?Xs-@aw0cnb(s$xA-zw_MJlD>WORD>WjO`t*v7x7(Kl6skZ07YDrF1^i(r$@w z24!IWFo`%3Ch@vQ$jtq2Fn6r$*U<^~z?SG{xb(~vv&<@OMZY44Ib`Y3^b`Ht2pe9T z<~npCPr#&J2WzEhaYbxL+l8iGvwqBRkON%6q-#W1;K^))-rR_4rzCSWqt*-!NKC-#_cqbVo#H>1E!DtbK4w6(e)ozy20 z)V)oAkQlknProoWkw-T{E*hPD1M%D83(95QFFa_|2;&$HV--PP6ArAL0})YVj`-$lU-*F_d?I|4hG!=|I2+kaI*{jB4EFQ-bG z(u#Ajk3Mw^Tz`W4_?GO_<$Vu+(@9lX56&>h?7;R^{TZ=g!KI#I4jXmI)S;bzCH*I^ zWsiRl6l2MEIYRO@HGTFo=Eaz39`75O-z(QG42eq9s=i-hfpfO$K{27)CSWaq%%hXwTgS7lj0t+i0yZ3Xu9`=z=b z^Jc}yOT1h~BaUEiv}{PR+26;ecpC!i{K`%9jdq%tj^k^yKd(ct{}P?Nq7Po1yjSHz zH{4KPcP)w}E~vhD@x1vq^~@z~7td@`?BXnvla(D;P~+XpASXbV(a64hi<jy+6|V zKJOeNOOu#-oj1*VN3{v2jrZg?>rzbbR@c%NGGI zm+TcHB=ifDBAhM{k)VZsD7I?gh?Lkrcpf$2U z3^=gI;50+->AL+Ov93ek&!)~)KJ#9%zZ1NJq7mtIyZ%%k9(^1>!{hKBXyud78)GNU zA0{ccx#Y|dVjH+au`@@>l-6p$C1T}$tn;q*E4mrH{+bw*7tv{9tF$ToRiBh;ggq=VYshrJ^u+GJ`u#BJ{S*7fCMCWo zHsGTzh`)zUV8I!5l-a=g_|3R0@+4A@dWfNH;XqWrX?K`Dt$ydEjpoG;moZV1GIFh7 zGJ?fhmJ^!-w!M9?LZs4McoItnR_RArSY~x@)3MKV`>xNVC#IeA-7+U*guJK}DGOQS zzYX%!N_{x6&#QbYgAppXM7MEDLcpL zx;O)$n64l(E#Q~pz13ySI?^MRh_kpdA^Nv8*rhIp$=dtqNgsoOWd2B(-SoHh`O#;= zpW3vDx%6>q_IIeD+xH>y3SNN0TAK;|TSfL^^as|l{oJ|Z`g+SC9IJgl7d}Xec8>Fj zmvN*hFY;mCIc~|FBIZ1=Vq;YFoH^NV$<^xjgeG9T!KmA`=M3@QSOdSzkKgWgFEQ@J zrJNsqN`_GB1y8l~KKnsqSF@>qe{`t$Wt6~wXxKEbyq>AcHkY^&$Ntji4f_$-YZm@_ z@0m7G&nI0-{M5`U-W_%Y<_JYez{jSt*11BgmkH6?rraGN{zbZ;tDqwohYeTJ*WdKdX#KP!yfVPc_e=9Fge2f_ypZzhsY4AI?^wnUI~$5T|6@23Vj!u{~>-T z9m|M(zrro~`?YRGd>zyv#~NE~F)Qz7gh;F5hGnRVPwGvW`g zT>2zJ+Mn@?cN;d&GNJP6VQd&pSdU8M8|3my)tjbH23j)VLVWCOn(;oksQlok+Jn_^ zP5jPI;G4jymp+S~H&=vgZGfLZRJa@-f{$ZJg!G-kzMemWxy9aI7~6zRhYq@Ap*1ER z&DB>2di?Td0k5R`Mwj8k(WWd7ezu>~M>q2Cb4zEYuIw$$T#N2@AU-l_>tai^`n0;Y z`LX&RGo_eF47razQV9Mrm_`QS8SMMxiRV&uPGI`!*w4F62P28C>InQ!!F%|aoY3F9 zyn>HC znGOEj;X^R)k*U{rneea2AM}M1#8g_04so$d9@Dn%4w*jj#|8Gt$O>;UK-Y1>N$A1A zFgWS$N|SFVd^HsH{~P-yYp7tu9Q(URTHkg)fgaq_J*DW*eo`w<`vs=@=U+E1tiWR8 z82n$Uz+(7f@Qz!szgC}#{g%EEI#Z9iDQ}{eW%Eou4!43$vT1)I^Uc}NS1Rg%S|97; zTY3_`bTB;$;(ZXkWOF0s=NTc7-Un0k7Cw(P{lR!$mdsXN_KL0FTdWs6K^s$sh;sN+ zZARz+*7UK2we(xl!+U=UuQb@cCRJTJJUfxjzbBlokeEST$) z;b5m`A7)=vu%r)&QLuJ6IIkcc&3<~Th0%Dt3mxQB=2vXPqc?aZ7rw`Relcs5O5ba? zo=5Fx?c?0@VY1WWm+}ycA!#X7?}e~WtzpQNzVDYuS-6gD5EB*4pxa{8P>*b6{#kcP zx06cSErF>|``Nprz~Ii+W3kHxm+Z+NxX!6`bFTShi{+E4e(x+~>UHvRbtRCV$6~L& zFGTjlVZWmpVNz|To-4oVWY(%T!{J5NL@&=C_=Aj#!sN-zz&g8vkDH<_6J3%5jN#=a zfpu8#kuLYQd-eD4dW(BIIv1OUqQeWO0hvvC)V&T{@Cz;s2IVXK#jvL;x*B2XPyL>j z+&uG$xH(Q*0B`+oR12N?V(cqT{tA_g9rd$Ag7o_rOGIzi3$b(=+Q8>FJ>`;g*jUov z(CN}JkCr$aE=ik3$u(?sjfi!8;r%EXcum*&?S8smN`LQ{H|TF8(Yq=dd%?7!`dzP; z`RzRvA?IR8;E%8KQ1_kmdIY-lYi{XP+uTp)(5p0x<(Clb|68`1x{Fgau>LbeQqFZ| z4QO>JR2o{g0q48a`8O7(SDm+oM_r8_?={#yMPok?l}a)6Yke1fbs{!qhkjIDKTte+ zJADs6$w}X})b%?9yu+(!9;u4lIJJan?+Obl>XL4{Qm!?gz-&%*?Cl|pzAd&@!u64m|*IBPDXt%A+nvK_mbg*-Ys0>xZ%Oj zMf{FT8Oazq0`FB9UFW}1W%e~$H8bY2Z;sUEnzq5zPxAEG*ed&^b{(B-)-yh7dq9uj zobHYv_KouC3`$9(1u@{OHP`N5_{kN*Xi2@3Z=}vz(Sr2`#9v}$sJuOo z&u135WPs;LxFk~gBQLF(!yGL5>F*$h`xofo&wJ$PCn1u(3vwWJ@i}}%-0q>09h>}1 zaQcJe5?`feV1IquhpHFre2mF<9sYrZ|dG`pZ@(VeCce;F|!K1EIRUxpA%O)xBav} z9z+k68M~pA;$+8evMKOetM>3pIqXtL5)h}L7q;FA>JypxOGgZUXC5brPmvcpU+Fx^ zqx*f54O>wn-c^|x={HZB^~Mt;7gkG!{H!zHs^KpkEH1@XHE#RYm(wnD1*V zerW}-tSAp->7VHI52oL#G&6~X;G{jokX3XP{(Lf+y;Jb&HxHQp?!$Imqn(-moX<|K zrr+SLbu#r4_Be8ZHf9 z>Tme?yXf_my9O;j-+SCKd5;sn7WF zOh34vU+4QBnDSJY0{hz^mc7`1z7x8np3T7?CGkip{{9X6^mQ|GhlXZzy=m~=6*PulBxH94BIl2!at z;aY^WW}l@g=+{$h#U_BBp;al~WXGu`pV1_xNQWc+8KpnfCrq`k<55JYPFu zlr&329ObTV*;yf6cJ^oNq7TiCtWzT!`=xvp*gr7<*ZRAp!R|_XM){1h87&O!*qG zj*!G&mpq)O`*`6GbQ_diqWeZj-3Xao7raEhP^l7+`RQ7SEP>~$G#FXM!T>tUF{uJ} zxRep>^A6S=98JlU_}7E!uU$Ftd$&z0Y`ix0K>lw#C{%W5 zGV?~84qjRM4Ee@|-%nGwl(2j#)ibMt+Q80d)&s8$X3vvqmQB9ZQ&X>}KQL=q^3yKq zf**h9b0~!OV|m) zso#TFzBwpF#wHJwQ^nm<2EF*()?lu0>1Pv6)n!>8fn3_yw3B+@uh?^jhX?inbv+My zG$)PR#lBBN+4D1$xSO|h`m~fo(I9YgiuN|p?;Fd!(y|Gd@&@RNs4pkIZ9<$Tcy~p! z>EnvZ6bzGt$b0_JeKKq>xsTKY7-{|QUbU$EKUg6)ild)fQ zXQ-sQ?U6BHEK;S9k|LHazS$zTv?voI>F)&A*P&421-A#!W?`KYqmSJ~->;9&tQPZ| zO<8K&XZQyCLZr*5UPHb#uL|{2GUH8kH8Rl9Z{BRUiM_1MF7oA7` zF_CiRcwoEa#%32QD5k1Tt^ZfD@V*!B>pE-)Cg$yzQIZO5PebJNrfpqPyLhN{E2sNc zKGxzQ$q8tMMU#dQ6X8yz_ zaAF->b_e^~#qsRxoyspoHtDuF#s1($cj~fa+id!nO8@9nu*SLZBZ>^{A9h~OW3TZp z`E9sM-Wz1v?ku|gf1*OOLZvHm)z8FXh>5Zw=T|GDzwNFgn|;{G`~Awg5fty|E&6Ol zt1=L~_Y5{7`rC-lupQlukWrJ_zX_Yb1Z3;44}*yThhCOg8XLf3o}LcR_0lI(@gK-K z6&-ti{FdnZtytqH-opp7xL+E88~&mhu}z65GkzfUwj8=Xy5$ZRuZ1gk4*qZzebY%Z zZiPy*&R!`QA3yGz_;fPQc=4sb`GH$jwh5fm)pNVjfUExun_96bxsui+&lbTOxA#cp z`ox-BrRz1zWz$Aem$8Oc*Y8};ciYqhtn>IqA=2m*{Y(z{ujkB{Hl;e^lZRtmQo-++ zWm_YpH+qT%gH5~H>D2McH2v$hRKx?@XWFU+wiHFF+v&BxCVsyK(V?b=|EPNsd~8Mh zvKEBNj~VgNt`;Wg(93=5uruhV!7899{wJE$DCRpM;DKH@_e)+B>Px}#RHePgj6|lY z>%-SE=KK!7F=e-N^(K#yin)mY2L9pBEBrY6px=&RPYjj*s)xAUbM@R%bSrV5E9?4N zRo&Eko2JMqv~wf$#n06rndi6^6IG4)-nq(^?R;@s$~=KsT<9?5=M52l9ryiKp8&*LKVgx!cf#&=o1 zB27LeUS%BO=df?lX!N&=u8c>w*@}0Ai+OALN~!Dd*83&iL_J5X*-U)olK8))>uqjf zzEv7U{jmcp>XVYa!Y4<``pa&ai_K{mbDampzVpPMU8SE`ft_~8a@{`Hrt7qYSeF%D z*o4jy-YPCW$&=t26}>^P=U%PL@;sSNudY{Rj#9Lnxxb4QyXM^m{*}gtS(~{+Q5d$i zV9InqQr`QTJw@J_asJp9DtCVOO9F>ocVkI&KR6Hd`@5!QJa1^N-;-foNQ|@;+WB3;b%w-`97ZAg3$u!O6QL37cxE1jCe}X4yMy%lk(aU+(iZ8YxVYvL% zI7B9%BwltKVg#)+^^r0;d(FjlOLYh4?^s{+O)-_@AFqJ{k@EW6vsTo{m#B+{tf7k1BbNnJX5{hZ@LZ$7@5DlWepL>? zD{Kbtx{-3`e5ho8#rpaOGDun0l1x#OuPNAOWDrGfrs`wk=GONSOC@$M{FE767vj2P z06gY@XrfNDk-k(YDf|yIUT<{cRciR8IT*;hrPzDrs_A>-Yoqts|K#;ACsTV8|74Px zyPQe?SgGspvp>+e9|MrjG6VhX(8K^;R?W*rb&1%PP&h-S9OQ zA7?+Kjt`%s&v+Rs6D%7a!WGds8UlUUo=*~-1PlcvM$wu@xib_vJ&c@fc zBJrB?9mmIsei{?G-j9^i__x_q`8%EW5_I<;?Kju$`|3FD6P?$=)TW;e*&iXFgAvKs zAww>N;;P-DFge*z>a_o z$N3GOcKV$s!M60Aik`}Dm`boFYfk%QclGG`_p7%W|yIzV=YR5!+d`iaJz~!|B0_57^{#SZLT@S6Fy5%KuT;^Y~wZ3P{5$CR{+m@D|w-=Z+n|}OOpW_8wk`h0QU)p+Qdz*0iq(O+(pNS71JVBv9-X)cd#5u635m-)}>U0xn zNIg9INY`(FeA;~dyzCVQo)-QsFFZtUzQ0V~Fv+{0cslFB=Zy@LM9g2UN9i)n=CJ>3 zzpMw>xV$`j91e0zm$WMOd|(^oVeX6|{{!ogk>W@H&P0}du0TuEFZY16R+QP|Wz>0h z)*mO`vG~EGhrqH0$=vhau-_@RV4EJHSKbhtSVVh?VO*BDPAiBZ-hy!mCMEYeFts0} zOHbyN4p01Y>EjR?2)65!8>a5P z+U85v)Gc<7`uO9@FbU0vuPE!clRjmA~!azCmdJ!+MU1p5)NMW$F$E%s^HPNvt+FZzt&!Oyvo(~-8 zGh#P5DGvG&n;PSflBpkiys{SUi`4B@ZcURN;8@JtG*v0 zZ@^1T!{>0C<%?7rnark+7QUfsJK`UrhgY=O5xe|aGyGsW3|28OU-Ab93J zpN30R1bbl;gJthSQ&#^7_HVet9suYFyz~d6p4qSZ*JD-UhB|3mVfY}+4@_PEg|;X} z+@=N{!X#=^vU+3_PXsgR|5&w#b*t;vjBd5vEUOoFwUva+2 zc|L8X`So#b-5xveskLc)kly)JE04@z|D_DE^w>Y#kA7pxgWrGyQ1q7ZJT$dex)%$T zSYZ*89{kCabKudx0MA&1eMS12zM#^-hi!SuQ*~zO!{*?T3q^1 z-m&sZd{oQ&i+(ZZzDMe9)Ajl!xmS83_lHlX$HzW^AZuceKJ^AP##(V+Xl4-K-z# zo}yzJiLu&A_or{@AD<-+mA{h(<`JhSxTY6@^Yw49blDmeAtq8U-Hy-Eb6xF7jGr1| z@+?s8g`KU1j!n_3c{<-6*x-|a4;i=C zE$zFaE~sVtmh<`G^QB;v6kTKund#`?+p?hVwPa>>|LKo9zn5K1JE`k76}`zATOTg% z(%VRKcGHYN_$?YRzlThXB%#60fk)3-H>wZ|AAWpM6fG?r*jDy)v9Gx0;&%8ac(i{a4?fzk6VRQt2)sYpiF@$h(-BYs+;1-f&s3p&OZt|B15J zVV|Td=xkb=6mQVQ*fhj3=GC=~tYw{^pj)hK`ufME^?SZ$PA~q-D@8}KmdExmAAuFy z$G*w*yVGCjzL>$G*Xh<89;>-|*P4yyd=9p6Me8=1Yws=u{o8j&rwh9L?&sJaScjO0 z`Y^uMo@X9~5B_N!_=fk98HnGasLaQ@t@p%-53=+a>iX1XX8yV{RM(#uo66tA{4xu0 z%*$kIue1;uVcERYGv1eGOfGE0{x55>J6inQMRc)o&YC(?>76umnR%b{y7Rm%I_O}! z^-+kNfNy#EEU@q2s1hPC@c~JB4!bZq^$@U-W04OBAioy%uwT$-zZ@tOoLk`U7fblY zgxDY1Yq1JExRa6-x9<>gSGPI(`taXqYYUU!YMQQx6KkS>lW$&NIe$UVHRdEfwpL7# zEwkAZ=``_N!jKU@)M;C<)%nb{aA~R>g}=pqn=E?%>R!@O`ngILFQKl5tc6#piava~ zN4kJtEAuLFt~tqfR0SKp20Mn6dfpY{^b&W1ahkC%J|+W+CA*$DmU$zjJo?qn2Z?t8 z57mHg{SmuWq~soBptkF(IL+0=E8ea61`_{ywBR{1AN&^B;hDtdzbE_3Q{{1U%Rn`*2!{KHM; z^zNbP%$wVH&GGwN=3O6T()pBF<(4C?U)Rdx8=DKCEA->-=9#|S`6u>@z)rdp+e*2T zfo*T+oN2pTE`cSAiMAc`N!JBFNz|6P@f%&{<_=$qyZOvFW{A?|YjQO(rHO%es$9@_|E7N(8D+{lc&}IHt{_$%GC+!kk&=Zq zs`YOk>7ULco-n^m?qJf|`M=%69wJI7%luyeeO4!Q{d3o2S2z$Mo6`jLnV#6!GgS(e zTUWqfrU#35*d=qbASbgP?b+v--->~GY|MJPhPWeVk>VeruZkBcYmrTJfoUm!)-A)a z;Vl^CM;FB2QlZ4X1}|T-5@W79`+^`V_Up@D0_EwGl)V{zuO}z#?GnAFtQ@9~-(&-4 zhmG8(MGLW2!Y5CEM*Qrr!(|;lD9={mvo|zKP9d)y!msO6e`5EI^2-(A>nC{>#{OGD{%}1_|>yb^oe=I!eBJA&qZj{5X zJUl|u;#=Bpxm!jNOYU%5beLeck|Yh2F7KPZzJu~scEkco>(E(t?yt*Mvz;#c@4v9; zdo||145mKS`^wac#3#WeTVjwme>@x}wXjt<>2N#qYe8~7jz=fJ@Ad`Qj%7OU1(xml z3cB*I_+~|EZqfh2Gbl>@olmk-SL={P_iiT^v(LOE%P3pOp)f)V0_PfWEA#4!Gr?;jIqjK%aihCymzV@i*MjhWbhK zKMs6XXh!@NB3+X2g8tUkpX=wQ!wdXC|F&sra{aCLZ~NF5zVzsBe1Q$0>n zvBoLt$lUf4K6ELuN&dR3>+^rf=XL|PtUVDXyS?ZX?)W4HSd#|B^^*q&cxA*w{T-K6 znLIZ&)^$5!k8Ync&Tq6{TBd{g$ssEwa>=ga-*ezwzW6r|XbhWHo zT#vj`U|*QDdL;5&Qk}`>I@l2!nfI!zsjCvJb4T>KU)`&kp4dOTB4w%-58w~W|L6+5 zl%glt!WC8CZssNRJE|Re%v>IszS{7r4Nep5CnQ3Cqm3RTPi^=s@EP^oHf#eWus3|a z1KXg5)t|jPObRU4-&ib{TS}rw?B6|75@m47`n%yWtGaHttLXR@RY!N+dj$5pr-9%3 z?k4{_ICSkBuA%3&aJ1@vl0S$8^?j(c%5BPRKc|ipKQ(jd(xo9XHwo)jR&(tS3!ALc zew-v+N{<1*pWBR$>51{zS)}e7nw?d@t9ef1$YDRRY0?+WyO(tR`iXa?C_8pcFY|3D zVpXkh;0Ekx)N$>f@Z9^ISM>Sksfd@sdUw_8W9q8c6zyH2ap>VUo;P!OPW+I1v0f=U zUN+|Xtg{gxVDQjR+V3^CY^mZsQ?Rn?c z>yeU*@v}QJN?tQAM)uWtr!Pm$ez4rt*02|X#gpy2>0+;(C@JirE?Hxjz`vfGrpNPy z%j_3~-$v>VrYs|@dR6bfW~~X%a*Q5s(mJmPpMUz5nPWHq7I?SC-(bBGm^r8za-yOX zADVOz&YC$b&JJDAbMbSjgG^X{i8UYH*L6G@JhM$_3g~MKyPJM93mGt&lH4=-t9vWa z^~CX*eC+g7Mn*^%Z0d`fMoFTk?3stZVB0-`>3)Gv8}p${o-og~x7LIi^K}k~6X_0B z=2QJloxj=N?Y2vb@6_dMFrHw|3rzwBerJk$Tx*~eYdIW#1?<@K`-Jb z_xk7O?R=+yWS_AI-5v1m_lY+#M3-rEHdBXos@XpM9qX|B7xjW41goj2&#A!rw9~8O zuWt58VLt{ZEnFOZ>|82<9*jMt6vc+0dD+*DyQ{;(rO{|~YtxvY!3o+F3WlKV@^DE# zL-)%byFw)q@uO@yj_;zPP_Xzb!PgA<%f17K5W9~}HP1w^|3#M0q}In?`RQ27kL zadmxSKEIFeRyksMU@JeK3Z4$Xp>zYmR)Evko5Ux7t_|#GZCmU4G1LtxbZrhdL`$i79d!=$*? z{0q=;#ze+Wg@9BZp2jUlbAKPq>9QaIu%bY+= z5=B4#79k6WC8Ma+k17VL`R+{k8@8wdAGQg9)W;!GiS&(Zo;M|#If1+6?RxK(>I%f@!L(`yb7Q5HG9O~#SifNaOwXed=YC< z;tzdtD64LS1gAyLwbb)Stc@l=J70C&9?H6At?QHj&}GkV$$IMkt;_0vAic`#l@DTp zhsvk(%!ACgn7AS~HKL4}S|I;2A7n!RsAzu?)88jo)$LQZX9#|}KH0v_Ed^Wph(BZc zR<#V+1Hk$!nvG80&mLz(u!kL)0wy(siUFtFd(huHFO_c1r^K%L9zSF1!=|@jBo$@E zPoqqJubg77IM@)q2YmHz?3hlPP27`x6~MyX*KJi74Av^_-gg=63y4Eq6ursDUb>7$ zr-w+D>Fk4qkGY~|V41IEjFg16@u#C4HdVtOnFC)QCspTm<~O?BbJ{uY1fK5#OYv(3 zU4P|$W}Z^15m)oU8qm+kAtcG_p=xRbIg>Ymmm zw^IhbUtOO~I}QbBJB@ZLo{{~9H-YzX%y~aISE)3`S_H4@@YhpUuYgwzraaVh&o!(y zQ_YxCX|6ZZDGSq%Luc{q2~)?xdBpU4=aazvBJY}a4~KW}y(VxTRe6NfBwjG_H)rsT z=l*0rBKXGR@QcNf6SvThYy|6G1~Nxz;}*`i~ea?m{eViys=RCx3;X;ZLnD^2HW!!^Vs^@ zrp&?lSMLv|A{MwL>=VT;KIXnv$NLtWv1>n#;7k&xpRDIQyG| z^9iQMnRI(485{lErVlq`IQTjBJ3$(AbuheQxqA9Lwz1!pP2;gcH~xY+#^Cv~^&$oW znDf2#`%3iNrP%P-V&_fKAo_QFp3Ws3?s#PBm-r;M)#Z-k(|zGe99@qi(Ie+C0gi`w z!K0qC|3%6$>AI8sE8(S^6%Ci}m-KU|(akqNA5<3{wW9mAm`^Se%eFl+&xvCfOj#H+ z|3)dm8U)ix{K6Euutzzmpj+p4qbKptr|WySpSWZ&d}>K-mo`0bf~=MuT`4i+im*S| zl@r+HJc0FJcN2K79Ffwdv|Eae)pYs;&qeeC!D+i^28Kr#!5RvG+(llF}QD|Oj?$HWIAvZ@b04d_`K!do6J9S*h% zYz=;=Bkq`bEyg^%hBgkS4RMKIgKkz){uX*JxW(L=+rg9f=G(rf4iz-0P z=ky;>h9B1DE$y)Xjbwj>tRL$7p7|{B8|{p`5c5V+N^5QSVtJ@keCw4>pLnH^EBZW@ zaCeA|v#@+WtPkunC(s)I4?{+gQ}mmM*V%g_t5fb$^3oL zG3WeNAM7)>uFL4E64diRd?p`Yi&Rt|o3Wx7mXF)Ey2K?+ zY{qsrOUJbhjG|4Ye4+BJH2V&3#EytObFMY9nBk)pMNQSu4q*T zJkc9{cfa#?Zsxf4TiqYKA}hov2E$!!PHmXK=3;O5S749z#G&$Cn9jdcmngaTkhpeW zDSj=B9i+Ke;-Mq!wNCf1#KdLFQwzN@@_A0ytbMgizfJwvlxy8j`ulS<)b~qTeEzWc z(Z_6L9c&ihUUm_?vl_aZ$QGf}A_l&;%r}0S8-$}-bxgn0o6eMD{a!PlWc}LIgY&G~ za+BV9U7gpsiOqjX;QguSj^Z=FUPZ@J>Me2fZb!=Zy|K@NH+97W+g8FQCl7g~_!N9$ zU$M767^-wBz|4c48jj61nBvSbWqdHgFMF>A@{)G?T8Wr@k%=y#Q*}~v+8`#ngI&p{ z^AO>xO6^r7|9LE4n!kl~T+YcU-kU~}3x6U+{}t<7Mff@w%g-Nuvl=)6lTkNyoQ zMq`)y#w9t>(Vu;eO!ET${1Wy#UIgx-uuCS=CtK`iJ-unhhW(zl=m&NYgYCajVS@N& zm>>A=#0yOQY{ozJqc-8v5c^^<_3+?hWyQ|1?=8n}=cG%+O&`K0BV2x$zC|92}6 zke#-wC12RT?c)pVl!`hIj{c46x(C~3A>wMy|5Mjz955`3hQ#y8*@R~Pd3W(2{$+mc zk*$o$?VC(He>m4AMbWXPsQlmOQ@;a$r(SUrIZ9Ebt6mxXCwl~-gMRY6o{NU;K))W# zjN{>H!EHQ4cT4=wQZ0}PZ?i9HYh8z#(T(o8;Sm@1yqm>z8{Ik-LLB`tS^uq1W_Mwa z1Ms=Aup>0C6Coe%X70o%`OF03VMOV7%z!tusd+1pT+fX!Uj>hRkMBfdu$WV>V^6g7 zAZvdj?#3TJDFW8x`4n(z19h20PwBjt)j+;Epv%^+4KVpNGS7bk5?tG|huWH&d-|N8stHoD1C-?^yq9n3QiutVGuNYhX6Mh9?`1-|(3qT~fFJ z@ig&CaJ6F(Ut*Lv>ESE=EooR!6rH+_jfM6}Ph3Qs#*EZw*O(_1RW75)-7My@U~0US zHKRT{O=PEF+A>S`mwJ`G(!Z6i?~uLbJsn2D|70O%Srd`Z+TyzkpE(Nbi|<>HdfAa$@IKanCBmtWsejk&owuB1i#b%owu((+k@V95_*Q5=(^nU` zWOPG#&xzr3tSwlFmwK$(d3;qfLNaI3@0zqIaO}>9NAJH~*Wvh8@HNPnPKpbEp9ek4 zx$)>0E9pC}--gK#$Tc=yZ|jjZ`6A?5Tzo_;ixdNsw7G^$ZsqaH!3De<+U1lsd#tvyyi|?>6KLmS_#V^^gt!*3-_>C%EBI1}f`Ha0v zzVOORux*Ku#d^FV-dhkanyP~yyWaXb|H{Y$Uaqz7q2D$nw&}O)EdTiu_=p{4{`_xL z;l3%eO569_Q1K+yb$=rXn2reahOyX>5u17cd&K$rin<*}j3M;4vBAt9!gf1ix>rhp zMOfd{BdKHXfl>L+8)(*$Cio`A?`-Bzb>D-|amIYGw8)Ofe>LBu?gi70KO^NU`c}eO z;WEA@F)ysxJStu7yzGtpBfctCiOrOXd1^gA0CCOuISJk0TE0b>f5?`=^4RyYVza3|*eAVSndj|$%kgOmrU_tX7J~&) zlyJFelVOpJZEP0*M*a&Xy-N4ZDP7;o!8UX)YRa6yPhdW++nBOHNQv(evX)Kt;`!x= z1p0oh3al?>%y-N$j9)-w_5~T_m$4BpnTFhRaS(Qb@BA_ozHK~n!LkRDQkYnJ`xCKW z6?XsU+1(QH)FXc&w_WZ{Y&G;TXTh`FA^up6D6h0(LdqiOPi<6Xxht8I~ARoO;uvK zC6Qm(=ZV>--nLo34tBcW<2mpMiYg4$&!j0BIL7o{^S^N?^Gg$q^usta%gpP65bnK(~0-wteWCv@C-(Sz`@S7X-b8YY|9A(MCcHViW zxQU~N{<)VP3z>%mzW3x^`fra=*|m%K)4ad;9=Dv26(!#{j*>mqJThXDPrf0R+MU_> z`QlfvC^q}!Dq3+RRC-r(Nj=tlKl+|p=<8yl1jGVz(hrud%z5nsI;X~9Xa1E+dSudm z=89v)b1ZM_ru}MU=hmj*t2|0LYzON1olL}(0ZTZ4GqS}Ua7&AH`YYo-ayy&ulk<^3 zwu7s?mlj!odDf;kDa^ZE=+12_o>SLppTEsK^Whtp)J(#@H*U8y`5jrayH}c2)Xz7X zA0~f+PmGDuur`ms%-+vk-BSBhU_E|!P(S}S->+zQ3^r~%&#%7FZ8Oh-iOu@l?zq3A9Yb$-eI)i*-KR}uUb{ci8qQQ~c<>%aD=ky5u5xYnXRseoSm(3~*#9o6Ib zj)kvOc_bgN^NIytO3{O$wfa_a_N6Ln#&^$T`nzI{3zdzm_wx_v-zzQsmdc}bDU-f< zd0n1@BTaoATmXM+@qQ|OFcsV!CSiYKQ|#!L`#aCZE^LGd7iiA1_ge zy+Aj!H^&O%P~0ajP8cR1x7YRCo&J&j zJ@#E%q}yzah5dAvp;57LNsB*3?+LoRv5{{Spe>9RdSKCXpcK+(#-!lYrf~)93;~Rb}k>&gP?g7WYy74KdFEN)MW?yS~ zs$CK;70}1*Kv!D7vgvcL`snx1Iw&%K3vo+`{gINnsunzV1L8_N{eXEeHaKg`7GHL| z>7$Ra*(+*RGWl4l|M!tG) z8*u~*hDuWQSi6W$wO$ro2aO#5fA;6^uMHpA(Ie%NosL_&g3X~mSp;sg)I!})?6m6G za|1GI8P@V=x(<9p%$(v(*S?gV2ew&jXjbINWOenoG$~KKOE9rE#bfVQo5s<1Z7K?; z^_$pctzAL9xaLt{-HWkT1-^+5T;SiEnfkP!vyTZj>-tSd-1+L*Y@UJf52pIlh{Z}< zUB$n?UfWQ4aa8A5DL?+SGkM3)y6;sVVd~;7^Y6jT(dQyN?{8jV%duh~WC7c#sQ%Bo zjX&Jykpj(4IW~fep0SO%?a3mf&T;*Yo~zA$_3ZZYrcN5dN7+<$BQXQni*?<#P|1eB z=%OKRarb3Uz+qmQ(~Ea5)+z5c)8l0&7$hfE9Hig3e5|hj;os}JzK5>ENfmZ`rCCDO z8Dy#dMt{LWp2X&x8u`99erSr~eu|G(MfO_)x0AaU`c%qTq>fo9elBFr_gQ$}H&(o( zabr!rC-^;FP9gt|3inCx??dDv_BTb((|aZ93e%s|wPnODDwN+ZtC2TtI#(H-U3T{V z{@N=~{xW?|z%MAOe%ZWB{jR@T{l~YAx%WDAZOeYl&G5p()c#(GteowUg3Z7)t=D%e zHX^@0#H~kfmH0XOLFV=?*gEDAXa9bb>C<*zLz$O@X;{5*IS|C(sx%vO5f94h%Xcdh zC(5C_aOQD(9s3%VjF6PbHi|yXWbRI8PV2l*Utc|uSi)Z2=6!eI&zl(?G`gt0jM=L> zb=^El$XING9>l_rnVj_5f}Y^R7~ZFd)%XA`p-rbh)Mw?9s2qJ{zDGXW86w|;U)UX&*w4tt$-s%WJE7|+dzvVj$#*w^*I!gJR8rx8 zktw@w>wW9}(#SF2IlpB>Y^!0ci@*Nvyi0yf{ZghIxYt5@Y}$7dp&Pbo%m!kD;scc& zY>%Q&=#N%n|MSDMCr7T!N_%BNCJJ$22UWUo)(qcV-3LCf*3sz>EZ_^~k^Tw6tbe4x z@w47wZog!o!s4OQ30~lbK`Iw?JH!1F_eO+FXcQttt`Y|id|i~+l($BGc#W2!5>=5o z<{5h&bPSWe*8|&B=M?>a_U7;(bJ+{7Rftpor<|rpq%2+*DutJ^Urz$PW;}tP|2OJa zz})|MpH8`RaP+<(Qy%BSz`9g>PicJz1ph z7q$H8w%{wFsK>~_HNt*g9rHB~ktc`UvJM=IqF?cgcGAqW=-1H$l}fMM-@Z5JD7uAZ zrk|+m*YFuo)IXPb-%?9g__-G!o!7(+Sml#lthsw;dgTCfqmyo~i`8om1B{b@9yv(Acq8o$h8EWI3}%T|1@ zDX+?}DErd|Q@)@%QQe=;nyKgpYvx9<3>PGab6ar50LraXo36EAZLcF2Mr zsqvdfGPL%}&+!Alr&s~MoY>$ecB_6~<$r%kU|ECTnRzg{Ku27rG>qZ#$Z*MjA#Qh5 zVzkW+Y>)L{>UXwUq}w^^TlkB0#2D*m${PHRG~<|mY6tf7;56#@>_ky=<+lj=cp5R@ zmtkki3}%G+eANPU@YoR*g**1+xa{)FPvB=7;tNw3%-f-Hfny;SbNXTjF1?tepS{bB ze@|QLv*K&mYs%uiS1pf_gR9H1IxRK7zz&mslxD<2hN&ro>kP;cjkHex!0rN3DG;) zRBx?U?*AS*C#ZX=^AL+*NR&J-W4>wP0Ml>l9}kg~r$Xf}a^79AJ@Jr%Cw>?vPvf#@ zRcT^Bfh8NCoBd0y_o_TEf%{ur8`<4$#@61lk@EIEJ=aw3Xv(G1+mz{pz_qRo7=bS` zviBDHvty6-Gv8RY7xhe)AndZ8Pw?@^W{*rrjm&m5LfW(xIopD7EvM^mKX{RcYuR6l zcrmT65N{5-tSa#yGK@iY+f0{t8~)c9XqN`dh)I|k-Ehw6^;ogG`BwG*9Jx)K*yTB3 z>Bi1lfj4DlB)Y$CLjLhE; z9KTHqhlk3xk9C>n_7!Z);4|P$77{0B(=>F_2Z%R^oiuCCC|Ug}cCswG{U;v^m-p%G zrSpQ9nH?@8()wh%h4GIXqvx~!__IWPVZOD>P;ecy!X*D$WJ0j$GtpTLV_u3vmpgnG zF%K?Hn6_7AWwA5;g{QwBIGadNv*Ii*>r1!Ztpwn3G@Zn z@EPb_XO{)5G1kuU}jrn?6E*X_IJA+zg^L1E0TaM`W*i!>{B*f>*tb$mVea!HWAVdoAzI|Xn%(; zr&15ye#_!uyKi8|vdW`PVKdI{Jk>FDtNvB!EIdAITV^mOHf>5}pXuW(^mN_9q%{Sv z@QxTS=^BB5Zcj`}=K9wqbsHwghaT*5m|SQ~49bns$Bdn8mNfPmKI+(h8xQr!n>21o zjU1YqxO1iVM#$RUf#0!=vGVwhuHT3%x=*+>690d@&TAF=nejXHeRZY%Wqmz0cR;*qa~pWclupxJ~aI$ zcB%+j!o0tM*gnB@$lxva0H5xE zqh*#qnMyNms%~>T{kR7DY*_bj`5J7}zfsF6UK#rm|CNwP`Pz-I(+2P+i}3AENo>(J z=$st7o0#(P6<|NUYPvtZ`NSt%+egW^W4iv@VJ|CISkF2BF1kM2BGW%6M!@zrx*o=O z@$ti#ctZ*NDATcyA%80>c-1BM@ENnI%nW@#)57z83$LlDDYDV(8$QX=ME4Olc#=(f z{8H*(U>h!lFNy-g_s5mMcDX*s)N}r;=9#X)=={7-0{iX~;$+ygGLG(x>i6@xI{nEw z=DwZIJ{G>A%bb6P>8DGrdf5GE;Fwm=oIn@eYDbu)oXsBMRZTnAcoQa9(ZBr@#J=!`w8~6+JmhXnJScdFPOsqz{jbWOD>;qi?@qc`Z?@IcG|hqz{?&%r<&1> zy&U+dDq4=+DwxWo)AcfKV7ROal9`&$W}RdHiHW+$3hb+Pnhj$D>!E35{5omp=g7r< z;hFZtD zm-rR)Nw2DU|*fl;yXB4Tw{|@mUoK*2uV4J7y;FoIPsTH-u)>svr z?2(Yb{^opMoxhK)eLs8j_BjLpsp!M|?+yX~CV(pprk1Sj@m7OD+o{X6BZ7SKecMwX zzkwhdWhwLR^w;=UJ|-4V2yyVSq0G-~^6tOJBf~9QTJZbS z?=J`W#9bjoUcBy_IYWInK}Y)AEn@ulHu>9mZb#m6Wsj2IAJMOo zGy1+4As>E#UrrIPe4LlD_mFmnznx>rddn8+It{-Q*dBI%_HlGAegExb_B&+?nhowM zF>$7L@A~KGMt@Jt!ppjh&%67i=##)cTXV0Sd-UUqR&L3}I=r+*nDj($D;*E4XC`#C zZ9=4GSFmm6qND;D zSdP8F34Zbyh>eoUjNPQ@6b9S`|4m< zCbBulLz(QRI1Cjrn^fhIzLwhKi`OwTM&G@$K-SFuGi=*fpbn1$3f2Yg8ws&CJ zZZJP(xbKz*#NMh^AWGs~F>TZCBKvp4lU@R|91~UhP1k+@9xmC04L&Byv=7}$1L8!i z^+{yqD2b1a{<>xFcBVgyzU>bWHWo0zHuWwNF6WcsgYi^N`zi$C;Ajcd9lm79}ue(-AQq5x{7AEAwJ|7pUk+x-Y~@OTV>(){O1Da zrsCk_rt&%6hp;EmOkJk64j%ShX8aomu5SnU@5Sg-;(@hGh>rRP=Kjg;ymATsMcg~s z&hoHV1%34lF(21uBz9&gzkF%g>r_5@iIdaL!n@>JA1=Mm5!0d(@r#gmBEbVWsdp<= z&Hpr>@tdE15SXToxYHZTVq4Vx1Ml$MbXA(BWs>4$OHlh4lw}`?7dEGF&iymsq#g3v4DaQGH9-bO*U)OGmdoq7rUi7{62PdU=$W9Mgm+qxCWA53Vz`A>$OMgoThg^5L75X>y z*dw;OB}a{7`GM=^u{@M@sH#(d%VseceBt<+IOkj5FgS8@K}}tu7oT z3F_*y=C^RXyX)xupAfIsw}Cku-OsU|@Imi^cXkm^+v}3ppL^utee_2TJjO?0lm13G zKb5}rW~NKZB8UCF!X;B-LL0OWmlOD5_c!`kwNyV^d(K7 z92FH)Wv^|kDOgv$BqK@V6z-+ylUmz|>KW@5I0sj8UKC3UbrM_vLa zJ;?N|JXZ9M*T>9g(KlIb4p;JFV?~2 zW9J`yto}*hShw$=9ua-)+4t1(cvAf>U63FD8%34VHa&aOW^xD#y0Df z%KtMkZ|B<)I}*9Tl_OmC;6IUkF}4D9_$$CaD2jvLEiQ6OhjQW4m;N;cKPE+AGZ)0h z?!FDXY90Las#{o!_h;&Fzf+#Q#9Nv+KWNEevso9i5AaD6{Af!xHuILsvoO5C_r!mw z&z!bALAX3;tbdo>FZ1sZ8+%-sJRjndyMwTAft|GJHGEnK>)|#0@Pg_0m7(%p1;4yN z{yy-7e#V{-tNh5CS1C+JOh9gE2XB4XJRR>LF=W}t{ozpJGDVs?8=PBYKtI2vsABqz zc?$ec*XV7b?te0t_>%O(K^xLr3GsZhc8vOf~E|8mYRH=XWhYecB#ky&-W=ax(Y>$;Vag) z50$U5qXyGxbcgF2d*l+`Bzb$?RzD(#b-1a=P;U6jgHOy;J<&Vaw514kBJe3+tu$?{ z?(N!wy}7TQ3f_1i{)o4u_nn#_h08whST-#S^UCM*_3uZPE!)1Qj*aTN<%7NET}_so zyJHsXa^(Wk^~p;3YixGAsncAC(AOMA=I`K^beH^6V3r;anLsaGbx2&l-jv z;3xFA<(uob4!alF*4wdPPKPHtUC$#QWi#)w%ji6gp6!)|w@v-o_f`h!cb<)ikP|Ds zatl8yCk+5I7e#%Iy@H(vU!zes!sHo#S9LC#Hl9!YDf%S4TRx?&li1xIgmsHG)XR%SoM7K+YNp{v)MGdh5+^*o23fBCut~FnPzX1BOG>3FwPv`KdRrd=r zkJd}9d5TN@88`UUd^9mins*72bnW%`MWP4sRbcPyZmhvzbaE(PqYk=1Z)ZLaro-3? zZR*>WeFxz~U*saD6KnXYCO*k~0^gyV$ffw?=G)JnxaeH}i4s|HlLi&h?^EgG4>qYc zuG8;72ewPmZ2X#S%1Mlb^61TjseGsC{ov6pV$5YS?@-T--5Dlt;f+(}CJr-tsgW%? zL-%wq9eX*muDTb&XC2mMZiZi+O~3Ti`7RkEGNQRp&Vr|&RvP@^3j8aF5@R}^PaZ#t zxsRwk^5duAq^7@{I(H9X4|vLSoHln-p*f}<)%71|n7TcJzP@)?*7?uiW0{W<5N9Wt zN}!WZRTv%2m#mBLW2;4Otb?BWe9};PO{~`*|A6&S`OK{Dm321*$MWfp@Nc`rrOhn- zLfJ>+Yh?KS=!D-J1*QfYTLb)gTg=vT#Gx$_GH$#6=Dl^W5tL^wSs3^|c6l>5!Pfvi zdP)3Kb9WFKdL90NZ=FQk&9aLFzpE$q(0q((C)GVjj0*=}I%Rse%;}8J*DL+(u-Cd@ zoo%c8Xx9p69$SKMU`+HOd)+C@Fbj-xeUF^6u%+YboBpQmFaE*Q(MR+FCylCYzISFj zbDr>XbM8zZ)A_ClJvRj3bB!|ZRrh*ho7=h{|1In{<&ifspqHxgCPG~G|NFbrS}_@d z-{Jh-9huEZeS`dt&a&@8Iee%Tl>)<&sz#XXI~7<)=kw}(W^HVI==T&Q#!p94Q|t>{ z&}SAzuRIUF)TXbj^ISpSt?mOok+xr(b{u>>Qf3C(8lx;M-q4OA5*NM4O0dNLD=d2DKi+$&HSftFxr{c8B z^qGptf*G*|Tqwnwi;qzU^gUIvdrv>$mc)Gm`@xC!>^*@^KMJ{Km1WDe^A0|qv*wZ3 z58U8kz*ev(r0EB5@NHnqipX=d+n_hbURd&T-On4>j*>(B{=Kd~TCTsl-CrL08(mpU zbg?MdTIQmy%#q(6a!JJ$QBvHY2MK=W!QtR5`gc3#u>2`Pq;yv^2eh1vO`(>)|6rEL zdN9uZdCYZd_(t$$y&Hz%&+C(u#7e2k{(vvQUzI(^dcD*w2{I!KEiiL)T4X1iMlCk) zu&=3ON!DzeQkJ&Q{{8q0-lyhD_8I8RVw!klMH{e2YeI1G<>VaLr7J9 zObZWPJ6WVe9P~-&Fx^JIVps>Jf@3SidQ~~K9*@b8vxcH~sWQSX)7FJaGWKPewc51X zlQZT#rm|j}tlu@Oi%VvqKfgFN`Z(X5(bS{LW2eJE`XRU+n`VKz4yFyI{StzoZua-U zxcTv2dV&`2Rw`u@-Lq$;?6O znXt92i$A&L*Msbd;BaOKjsHlO~UUJ1&*B} zDSh&)hPm%No7+DE%(dy4k*$b@bHpqA9+oY3E+h?|;u~m!D3eGk67W) z_PxYBZ`0f$JdS(Q#?eiWhnwe-5IAF!7D9N23+ z&#SDzVdyP_X#;+j>6T-|$%8DxTD>1zh@#8MLnLFLa7m8*m>&Gd&Z{2DC6Q8MpId(a zIZT?pM(6!1LQYN~wj+KCU;avb&gr^O_h27(UjlFx1zhqOeQ^{vFfVxHIHBx!z&iR1 zez~QY4f2 zzUDlB48NSXqptJMem4ExnMR#AvF7}HF9YX6JKdMqtTE=6d93uoj`kO@Hd>*58<~v99AwoBq8{?6OSjpvTH|3wQYY z_xjtuu8$8FxX4B!`uAG+j${rW_eAxH_XVc9lS40U=c$edAF!9tZREy|VX`=RxLm+L zqZ|0#U@DOVpB-fMLfBvX{2YCpJJZKvoGO}EJ$m1N*f22fV!t_`)aS!?q0ecm+c$ej zY=FBw;veUh9J%y2HiJ)E^98<~>3uQ=+fVIwCeLDB%viT`_FN4tN3ooNzg4;=6~kre zDD3F)?7>tB+w24EH5GdihX;Go@@niGoj{i_@o?SeQ=sEl)bEk5n+EXIPMX!l`HQ_j zkTq}M+x22iq%8d{ME*iGB;0T zFLQJkHf?Agy?*U`!N)AIoQ;*UG8q* z&>z7i2UBIh2ldc{6x$wn@63?p9>}C9ehW56iLNWnAKxQr7x;tR(Y{BX-5+wqdfVp{}=48yVxL z*-!mv{k!>LmlOss@1!}%BA;e;Ng>wHdEj0B2iPMRj9J)w*zVaEqtadc5BsQ+d^`L(9b3ZX*`v+V8F;T?i$gh!{X*~=|0;HmE=@r%EQM=s;{ z+Vp0Gl)+!%se8{f) zWu+@h@*#r_-bkFtTBa|hz`ooCJx{x%K1ovyUqSeyXZRxqQ<|VTCUt7-y|vLfIOLc5 z>7w^9mDkA{x{s`5Ee3KbPlkm{%R;(;$7&NLw~`<#36d4BI0?;PXabI#stuf2NBHRpHEY3YV1`*qziV5bsF?<0#0 z1CyXAL3#M+?{r?k`dUCl$!|#9Dib~!hP})dq%--#MXA$Gu^dh zeA9l7kRPh){(iq8eo(6=E26IhELb;L-_rR{O9`u<1n;{VncJ z{Or8%l>yk09zRYTnLK(fR4l2>W2d)2a}?EeyF5HXM(#i-+&Un~tY_k|Z{Gk9Uh^Sq z*9y1XuQSTf@>maflETOX|70&K(;J@2j4XFchb_V@^}De910 z>Wv^KNSv5!hn+@!ZUB$9Bn3EVbjryl;)4dBrb-r%R1QSTF~(Hcg~Xx^$JY`UM8Mh;Vl7-0Ao*;XVVjfW8zpu8^Yi<^<+`x#vw zx^P8tkr~>wY)bGLu&=AnG{^Bjgpan~SHmRljo@+XT50C4N;_n(OB%hW`$7G-X(?-2 z=9J*AFX=18@$a`Io%Mb&czIVae(~)QN|{!ewb{OR_G9c4pXfTNYgxh6-A1;O>4CYn z_^B@Elr^SLRNCAjugJYNxPLaYZZ@^_oyWkArR=BccixNdzrFhVmyD6MjNMY;RGx+f zBuOflyg=8NAY_fbQ_wGoPMNmYcmkU_=Jn~j$d==?4?WR^*%hVhm=UbPfSjgJa#}os zDtByDznp2C?|19(2e*UUUm7L1Tbj0r?b*Z|h#Qds`xN|2eV8I3PEpR#EWztd_#*Qj zmDdHvpd!~LpDbYS?2$eAUEQ!ba?%K7h6T31=&fR-bjRRJzR~#|=@(oM zm45UW`dW9(mN7AUCYu)T)!#nvVfwgFB77SR(|uA79_1|OSVeIi`hWctV|k`qyf=dD zV&5xp+5Q&%nP`&fzu-Ii*D`b>pU#bz`p7kGiu8i{E$@lgAN%tQFo;eX^d9Gdr?Kaw z(zWBSh7xc><IKm4_#Y#Ab?ZfkrYhOBS@RP##jDE;n~@O2OJ;R9r$9&@8YFbK0)qn(s) zCpcl`37*Gb4l2U)fwi+~*#!JJ*42Ic9`-S5-U*%`QyhDVdZtt7aJd9NV8e$li9c4? zbso4qMYk-zWEnoV6+Lf(A0LMf>h(qIUoD?$Cv_?DR=;!tKY4f+esCw4@~M04?&|zY zK8ciF8-t%y_dT2O18&Js2i zULRbR#M8p0YqfwB-i*KZ%Vv(x;!Lh69rK0&40`iJJb)ze*NFVHN zf(-?_MMcFp``lnp{r=t8KP5N3a%3j_Dlq;N9gUDx$R3J`=NDm^L*AW?E7qp(||E_L zG3ST6w+VlQmwM=SzrM>aKO=|jWMMi2j(%Rvc|8~UL`6&9(PJoie{_ZxrtRG4I*$b4 zP`+NQ%X%NZYg#WpAgyzKvj*VDSu35?hy8uFg^RJTKVq&c$`*;gi%Nc3S{>U%@S#3r zd;feF{Jct+KRR5dRtTPt>bj!9zvw4geibFjd&bOf1-imesxrxpl?IM=sHC6R0wMgx z6m?(@p?276D0%?jz0tCnzlSVCQ66L_HYMGy+b(V){M>;l{u|!|^?t{11?$b;_)*db zyV1|lv3FSJk?mmUo16%jBAnIhz&EcsEmHi`aLE8Rub-zcU8g;q<2rwhs>ACe@Dt@_z;^uTcX#eEQ@p<&Lcl4 zI#S>L0J(~jT7kEn_>y=eS0lvpc9`_S9-+cizpTdRSyJTV-QerWIs7BHX>Rt7JoK?m z<#yrcVl=WTpI7$H4ep1|tI>lXzp7Z)k$T=B|?QemLQP6Div*dA+)S3O;|mCEK>s+n;wU z;HT&aKAx~AZhIwYc$L>K%a^|pA8A{UU;V^^tYPAJ`dSMxAr*dP z&g9Z{tIK+@kF|Spr0JjYne=*G>~CVbAnPx76`S%c;Jv;G!_OtL-j?`fCUSR0lO1x- zY51V*Q^l<1nY-(8mZg@9J()R<@A-yR%zM=HJ#ROGQOfmAUj!vp9AD^2M^HRsqEa|{2AWK)H^g)AAG*I!=LZy z+u-px;Qt3dg^JR>tDpJ&tXt--)ay$Rbg+u%eXrZDQYU;rZ4Q%?6Opa3A1x_`jtmUK zeWq>T7;#F5==4Pz;*$YeIYkdsm~pFqXKSU~G|sl*w(o?GfT4TL`ZBSoX?w{WDTkON z(TmJDS9zrg(fv&5&zT&4;Z2mp8Gy$pXv?aC1cfOTRrYvV+Cenow!yIy}*VNV)E-#4)^ zgX&_#$C1(pthb`nW%bxzIH~}DLN;6`YbT`gGE|n=lZB?gtYt&A6m6}wk0u0hXj`-ob@9va`LahP4{t} ziE=D(OOu?$cL7Uxlr^_?>)_`;M%ULg693v@m!tpI{mq!w#vzQqsFBa?dGDAm~6y*H#;ILn|{b<^<67n|> zJl??jv5&1p=}lVmCfdL{2ke74|Gl!8wO04n0>5ASTe`2g?}y9mLb_h|vvCWUadWSx zTjt<{;skaTA7V#nQ%UeAPRcjmC-?CCKdNxdvNXAXj|!_S&Sy3cA=c?Bmt0`a2vj0I z5PaU_TwvQr5sTTO_jEp^zQ1sRHAIhkA3gZ|mR>p3Fj~5!1AadiJzNK5If_1JoG5w; z4{1{mu!TPOidJcS(u=e5m~@=?(M>3tx6!0KUCbwyS>r2V-&nmS7zoxwCtV!i{DnSt zx>+agP`3i}&A6z69N(ro8^FSc_#?CLeY^?(%6FL0v0(8YUPRtAQ1{V1@a<#2MF+Re z^iBJf#JYkf`K7Mz@6Lzxr^@@uhv0=$M#>=eTAMz_f6^C;bh+ja3|@EElsYD+0UuZ zUt17E;Sb`Wyoa33l9z9P<&kyFt)8n*Uu@;PV$+?)==Q(C*FX08XWyV>RcRlt^T;1H z?5Ff+{a;KQ{Cx+V8M<^ueX+x=KUa_MY|N70B|pHAO&WZt;SX!9HBOdvWAFLVEz?q%yz9ZY*py>ww7eH$kH4#_zB__-GdD7T z&x%D!1I{E)N*asaUEN>WQ>U9{l`FilX;XE-IDB##U8_^Uhv98^G8drt7bjCX335_pm%W60(h^^?1`z+N!paPm`PJKL4-8) zgiGhbZh6txjG^qQ&DgS^I|`0=EbE1$DcHl;MF*p3EV7oHy`tnwCE_i!ueZD$DWg_K z$w$n;1s@sIhra@^ z$ocU48jmbZ9EGnseSP?Gk9>NEI04wq*yOuw>Zq;_!mhaq*fm9Q+->oH?5Rf1A`LjJeF`CkH{_ZPI!c@9%9Ni4{T|>@4QabQ%ZJL_viJSRleOEIshmO@{9LaumZW!3hzW6ts%J~o;sRg)=D9)H= z(1G^*T|bkGy?x(8(^tEZTMoAPUR5@mPTVx_w6EEpjUHkn$9cc&Bhx-D3JMElv zrmS6t>9#6`-Ncklb_)E*vHx!$rpxp_e8<-f^}U~~MallpkUPNdDEj9e{l5O3Kf+U+ zKK^~HX>a|c$b0bn|38#NTutkzbp2;azL}dQ*PR>-9&3N%O3_pDJ5x zUHe%sS&;nA^>aRd?w6S5J^|0P9KKc2Ud|~c@uzYI46;qXq6f%4)3oz8C3G1RA)8f{3LKhE3*Pd{qeS*Ed}4t6jf1=`HF#-vns7PF8ge}$ zKH$LR-@1jJCTD_5g-si_eH9^3(2JjkXRC;9^*D5Gh2ooeunT*Z)gSpJelz`!k?0L< z+PzTs?eyZo^+?XVJ2z2}jjz$|R9t}H{94$z`tCw03Q9 zT}F+<_j_Y}hII$Wnhe~xL!R`@YPXC*4&5?qK!)s#l&cxQQuM$^ZCaFMu>66jd=*tg z?rT#6@H?S2`@HEB``#>Ur`|*r@EJ8SN0@}ygtyG@mk%gsSI0SL+~aT=)H`?`Qh6=< zJs@$v(eFBYMAvoNe*DtqL7q-~WdWD)v~6%d_40v{8K&oRsWkz~G@0>)joCaf_BXM; zpO0OsO*hWFq)LGZ$y{Iezq(%ET6gU*(K-Dw{O_umOU+9k{bV++mL@|{M9FS ze)eI{7KT5naOp)~{t^woA1qN7_~{&#O+8+fIqh8|1)sNHr2kUzjf^zCQTXzKlcpVT1Aa$mvWpF6QSShxXvr> z83Tnr(rL?N_sD@(_;Om#e)PK@8%++mWK}(E0l#OR&W}BS17k3&wP|COcLw-{lgMIv zuwMWFL1*&gFZ73S`KSc3uCc`_{5}5CCkNN_e|c}cwR$X_xA^mAVWzwt>zg_y?@0`> z`lcW4y#FlWl1Y}GhJDTcd;q?$Q)_&{74}IIFvz{L+IRHlGz&+t$MUz91zt%g8?usO2W^ZnvXzw2g416wq~~qXtN6VHPyO>qVo@^x73~PY zZtQxh^XmTyti}0&)c*zl=ba7jpzrGcKGwsnTl8EziEU|v-Qm)>Ix(UpOa_()d;I}A zy$AZ;&yi=`J7DVW%*Xz|ECfULCo+`pm+SR?0%x{YZ6f4PFl-s;L`rjT9!Z!dC6M)X zLT{3`B4z1;f3Hcz71;o;bap^?7Y>(iu~mv*i|z5x|Nd@Oh81fKU!#6kyNf^NKKlLY zcLQt981<3qA9dZPHN>yjdQ9K@4OxYv4;XKXp43JrUS5xl)|UVBh8a9E_&k^~Ub`06z_TaMWx5WJaVe#1K zchy|MkeCf&5z@Pye*T|V0qOhPE8m|o`OTm`YJ!2WDLt5>c<8(p&01~7dy;{{ z{XFUu(@sP2t5Fv0rJ}6p@g@}U$Pp_Rc|n)1!xZ#^AJk=kNNe7upV0q5>w|4ucYW_+ z8^0v5_$6l=^}V;>jGNGVrM3nn5&mrl+|_+B@uDen_e}b^zEy(T`BJ+`*^-fXC3*0b z^EE!Ghek*nxW>{xnK16a{w+hSjDm@q@>~QtLeVaa?R+ z(ARW92eIZSFbUW2mx3HmQPnNFEWcNAOVelI>F(>bJXcF(%>NLRaDu)+#EmUD{Bm6M z!vCP#j*a?P!dLHt;4-Lmh0(n}ei|n2!88`1PaF%*@>d*(M*uU)9y>3#Tu9P^Rq>}oQJb;&Q3QDd+dAg zb_cwY0Na(@pZlbBdy$FVeDV`>I>UFt@0hk#m;W|$^4Mr%a^nBO=XJI0uAFI>JLGiE z>(1}*4Py`JA3WB2J@ZPnY92YU*DJ#^W1n{+Qi>t>dxY&%XE34PVym&2mFjbwALlIx7$}V(a^Eivs zewWcjF2nYIGWf4s=q?AQ^~+<{MMdAQ!(ZBdY}==cMCN5vfA+f__~5O1M~}htor1@rovux$2suh$7km-3?T4gi{_l24 zAM|QP{$?*-L5yAY(2B!#U5aMMA7dQzPL=1E==aWktjCRiuP$3LOU^TEWVmE56Fgok z{%!V~qL%#ma^ZmV$L{6SJh1wS!lexMR1@7%lFUuaE%YFxxV9gk;>FNa#v^9(jHbFa zThg=Vqi^3kG)$hYz+UEvnfuLK=(4Dke@)QuY|gngPdkz1?6-Z}==NFs0eHeE>^Ti| zd-RCb*W)zd%rI52n;y&V=1yvC9!@is65{_LH<)I|Ur)={UcKjXdoVVCgvndA%zAMN zel*TBJtHAm%njCoeCi0+ zor)aFN%heYC`yJLw&)`;@$f}9Et(iEPujwV4PoyAgJILqqS0Us^gFxu!xpECxo4+Q zpH14CywvX~`bE+2zhf_K`E%d%BldE&U9w?kgp>#nlOtqYzkYy!^^fRr)DwBWqKK2G zZ`JR9^YB~1*|UFRd^}tD?Qox8PD~1yP1g9{JH{uwc9^zO&)GB$Ik%Gzqx)8L?T)!x zkGPRG{n<5K3a9r=@^is!wYpz=ja$xs5Ge)0_t;dX8)rMq_QAduZEnvX?9+ky1}o~Mt(|pUI#<Equ*E?9%=4Ha3mVACRaK0Xc-3;<=d>C#F3fsyZ}w%>XHEb$*=GVvrHZ%4`TDb z*rc)3+MkV@+TU0YnYSZKM@r#%=unW|{%&CaObY$&LE>n9!0U25?{)A;%Cx@NM5hiO z_k-YB6x~nfmJb|!c*_N*oa+A4EPCw!zSJk5cJrcR2h)($D;dFGonmio|9QAOAW%*M0ilmu8I| zm&eTcB*{1%Jk!6gTr*{QT_Eef2b>7_{!Xzi$ZC}HIIx9*Ux_Wz$48? zkBudhkkt?ONDKVpF8di9dd{@XShGWEI(B(OSR1cdJi_*uX56T>>j#*%_ky6C+`B&kt>2LL1C2;wdSHK%OY?9RVc%1hXZM(u;NY8x#%G9ZIH?ybx zHo}bY=5ft+^=#=7yqUVD=*Q%-_l>@*|1T*-3|31Xp{`V*UEf4Ukt25Yn0^gS=Yj{_ zH91`3b@a<8$ZFn1Kz(1+kH{=CK1HwaQMmlEi1;Io%@a@h>M=NbqiM(Z&+#MMD!A_E z3F44mMz+m4rtO6=`Sw%&lCRlQ_f#}_*y&vlebNY9wbjVljwCksGqA_UM$asrp}LnV zju```!FRWh&}D5zTMkEFa|oTGlSVlFG3*7~w>O_z(;74+4p6vHzTvDgEsMFH)tX-? zQ{v+do34%Mq@0wfhH2kaV4I3A4rv$b9NVzcoBPX|pY!{8>)p<4_V*F+B~Dt-yuR6* zInp3XTx-#5a8@3<6ifzXDsxQl-5V_1{L}dWdtTDD9zenfQ)r_k0!)*`f;ZV4wIUJ+kU=?wPq7mwi%EnoD7loBeKo z$v3w{xg4e~Uq591YuqVX;>M4V+4+64zOC~P=UdkOO{^1&KKUoOZ`8GKkd-T%(S>-x zB}8(L3+|s8X9BVV)4@qhZGo>A3#W1FPC!;8tJ&d*36qVppiKpQ#KM5r z9WoN0=U{Lh>@-)0ne_HG=VzS#`d4et+qDO~CFyRxF0H}Oz_{GH?T(I($>-GvU-OI4 z%uQ#Wb1a;&^P2sACo=6o958P^1F{TV;<6fE3ADhkju(F^8L>}B?_-neNx1yn5?&lV zes5&TPAZ9vaA8g}mscU%{Ifady{cwiy4(h^ zOkS^F!oQN&;TNdKo9N4`!S8xgx;I@f$=M_}8ip+K)uAv+d)X_V4aC1Y9CJQ@RgyE) zVLk7@9%A~)&Tm9@uQXsCIW!o1_>=V0ZeouiF9@5;xnp{S6hnV@g){4@^t#?F_j~12 z&Wy83tLPbgaIa)K{}k}E&9>{Dzh1(5t|xXq=;1EccgtMlvU_K7W;`7!FF5PjG!pql z@5=Ts`rM&Uzuz)aa))3uyE<_6r|Ri498Y4#o66~MAKhM4(N8E^72-?m^+m_OjPJ2W zP9l!OhA2tX)GyoD1|-8N^n2)O3&96EX>pi&SG`iP&qF)?nA^lsXo|1$j>KE75GD(I zdL?!Im}6n!9Mf-4Ig`A9B}#6!&}APq+0IRW{{1`g7M{ChZzG>1+C@x<^fB{m&03eD zRHV2E>2~(@^vk|DQPQKVe$NDSk%}sOACT&OgP)J+Y5FEdS5sG&{zVd8;X^8Mah8I$<=u&G^5Q$PD!;mrDex+>_`$N8mc6mdg$`ef4=ei@8x zbu=~&spgn<#(qwHezk^i6lLbbxasinHBDLSS+*o)*k6u-i=KPWEmwJ6lgaQDd02zM zdUS6PDS?-!e${rkWo2n(8`uLXx(fcbNqOR^f5#cMVU&!pFy-pr%Jp8Ub;v98k;QbM z7d$@HeMQ&MGbiDUp{N7#->BYediQuh8d!SeV@=%h;2yqg+2f+Y-sfX%%|svH6+Zhq zy4mIQb3MoYt#kPI|7k2-VCLm!U)qyQf8RgH^oh#lyELW^LvwZ0#wox)jzn&p0lSmc z2|1r314?JfW}WGiEx~s^y6NmC!=*TOtjDeOMy09MRgbUL-l7e}I+fBV^*3+2RqQPXZvSeMMWqF6W6*y%L$dH>&klW=x zquXeFx0v(xB|ac_o{W%o7M>vF@z+0-*Yn7dZ}qbsw&@gChet}SPw=CV3oKb3V&Jjo zd{)u4Q;MOHGJy7Z_=Vv+&#=GQwCM*uSCevfE%pZ6FgvaD^Y8T7NPu7LNt{b3O}sOw!grycyjjNNhDbYAhF z#cbbYO?0}2mK|$Guy;Qdz^7Knfb4&+>o>R>_#pI%PO5{hJ2o2II$D~;hn57h_~|-) z@H^}!?DUzD7lzWHN-?h;xa=1<=N3g*Eji3W^tkWk)NSI-V*uklHhLdBYDK4C1dqob z4ifigKyW^H8JqWy(g$w`ryYVkeq%9Yy@{}iwRo-Wg2*rrUR?>`<*EY6RE>ojd8_8jmloh=)W z;un1~9lcL%G-haU9aNeK+nxiPsDGpQrPw#;>Ar6k3pU(-wvmNfvVS+9;F52_7b$uN znalrII@D8_eeDLYVo^H3c^0o{=edRRiB0q2b9a6fDUs>Je_a1y#l|Vk&y{XB6Iq!N_AX54-)#ciLoY)u0 zrOLPCoL18-W9qu3KC;3?>-AVGy(i{8Q}4_892s>pTGEoZ>0D;hQsU!mCaO#Oj#ExP<|E5LR&Fz>xr*yMc{49CvW=yvD%z@at^5={(#&xlM*a8rv@HhB2Csnu+AupNtE8FU^QXj0$`wrRi-nfy{B_lp`XT@BP zo%yu1^xx`Q*W_m0HSh0}-`e`*JIDTi;gA{c%_ia74jJy@Gql?na9uv-b16zHf#>-* z8vVQO=T8RWg9hE;^#sHax6WFbuo(;t2}srP#4T(boKGCfjzQ&p!s1cY_ih%Bsq;!R zmrFXnt2Byc!uL;ddn6t<5h)Wz$d-{2aw4@ZODXpI(U#6Yr`G>#JNV?!tn=Yb@N8i_ z^mA9xJGD*hlKrXhfe&`161-XBpTJ`wmpTqVJ%jkFyU?4zi3(c!S^NGFOGm!X!gIA^ z+-@$V-<9S!JC*+Y7OchD8fLDjtM{2(p|plIY4;8@b_%d&EBXuDr%7ul-wNziJdxg?ltTBgM>M`o}=sHJP{J@zH@mEsPEftv~ z^WoD6BR5wxA-icC^?M!XzyiIHyE$|r>Ut;@20TZ>y(77O_@;SLs%J!Jr|RdC5B8=5O|{S^>G(PS>jsds&aijC;$c!pA+M<*k=y zU3vYUGcHNU*v^qALiU0c3#F7L_1;kfEPQ%+(bMq)QVu)y3gghLwe-kNzsLvoeh4Z68fTnh8GLq)94rQU)jJ;{Itrvvn}IjW>MB{_PgeJ%=*!lb3#FMQ~!+$ zfQQ(}er(f&5yXai8r*00ySNyg*=3T_Wjl%w%dfD{q*KpYx3&y~{uRc>o5No}=ZvUyABYyfg zQhM&e{|2&)gR3LulfuZGm*^+zT`+4_pCJ)4w2D_g=|$WR3;#SPDY2$=;;-qpStt5r zA|};i{G%T*YkYO#e8V~%$vk<6U+`6VeKM1C#j*9sFY%xH2eO#)ocT5*>j|ZE;F{B9FLgI@Z)W}`K4e%d{`2jW#%z_sZ0mUanX-IwwUj4Kfug`gO-k2<&}FU zF*e|{9(Qud4;C&oQ>rjI2c9RCDx)*X3g6iueC(d2_=<{)uRVC8tDGZ7fdLE5A@*G> zur;lH(s#dU+Xk`t07%rv%z1&29k$#r*S5mTA`kcmJ%y9X9&pL_WMR_xJiM_bFWwA3 zJIAAdBxjBNb0U7duoJj4RhRj2@+e8oI2t`TQsyl=vFWe=WP0{gFbz~Zo;Hp+_6zjMSH>aNSUzMB2C{>(g* zn1lOt`O2L(_XeN`?!rAq&%S3(qz)e(HGQD27o)Dp&>`${p^0XOtJiw z{lj`bpe%7(%W~FakF3!GKacMsrzwlA?AMIlAF*{>g}x3So>^GK-bH3p64`rO@NE~D z=rOqW61G|0gU3=O;#=%*fE^r{8{(fY!bhy6ao8q&93|Uc5Yuome)z$&Y=lP|&UiY3 zykG%1kZfQ?8gri8QQjjLkd-u^5G8ZLQ8c9;dUptuEUCS+X{4$JwoktX?`K82fABD6Fbl*=$7kN$3ED? zCTEF-KQ8^$jHP4f*zRRpPQO~zl7Yp?1*UT5rS(dvM3<$P67kk2EVcE49{Tap+0vH zCB`bUAw?S}f~5xw6lkr-TD>8_Oi@Jp1=GjGso=o|Mod*iboQGv&!Sbr&N4hkKd5f zD;i0kzF&m6&crrI#hUc-e7Dq{312mxIA1Sx8IqN9$sZ9h-+2{V@?GE_Y)VltcpbB^ z+n)#CB~H?Imz=y2a|~V~Ufts_nI}u!@+G>e2^DFFYdsBsu_zZbgfuh`$FCfCnb1y7iDh)!$&-#lLT z`#<;n@+%mN{Oxr8yKRAIynw%;nZ#WMzxQmoPM06tkfOKpMoJ!ZbsvBWe}+t|>g_1m zQz}gE4k68A7yP98wJNtR!#6(8V`sgx2APPW zz+GMcM3(MKUCY%6?8|Z18}`x06N1aA?)PdP{C;)qdK;7OATofdobjC0)`uT3hcB83 z?0p-U(>A@uzJ6q`{VVp**%XdiQqK06p8 ziOymByDvgovyW#lsrzL%zJi{C4<1?1E!BFkkHeb}cjyoPq%U^v$LA(IX)9xcSR}Lqj!(T=F5@j8oXpE9r+C(lb@Qkxlj$W*6shryg&50ziNSv zWRL8`TK)DD+Iv0mbyFkXhu{0Z&?c}N=PVqG^SREQOkbti5s*%W^xagBePKFlv!dF$ zMGBx>c>E4FOvnWKRt6J&13uQpo;k`TB{(nk;hc8`Y{kTjx_;@?#$Gq?vIr@DADbKx z=gLp?JJtVj$MtiwOPl%g0$ExGOXqs%3ASzUkBa8Bz<)Zj&Gi<3R$aT&mbHF9ez!to z$hCinl(BK6r6stk@$fPgz*g_XCroUVIF`A%W`(ZD5bSmoT`6gvEp!^cyvRheO=VrG z9Gv6!Qo7IQzw}A2;d;ELT43tdJH5$gcnP!a=7xX#aXr`=&e8XC`()5G$DYG079vN; z{*c(G@NI3^__1{d7c*BszX4oqD0RrqIRV*X3FfV$_SSm*06t&Qi3cvJjU2ea+2H-o zH~;l*`4i07$7S`slFjjHQyshJQo2mlT)NNpTD(U+>;Y{W)IB)AE_Ho!oB1+I{8BBy zu6w$b*ceSTbw7fNIWsjF%WFT|u{ST4vI%F~Sv-W5C`8vOA*j=yf6_E0r-4s=9W8Pz@eSFs~hx_A~ zHsF!CHBGm<&axZqxWZ z@EzY`v%6i7ANTp-zO&P*&m8L*@78&sl*6{+9I}9>?9Fwn&<=O>^9QW9`X@`cSg@`C zWc75VUdMhei!DQQoxUgXzff8h;EZ~NGeD+jSqFckD03FS^b6C^+y>X^r1c^CCUx&5 zz8L-&TEUv@q;%JjpM&Z8D{XLJq{CO8qG`zBZR+v~zJ=4XwsH3Q zS8L*GjtnmM4+-%TP%T_meFtvPI!mgwbHEk9iN4Q@?4U}7{CW#N6X+$*Ajhl&Mq+s* z()orCNCNhS09WNp1i7q}ddcm9gGKHNKr-&e0+YJ)47zFd#* zT+FH1XfXKU4Ga7d_*3r#{t!4(10Los(wa z&*mG}xk2EXT-a9F6y3r8hA&lQBZ`i*hDMBH&uc;q7<_e<9&OUt-{QXtm#+pBE9{#v zIWQ4y_CC|zDos0hfG@*MTh|N0QC-j7V?Dru3^8Tz=8%Cu zKv#EYLhN%qU#~DZf1em>Kby5N$GfkK_n&`T!6+zN=s07j-zgL6dZq%GGY@_uv!z>8 z_ncJY!!S8LEJ99hbjv$O(T%l2R)JmCf|=%>&h(!i)oqrEwIWSL?4l(g!;!To$0tf1 z>{&bI0JC}tze2f*Q8UIRg%{{{wewh5E%v(F_cMj-aux|3rTV&bv3I;l)7a-ZLm1SG|!*xO{BYSYt z6);R4IrHT&Wv-qY;FER@^xWF^g?`t*V)(o8a*jY2aRxoJqRjL0*B_`6jFGbJ|_kbVWk1lEKCYK~buTUHvUBclWDT|!crn6hYKOk$%U)e2x?~Rlu z_lU7kjmo{A(?vdXzhf5*e@g}hpq<|!a4=!3bT+*e%er*ca^Gx`?*oS>ZUETh>K1N45&Xl!6r`X4^ z^L>r-`K2UsiP&gs*_izrTe`8$Jd*r`nTH3!Ra{!2$6>m2G3Q9#17MO_Bldq0F6Uj`1L`*{uR2Gf1|a;CVxK5yw{nw$Z_**6mp7hc6#MB zxV2%EJhB!&QH@i?UP8y-c0!~yO3D1QWcR*%`nfMGT&l|R7E>^Nkw~fS3P@UO=zh)~ z*A8D7Z{-b>+sGv!e;X+~KM#|=mQU5U2ATJ(Jc=?c#^SRq&bMLsHwl+U;F=WmeHi;( z$dCTsNeA#7q-bAupOir^eIgnDR?9@oj&{yeoavf{ODe1Xg71JCt3>>8^wc(0or|5t z=t${JTTDM|*7W{)B4rY1ptoCLFFzT(2>5a*xi;uB58I*h`U2VI;Noss^gZ#lume-H z-GNP1zk6f9;iU3l=00@Dtkk^+|6rH;4Ka1<==|$(e*8DOSXtjKk8HJCE-;(O34g$c z*?Y))6Vw+uKi||TPjURF-7>k2^6LJ1{$X(4Hh&&_f2b$FYN6}*toW>5)glZ#XHDh0$|fv%j~*$J}PlsYB_9#_7jKWqQ*1-3W>`&ke6TC45^ z{9xHX$3w4T)2xPI)&^k<&lzIOb@uZ4#315KU(k}rY|V;|!Aop^e=*OrpC2u$BlK8$ zj_fs6Z#y^hIcWs=k}4vH@L64yaefy)=HIMMIbI?=?&^i_cFBPuI?ujiSX`jrLgv`~ z4y?DEh0C>_@Bo#gq*}V*^eXM> zNBW5u{epR?$644( z)vz&p45rVf4L^m;Li`~P7>W+!SNsfNL%F|hKsMF3Q<%?j;I0&9wRppRoXHezcmkh? zuGGbuGyl5ac6puPU;brjYs%6M{NW7zoK(vQMmDu6_p)~8`^W&!*v5{`4+a!sF z&q{XL8ZSeM;kcPIwm;^$RCz9T#eQAgQ}no_u5*$7`nU6c^G$kj`|0{v$pcehsX_I{)At}FHE`n!%0C-hvn_@U{S5$~CS+TX&N7MTgQ zwHmQ7bGhYLOJDo6S@51kIdY0mOpP2FeyEQ=bZEYt>oBpBn*?@tiNxf z!6CL&DqUNT&NK3wF7IJvy-pgzoXfZb|0Ve29lRm-aXNTql&qg+o?3ywzBFJ{b|wy! z5y(qgti?xXan29;(Fvt=YjvBoTw(51K)$j3SJQsSEqjw+FY9a1tvIQ>k)eby43n&%M93K0 zFTrzg1n@-nKgEwf#W^@8N+P3(I@k{!&ThZBki{Rz7GY9Czf2h9lgoXu_j<=8YZmL0 zJP$dC>Z>vT=WDFXdf_WQ4^JW+{UnyNo&99mgTxeT?2+-c*;l}NysC&FiW6?hR0RHb zww|kX^9Hxu&`e-?-itZU2Iki7{4isLeAZImZ*UJ@`Ns(PhILR;f~lsRFHDJ)C!Ec{ zw&sRirvK%$Kn~OQ{gDa3iPnNy9bbX?pRBv(*SMrp8r?q5^c%rgD4IAzf2!{#NBhJx zAY2Nj2$O`fV?I-6s!6NTk2w}0XV6nSDY2EW^P2sAT?U=!)^~&RQTOYifjtR6OHmj; zbxMTT?j8fDKNUUj7tNxi!j0F-{`0RW*x}-CVqPKF8C=x#+rf?hNfPws6_}Rv9}xfb zfa#aOD*f)Dgt7eSxy$5#MES{w4p{a$o4+(|_6;!={KzoIkJtImx@7i$Q@uDoRCqD~R>{{!?Cir&L+$4UJ&fwi`9_{+LPNqKO(HkCgUbDgp8*`KYM z%MXroHoK|I-5p=L%aTOPjP7Rat+nuZ_A}~pcRO?6zCN=wSW)oXZSkF^=m7k+O}lHF z@3rxTbbk=R&^$OXg|FB<9S3su3 zy7GP_d?4Z5%d-sm5c={iNlpDNmDrE$y0-}vPy zXPDXOa84mdbkeRS;gSnk=5&0ERE0mNy$>I)$gdVA4Nj+?Nw(Rv=fsZY`{TK$t(HC@x{KVvV!R?ne75LpIx^CIwC69vvanghq!DUOiRkozg>oRXL$BlR`=xqY+D zyiwQ67bd2AD{MPDZ`9LHw;^GZspt_v4EI`@eP*O9jJ<8o55e!=~d^$Tq1&qqpqu(qW+5B)cC zWk+^X$|axtZr08@2eFM#tJj6%Y0w)v6w9fGU<0)#Ot$ulJ?B2R{lpA5{dOc;e_x5b z{1Vu@F{$+UTJD8k~lr_bcls3*UY+Da~O7=)&IRtJsf(@ z!<$_))UqpfmUbdC#pT#z+_iN5)jrW>Dh%Hk8+EkGS??A2%5c-(P0**+*aWt)MDTc7 z=Zd|IKXP6_`j%-M^{zJ9eJo6Z?Q3e07MXNDd8u-zkh9=UOE>XXb8HWgaZY?!kAt$D z@7tlj{i$}ijCnxpb=JaAn%E3H?L^|Mq3hbXj(C4>2d{aBs=FnTgQr>;9$d!XlbW$H z4_Vgqo%;TUAz(4mVKF*QKg;BTOQ}b*6>) zQ55%j@Vjnr^2m3{vAwyxG7!67MXTH6=b)-fnsFw(!1zm^E?j=gtLynKa+?pwdZgg* z!F5W#*efSOUAK+`?~FpCU8rg^&VM#(Iu^}y?#}Ue-j5_cU?YsTwFvS9!duv z$82|%rj5lng@eJc=_-EiYW*4}kI?b|R?aVXYeva*uot_h>hdi{CfDs>aBFrx&d=;T>WXJ&k>C z+Ruc3Hf*o2bcJV6fo*}4mKF0#ct$;rv%}Zh^wm1EH`>>npREpnI|gGod`!4_a}&QD zUEj)@Zb>^I9Lyl)?>1V7ED9da_VdL#i#GrvR&%n)BT3%es#vkpr%V-=1z^ zee7rIg!!ap-2y{r|ZyHqPkF(<47$u~_%vcgJ--6Qshf z2z~J{&vYME_yl`m^sGzK5r&=C*Y1E*QZyA?mpNM^QOOn9sRqA>l%f_q=c2_k5x=p6D7SAlB z=Z^hs>7m5&j`;88TmEjC6kDzPalm|C*H)tAPR`uYL2KS7ZPF7#WhH(-y|4D%gz+V|ChE79L6c3Ly7b1U7P=L-(dr z>Hi5WoW@4vS2opYYs&kwe{kJapwp;2*dwX#hfDTbCY^dVa|V3)+z7}A?8|<5d^cFF zb;;;6;(Mkm!1!CG^UAP`^KpWJ%=ydIKlPa?X@l_R(iMCE-43F7{h8{vK8%M ztSh>;DY(As+W9w}p`J8y$rSd2i}TDFRq5YEZ43M4$&VgcxGP-hST>d_?fw6vi&kk? z)zjkNj+5C+&MRf6?EPw*udY9OaYhx;<+Z zW?icWR>H!xsZ_VW(ep6TGjulWlNpbgxnBo)XKeISO8j@ApUbw=-2b?6@ZPGPYet{g z^aZw*J3Z7nvwg*UW(Ut<)2>IlJgW+r`K;~@>!Q;XAnwIDaC__Ulm8poryY~s(zCD` zqjo;mITK}TZvQf$ovbmYu8e?pQ&bV%&zU#K*k32$-=>AZZLhAM&( z0ZnNy@UqK`ntJZxOzET^$X;Wk47tF`BU4{ECAd8XW-{qhvqsOL?-UJ#SFKsmD>-xO z-(B!|mF8#tY>S(EZv3zrof>D~9{7n=RMwL1e>9ue9n1+QwE}n4ueG_dzQ1{|xf=Yf zU4q~|3O5duxkHIpUt5=>OB0=bU3~n1Wek4S`K!X$tO4KXan*gOPihh~=QZVwIo7`C zTo=unbRK^tifVxGn%~FF&({~Ne=hvxmfvXl!g)`9ue(u~|1S1BiTCUJuE@!`aT&f4 zhlEL42ll1aTc*z&{05$9rhfm+(YkGaSz~hVnkY;jp49XH`AlLGVCSOfSX$0PRftVB zNauArGki@tFFI3^)Z>sjWsZ=IgG~Q_0so#hgZW+eOXMJx&=FtOWvv^=+K%p1(aKlB zeW9*Z&8Ocpp;GV~v<7=xMPn1WB}E>WJYnsz={L?$eOsFGK4y%5_TDa!Y=NJD9>Mw2 zvhOL#*ouv^Jq5>T>62r-Z(p0{_emQt$2K(tlQId}{S$C%pM%$Y=P3TV%j(iO@+Myva$4cM4%#*>U{aj<17u#dsH^RR&=~`od(ez93+w|$*=}jF!OyrlB z&HQqAmz03Ar%=-fibUQZNXd z_iM3BivRaXN^IN}rT8%t*_T^J{i5sGVvBCSXBN-n3OP$XoChWbd2}Xl0QW5(PUUk3 zeNwLPgU87Jw&5}qxzbOTKdA=~eNy9i@Ywn;1P7AYvOiIII;kOgpo8J&+09_f6eUD% zJgqYRNCulW?NbqZ|DIvu-;6w{2y({{!7_j;_!&8oqNaJw{Cj24uf;I9?U{18kGypp1I=p|AR+o+H3mbi~qW z$0?)B6ng(nzdOSJh0=8JNxw|Jm-(;6F&55e&xt5x)TLhu+kZ{ds7z4@GZ6!ih? zISpPy(Od1JWiGh1Ip4+X@7D=J{`EZ{JdOrt(C_kR*^nQfY!!~R6a&*nC4YU4;lF}AV^XM}@9+p<3T*&YW$3@SN zF00OUL01Z)VR})6gxwWAV-KRyUXQ_(->HgG$7f>8#%q{ZRMyTZLpiMTXVDCo>#H~=y@jAz7W1w-x1l0UHnLN=~YKs^@3MkQK9f zj1QhK9X{7Ny_)Ef(z!j-d8S9M!Z(zFf3CPGO7dCuE-KYd{BQj)^p(YHoUNkUeNDyS z`FIK2Bt@O^A*m=XIDrNZ{pnA=!C&t}7E?;sH*an|Z;~TR{BYLmM_&KieF59!TETgn zyV(B64esZhv+(^N&x|3JcHAF6sp62ceg-a6(J#efuC1?cIRAByl5;!sJMvlf%2(K< z9>U{w1oQa=`lRoOWnxnabi3=$y78T=>r*GMDSKYxRVk{SJwg_B3NCjNuwALpT_~E( zy7g9kGag@Gbo{%XRo5^7Gk#YHPa?nrV@{Qh)H9An>kRAp9C9C8AcsMN9Wb`9n(vRP{^`d^9Y+iB0qk{G_MX`4=nTlKUmGZLbzQk9V$h z$;8U0t<>{_EPR0ao(D|KdIv@<4fvuWiFEr9<@~ zwQznZ--(uO+4Oj=(cUXPE@M+*&H2<|CTg<&jzXSYXF%|n&SR~MttOdqqTcZ_ za;4R7m&^lmVbdyX>(kZ8XMLO~S&R;T^E$T-{Z5bL7Z#3U3%+@5Du2qnYvpWx^{bU8 zzvnacv+7PMYW21K2NIqRR%a13!Vw zRkVJTU#9$F=2arg?m|DU|6k6890oqG)0gaz%*hnUSZBh&p2x?MqPNSSTY2IZZ&&=F zqr+D;7G9uaZREb}4@Vj2b-ED)slQIYD@322qoMBmPHE7w)-+{V{g<9U-SG+i0G)tM zb$`(LB%yu&ehzNS(m7oF#>^)>?K*T0)&C}5{m>|RvfGTYm)I+xckDggEPhNqw__># zI(X3RV|AOID`B3q^HraV>*@DhND(2cJm@qn8N|`=&AeCX?$dW4!$+k0+9fk~vi2gI z2&M6s?yV2@6BqF%qiC`vKUs_&fuebf@neQ=;qoD5F4*nFMuC!GCqHt@$6z*ZKLyYJ zEJ~`MG4Gq)$ND0fntG+-cwLVc7Ct*Gyv^R-y3LB+4VME6BBVcje=+2ju~B(2 z0s-vIS0IC^$GM}UC6Be!Zv9Hvw*?pxMK{m^wODG_usnrz%9fP^G9De&&Y#_q+*6Cfm~xQ?!lFXX7|s=K-7-<~wklIycUq;KTn{I*Ux=QE}|eD&w07 z-KU~UpXm19bA)&_)!g#K4P-6IOIoxx<4L8ECoheko%8TG z$Q#?OcFV#o_*5=JoZ;#COn3=q9emsJqb`ZFMCaS+g(-K@8T$K}1NcDX4A|B3M{@lP zXMv;vImp@CrtE6h4-v%4i5s=-Cf_X_-XUKWOE4|2Jc zmQR?Bi}iEGTE)H|*F}!G(DLawYjZ$GP1XH#4;f$|ut`}sR~BT=%)|QMu?BqcM;`gC zD)Css2yVVlEK&I2_gR;opwmvwxafub*n{uk6aNHj$bJ*=*C^==4mrGs9*0wriLYmm zvgw0+k+K{4=OJXXb1c5)DtfB4laLkHj+FK#yizJ{gd7H!Iqn_5bmT1DW1B}FMe6>U z&mK^Hn9lo#!w*gbXEdAo7Dw;V8{Y$*tFE?>kjad}2P-0F`;jQ=M;zapJ@I{FVHWIX z?9Utz0y59S^F-B&kXIgJ4k5D*r7ZA&e@$eaq?z}4JaXQW_x^MwLJ|)!V`&lC?;W4( zIdMB7zN&JV`LPH8*IB_~w`2_&4G)zCJ2yp_@ol5%voFjV@cIJ(u46l>Xx9QW58C!M zeBY^-`ueUv!X^EDa60&V>PZ`>t$-i2y>75?QL>4%eR*)9qbqW@{mLg-(L+^y1`ZNA zM)j}U((k!j9`*LhFnln_WAAK^EMg4j>fF7<<@@ddX~fw0V+j6YFX{5mWKTOWofwF> z;8P1@gEqOxM>V)_W)U(s<>qMFDx#QNQoM+q9DkH!6R$lwx0$ z6nW~boqn0~h3ym>{ z$$N!0xn!ioon`8D0(*}w;7b)9u`qG!e(v}96`va}SJUXQ*Wj^>!o&O7zis{{LJE#G z^)RT0SKe8of3I2?+!iXW{)aic0A4NA(=aL1SkINC6PfyIbr-+HdG$EXv>4whe`0_0 zC-xYf@bdspeQ+S=oNy<#=?l}kfKg=6<)pv*==63ubV+kVAWjUDjsmN zF6g$1Ef4!oG1e;TG&UUpJ1buKrX4!xZ1}Bfpv$rg%t_xWrhO|_gzrS&;G_}T%^0_z zKZMtKiabV9HHV#!{oZ-a4>ojqKV+lmQyy?e`-+1BnTsy`8FHXFn_RM*xqk!l)#dQP zHr1|)t^cQfIoDr5yL<>AY2D5ItiqLUqWjR%%62SseV1}SdhC-P{oS(av0vsQL;Q$x z6tMO*cE|zDrHVc%?2~%*n*$rdWKAW;?;>o{FZ-lyl`zhB!dAbGsprOZbe-1OV(P8x zPLZuCO#ae2cnOt$v#|mBd$zg*3!4gmS?lqU58qv(fLBW7amh7{7de>S^ivf!?_lH; zIoxuIc~nuWIbpJ>5@VBfKv9*cy1%^s5%SNC+X6bHijz zU(V0C7b)K$L+IC8w^!EY(NeoDxP!akvyO01H~a37@w?PDA9CP3QRuPJi-X;-2`>L= zXLMDTeYpBo=g;YbAv*u$$USn*}4x*o=Paqy9s|b*5pmS zA5#?h@>HJ`I{^Rf!0;7BchUVIwq*IE@b?H_1Do#?A8~EPnFt?7NdEcQjJIdcw*bE~ z?8Ev;;tz8K_7L^pR~ko1$AtKJneUZBbAsDVebakE{ST(;hjf1Zw9R3Md|QQDg^a$* z-@1)6fa|D;@m{#M-Trtio71i1lN9YvkM zO02m7KKvB61N6x<-yqus>!oNs*pojFn|ZYb?fN(nE$uD2*6Tplze@{DnHI3_oo1eU zKG!Ed7o+X=N6Aal9|P~3rY^Fd^{km2IFE*X{`=v7$kxUQqCpm$$ zHPGMKbR-fS)-3EGe-D$EU{X>e&o2>+UDEx#FYEpJ#`u&@rrYX!Y&dOd z6DLw0hpY`_54a>RIA$k(06$x*1NIj9ABhL{E30D;R^e`-k8x7NNchg8_z)?JZC3tB zIn~o8D^dp}U2C8GiVyY7__KHv5iJ`9e~gSpn=T!V*^c(R6pPI~`pxu6xd-<2GjzK3 zLgeLLkk->fBeT>F~T!eC!wPM)wr_m9u$3yK;x)S(K)YuPmFYm=`DHPGLI`T4aV zcC00%CGaDAk!E^KyeJ+a@#mWFo=eR9%N*jQc|AR{0{e{(ZA`yZ?-%XD7ciK>jla94 z;zAQ6k~O`0E%yJlIa{b~aGkx63`tSvrTVJw>w7p07+$hB7!N09$`JfL=evYIf$3n6 zSG1Q`qUU-g{ulTbDC$FIjy+ysd_#2!E<=T}k&+uc+36u}N&7oGJMbCl*jF`5=#`@@ zG+#4(6#W8BpH0h(ntrODZJ6qn5$r`3xtKo`H9M*6InODu@a(;oVKcX@kXIJG7b&IB zxa8|+VRDZ>TG#~U&sI9U&u@iG?hao0JgZ-tqE|S1F;aFNbj$V<@cI*VUS228zn|F$ zk7cX{DtM*;0B{l5Kx`go@@R*1Ue{6YioS~o9@EY+>OLYDybtmmS6)-j`>XVQjSK-P zW7z~Ocxw7mN9v>;`0AQJ2lw*^-@du67LW9D&YB*ZpRtx*st_g~c$L2zn{xC+9@zS0 zuT(}4t!Q>r?56kmq`~M&IolGygz$(qMfA|+nseIpq2yi6*l)==e*{iTQQFn;i$$U& z^LE`I`mNJ(CN~b3ytL-0d=W z(mwe)8!LbwX;`$JV2<8a+b8qDDJ~rYX2;UwY~uI-m6i%`QY{}X8hal|1a12v-DVa z?>TGi1=9|@Mg*r)34F`m4Z43f;Y^~z=x{S2t6a*SMNv=7=ZLy*{7;y)fk)aI9gr#b zdjI(eKFq+ZDJsGJ>?Qa!Wey2cc>U=0zX6@YqzZaNMX;3e+~UVyKj2@EK4yNjpJiN1 z`-c?2HRmh2-a$u=@2H|+hN9bGJ2w!Ug$>B!@q71AoPc=1F6EkN(tBs4M^atFuJk_s zXwXYP$6od_`npCA{I>l~`+6`RJ}7$mW&BEyJjs0ov8LMKqR~Fu&AHFkJL`&oA zx=ePw7hS+Ke1W~B!lg~aR_wkRM=H#xb4?#O^QGxecKmeoeMPk=nEue{BKY@ZIuGf8 zG;J7hTBp5+KAJVVnFs8&&VoNu^s&OGK_kkWI#Iv9#mx6d_tD=y^Gv6oB}C4u!YjHk ziFw!|zs)-ZKk8%gft@Bw)~3U+LsxX8*j9CZrt>z!S`T$>>}wq97C55wRp1+N1>i%D zRtnCaiqm?H4zs#ZXtYhA(zw)v0v?c)r0>Dw{&@czJCLDi{PDXnr-b> z_NT^2NtmhI{1;3ZJFI=Zd(4MF)8O{o{*JEa6qf?BCkM#Y0Vl*PZW~cNJB)<_SBzx_VpbUtLz~Fz1fw z_PopZQ*;Wy7B+1GYpi2)J)+?H^ z7GD_kqoq-5)0VZP0+PY9AJw7t{|E4(iWY9wb@kHwWbhDzdf?dw;2#c<$+K<8M zd4~F>{UNu!l}4BIhpMsX(f(emv?9|j{c~CN>e=?S;fEgNnSL2{6)eMIuS{O=mw^M&r#1&k22ps1l~;12l!H*yVONAev*vN~V3{jTs{vx)w=Go`}_~kM_ z7aoEsnuOd-QIGlHj=?xB_)(YVG`=8jU{9SG8RfSY#^cas&J4kSy`oDNR&Ct;NU3+t zD~s@xR1I9rEO?<%D)+TdDxTHfxw=NTSN2T7W9g;`Tht8t+n;VV^}PhFR_2yw9&x5! zt)_mC8u34=%WZsoQa^Q(Tl56e(TTn8jErEr(R;>53y=-wnWOvPg&O)h<-kytwDz)g zoK^IbFAwSWVR`94;5e@!{|luK%-f0%&tyGD&a?ZBuBRF^FF5U+ws(OGdeUU?H!Jc+&XtnJ#SYUj6QbbHhIBC#YS}> zdBq>*m!GqH#k&++qY3cfvB;TJ+@HI6WD_`#Hgo;*BK0VW*&I1GVFa9l13+RUC%8Z;`fm{ zUIh!Yui{n1N7NV#`?4OnMHu^(cANv!Xhd*1RM@5mO*wb>Vm|ZhFv;pfNzt*vA|02(zXZbqi0m~w}qb^ z1dnOcTkt7wRnWg93+r&dWiow8gOHl_)U!d+QT}5~2*egFmw>}s7n7d0P zcuzA{RaiyUe$(IS(LG$e)i{6TBp9bB=m`euHp@TACk2MwI-X7gZu{v`l1P?@c|`fS;(yJZDqMbFq&(`@Onu_$*8^CP80y zPsclLVFs7Kzh+FbpP6A8cfw{G8-ZoMu{ed&^ahN!p5d}p%X z>8|_UoiLrBI-7j5|H=<&s}==(4Ib(toV$Vj5VAH_>p149yPH zX_i|qUf>L)5R8Xh8fg`~^ul5x{apB|46<1^0G8~(C)+KY3x9-F$l)gE6_2dO7ys5Xta?DVT)Ykt1BnQJ;u#|8?SY5X!eFTRLi{;1#! z_N%|3GwyHZfgjgL%3QEX?Qg?_MBt|>+ARses49wRXvT&8ZFSB33VxY=rA=wEi`%wT z|LSe+y}DVlk$LZMwh85|%lIw{_OTIIoA8r5?k=!FhmUw=Kl;_PO(K!Y>2jB!Z1U&( z(###j#_RHItgG8%E%qLYdY;pDP_ifXm%nnx^n?hRir%44XP;afjvgF5*8=9H{NS@< zqn7O7|Bb#)PMr?(%Cixie|r%b8T#lykr)5aHcURRroUZcl+Jtmt@;~tz*d#EaD+d> zH?8Sp>dXFCt5xV55`@d!`1iQQo;)+ykYB!zmOW2(nZI<*FLs>&<+=;`rcHChN&JXt{!)gEp)q z$(LdK`5`){2DI~aWULLq!l7?H{7FC}-}g(eyt+^3uxzT{245E&&DxG$^C9OvRtXn3 zx>Qd(wkFIE&%hZgI&1l4>T-+omEwXc`7&nPbwNI1Q;PNa{ws$qhkEzxJilZ`cm6O} zxMZtu#+x0_zTUrtTmzq^3-FcK7=EGoBbQ{!iZ0Z$IkLlrUU%L!^Tp3#3 zt*95aRAr`^?@p*0ExjGMr>QsSGtAAgksn@a{8`Q#V1M!69Qf>!;E~4ZbW^a7C|cM- zx9tY>v3H9`%Cc`nnlz2XpKL(VC&p*R-=^*B_0svs)rRxdck6nN)5Ift9qWQhv)hn> zM7#8R^;^-r<(#d84oK1co4T&wx@OA$fPIZkOQ`ESPXf~M=P2p8+b`dL;+FtxbfUHB z2-A9H3G$XM*L}#5-ST9dshe>0(%wYueXX+D>8a~w>~cS87$)oH;yVc)b|59^5#YP8 zrb8Fw4FCBz==c6H{X@O0-j=iNzcb~!y$k<^q^qdoj@K6{VabTQu_kmm!@7(-bn!Is zV2tfgxL=QcuE`3KqWe5j4}MG0ptND~djiuxw^Hxd(jZ^#6fT9|j+9bhTpHAhmXAF6 z`TpC?4;RNrOZEi%`#t*TcIxPm5$PNu%P5Uc5%j={YJrPT6o0NR+Y97N(Vvx7q1nN+Y2M5$@j>GDzRq) zn_OmHq_jhqa_L(=M`S659toM?`fB)0!QLy*EaKD(m+g~1(s`DyqxcrSa7g~(Z`$AY z42!~lJaW6mrp+=86j`1G9R)h(QNMAfY)!C{S()cO_#$dy`kqRoK@AgcDgu|A8|nMl zk(|A#>-9Jo{fiknv$*tH3qylpM#j7IamwBdLonf5!QzOxBRmSfGHj5RR z-xEI6{B-nZoPW?k_ixu={oMh`Ic?ej?ja#qu)jDzYR9j-E~^Y=et7PcTNWSH@`Sw{-zM24SHr+)=Jzms-bw&-rFt;0F1XviwYCGGTRDt=$9 z=>9maxJ#PU!w`z^868`O)-LfjMNild4Ayj0KPv8$YZ1~0 zeAn}o*n5Ggo!{Ba7wY}<3m)0CAm;ZHf!o+V)+7DlSwg9M`Y1`C8d-Nv_?u6?avwd@ zw)gzCZ zC&h0C@4O};4bY8-VcS;tN`xf%I9i_dLodg^O;Ho%G>VcAj#*EyU+^#AagP*3=WNrR zx%S<^UuWQ#qcUS~AGRhfO8VvQez&x@Y|~?l*=HMPD7EuSl2_<)i!h(YkA8jGBcAAJS-%fCNmuk-OF1WTqb}q3)aOgfhgPdmURi_wLeYs&TvC`m zzc!UmmVCt81g~mSqfz(}!9KvI@JeoJ?B>k222qj?dDffgRe85ePKSJ@m`fJ7)9v`C zup97mZPWM2p%P<*HWHhkWAvpx)=+!;hWWEZT>MqIO@8fkO5fFYU3*4=`84UPr)SD5 zzl;HS_Jc>B!2h*>%O`WuDV7IEdjmN_m)2g1D(I7Y<^8g=E_QbJy;5tQSKhxFA^mgc zIy+O?BOQ}qBU3O^en2mf^|Dv;aL%EV((`SbK7xPDiX3E7Ml)akei&K8a6RrLupv7a z4Mq)|?vyzJ+3+4RN!HB#zv~K^vN%G*ll!GiZPP!V-!N&}-*H|`{1II4%jm3Zs(`HT zSNP-#mb}1zZePE;?3V-!!z3EsBzFt@slHwS+oPzwLr10G#QZ<;eDJfqlY;XU{MP*1 zp3dB#L2h?#4}M{am}ly46*j)z1Ncv#WS*C#EfwWNZXZgQYr5s{g?{-8ySAO!mR?0q z6}HUuZ56)cdF*O^ewq0;`_lU^$p#kwVF_e}D?C#APtMqm2S1n%8O>16KKnCLwlBx# z3w|#?@|r)Sj(GH^uZLmB-U9{qmG-8s64C>E?=A*Y?}rkD79*XN6jt-xF`6)JS;5oV=2f4(!zjTeWA}(2F#K+a#+QH-adM3AgZ0S|6 zme(a)Mm;MklT6psU36`VQoaWk82?f>O<(SjldVntxUDttUi;wnUWNbh1O44ekNolu zc=)yjbX}cbeXyy=CHViO;OE={DT`iU$3uA3Mt*tmZb0^hd8E9xmsR1Phv2wBYKSky zugx4_r@6Q(_}p>y<#Q3zs3_lMzC650=VhyfD_a^ex0Pex_!)MLl}_or^-IFqkG=m) zuy$`ER~)y@L(Xl}rpp2OY<so^(uX{Xy9?7`zNe_mJa7F&7TCWH`Mnoq^XCEqzBtNELV=McG2uu3fBG)8QkN zGk;V9E9h?re!g6k9Ktt-q72vqr$bNhPYJJ#qyN}6ux_N(M7FvWeRK)-bJacxldccF zvJ&1hoPEJ;v6)gwM^q(-xfkRBSmq9LEObBk-EYR8z7?SJd+v zX9%KONl{r1PipL9KKI-pm#tf zx}XDl%rOBO?~RZe>^t8?dj`AZLUTPf`k?b4{0nlNLD;Ol3XU<}+I!Ya>6i3ibW`G zQCiPen+w2qX2ho6vg2pCt{R2WFw44vcV1 zLkrLCxfdZh_J_%Z^=_$kIA;HJrWJbM7v17JbvTzj9ky7!jLY7vH~aF2KKuwG&we#7 zOco@@1_XQ0bU(VK7~fgGDIk573}(L>Pl>?t4esNXU0_9A<1IdCoY9Q8SGfPa^;Sc%1gk4R|&3nlOugMgtZ`) z(ps_s=kv!~b-4T3L)lc?t)ER`9NN@+vF;NOC%fc3)&fNtkRdoJc^m9Su7t@-{Kwos z>Bc7)XK~lv47bYVxwh;8B#>I z^_{jRU-mn7-BgdgQ#PHC$Qh=+PGZZK8(dmr>T&B2*md88mqj00^d5bq4gRr_d&Neh z;QL>0WzROlCEHu-x_R&*O75XISJV>ze#s=$CN(V_mwI=e`LKs2<50g9^%)J%i7F%Ow`pX<;5o&9uC9~N{VGa;ysP|6pZqb{ zFB#v#Uj{nvk0QL%4IFtWWoQ3uQ?=1Lev|G|a`yuhwjuhbbjXm;W{z1-JMRB-ed}nr zG=vWi+ktH<`ejA4eh=y-~JUxjuUb#<{n_%~`+*)3iFjJzt zBX;tASgXH_%XwJ+v8QK0yC*Zg`r(Zf)lY`M&`r##$nBl<2YZWa*a6;l;3@YFHF-Kv zUZiqiXAI`4uXGxP?gfvb3(2G8;S+SRf`1wEHg&p4AW_VAe>li38()UYnS>sE459Pr z?3U5^gzvu(Y(F^2^zb5ITYkRPm(Nz!X|(Qu9})B##Vr3??LO4`nn4?VvJ%`*E5?6$ z>~FGQTRJpSj?Ida`OBi@{7(E+3^Q%&EX~sHVKS?huA|QE9e!pnkh3zFICKUX;5S;V zFlF3(!x>ZGU(d~%e{J-AdU(&+Cq^PBelyLo-` zg{9~C`;LA(Xr+!b<$$j578_&o7x542vDkhXz9Ly`Umc7&=C53L%Ws8sJ2Xk_lD|9X zOn2QIbNy6bF6s}LNA&Lv=pIV6;_Q+(roHX_Ho9%itE|0aa8H{gk3Y zy*Jo1bh2=blmFIztoMO%8K2dZrT!0KO_8N5Is`A20X$X@2cF&jUToJw@9MHXNf;?_ zZDP;Me)uG9()yX{8-JfM?WfYn-WG z@0-3H7rAJTk=SczA=TQ}Znbs*> zrpLjLn6;LxcTT$d19o2-O+7f@_1NQ<^cRuQqN5)hCsLN~#?E0~lw5`v-dPtJMJs1$ z^i;^q6g{^v`075-N?k9zMn%ikX6i{W?dTC)*Uq>8fic^EJ~oQqMZ{hg6R79k`szMD z`bSfDD$T05@QKO(y(ej2A8vR8`+L{Z=zLrli(kpl8B<+@zj2|C{{7+QaM?YNvvc9S zoOIH`r~k_SGWt5cq{r!b;HL^c$z7Loi^sarHkfwk@i%-}VSHwF08@f~?FG2E4eWECB{%)#mm{3jO26HM>}Yp8o!3;zcL#CS zNB-VmJ<(fjLatKJvSSTg*X68=?axE(54K=qZ`1d;^*j4_e`FVmvSBOgq^j6Wq{xjN z=8NF<-41i_PyM__c2oXmU&kJH^A+8GJ%87IYytLSSqotwh~I`#+6kWI-)Ke+d>B>0 z9}{J|gAJIXRLm!_(Tq0uoI+kRaR>Yk^0De%UE!RCL>+WW##t`tMz8fUapU>iQYRBO z&0t<0v45EfF1b1wvbs~y2ct92IU-UvPB4A7n#V1j*q;u=x3o?BJ_6s{3%l>sdVJQ6 z((h^`bE=j(xF46ef^Hq(dBgq#hi9if=ot9<+PcnqOhbM-gtNVS;@j5h*LJwrt~quD zw{JK0E^E7)ka^j|R@<)gw|f_UjApr{(KMe#F5v9JxyS~ZfzKX?Z_Chjp1s7Ax(haE8zweI>mi@!K2U#1#%{(!qBR&$?r)OmyxqA#7kkatz=qifj z#$LFenYUFM8~dPFE)^!Z4n#`*udxXp${81RebT|=1)@6mIdf4~wm1{l$L%Z`Vsx*poKa@m?JT2gJUrD*hN0P5m4D-IAtU z=~9~dS-||#tAi=q(h}ivg8j$li+YR=R})_d)$Q(+p`)?0N2fV}{Y7JkJmqEqlh!9= z@VgD}-KJ6K*=*{*&x|Mgne&>EnhbeLGwP`o>S;ZR@j_stDG*w`0CL**02cE;4nf z;!Hul>0NEgr=HEQbc7#xOdY7_p_C<`$>)eQ;GxlPzp(alcG%A=2c&sl>^7I_cIhxZ zS}y&@{?h{&;= zDvF&>yNrIRj4gmoYuJl?z8&4z1Z;V$oA$d?j&qbJdZk&};O}jxj}&uYUK)ad8q3=J zaEYETt`!KA2FJmBxADl3W2WuH(c#|s(#+izz{@$Q@rmHyZ$|~!=dAl?9;;E1vPB|; zny2%2GG3JIL;mxBp*-2qm*LYz(JuTP6hSW&8K1#s{;7y9+E==NcFh$opD)t&)uo^0m5i z6x}|r^BVuO=_4K4v(*GQ-L;sGkuDu)Yk;p_i0)!r+9*lMzOpDbZcaLdF22ZD==__2 zZC=Wm0`TMc!Te{i@FFT~Y1Xxs2zJ^>VP}fJ*E2nk6@s-W47NE=MPPu~9v>MTkn8BN z|0ouacH!VAEqV7o{D3x_?UvFOPjNrM?~opHp~ng!}F-*)O*?1SA+~Z(#k)7~A#R;*@Y90;XENhUw_$L4X)IgGDSqA71$+6VXk+GqyOFZE ziVi#FP(Vr}XY|H`16%>d)Zg5+P1%9$1M!nuDLK9g!52H}i9`N-_7n3a!5(y?WjH&= z8uyjknz5)tMUC;v&2L1WPQgF!diE(6FM2tX?o%zxP|uX3OtfDLGDm#}Ce=xwWW_#~ zvsRLGu3uHoUTNg>%HxK*&lU$$s%Xx8!QWKR+UyM;gWaw9YfRPPI#glvFH`>wrMjr& zuCDKwkK9qxvJ&HffE{idKbww&Q|S>JU&Q}@rQ|24-VCG$$1&;0kzy0#Jf9Yyo;6ZCPD*SD|# z-GjGz0j7LZ?FcD#3!l~O_Y}=+=aE@|n)vEjJ=Ujv@G+a{_X9_PCAM@3>YYswXv^)3 zqGUgFOx1m0-&hjwri)qcD*U5P9(jQ6Qv5k~Y%mRfP=^iBMd1&k!)a_uGjgUN{Nrh$L})G0Tw;rxQgFW&~Y@!6~~%RP!YJY6e4wxM1rwVJVQ@pIkhxuoM) zy1%T%Kl14d*o(F?=@mkTxZ{xdoeqr0eM`pl%L2}a0^?SOwp7$GhYnX&Tyg;%*qG(I zO^<#qlGd{SuK5{02F96jKA1h!zfmQ|&M<5<(!-~wS`U9T!6nDB1E_~=;5THrUiyE| zBAoSo0{;M)qvQifV7T0AA12MgUA&20>`hKs`*l0aFF)hId`Iv%M!fP%8Za7)w(Q21 zVl=vxGWvIN_OFVHpbzhM$h29BpG{e>7YJ^@6_)&IVt3sKUm=r*;1<&=G=ud~{lx+wcTJ;-WQyQ!d$rjF6Tsl3@>Kk zW&bO^|9W2@-nnINeE2tTgtYt>JYVRRDx4W%(;93Zj(MVGYB_YEPj&mbEDTgUc>g$= zA~@H;w4WU>wrh1qJFEA}Eg46i-|(G){Qg;9J*Lj4@yY$}e)%0)l}-77^-4alDZ9`~ z+}j!Z_i`ZHNO{|i5&QKTGD|1rzKrjKzr6DHdNZC|WeQF|ANm|c)hBXBy~VfLX(So1 z+xI)<+;5_@quCoHpKr9%%vT3O)_5;AL_4ma*GY{3-dTG5CSrXJr9qR}zt;?t13w0r z!wy$?2j>>~OugC9)iv`*-LJzMhRZBuR$pW5Ki2ZM@)X{33VscbP7BDP>w0YcvQdA3 zZ+d4c`u-Se`WAR?CyhFeeeX71A5DjtH$9MLD=L#dxQ>eb=#$!oy)yI@>{QEnr88K* z1mJ_4czv>p{yCjBrw{r7W_;QCE&hAgqyIza{4gHA&cSupp$c{{@k;i(__oRzB_|$o z1|YVwEw}4DRI}C$_3b4&bY6QV#J~OLUP)g|=Oqqv-&M{APKkZWk3Z>rUSxh%)F!n{3Kxcod__nX%285A}4>A7_GU2Gk} zR;R%(uNSgon=)Z@T@9U|O}S_4e5l`1i6gKH((gV>rQ5e2bJv^5AIsb|B@gpsp5V1X z#eaZbheMoMbHy50cY6BeJ!Jl4;h{Gmiz*l%GmeXW{L{Yz(hb~uDlnt(=JCoyWMotR z;(RFZCgGns!^zV<9D=AF9Ipg`h@JPIObsMPXDK}vE{$X$(Zn*4|-DS+!YPdp=h0C>c z-g8$0*VG7KXO_&dZxd{3hP`<`kGB|HJ+hb&IAf&rNHFyE@Pjl4-RqbL*~+{VN)NGl zt?Zch)cdnw2Mf*DA(JrnZF;YR=_~5l!Z^Aw)yTxzrF~5qF5t`gQ-@3|a*10CeIF%n zA@A?w@XuA!;;U3zUBC*B>7ncDd0NhU!cVzPb--c_D{As#KmT8^@6^gI z1h>bKDLTxN0;WzL6*2c6Spx?C5FDr5R~{+KI+z-aS6pNaqgt48s>+!TJx7njC5x4jcdS!bt=8*!y{a?LL!+zzzsP78SbpObF^DK5`kDpul!JlnT zY$M`eqx+!)+nFD`(zk13Ym)&?VKnn-H{QcHuh`;~ZKuJC4f9Hyoe`3Sz4QH&G3&7@ z{MJ_H%{G@J5YSMDYQ$CcT%NoZLvKVU!az!Uih zZ_~wT=pYZ7a#i1A=B$Fq&gXn)+GO??z73Wp(Gl=lU=kiz(Wx{+cY3*rX&d!)c=3R= zDibCJ*?Wdk#>V*NeAg@KkacJ67ba8DEsjeR+y-}2N64o9@S3-Dy;Lv5o)FykeDv3f zn$P3xujXbh4gE&w?~jp7w65=woM3@%8e7}GWBiwll&8m~==IM#x_l*z2bbFp zmy9*nNhPq=$a6DHij4G2rmH>~c-19C8RN^ny6s=})z^tVO<#?$@J}DyGHG2$w%i6> z{@wBByUoExuXl&bDSSfMlq|Jw-+Qcep)`C{n52RSKF~tHi5p_8;tXHsPtHQazRISm zU<4E`A7!4Y--B+N{HWhfI?s6mu~AcGskJ}BmJe(}6XwE_U|8zT$9^Xhx-)pXT-nVx zQX+$CR2;ic-ly~#-l7RImCmGN(}oWM(qdPHOev1f1a$WATk^5uk951P9H856?F3V& zD((-d^n8)yj8`(X<($O&E;)wGK~dvnCjHkB_?Kz`*f21&jfca-RL3uD9c-XyVC!Jn zTPC&iT!G4_KRs?PvKpJ}{mt}Pc;8`%(E&_e2hOpzsT7#AmWqkkenO8nc~#53$`#R78hY z{})@>Y4gO~EqW(-?tb-taDCsx-bm58MLOJ?fGNA3O8FTv`>y@&rwJaZh`cM5mJBt0 z#`!KTnDThN^ph$0GFi`lxLWg=^{YZ0D5lfR0RPggy-Dw3NmD;n{tPak>;Qw1-X+(I z;d9c`$vVGp-}_$%mnnN|Gj1|w53Zxa{dGQ0knXJz*@>OrFUd?94(!uu)uL9meu0f^T-_J*9*UGGN8ihA*^sIHb-wlc?0-szRb^EvlpD7Z!V+TW0+ zH(RT}H3;2B%T4&1K~{eRz1nJg4}ISf{2G23+Wdmw4X~&`<9}XJt>LC#io#n|WRB>` z+FJyDZ;QLZZIEC^lq_o-B?Y6RG$@C zF0g?6AM5Y-_G4H03BK&$$qM`!CA)Spcj9|>7h|%~dCo9GZmy^UdYwIBA9`W$>ZG&C z5o4oIto3k!7kl9kqhxPFzx+k{uOgHFP~k?w#U+dgPHX4_J^%lZ$MBRY?W#v3rHu8R zndk}9qK}^B4#sua4z?r5mT41yM4QHCdlRy608A9KGZ0Q7gfxmrtCQ53o(Cst{{ycey;QSAS z7g7|3?z|{IjAEl4Ykcxk`AA9IH|G3ohxc{j?6gDnFMXW{|5IhBPCw-mWCvZMrF><0 z)dadfCuJ|5i?Q}5dN{--rI9J^k7L^6Vu)V?XWXB|O@EydviDip&L>&j!QV4^o z%srQi_@wd-WF72jSFsL#*}yC13PwuZJyFtQl}FCe-an#mFa0Za!Dl_vbrk;Cnah1+ zO}ZbC4z7dOiCh2T9u1T0MNQaR4&Gz;&${0XDyZXU{ar^ohK|yvE)&rAogu-E+ti8iRf^p2_6d&+*c>iRN^@o#`?w<58rhV{k^}U>hJ3~d@bv}I zsUa_L(l7XOSa4qF?df}7={JHi4Z!aGF^F|$oLkl*pZQAsQsW4|PR2#c-H|%a1F?7e zBo6b_GX1@-N%4nXAK7_VJ%*-&VfpL2PPa;Vm-J<9q`_X;rn9m5Mz!DF5Aj8#o`2>x zeYQ+yJ-(u|lE=Yr8lOm*WS$wggONou9W4kbtJ+h){E&Xz83;hh;SiD!^vM_`+0Xx^AB|38<}>?w#EeLJmX`A? zGI2&X`-LmW8x>s*SwrpcZtJYhgY0YbTCxN6uGeAw9JHdSJMJXc!BnfDpE(}n7M#R&Q9Yg5iA_|o@m z#~&QH&o7t@(}8JjQHeFpl9j*b#(z9#@We(Bk_11$KE)&7FV%e_*|XqxvBfWk+)YvU zM1Gl&Rp+z)1F*A=V{hZ{klWW99xd-7FZtsE{s7+9TQU+j0Qe*VUR{snN&2J?#x2;D$Y6<54XRj1nZTj0x z_K)XipVdE_x_73r4Ib#f=sn~gicoDy+x+^Q39V;;vX5THo-gZt0^@NAIcVAZuD3{Q8w{7u+WG+640hGr&&m24~hJ4`-0a(P0a+ z=SyDJBW+uUNg{k5*t8;#spstPi6mzKZ&Rn2;5nH4`g{^0e)#^|{q?)m*8V+{<+pBq z3csYX_T?)cqszTbUM-$*CwLG=M=U+Dx_4Dj|G{Xr*XiYF4(oAV*X`8loY{zPkpH3w zBk`NK(d1o)|NEvH&zB`2wXnr-((|?W4~=8$S-oqVP50eD@YfO>P5%!4K63K6JtnPZ z7RJsFUw*b3hmR~BZ1Uu$jk?73O6%|_`D&gi*Ho*|+i6^;|0;Ut6P=&wDe$B7y9sZH z3%%9`|9>A`*Ae-S3w|D)c|WIu6?_B%I;c@zD>E6YAcz4QFwmgpAh4xcID zgU%#0Wyp^ov1ZlvH~vD-;iT`uulBa&Qlnm(HmN^7W}XfvH1A*4U{199f}P%Nc>nb) zbiQArvpiDAC*{T=t9{HEe~#?3K7P;97b&a{agzscs{y!mRHwozf$+|~8_S#fkY zd+;fZ{&)CU?10&8e7nIXE3u_fbnAv!rtSpiX<>Z!Ip$;azWqO@uU!}k4_H!vw+lM` z`N-XEs_Y8RkNte=q~N?S!G^J%wO3JLF2N6-Wo-+koyCI3y7T>-F1l>?vrS1{a{3)? zjPcVkazJoBtU9EBFUMa&{Rd#akQtZG>6U7&m%TRor0vTv8IUtV(p&hr2k>}J&Vjoe z=$0>c3z&D#*`;oNnuh%n^1{Cd`Q$8eh=dIT@)uaL$Mm@!$Ymoed9t0S-bw5`k)hYa z=#}b|KeXv?rQtSG=j8BvYy94r06Fn!5nQYqH{+4~6 z2fjV^l7Otf6e;WWnRc(%3LmR&@hNb~JX3Mn?gCrP{{60n{VI&!>hKx;-2+)TTNgR> z;uU@=3pTRt9s2uw;ApP~=s_#sR54d)Gkt8vm7@B5_Geb%>sblie9 z!1gS}Z}SXY7uhUKyo$5Dor$>*e)cZ=qU;+@A8$Jq91r^Wr`z!bhizaeO+KihBS< zJ&q|?pAf90Gp&?hvlKlAn|XJcTRtkP+o%Y3pf+U!H?VQGX@esn=jLTWFLVbizLO4K z^UKL)$dz_59`N^26JKzrzeVR;2tQaGI0wCu4&Bq~CwqfSij)hUmo79mW8F?aGqS4j z;Ev1SN8vN}m^StM+vHh28;tGR-={qEAD85rsmrCFmvY$J#)l_Ac@|kRa+|5$I9~+p z+*tMw_rUcRsl~Zi9YnIEP_Z~Gd#LGe*O=!{pkHh8MWp=nHuK};;PR{R-CKI)(*r)a z^bKb;v5x&Ol)N|oF=+dXbNn*E@?~zvyLI0qqrg`r{XSg!fn7N@DNH>?W-U#l{JbAAbAlcI z_NL(WR?jEr#g;8@%;$ETY}T1C>i72_1h>OG<)bAGIr-{aZtz@wc?Gs2*C*(I(93*1 z8DH4ga=k(a@G|UgG`>OLw4(L+TV_=uF>1U`^^pJGw!U4 z8FoqnuPlFP=5=Qp_I=&T(NgrhPrS?rOW{j)^t0cX>*@=-%;gg4YrR8nPV*|f)jYt+$*X!7N)1wSKFcZ2LI(E|jhrt>p$J(* zf0*)=^XT!b)rs|Lf@Q<2;?@CIGzwq;pCJouSqhuBcXfUv+H)RKjo`e8e(NJ-o++#2 z1O7w&sm_g%u4^Nt^Bj+S+8P-sZIXg@v}(10q(;8c3;gkH%Wkav$tX$FIb2-Z!6?F; zDyqDPu;i=JnAbn0-f_1qE=pOkrS5~A#JeI~3L$Up2oA-jZ%0MSedJ3{TAfy>*9pGa zrX(Yox5}B{>iHB)HhpoR9ZF>ByLyaIZ-E_Wa;)w-^C`q3Fe2T|dVhIJ


      ~LH534s$u}NNhs$KBu`k9{I)aSYf`u@=*bfe&_ZEAzx zkEVsdh3+^d8A*aA3EF2Gi zfdF;-p12g1@ESE&5QW@g6dHo3=3r4S$9|Z`L!S$2P4qI8fJK&QWB({0CX`Dr_X*=UqJ3;_BGQ59-TU zU*wnM$hH(ctcxx@srkk+>ULNbQwLK>L(xIvgf;U@E@UL#4teC|e$!U31MqLgD=?DC zlk(v2B2^{7tV2H*mCV#v3Ggp#vgmJlx|lwr;ve}9-+?>O>spw~d0^Tzp%;A1f!!(2 z`W8yt;2ZC=-Z`mFf#5b#?|NcaUcs_6O4l81N)K@MTTI(5=xoZY!Vj*YzqM%_KATeN z^qzWkzfNK`Rnmq5S2!3rbb{5PDigw1)V{0w^ONygjseRMr z^WbG{Cli>sD*VuH$V9N2Zqef%>he8?^QN2hvo zUVj+}et27yWLW2s8~C{lr6DuIB~eP#chvhhSy|5=^T{Ii&1)u^x-EvkPepZ}=zLDx zz&XCN@r6(WoXBq`-0MKrze?Bz$3}C(r?{Hwc3OLrGvSaaH13BV@p8faZwkvfpGYiruB<`C1a&Tzjl4noP@jPqoRV6#))%)t%nVAI7|yi`6oZ|&cS zmbdW@f5rM#d$3@kG!5BbXXb93#^IMS?J@J)e(t>Ho1yD9c^>Al=-{#!zmDHA@TY}3 znf$4^ce6QDc=P=b{3woVhRqc7hN5?nx7*bF8t20gwtrzi!~Xrmt0*~(zms;$P5=Fs zb@(sz$2q`M#Cyjh(UuSLu@?V*{;S|Ts}!65i0m;F{(8^}zRP~orp&!qw^OnfHuuT$ zN-l|;Aof1^s%fPB9U@<_(-`xo?#~YydzsM#$A8563$r-CjMIL@!*>>ZnKvcC?cJNQk! z{exeYp_fo}wh`wN@AgU)#^Gb|MPHN+lX>Y)pW4ixNl~q6{L-V#`QTUV*|4i|QvF7{ zz2amKlY>XW4i(h>pjuax&VA%m>Cpu*LeBE{s&M%dIh>OwCNz01N_!tI9*}D5@Q;eE z+#Yz}EBRfr=^f5uv~UV4ZnqjyQWrZTo5~{x>&d=o?qvH3{{3sVki72dJ49(-ZOOfL(Mv>!gghERA&g~>8IPF;AcL0=d$TT z9?Nd$RwDML1I@Qp+~@7Vk+CnbDZVuqzkcV?Ri0~r&KzuC9rkXUo5AC6$-x*^G;y$bZ^u#BBv@H0%9(?8IdAZ{YJhqsA$WCU#5S$DsPAVa0+TicEL@}DczKgY$sBOJ4516*t=!Uh2 z%85?t4t8@3CUcHx6EpuLs1zLQZc&p?)tC5+?}N`g_E+!i(c|bV_8XV2y<|qlx}x>R zbbAJ;6#T1rDHCR<#YfZvA9k)vgye1%B@xX{o+@k!o_CUMjpFQie09_J&ouSQNcQ(G z%ND18N6x%KuB+&)G=5o&ekWTQpOmd`%HhmOdT>k2@rz~C0_0o&3uQ~{m5X5B2Gxxj zIyd^~9+quz%(wsjd^WSI# zw(Lb`V`nxhLU!S2z)6ePo7;4Rv7RHT?n`yPHu-Pc%k&RB?6RMAfBza?T#Am^l8pAq z!ZrA20G}30VPH@i)QOZ7bD8_CGTUL2zN5b%$QH9twBCSx7Od3ttKj#*sLcU8rKo;~ zFj?`Lz8?=?=cEt7IXme^Ey@J`r3B+@_is_s=La2c^l(#d6@KA9u*>Lh6ony6IhoQg zFRlGXqMlyqIo2&}koAPpsKolo^NQFYN9iHI{L?DCzppQfgtPuXwUr4jb`Vffs0QqJj3}p?``@-$zs@V zVP92pxC`tv=kpfE_6YrIP2}8n*M-TDS@@rBArfy4XEouQWW&7(xj=mfZhB;f*VMzR zgt~0i9QCF?Kj0we5_K?ZOT)JVG8&&!F6P7QJ5Bu2KXB$WSi@P@*td2EAAro~VXl~C zGkz&kug&VZWY~Pue`Zw#M{+fGemt})Hm%fS`D6ICF0;{*!<)n};FYfES1RFO`wQe6 zzuGTjK9?$ar1rPy zb3ejP1UvkeDLA7m5qA0D6^G)JJ9Q>q<}Gi(IiD{-ia8cl{%^nFd>CtfRlipuYl+{1 zH3_>%C*9|~PemoZ6iJBxshO-hd^Delcvu8NtbF-OeK3l<>wiI22!@jIz zgnnO?x_O3tNKyX0rY_4}!afy08RsjjH*coCd&u`0{eEqBzx2uxA!#1sGrGQCep{~l z$b=O!>od_$W?sx-&BdLpGg&iXZ{no%-vwmiL!Gw@8IhZyQz#rT^`*iVK=$aQ*1zih zkzu0llh^K;zV;9M);H1Pf#yxOoOqB)6mxvl`pVRk32p8Yf(yFFo-BerrJ@(syrAyC za79Y|iKagODyj3C{kz^J&%D%mtd5@nMHyLp)`I7$G&x*u z4>WyaH!>2Nh9YlxhCJn58k4`8_sMU6p9D&AMg}%lt8#D-7i)t}!*ik2LzZ{FOoXhi z7+fzSEkBo)&^?wNugB%PIq>WL(8RaXxy^cR(<}0vV^FwkXWh**Oy@N&>(|cjz`H*R z{)URPv#hDRBJ7p+rO|b&-ql0rKG0z^e9F=h%mz;%=eRC=O9uu>#Zi>JDfS*w@Mx@i zn=X0fvrgDH^u<=SFLJLywB+fi^V_?V`L>P;7IJX7+-2=t$ef>>weFpToQp9UY#2J} z`71cPvw=^#vk$$(T=6kBI>~$S$C^C{?A^+3oO#Or_tbLEn^}bqlk29RH)9U0wNC$T zbCR>UZUkf__We#;)RFS$i`i#Ym@LLE zuxh4!2fujz=s*8WnonJIb;-q*_`&S2>nV-3H@IF~N1xZ%w2__Q?m~q%0)_2YyEYm-#xjhJLhxf z{pD@=(fP*A1-IIW6#GlhJzpFJ-{@GQZaQ%M<6G%CyB3+$&RhC5^F-gB{>CQR%L4tSp5MsRi+*rqPu;%oc^)4nQ9T4Vxy zFM`3YXvT_qu4sQ})-mdG2Yp)6);+H;umAZyoH?;1cpMyf<(4e8ucGulbRMo*ekRxd z1GeUhSN=jCH;;Yc$bPy!qp+i@u^j&o$JE(%CU2XpJ+exxe}qStS@zT=TE^Zs#Vvc4 zrr^jF{gOCZ$}KnJ?;m)NJ=Q+-bpXe|{2{!W{i-l+YExKEGgnkcR*)l?TMmPj*?iS6 zBReqngzIu&3Fxbe7w+&cd||cjcg5ErJMR-F#U`0@WajLY?!#Q1wI}ikKC9Ywv%kuC zL2fg)tgcHu%f5c`)i<0wdfg|_k6_mXe||h}q>hC!AUl-{Ex3E+EMNBw5-|bsa?)dmR+Gg^v-c4wauKK$OX*?M@Eptewtl@Hf zhg)t~vV0Y0Cpf_lEzGyhp3{Bmrzvt}A@38T5*e%)V z+(a%}rDZ@q9%ItZd4n@T*aLNR=!<)uHf8)}wh3#eQ`y3ItKS{KH3uv_XzQvm`^k{j zV8WA_=j)KqPg|z@i=AHRHMhfWM+f|q+jI@P?2EY zH&pD#>rFj}p(FK!Y4gB~J*mu|2V0a+vD+;M4s7HMmn@1Kvrm{DpdX!P(o)YCb@E7E z(z$iUCGXcorkFt2&GtXh4OzU93U~B@M=Lb=do$+aOwK39y6{Y$VOSqT3I&9DrN`tF$aDMj;mAT?7W7-ZLgj; z%MmSwYX*-&_5AwBei@9P_1;r7Uoa!R;aOTBi#b=wBi9@Gq*-epXO&0F*I_z;KkW&V zx=D4|537L7`Nt@90SJMZgg2;=Eq?OefuK7A+0v8kH=4&9q@r^3+;0JEc&z zRr3FX^ouS+2 zN$gqH^i@}>(+)nV-B08`_W39B>iYO+nI6CMUBj0N{r_%mWX9A(ySH_F)lZ`1Pj32I zBlfoniwoIz_4mAdy6v?4+2q3xQJ6Wl*e%W{t}k+tebD<&7+-a9s4b$DOs3&x7)N`b*CVlk!MZt z-*no{t5~{U}Lu_OuB&M~`)P zo5mj5J;=1PcdYUVFJrE$=l?oy#{!1|eU`#O;@(y*Qo^T*RNu&Y15U*GVLClO;NQuK z4_HS=N4u@afUJ{)e_}3pi33^RD7@duyjT4n z-6*tuub-mB6^GmSCbUgs(la}jG4An7pIM2jTaxGb4`YQgN{pG~+|2_~`XG>*-BsToxNv_<{;P*0q^vw@(iTvlV$^NBrV;(cvbIi;%V-;Io`H$8X5V8b`5DJmr>tti`MU6Po_l5%Y1-hn;2G z2$_n^{V3&>b6`N;ORvkRHSKk3&@X*Sc56%Kl4-VXL&rLsda>iOze}NC_~}pVS|*q> znF>VD!e5=3+Y!113uGj>G?L~ zRoI^!yI5v3}dn&EKu_kU6gIE8*y%zN`cP{M*nmS%ojg z`fw#{wl`r#e{-iLT!+QTVGdy19h?{;myjEt=#309sbAtQM4vFtCwuzo@ORgHq=rMz ztgdde`fiqs=u*+W{E0lJ^?A6-*!^~ir_+2l5oaM6!8a=7qZ5Pv((U`{f9QYJvHMk6 zjvs!7_|KWwtC+lx?udVbBiK-O(e0s2mY99#^@DuWO5~Ec*bO+bs6e>P`b%F+cRIAb z7SK)Gf8=v~z^#cnW*xfWk@~INQWsmcOVxDSjbI*0 zj_;HPj9=aQn><&`u3!4oWRo|~I{Y*BHSOkm%ctOK#(?P9JTLkc{eK#~{FByx(i!6H z&oSdr_uI3_$nv940_=rym*IS0&gN3+pHBCM!c|N?4sYy|>Zv1TM;Vcs4nJ0YWcuHF zSZgd`OuB-Z~J9tM{N2k=ysnpe}puQ zHWtiAZvAf<%(}ffejvW@h;K7w+BYp7LxvJQ8FkPrKb$u8mxwm0;HzQUPU+?`=ROr? z?{{9wcPQq&GqMluT)>QvvbZbeGWk*f6(u-}~>Jqx0gjeuL;z3@S(~R@KBf_Nh$6ncw zy>L=|=C^*xITkHBYY16P{+uQc-=punxXsj2N%X4c_oE{Vm@>#sy++5NGjMy`>UQ=C zb+51-zC!Nl_-tTp8HGQIm$`JAq>mf={PiQ)3yy)4mDltwXZ*v_`%kUok+k(f+gWqg z`_tK@U(c%B#^Sf&V#0S)D2@E;3G?-chdR#YFLc^=me6^7=J2cgE&e59L)Zbd7;An&YtDRoRMl9t`m*j z@&UTE4a{#t^XNK#yvDR8^ECZ?p8nUiu5eByehtpKr6D>3g<-4w(rONC)9`>iEE*;e z=*4aHoadGW9={};8Ctfh`g-IVfd-Y=VZCs_$|H;EJOJCafcj_kOZlGG6tQd z6Th<04lWK#pD5b*p_pTg3Ofq9p~5;#$GN%O>%USKf66t{x!m~*T~t@(sAK7aO1Ci^ z9m!id?^&zp@;wL_!igh{#ZH{+9NG`=eWU-oiXw95rOLi-W4~sRkaw?-Zrg{(a80F&QZ*vySWHW+U4f}GDC&ZEPv z$Pk+Uxqo|D1NtQ=c0~#gEPoKc-RAtAI{KNjqd8lJ_1+-%c|Wm+Z$H|McYEPu_m~-A ze&GC^GhV45-<0>`KlQu5V&2)}kO$c5`mw%gbM`g$ogdvqbOh$X4LchyciC6Ph8yrc zdk;j1hTpq|d0E@SO)I-FO3vW-JNX8W)Xc})Z&8?hSQP)+3y=+zg10iy^vOz=-@coJ zz0!ULKHl&H(60=(<=L@8D*$(5wM+V9=ThIYwOdV@IdOOkz9W%Cr$fK3uwr3^l-+Ie z_wjKZJ_~Exr}cIHrn2IAx=`oo{xp*w6~~Fn__U(U{}=Qq!FnSfYp0tcW#IKrf{Sxu zALrLGMjUBx%Ir}~UA9NI$BZ?>H}Iqqx#dHPd%t~!PNyC6Hv3V97V&ley$T=wEdJr1 zG4Az3_n{DPLAdO?Xv)TiJy3LtcU8b4p__DJsER*yS0AVHV7LP?Cfh%#HX&BcRAx|*9cw1K(Ca?Zfzj4%Vbm8 zC!miVde|?4n*sR;`J|7wId~&ybx@a^OQR=ffb2aRT=E;pax8iD8GOA|Va#sj)n&AU zJ?E8yE*ac7N=CtB>zGHRB58VP@%6G-50goM>NNRAM##zOewnpe*VE=+&J@z_dW5F^ z5_`^zI{m2gk}S$6i+B2DdubhKqHR8zi44ca!cy4Q(|+nQ zM%S*u`QXUZKP6uuGyW+IDWmK0+gb35k+&+Gjb#i{*Vm%&j-=l2R%LF9Z{DHqO}P=2 zPUwaXz}5Nj1-j9fLAe;;B{kdWHkS0V3T4oO{n^&kZkf(L)W(81E;&3`=c8mQU55>4 zn|-tjw{32?WZ55-^shqSzvPg9F116)cq=P5cuiHe6wV~syN>75tq3KZ9rl#=8MN40${wu6y zZQK0&(7arD!&*f@5&LKQG^V|%5Jll?uH3Klar8@FfA*7q;#;r`^{{s+KHE}yWNl~D z-(SU|W3JCWLt!Ai1BLzrUw_Gx0TI&j4QX{VCZEKMR9A%d}k${m$4vKgorU5^P$J6$?nQJdx7iZ0uvu zxjhjw0Nu?oWL3@6Ge_*@JcpXhHTbWH4JkR3WEe7pBlM3qVSQs$&q*D7aTPx9KKyBS zHBT1l6E0`5Pkd1~AfsHm&PPtw`QQF5Qi3mC@*w6VAhgVQ@>*S`y~UM;=Aw1>RNpxpyQ+t%F=g7TK-)3Mqk^oEYA z`ejYb_jmcu%tN`>gvp=OK>^xCBpkO(a8q_;XZIS!yZBTTULFa&9gxbD<L7#ECf4D5|5+Scx6D46BnO_JlA!A_U4?WW40REA&N$PUjjlEMq zqLze?RVocD7_$>s(`{ttX!hyhq3g*3g>^o@c;JymzqzIU7?)g6A1=e08w)bObVlB) zkQ6(cbabbQhhG1E{qX`>^Z>V+3(Ot;Yg{_zM}qY>b8Wg(It>|$;Xj-?X&!pxB#u4M zoFqD3dEh^6X@>3ye@e;wV&^puj_(frj-l5%qo+bp=A&oHm({ehj`+t?m|jx1GuK39 zR?K7nhNz#zrCnP54!<<%FIyu@_Rx>-oDc2CDxN*l@qvI{%6)iY|Ar5(Hg1P$%UaKd zWpZQxef@nazF&6X=VIx+2&u!~^95r@p9LX7-uNf=y_o4#fyc4`4eknkY_Vfq)TAqC z!cN`V?~#7vBV;>kMTNJJ zFTAxkLZ0o=VQ(OdNy41nj&sn4rPO0}tE#45yncv}mOQ^Wv&fx9*zbIX9H_W`2O0Nx z{8hMFGt9;B-zUt0=sMc4k6s?lzmliF&fB3LvFC9kKDiWL!BIJZ40V`wR#f#&UMck( zdbcQi!)%I>PZqo7-OIW>X0uQJFIbdKx4F0f=1h3Tw0!6(yR$xA0YCYqwQl}j@%+Ph z?L>h!a6`KxM`7>v30%!PQF^_U7JZTv^S^Qaqg-z4aJf2jW)gcfh4{JP|5#(Z`d_as zeq4U@$b;6L6IKRWCDvuXvTs+&3ZJwT{X6qLT~EJ>nWM{D>+#x_yeQrYJ?194*HO=x?`j- zDEWusbFvj@dn1#yacxq#{EdywPc8l8>WB{+cnQgnwNzUfA-xykZ#^5n?-vJT1$*xz zsa>*XQ<#)MADo`~b}anf_KbD4yF^Lf$6hJSnyucTC>j5qj=i1RBL}R#;7Mc|mrm)i zvKI5loAC1|@MQ<0PlIpWEpw!_g6F7^<9&1;_?L6yGX6GWLz$cUnQhm@q{uui~2dXkCPU=VQ1j3KOZnn)GjlMIV@c@cM%F5g%Fh2;_b?l1*f;X8tI2NtcJZ zUh)h3?wh}VNNUQw@F4wc#?8o@u{C*E5PttGUGGoUhDn1mvBy(xzOH+9w^MI;9>^EB zQ)j2xo2=;^CM&TENcc+UHwn7UX)XNHn|)y15>aya8G1{2#BU=fsc+d8#ibr?%)h{X zC!@nqK-+R+{*V{fxkKC#Rwi15$ozbz+;_=OFNxx#eQ+O|$oT(k@-`2=0t6Agq zK=$awOG}nh0v-2N`ntkBeAMM)+)TWW{ZhSfsZ%dzy{-O2hjqpkflm#E>*>Pe-U8F+ z_A$;oaSL>!|^Dz3X_bsA^mPv8^us7{PytW?A@g zyuU8n+qM69-7LTkq%@p>_8uQ4)8*C6+JCEiJ1y?89j-%~&~#@0!2BPH%@o3`Q{rs&Q0D(qY{P7P z`d*lnYi!26?^t_OMUJB|6xnu$!RVW?DYcR70(NA`K{Hj1l-%&bcO$bt#yFAeGCXU- z&y2^}UpWGDq8VIV=D;SL_Zcg!eRU(``!y3YXYL3{rHN5;1U>&5hi+Rv`<@FMkm1xV zYttNSe6oPGKy5g;|J3qG9sC;fdWW+>qK%0q`kP-H55R`qEU%M0*_gy{rCX_^uqEMs-zD_fuFX|p4 zdmM7}JBi>qvUZACgTIr2X>Zrr@5Z&}2|Mmb%|p|wuAf4mXQL^y!MUYe@@pMkZnv75 z`0Oyw?|txa6n?~yyN&jj{PIOApFC+AhQ5UH&cRDK+?(<4Z)C+C+_D85viVK*Q|Uhq zttUIK|N5OczFX1-BIL^j9!a;)CkIDx?q#hADW6u)S>rZ^%M1M5PQ-p%N%*v zoa!|mmEZw@&~rzb?6fcU!s4i!a8#>JQW)Yf6?J9q{6pNGkl)UgL^_- zu5HO8?Qs9)yX{fVO0v#$I`T3gi?CbU$lB@B(17gfA2Wv5aYNUA+Zk^Z+CN}#uo)i$ z`1Wm)760fr&>O%xY2Vx}Ne80Wo9LJK%Oe{}<&grESNik;&IsnLs1$k(O}tXqL(RUg zqkH`^^bTCMBlMZ8LFvo>^yBqzxj#a`?;>OC#=-$vo!Yb^^CbGx(z^VvvQM)yI<>xb zgt50sTKw<66`Gee0W&{bfoJSQk}SH+ldjWOFYGgGlJUs-6^g?Zw(<0-xj(!v@^AQz zXW);WS-o zW`}z7x0^N2eK>6&KZolaZG36@)YQ|=$M}oDw$h1ViS+%5O^mN4yi$vO{9J78{tI?k z=g*}1HbQx_S z`njvvoGWC6b5xN1#|=xr^!j47k3S#4hd|ENvY<=c4vuQ+q^7R>He~M!Z!q6@-7ZuV zzgc_oXwkj?+hVjyzkUB@M_ra3{@`4@w<9GY5i$gH9=&tLtfQjCLi^5fN-`en)@3<&}=7VSm=313AxOiAQ|POrH%y zp8LO$X1gi-Vend~H8K6v`E0u*y3PD$>A+?nuU2@p4WGUBP1!o1!BkF4=QLw`p0W7s zM(=crJ!nJ{H^?K_ArNvRkURVZQ#!C+qt$NBaG8 z$F6h0az_mg<#9p=5s$n~2Sx0@^ML#nqwJBR?oa*=b`TE{>@YV+X93e9b zyX58|zxX6ln*V{_VI$LCRQM9)L7_5wl~Krh4p5dhA}wylv7TO8#<lHd7%lWEoge)mezTt_~Ku30i4t~f-`YI!{tj7N{4Q1E?S{?l%|SAHe{=`GKMHq{R}{{RpULI$ zu;U;Tju$C~8Aqo-MYnn`fd4?wcf1iH`?~A;y;mqg<~U^6r_gbJhaA7td#|JWzmGDD zbUMD=0avc8PVb2)tl65IGFO2o;M=JPoT!&^g0dMd_@~H?ZM=jJppYY@DKGW^8STzS zjrJ}Hdl!5Dyx2H5#a=H{gnWY@dxe9upu$EpG0$9W7?e5iyKCms}e_|59fRhY>3g>JCS~@`TxMOUAf;;w~IoILpCO{mTwVF zpK0IwuivBL!=0q;zr^OF_?(z+FKZgkmP*4O68`Z)OJ<_tK4&RPhaqP^@gBAhvvm0c z`D*6aEBG(yIyinG8#{Ds@r#B_VdjH+>%69Zw;kn`Jom7TeqXm|`~LM-_Ag|6_}5&+y0yv%zl3jeOL_LJ zrKywh={=GPZv7p&!fP@G6{8yJPmvE7eTAuOD=Lj9tQB{hWR#|5uzr{{g(RJ-Yq(MqZ?lWJplzVI%aU2BUe^Fq^-;*?3pR3Ca`)@>uBXnV>$6Xnl|=(>VE$g>QiIaY0m$GL!)qvIllsX#dfpkuT@O`huqR*LX)Ms z?moY+|L^OFtu;DSg+xbLuafqiw5coT;2I;xNq;v|-b0?9Vg=^|{bF$$r zBiU0p)~Tm^o4)WI9<_~xmMz&`hiuipm;5`{@$lnpB>mJY*Bv^cTv6B<;eYr+V%q;T zUA7s}kNIii3VH6BaoUa}AG&&lmB)1b*PjuP5g(Yg&=2|JXvXjl>V!*@`Pj4vSsV4` zjJo$YJNI|?IK7dXj0;G~zugk|tRGu-Q>Xip`@XWcR_YzYkf-!yKHQOl^PXBqN?z6j z`4VGG&pt069N(d=8HW5CkO%n3{WoMpS9s0AWnIG@sqob?&T1`*t=<=Ysn$i8)8^{o zlBS7{Eh~L0YfgPVQ7Nzd-bVlag!_LaG4-KBH?!u|?&u9_-DjOw%amP>*;af_IlG`< z%=Lo4Yd%lHxpZO-=bF|*?&!qJjk>M%q)fUT*LTMK&mizVXTXfUBKoeZ?2b-$bjC2im7xtkFIRS)Uf6{?KQCvdyQ0~Oou$e9z8aEmqM4tH|&d@$el!| z_d*`}PIFThXI6S-%mFWF_UbZlqYF5gRF~Q3>@QvezXVy?TYZjfp~*#WbQdUidPj_pG|N{iGIkMzc+2B05;`)lbQFa`21M{QWzac)p?=iu3rYvVHn(< zF}mFMq33Ng_sw;$o;kZh*Jqpl^ye?b<@dol-e&9-u6@k>Fk3%=3V&erXX7uyvQ15g zkDu7!{=p{&<5C6_V!yARxsN~mlbu-iK8(G6s4!WdM9KHd-5Z{T*U8(6PbFOx%3<4WB2E9Zfq?3+^}e4)5oJ@*1_IuUg?Fe=%-^Nr4Krz zvlHDi=OBEuYP!tI-`DN!jHNelrsKc<_Qf~v?X%f0kKi0+An%1<=zi3FtL`Jt_zD$6 z_P5+TXWtv$GD^~>(a*hLol>+*Xqzduka-U|NR=O0OTqDJj~?+jXD>KWq;l+i#SW8- zb-9hiaCH=p1wAq+Ew<+OeX{Q#eQn@&J5=a*zT>7IGriJv=dTl*$NImTG(C0s+prieJig2}lX{i#9HtFy;4kE6&wNtJ0DI1HU%e;0bD~i9veniaLY2r-y{v(^5_@%hsd|4 zQ6|-=;a9(ePrkn%E_ZGsS3zh0MHc$g8vF*VGW9i$b%+zCXN3N@?+qRhE;E?FY>d1J z_xyKLF81}igLL@}XI=bOZu=_w^b{T$H%Ny+KLxvvz2-fi%ro&Wox~b+uWn;$-}6cL z0oZmRPp!*)Er~NC`J512U#j_*3fPlSXCHt8muB=#^1Y(%SE+XB7sd(REm3gy|dl zPUvUS)B1ki0J5Y7Udiv^M`vUm^J}be-5$v0x!P24(Iyb%p>-b2|w{lMfR!j-oOW#{(j7{<}38oP83gU>L?t3niB)q)4mDm zkoz7zi_go-CSCQIw_2mix!KS!2cHKd-9wROmQLe!Jk5eK4xONlB)b`F&Uxgga@ddk zz}}~#PFoZ*E`<@RLeu*CqTl4{twOJ_{NKmEm7!(a2>oArxFiZ?_v$!zWe***)x8^0 z_*OX_lnUL0(rlzoU*rpq%&g5Ba4Ey(AUvNAMFY|y$}7XM%Lp_u{UHKhp*D_QfZqVG z$HwEvCa?CjY_+g+B+fS>t;KiQNckz0`w$)rq3gy6S3=*F zOg81&EukJ`O6JFAs)|Q0C-ljW-{RA+j*0hoYg=$Nk_O zK5Q+Sf{Jepe4Xgn1RvpM7U~(9Ky-BaC0x!?&X4eIv!C_m%{h_M1z%X3(NTSy)hCC( zbIG3>gHjouZFIDsX4=_lOICf0HT`E-CS>uGIZI9l~Tk{M#in(G!OSr0*}L4i+Nw{n2gu*vD%F zvZNSXk88T@ei`nTBCGH_OnFUzfbBj$T`I%Z&j7#a(erQ#uwK5>nmHJGMjhs#Nj2a% zh$)W~7LTHMq)X;}h`$!>+Dqd@@9)LB-U@Oi$NE2FmbFTEI@a2g*LY;ux4PVq3Vwd- z2c=Xmm!u?}awqQYOFz?oj@I4A3|TV`*Ci;7%rJ9c524{#RDaOUBXZs}1F`|*qV zxn@d`X(9D0`xn0I9-Hz|SD&JnulbEB+qWz^<~ei|Z$fw^>yV{7{xijqI7~(sa!F-)Ou2_d$$}re^7A=$#vuN`9cgjK5!>%nJMddl z4c%%uwztSpYdr|5f;vkVV#Mpd<&e);r6m%NAU?*28-Ge{97f8xW$jh-z# zGRlAE1f?!~k_E%;x9jhE*d}$bd^g&6F2i~Ew}D&zolh#xU<|vC|IhTC^_VLlYiox| zyFc)ChAd{zF#HBGemom!@)69S^Y;h1%zqh(^ zZv0vL8TKm+&zo`3ex}ka_%6euq}TE6^smM)orhaT zLetv>d0dM&oPX8UT=x&*OttsDQV)KOLc4z9QWSq@3jYiW9i!?k3r$1MD<<88*$2Ns zcdjt83HGw^z2bL5&UiO8->(Dku>;wg6I?8nz%k``X{ zHMrN|8BLz_ozTxF$V6=~jn6aLHTNUL*nBtxV{7E78B4I7uIHqMfA|y7`t* zs-P!6^KqmE=7m1v3~&FwxGW%D@QbZ5c{%599*B^~%)yC}pN?LQto%cK!@Px_71>G= zxJpUy>#{w;T%pkMa%kB%iZ;Kz4#daG#=6dY`20D8+;9#2qeew_9c*i&+gp`hx~x{+ z(qaE(Eta#3j=zh~yyvrGe({&|Nf`3iBN<%s48M^D*<0R1rup{_xEHtmQYQ)erW358 z(GhKNtO-?m+8*^vI!kwAr_cV*YWWAO3{O&O5dr^6+AmMH1@A|OL5MKBix z3LR{@dfx22`B3}PuYwQ zFzhg#7Ay?cl>DX-%^~G35pXDS|{q6u5aMW)={R+OO2Aby{R_82=#sT?}x=^TFPUrF2&ItK?qDwNO zt2uWyw9J0F8Z&)!pX#|NTQAecN7rPGZxtH$HaazhjCI3gGVQ=dGwiBgJTdE%vLz!W zOKz`}9Bq3BBq63-bSlZiunjM#iQ(pP#`MZBxdylgoKH z2h7s7sjyvBBil^il_JRHH?8){A8==moi=0U&nr!wD*R43l?sROx2bT3dF~bKjs?vF za%#9Pix+FDgGrpZfS&karYI?P$|F(Cg^kc(Ax;dzSY-9}Sog+*%QgI8@_YlnPsVg6 zA9f@wx|_5XFQU_A-+R+{hbejvUhoC$hDSb`kN$L)n>pOF5w@QTvL3F0{=1Ew5hZ))98HO`8yl>I4AltAKEyHzPl?rb0_KrP5W_P zPw_7@lFsO0`hLZ^M44RT;XI5V=+DFBnRpwvh?KF&*B8xT%?gj=>9^tXNe1?<2}1L| zfjFXLAbO$NKgPUnhbue@pEKyxqN7$G_%v^`{*Og(7iT8xi-Y=!T|FZvacPte0uVjdKy{~!rL%gcpw8Ey@MfJT z8xfEq$O$~|ukTii3_`ib9lSzhPN1cg5N%susgFdVBf8#tHe zg^n|Q3v8h`!7Hm4kg0LaSf2T+&dWB+IX2Y35GM02UHtd(*A=F*CMfWhM`o+1U(#=7X}o6RSO z;pCKLjNhI$DBoAcw<`K(g}W=Tul~#@pJ5~RBp$v69b>(^e+xd(==IdY;RuO?%}B#< z&?^u0N~aPr-=o4iak+_Gu8-%upD{kU4Tsf<9C37;d^@K{lHyxlAyEK+&Ux%4@I}!D z*Y?^S|rlm&Nqi3jMvZuU+UE{UPmMp+qaM?5`1&)KMmHsW{^+-aZ|^d!>LZhPRuE zb$O+neo2E(T6CGaZN8Ru*;Vwi)voBY6=p7UV)9n~p8fNJQl56}MdqKX2YyM0g~=Yqu2XRWa+fvJ zO6H_7v8)~KxcsC|;cz`&*R7DrChub3HQ#;VrIncNmafTkJso$n&y3S`8qZkrn>_H9 zY~*OmIp1%ax=i4hdxlUR`7POm9p3r9;FXDI$u~NV0x9*o{<8K3&hUdun14yF@R#b~ z8}n0LR)^7HY>UNbk$P&)9(3eBm%M!eo+&tu{B1wC{;=uO_BFBgX!idzn@pbH+TfMXSGZ-q#jmo%#p8xa>Z6>sX0@-w$vA(ZUTC_S!F8{;oi#f0i8E8_r`X^)k>y@c zX7)7g=hRwL?>DPO$n0)m@+tN%wcmkLR@;=t!-xpU*dR<=!H*f2);#|c=WnKpughr> zJmze!*vsFU2K#p#e5Ke(xl8vQ`~Qc`SsyT-?s!|r_s>829pw(2Iyp2Qe<~RR^7ATu z7g{nl`+4Vg{XrhtY3<>bAlFGv8%xT*+D6eb$n@X!NEPgi9%R+&STZ*#aj&p0_2c90 z0(HrrbDPEGw4bYl?)-CWfA^LpOMl+Y{KM0@hDL9|zk{(<3p-+qrr}tqmM*iZn4lm9+Rbk_i(6BktE1lhL#yLBl6xs37 z+Q26p|6=Ze8}qIu`%5`HC=V*)&jb6HUKQ=o>~XMHabi944ktQKj+8H=z1w-;`Flh% z_?&8oqp~qPyJ_RgM(B3g z%9?NPTXsFCyqw?BQr~OX!GyQtIP)Fnm?M{PV&r+###^IjNK%pYJ$@d`uxGaMPZhU> z9pikY-eHoL_1$P|4Q1a~-+Nm+|8efXLVW8Ymu%pWF>iwVdJwyVh~xMaZ=8YYwM9IHKXKM4Q$$4!+T)9-S}L`Z^toUzKP$y7X90WTukAoC82H6 z8E*BAplq~wdLI=xX&g6Izb_ISx;Md>!6U0$>v3lC2;FwBV_&841Roinz@6$jK2kD` zg4dBVLjHK4bNq&w*lNIqP}nnBzvIj)ugpV_q42yJcEKl1-*|nIk3R7IwqQe>@V7|W zgAMRBWUM2{W3P_Q$*?nC$^K{PxMn{$rM(%?>}%?Ka02}AEx_;mUSH|4kx_VwTsAr`{{t8C z4-=QVf7++RjfO|@CM+Jr*@et)3WaBK4!SQi4t4z&d|eyy@fA05m-)ZtNrdbw4BsMg zxa3$DAs^!-zV2eyfL2|r=i=7k9Gx<5sdB@PCGiILH!f( zf~uK3)`-Q2S-rT(rE-VKTI51Da{XoM)xP!x9AX=b$^<1RT+yfOlQ%FXy<$&Nhqc{- zED@ajjX!6L+0D|`MlDSwSK3bVFKM(ej2T=8vHd> z=WWygxZdSGa=nGgYjI>{(Q*G9pESRs!(?Z!aAIUalRxM6vW_;QuD3numefVUrF&54 zsVBVZ?!`#aUR|Z{QJa{7tzo0Wv$bfwE-UD4vm!Aft zW4%b3@R-6fa+t0@FroC3cjvzMdn`YvQ z?S8S=aIpuP{*?^wnZoJE_{I5?b5zR*rREybb_&y{6_y>+<@r%8(GNzZY$G=|SAEd+ zOhwn4>lgE$^(F90wijL8TcKrFgSE86vpF%xNITB>tWQgiGGl(4xyY<6yJ8h)ByG6; z3HI!tn=tD7Psq!UA}?vvPn|2~mR4i1okcc1jJ4=p{1vsrFQyZVrr>`RZsM)XekuF= zo6|GP;#+q9(d1jjb0QVK7A&2=9dGIC0T~_#S?ul5_V6qI*VfYB#@!If{=3qdg-aN6 z>ARGl6X`1;N9=FXQiZaOj__!6QO-nWyy?3*w7i3_be#-`hvD0)!!0Uo@=>=CzB|x| zwZzAzg z6;i|RQrLh_x#sr~GMBP+qIWWUmbb=#>;v=+>{k`GqnXcJ-eu zE-7~$|5%OjA3DG-GaBi>R1_X*TX;GO9pQ=CIKCBs#PBP6)eTC~-_c97b#aDAnDnxE zj5kNQBu^cD3RjPiFv>hOTpMiKwYvWpeQ1*j*t~yW!jCEylo}pnv3R|1 zx1BDV_F><a;(r?~{__!evP$KIle7O65si+`rmhvDIfJ;VL}ehMlK%O_xoX&{>KHcELyJX z`cGsn8@gd%M0-od+O};XWQxdgoX7^>>*7j}v|?>D8NSJ!Zb1n!H?cTL;MdshEmSi#JZNB_d- z)Fk>Dx``j)pjJq#@AaVG+a@<-@%f%Q|Jf6SmRAa7vC-i!>5_5y%&E>?zYg1l|Ao7Z zOA1ws#>{VC$2eH#Ug*1{$J;@en=0xs58yf2sGKM$y$3Nrj>3O)sz}*)$1N!jQ+`X$ z*!9g+{LPfMp9uY4Yw3u?kh>H_Z?m2?NOJboyR5dKH-#zB{c}R|;InKK^UgNyaE^n+ zx4JiTUVdH9m1p6zJT7xMzVK;rd8KeEgtCkt_w%4Yq(_bwy1d0(d9MS zF@JY&tIH@cI>h|&$09G2mQA`JY#fh%_eVX(l(#socDi5E7WSdvT6|E49X>(l=@xzQ zaZ|4(f(KK;nk!Nkh>&sUh~I>dUWMLykx_?Db5_^+D(s))vDPh8-X%ph>TCPgn7TMx z!!1QS;0x(1uf$&;l)C|!^m`Y(TX>2i`(THUtyrIYj6?e(r2=iQ=q#P*dhl4DT60Zk z3iQ8oGdb_pl4GeWossD^f&V%$wa)Ws_zi>VntE1Yo}WiPK41OP=!c%|kH`4puBOXz zu%%P-B4e$KF789P?f)0=w=nTL%2j-5 zLdmTi2)-`jax^l5-k1HuKIVmztYs2mcl+q8fDDA|vM;eu zim(o^$U45}?tol^7jXiAtyAlm{;c9TgFehgyfSdMk+D{?_&xcM0oI`jRAN0=yH%77 z93GTZ1(+i<=x6q^K5*j8&rSJ$j(*mObjfrb7Rl|E4$I6uqQZFC*W0*=jp4Wf*v?$= zNl|=rDqJ3{%Wo(BRpDZojw}8?^ZrxCLgP%d*DGB)BRCspGncMn%Kvo)j*s>G&AZiQ z_b;L8euccZF|y@*tcw-CKBdR4`oHV6^o4UhkEt_+}&X3;o`o z6bA*r2Gje)FaH}~bF6v)Sb_hPy^(S?6Z?Xbk#Y=~_V*XC6=S`bcVmQnkKF$~)`we~ z<74lfPrS|WTSVWjxhGr>v-U`|$0Mf(dF4AF>j&(Wr;Z779!F3%RP@S9cy}$5z#A`( zyx@|~TboV+IkYx(tuXV3{y)aDu~g~4@U^b%V(4C);uAW1SN!&~&nk`&KpQvK!aHKk zqcEMds}nid=L~@df$3uis&4j4L-shUj(TJ{-07ydBP9de@?t5%#rM5iZliyU4L@0P z{3qyOoGAR8uJ;_(ba}5sCs@3r8~uwebHo2Doh4!Mhkr4 zk{=%9%YZe26YqS85780&+MSW1?WD(Co#wpkPcwxV9F!FaBJMWpg-Z-9f(y$9@p3A)74%hDMD9N`eLIz$A z$g2NSo?u{vC(w^@_GmbPwKUVz& zV^${mP95x>w}y-7XP>`oFR!_fsK(JOt>0{^zSZ~?TsBK>6a$VI(!B8 zNyZsDaMKHP#a=v&{UYhEN?Z7azP#sSkpSaxe{8p6LozYt;=DhR^^FIv*G3Qg?~3@L zL0@nmZe8Gnd3QH_MqE43dW7z<6S;O)%Vzta)oxXMV;y^{{v}L4)xGkT{`g7hm}#i_ zfHP7UA7jHB)+qhpj*MpQ#i>Gj*ppEJFZjoqjiPM*mxm{PT%eN*rNRuA%C&I@Q43<+aLC;TLzES zNb%4zn2#)LZar-4Hkh$u;u`jv z$V^T+?7LO$H_GXGX-fW>ZNOhUG~R*i3sWM;i@yn*$y7dx`@$th>gzCrDwsU)UK%0m zzUOSvbhKIYR8Fi<7@BA2J@tD^K67Q_8C?%8EgjZu&dYHk3Gz{egb#JvCnNLto4Il` z^8L?WisXIn3@ws5TZC-xYuakxbS~Kjk1aRy_Mfm}`(q1jFRgxO3Umhx2Ki;uZq6%X z-d%;>BFSODtU~A3l>Oo9i|~Guxn!2;{Iniu-ZiRFQ08Exumo;tf4E>JTI({-_ns*u z6I%ajzbo>PFI#lc>HEQw-#YI*f6tn!%jV%D9bf#9O#4#d8uUj; z`Kd^4OD41E6#hbx#n{Nt*m~oK(02C8Bd=8c7@Gj*YA25FHsJkdOY=K*qI{di2O{CEl-DY)?*>_4i)D_ z&gQ9D%CryrJu5Q1q;Rb$x%aVKeApIuhNFHo59eo|^vZn3k;7 zrFNS!&5l=n4=HHM@S}M;JtK4Di~4)|+P5D0Zaco%N8w*G5wa79-pGz){X9J$uYr?z zCo5bD?C@+HL$9{c9U-YU$4r|YMtx6dA6gDq&gnXv_kHYXc0OzWKKhTTXLao_ctk&Z z9hCRrduGfbQiSrVk9B=YwTBUFX@t)7~S{cg#2 z_@VeMOlHCz|2Hher-_0)i(6804nalQVYBhrHed2cIpS&9jC~w?B8Ax{f|4LklvGE* zG6NamROBrgkHE=8ZoZp5C;L5IMr?vBvi5awSz6kptynaUt`5OoevbS(ty7+>CanO^V=v8i`=}@BE|&dP+8Db zt+d8B75>9kI&Ss5mQS~_^yukRcf~hTf4AI3k2$)w38TU(e9@n^w1fXX!>7lS=UqH9 zuwR%|S`m;lUj`(AY`Z_}=hL;_vSKT~*x*K2{}Vpj6Q4A@5iVO-<2!a%xKy2wy#hMk zMODHj;;OELotw;izuj%hSEs;yE=lH>nyayeSk3;snYsRNzY};>><9Q4fjG;v)huH+`v99e}{1SU{RD5ZjT+r`$4HT*0e7> zUp3xg&Yxr2jk?~cdCWZdu@kBM2whoIJs*C~`oKn`JNO3t3g1!Gc}4iWHWu}y4ec}G zHX)}P?Dk4H?Zd{-^x<-fbxLoz!3ytuspB8Wx-!q!SkjRme?oBOr%p%DH6=n4WY%df zcprT!^00!;@nf*haANv0U3T?Yui8j((f%d!@enhfug!q$YnvW(PW=^-V~hvO|3Wrg z(v!E#~z?tP5va=X0tUEA;0q)GOHFQBTX?G4D{n{@^`M++c6nZJtlI=JHF428_Xp zIFp(+^YWFtP8z{;Qg~(A5ICPzzmxlQT|2K|#XpTgvUK{}{=C6>dxkb|V-I@*CrUQq zTu931N^ieBzr}dYnrdecGhQ_2e5#q9O#TDxvz=(!NvCz;b&sSv>XY2?LtgntV?>jqza}g>ck46?_Js7<;>RaCisgcgZik!{s~jykMGFQZcccr@Nv|oG6l)Lk}WqHl@_wEMqyN12;AU*a^WIf!3{+ATniT{fC zk)g*~<(9&YDMQ-g(uV<=T{=8s{H*ucgHCYpEmgdI(4nOI!lYSUJKvr?*;0Jn zBbQf5GQs4xB68o&R$C5YXR7c$`o?M1{NmlN|3@K>z`UCO?9&adGzpEa(+ z1MF}W60Ou}xes^Hi3-?rT(tZvIIq9ycbSIpAs=9ywUu=`_HIYvz_vyY|L_SuQCXKO zT-xZD2NR+s%aKUAh>iIFU(~9h+tA+90eOU-$D5GNvRNBe0Xye1@VAC}WnnE7x-{}U zh0fzmpE)qp)J3Dp;WA->UyiZIZTg1^W5>{8Y-pKH#1Hq1xA6bbGECyM2+B+Jsbj45 ziF&56wT8*e*$mN<0lie5HJs5mHA3#ehySTH{3iBrlg^oUB+SRybDVi)Ew)2P;4PH$ z$lvfO-h|C>kQHx47WpZBcpHyM^P5l--#_uJedxsYrroOWW7wD)5stsNKGr%Zg1w|d0`|r!(Z}>*t?(ushBtC%uuj{1v_*y1i$d2}_OpjB&|a|t zJxRZf6=RSE&NA(`AbUI~swUO_rqQSR`A67V72FajMY?kqL4P=Qz2PmN#)rrZ6Nh?! z1H6Jm$f;Aq{mEG#8Tzw;yhA!J)#rRlWX}qD9^uDn6P(0??2Bhc$U@@m^+BX0Y6CZV z2fUqA9$8&hm&?~peKIUNehW@=)`(?8)Pc6O7@13J*0ZxL4#!*A{CUxXPDUP8x?rT# zTIZ79_+2Q5e049J`}k}8@^cHHyeQ1siyb`DpSJv9Kxo?Y9EPvYnxO^yq9fyxQ>_V; z@6qcfEg_O(k4xU6-DH^-luhY9^2@tk@q82|NxYnu7mM8Vbw>Zg$Bk^dK1=T4thybM z(lDRS_lI!N6uw@e$BPrzx~}qkecz6{_+FPhPpSJ~4#H0U0~;2{oNI?WzBjaf?d#FM zZ^3oR*T5_9pX9u4WCrEn=_SnJmOMU>WJ0%h4^Crq>@1eOqKy0DXK8Y18LIeh-isb9 zK1lNWWrroJh<-QU{Gb#dDrVObbg zM#bLeR9r8%;9risIB_1Hi4PlDC-x=bT!+^96@W|lOBMEzaGcILcni+3Ve@_R5ggk7 z)?AcvqF-iPVe4YgG7Xe3aGGZqFl90=s#pb`-9J8KPkrZ1S5HGSWCl(+lw()egODZADt<})v zFU6sNe0vMoaTl+QA?!K)=RMeu4g6NWoZZA3jQHKM@h*B)8`bW@X@*OX;RJ0h^}oodNbPrY(W*;2Ypj$||KD0;l= z|4WOzU#PQ=XHhgi3mf6l<{zZvss#V?>q0tQUhK~ms^j0RPbr<|y~TAtQdff4k~L=A zo`h~}_u2@_o1OhJHpOcXBHKKn%kNOK*U^Q1oEWO?ez8&C=#fsWZ4`EF*Wu?3j#*9# zN|3%Prv5@A`;UL_!&i5r;RF4irf2p0*DTX*;ViauPW*h){CD9$y~ejXTw^$?PLwYX zAAq`4sDhkjUvm7-!PDxDy!*jE{1al6-W>l;%UK(zhqF`lTemD=zw+)mp2^M}fX~Tu z^pQ6E-O?7W(a&|^$6_ybv#(E*y^NIE?Azxo49XhHC&An(&c+QbkCg4BBzgAGYy0!T z+28C;rT$&rl7XCV0?%Qr&i{zq9;urO8+m+!ow0aG(Vu*A7+D_ad=u``=5Ej*^CvfL zB<^C5jNB3WM1{mrl5imU(t@T8SB>{bX1K{~9Bbq3mfUc8X)})7F>R&Yd=$a?nify9 z9Gr`ta1C?PrWBqdTT!UN8YU|`i1HPYTPz8aF6ftTcW}#>MNJx0j4=Il>aV5@wPeXv(nAcI!uT^61g@}&glLfggSjAnfm*zr23oPX?>(+@ndl6Cusrx~ZK;?pyi z9(QyI{dox4!z|{Xhm&<)PmE(_|zl!GvAP zTy5ig=|~v}Z=>^1_(aIXSp%)G@rUbrbUFO()oy|MBYCYcQ9ZM}pBV@2II5wuRQRB- zeZ_q5vbZP7Jf@wUV{TGtWa-gNXwHnS?vm4RH-`?;;m=%U?Z3sO*BLf_eb$E2WT%1m zbzM5c?LUvtZN?CVZ5DrFKep^P8sazpc@?i5hx_QnMoZ2W$Kup}*DCaWyKdNjJ`0m8 z==W?CjV4Q<=+KjP8>st7OLRZa!h-Tn0n=a9^M8KFStmWBBn|ub$E^Dl>cQEIj%J_w zq^u=Zox{94DX8PgblKGV9`-+e^uXOS!yOr?um3i~E3KM(rRTlS_ePKZP5=AQ9~My` zPFz21>gF2bxI)S1I>g?l`aPG!qhtkKF&n9($q9Ev^H1Lpx$FaE>n(=+WyN~8JP-59 z;GrgO%RkY5%-bMB>RI;i&Czw$3fJ}X$EMixSBdpS_mZr8W7*HBw9UBZl3Xd=;zj<} zziaGqsBmrK={}u={aV{}Cfu~!ZaEUky#J5s^D4ZJ=cR)3Sz%octMPfYnYGd~)R`C&lkovEDs)Uy@f|`plWw$mcf3QK3GI-zs4(@dy?v!o zCOsDh;_rvCC!xcBYB&1}ClcZJ%|;~L_&B%pd-i^9>ORk9{FC%!y;&d}S)Co4`Q~%4 z6q;cA*57}4q{9H6{zv4=#z}aiestvRin*lOZe6zz9dckhocdnV+B~QJ=Z;4`li!Q1 zqbs*GWzabZGM}0FTV{XaL;{CC|H@}N{IrGGReXk@c{rx4kr#G@i#G_q>(5CdlXQ5Bp(L|@~ctKMxcKFll{1RuK$Y}ERBBMuc(f5L!jq<Odj-BsV(9c|7`wcdzQTl)T zcOvE1a-F9UtaUtnk$u1mRCo*BVD=A#(wMcw;4=7|O#JWZzWH3YpHe&B@*tb8%jD>1 zD#K}VA2Ve$%UZiOErP5UImdUa;F4HtnrZ0d>se#;3S==h;ttopa@N;%>iPvAZl8q9 zmsincAWItX7H0_T;JoF2I*r9LnQ_97!}C&?gL6h*;A&Y&nJ z#0=(u7(f95i2@?R`yJ8icm2Hgy{flUb?ZG()sH_jJJY96PoFS7r@PPoetmJPu@i!2 zZ`AdnY;Jlj?EaDN1+T5^(;+v7mi^0h+Kd}-4i%~KXWj4K&-Hz~|2{wenztpn9jpER z`^S>Sc_3Kw_+7Nl;{X0LXx;z6Ur()j|MUCTxAyyP)jvO*e$}s)%S89tU7mie9=!j^ zpZnd>amFxoPi8`f|9(9|euKkvd-tE$T^BsMw%qZAz8U@h+%IQp%l_*U@t5nFlgjUp zWsW{ke=KXRqz^5xbFG}$@A~sKfBgM`eokj6WePpKTc26?Lj3FUi+h)XC6{x|-z~Mb z>0A7Yd*&|Q5Gvi=@yxv*?`lWg`9}Isf;PG_dyL)ccfr<8{;WrTO(%n~adOM=DEF&8 zyXns|{_E?4$IbPZYUfy(@%QaXci4R|m;SwM{&;WF1#@D|`uDsS(;oWAQlP+fp)=Yp zwrlHb;G7dI=e7H+J$NnM1KP1xU--}Y>U8cuZ_jzxHh(N{8B-!yTD<(f|Lh03PojeJ za#rm-TYukog7;S0WV{IXu#By4ET|H}Gwy3KZcDdk|IBw4ZIX?&7Y54?zZV5dy?*XN z?3O+>u3yH`!S;V%i}#w5CUl#&l3QE>C;Yh|1h2i65HL)r$4Q`vF)uxH@()qd2~6W3dBdmMJEf9z00RWB=wC>iHYx%aP4tiLe!wx=)XRW zOo)q%h>wbmiT~q$F){JUDN)gVeorQ1(9j^!xQN7S$wb8@MMtJ2Bn=x9krLVOUz08$ zS*u%ALgb*h==hZ60un8d9GxNqeUrOI#P^MkjqSE?%-(f-*YAB{-{ig9_HHk*Z|uHt zdtcc5T(^|y9ROo;Cj z)3;ozr~G?f!jo`xpRlAGpOX5?My3o)j86SzRkqle-eE{LF*-6iB`K);sh@c72>VrX zRO%;ew@ryi85D*rCnonxjEEdiCH3>1n2;Ex9EOCiWw}z=Qm&EuDPOB{sh@7J^M#>S zIJgCMIrZ}^;la^Ksh@6eZb}NzQ9e2;DIp9wj_TbvA~7cQOJYEuLGh7cs1k9>eFqMT z9u%HB5g!|d90zCUu+`$eQDOM(em@vjO#ND+ECwZqW5WVV6$s z=YlsZyIw+UbQn%b3BCJ=rxqtAMyCF!Cef(KFdQVVrJER*496#jVPBTv_!Q@k)X#DB z(8$CvT*%9CMDnos@YIR;s4x^nP{heGVW<;B!gN_RD1JcvkoeTE5e^YCQL(9?Ze-s< zF=6;N<2V^HC?z5F^P3P6mST|Ku%sIk7lzZOrk{u~>}$TjBuDfK!-3tEdrTOrLd3AX zzn$n)zmhrPgyrfXxnHdPIQ8?Jn3UWv45y2rc``C3DGWy)1reU(j&caw*X7{qIt+Vr zP|8uUf4vHhuGMXDa-|9tYIGYMsfn{&L`rO2pFi6^qoN1LL`Ek?Cnv-XN{LB`j~Eh> z^w&N2uSxtzyJ>8SHq)fPR+#_l<;f9$tpNYkDHW!X^2-5HSH;vl=_az*p96vbN zPZIv-$||+e57U9e$xqD-Ux9}^@#M(AxztFVGVj|bDb6?bzqz_kt@JDZ&82N>r5!Qo zZ?9@nEBW3I@!_jAy<<`wjl!3Hq(fd(MEKGlJT!c1|J_MGwLaA(#qzgp&8fG7Fz>KE zubsSl#zckjEHZd#ShwO@?F{QGqGBTcdP$cmztCSh%SOc{Cq~9aMMb29aUY8c<31Lh z7{-H7pRgV}`-ZVt`VI~A;UT8d-!%TE*0Cq1QWy^jG4Uy3Ecm3jgunZNBh^YKIgHia zu^`N~rvK2W=rGos{zIexu1z|%3O_C;J|-^0x2!OJ261t2V+vyt#fA41_$~QmP16OzMv z7WnP!XiR);>fc&PXsQ6+RtPnj~}V!eLcyB=DjyUti~f}!M_ib({WX>KZf z?f;i0c$>$kyc#K%Ol&(NxLEBYN zJSd%#qR}5ho(e`{2?ZT@D(i(N$Lx}jmt?VyLTM*vmTnDkoWi|VtRP>q9%`a+ z6lv&P6kX^W`I4p3JG!(-iKlJPWU-)f8YEV-@j-8;$GtDumbUU;Ifz!?Pu!BlP*~!u zvZ2sSQMN*gI#ka}?i0&!f|$#j?i9BurxOvFX<-$Q)Odg_QLZ!qM7*iYs=iTi!-4aFq&w~#pB&SO=f&GH!` z)>9Zm#o6*3FRrn^4&v=9!(HM=<9iN$DQVvom&h<77Pp*O9kt|-~x>P#^5rXmitlF2FJK;Nt|C-bb#e{WUaR-J=S&{@TU_e@ z!E0W%YZN);5{W! z-3)*dnxq=mb%;9RV+#i7{ocpF+w-l|`ODJE)I1b=-rqmGa9wD&b)@a%G&4$ueqY+D zp1~62V~_e8t2*4Jz8|;UWl9^N+r~FY>yV(DO;FX3dtpQCoU}|el>c2`ze<|HdNW8i z7_2xrd}QKV?+XTxDI#9B?x6a=>Ag$6=8!!7-Lj{l{P%JSvEE&z3AVvHep@7(c*Z)C ze}62rQ-@6|{y$$Ybb5On4W1iC}=MS1>qX$fWNf1IUG5XAf`iCU0Tzr_ejR%X{o)AMaye zxX_1u#K#1KY?){;^ckO{GjM1>Uvhx2_?mApa7E}KhcLiU=z9(m3`$}kv(OJ5<2Wby zk&~R_G-o(V&|%sDnjwQvhAwcCpSi>@1Ouo2ih&J7zYPfD@OvHCa|3BGU_dA>21p5| zBRv_&NG5_w%S?5?BpPr_$C(yk_z2MZf++JdC5n9OfDKKKtT#om?9J< z7<8mKB`8TLf`P*h{Y`7A(rwmkFbnK zd5q;e&J(O)B~S7cPxB1VvWnHLVJ+)e&jvQKiOp!V%Px*|``GWm?$pOCNYrf%I4swX^_@2WY z;V3_FjN_c(M^18z)12Wf=lF^9T;L)#VAe*N>Yl_l%Xu;C{G0{ zQi;k`p(@p=P7P{Oi#w@J9q!_8>Qaw;s80j#r6G-IOcU;-Da~k33tG~O*0dq`>eG() zbf6=h=u8*7(v9x)peMbEpf{035ltWZ(vKMWGk{p)h$n$W29iWFDGXvTLm0|1hBJbZ z+|MXRGlsE@V>}a>$Rs8+g$J0*G^R6ynapA~bC}D6%ws+aSjZw4vxJ9O%ELUuG9KkI zmh(7Iu!5C5$x}SdGd#;GR>%|j_29Q3%tlKUgBk5;ZOjhHp8@A->~#4s(Q~ z{J=4ebAlf^$tg~AhO?aGC(d($i~P(be&I5|a)qk|-&L>UdTt;M!B_0G+(bIklYxw6 z;$||Fg{)-b7P6CroaEwGZX-9hlZU+IBR_XgfPxgFFhwXzF^W@yl9Zw}WhhHI%2R=g zRH8Cfs7f`eQ-hk+;!bK)hr76&gT4+Q;yb?QFh@Ab4;WRILkSH;yf3) z$j@Bj7cTQFSGY>h&U78ua|3C(k+j@II?|JYjAY_wGLwa@WaAdHlY^Y(;#O`WH@B0A zyyPQ4K{H4J3Q~x|6rm`^C{77VQi{@)p)BPnPX#JciON)=D%Ge?4Qf)0JE=__?&5Ch zQjdG6PXq3yA&qEE6Yira&1g;wTGEQvw4p8SXio<^(uvM=p)1|!P7iw0iwJrXNfgoa zp)dW2p+5tNC60I!NMs;MB$L7*1~Y`A3}ZMW2%4DgXB49u!&t^Ko(W835|f$2159Na z)0x3cW-*&N%;iDmF`or2WD$#5!b2?OVIE-_kMbDHd7LL$!AhRwDW2vTo@EuQS;Jb^ zv7QZVWD}d&!dAAiogLil`&wqQkd@0trU*qT zMsZ3|l2VkW3}q=tc`8tmN>ru_RjEdGYEY9}+(~Wfa2Iz|mwMboeHw5t4QWJUns6UY zX-3eD+=7<0qBU)3OFP=rfsS;dGhOIPH@eeS*6%n^?A1IIYd34Y`xr#Q_S&T@{QIL`$x@-vtCh0FZP6|NGrr(VbP z+&~&`BrUv0eDX~4ZSq!Ep2!hJNQ8O>=yOIp#IHngQ3?dd>A zI?C9jzvzW~s=JFu(n9l+hvWUej;USjtFpsc|M|q6p zJkArWU?orT6i@RE&$5cutYIzdSkDGFvWd-XVJq9%&JLdAd3N#wFS3i5c$rstmDkwK z>+InT-sCOb<{jSUJ@&GX_xXSi`G}ACgira5&-sG=e8~a6;%mO)TMlxF@A#g>9N{QG zaE#-e;73k!iqo9oEa&)%^IYH}KXZv+xXiCy;VQxJ)i;oa8%fJeq$52U$Vet`CiuxY z3t7p=Eo3JLImyMX+(vG0Cl7haM}F?000k*TVTw?cViczYB`HN|%21Yal&1m}sYElH z(}I??qBU)3OFP=rfsS;dGhOIPH@eeJlYEp|ksZAa3;%@3vk9(+31MVgGEvpfYX~KOpr5Vj>K}%ZEnl`kh9l=l49q33W zI@5)&bfY^x=t(ak=uIS1MAL`9^dpA;3?P;`;z=Npfh3Vk3WFHT5QZ|0;f!D;_cMyo zjA1O}7|#SIGKtAd;Q^*Hjp@u_CbO8$9Om*M^O(;97P5%NEa4%R@-UCEj7NElsZeQHnNG$Y+)`p}nt#L%As#1cn52_zES`jSL4DGXvTLm0|1hBJbZ+|MXR zGlsE@V>}a>$Rs8+g$J0*G^R6ynapA~bC}D6%ws+aSjZw4vxJ9O%ELUuG9KkImh(7I zu!5C5$x}SdGd#;GR>%|j_29Q3%tlKUgBk5;ZOjhHp8@A->~#4s(Q~{J=4e zbAlf^$tg~AhO?aGC(d($i~P(be&I5|a)qk|_XJ(X_1r)jZX_)?k&g6aAS0Q$napG% zE7`b(?BpOPxww_v$j$BKAusvJ&m9z?AcZJQ5sFfb;*_8yr6^4q$`ah3R-Ot}q!N{> zLRG3!of_1n7I#vcI^4zG)TJKxP@e|eOG6sbm?qpuQ<~A77PO=lt!YDB+R>g4bfgoV z=|We!(VZUjq!$tNCXy(k=|f-o5kr3l5KA2KB#_8Jl1L_nK@4UHLm9?!Mlh258O3PE zFqUzQX95$M#AK%M08^R9bY?J@T;^AAq~#{kk)8}>BojB2nJi=_ z8@G_19ONVyw{jb~xt%=ZB_H{@g8~$!5QQm1QHoKV5|pGAr71&M%2A#QRHPD>sX|q% zQJospq!xEln>yUZ-PENX_fVe(+)G0m(U>OOM^l>7oEEgC6|HGQaLaBx+S7rKbfPm| z=t?)b(}SM$B7)vT5=At9=u1Ch=+6LRi6fo_5*bJm$)qrd!3-g|=WrOq8No>IXB49u z!&t^Ko(W835|f$2159Na)0x3cW-*&N%;iDmF`or2WD$#5!b2?OVIE-_kMbDHd7LL$ z!AhRwDW2vTo@EuQS;Jb^v7QZVWD}d&!dAAiogF;K^X%jWUSt<9@iMRQDzCAd*V)4x zyvbX<%{#oyd+cQ&@ACm4@(~~N37_&ApYsL#`H};C#n*hpw;bdU-|;<%Il@tX;26g_ z!H=Be6sI}ESDP6Jl zYEp|ksZAa3;%@3vk9(+31Ma0Ejc800?xQKqXif`S(u&r!p)JAvx9#abM>^4&E_9_E z-RVJ3dJ#cyB8eiJKJ=v@G4y8uvBVKi0*MSHiDXh3#9)Rnlwk~K1S7ehQH*8`V;RSI zCNPmnOlArXFqLUcX9hEw#cbvAZhTiM2TcJLg}vy&HikzKsR%e=y?yvA-`XAf`iCU5aJ z@9-|~v6p?k&j)e`nM?e_Wq#!fR|)#uT*vj?KpJi&EjN*l^kg6-nYfwEWFafrxP|QG zASb!FmEb<~+}utc@{*7I+(7{fQi#G7p(w>DP6#F`ZVBP8q$cyG~qs)(v0S`pe3znO&i+Mj`nn*Bc13>7rN4o z?)0E1y@;SUkwg(qANtad82U4SSmKB$fkXz9L^3H1VlYD($}omAf|1 zPIHE{oZ~0XbAgNe%q4!|GQV<#tAq;K|GAzUNW+b!6|HGQTiVf{4s@gwo#{eXy3rkzgZ|dttd|%;Zz72znqXo^lb?n9 z5kr3l5KAzbWIPEZGLR&aF>!Dxm<)I@Lm0|1hBJbZ+|MXRGlsE@V>}a>$Rs8cOnUkN zQ<=teW-yak%w`UAd60R`X8{XY#A2545KDQOU}8QKK!zUWF_!Zhp}hc|eWw|JX(c$fFs z%Rb)c13u&S|Ocm?*aeGOGX^2TWLyc*|eKe&R&1pePTG1L4;fC50 zOqSW64s@gwo#{eXy3w5;^rRON^d^!hqUl3lg08tS^k)FE#1T&di3}u(WKtN!V1_W1 zVGL&kBe|bZjAjgD8OL}gFp)`2W(p55m1#_81~Zw(Z00bR2bsrw7O;>-EM^H0v6P2- zgk?O+V=U)!o?rzld6K7inrC>HRjg(WYgxy7Hn5RRY-S5v*~WHu@Ep&xlNWfAUA)B0 zyuz!z#%^9`4{z`$Z}B$o@GkGMmwmj?2Ykp!e9R|&%4dAe7wqRt4)7IU^9|o}kVAaO z_Z;R3NBMzc9Onc-a*|V=<_u>!$4{K+0vGw2OZ>uRe&q^R3Hs08KpIRQ8%m2wQbXxT zPX;m)^gq0r%w!=e*|>%5BfT>JlIy0EbEM_x@xje``=Cgo>EMhTB zc!;Gu%p)x0Q66JCkMjg8Sjm$-#nU{)v#eq@Ygo%V*0X_)Y+^H8*vdAxvxDb&o}IkF zi|pbhUgi~EIM>xt49OF1A_>q&G;xuPC%Q=4HJQujg&s^dcF7qo_xJuCP{yKsQy>B25 zHTnl#Q+=(3WQ6^df@ZL=r_bedtR+V(8BR zVu>T31QIa;a43mnQkcL*CNY^QJit_@F`XIAWEQiT!(1L@9`jkiLKYEB+P#E_Sc=Kp zLyxeGM|q6pJkArWU?orT6i@RE&$5cutYIzdSkDGFvWd-XVJq9%&JLdAd3N#wFS3i5 zc$rstmDkwK>+InT-sCOb<{jSUJ@&GX_xXSi`G}ACgira5&-sG=e8~a6;%mO)TMlxF z@A#g>9N{QGaE#-e;73k!iqo9oEa&)%^IYH}KXZv+xXiCy;VPjF_F=B)2GVdNX}O7X zq^A|FX+vAu(Vh;NusUQC>riL9(3NgSkB`-!3tLLBv0`)&+sg(Sj`&NvX1p^U?ZE@%oet? zjqU8hnIm{0hW&-k1# z*w2?7;48l78@}Zrhxm@~Im{7`@&m^>&Ix|xB&Rsd8P0N!pE%D2F7h*%_=U^-$`!5> zjB9lr*K-4DFadlhEjN*l^kg6-nYfwEWFafrxP|QGASb!FmD|Y8?c^aZMJP%!ic^A; zl%h0cC`&oYQ-O+9!bJC>DpaK!HK<7~g5h~;Q-`~_o4VBF9_rJ8dud1`8qKQXb|JmhmW$v7EhnIm{0hW&-k1#*w2@AmUb7q za=_!S_?mC{mbRX6M|(QZkxtw|8g3*lH<6C?WFRA%xS7mkAuHLqh3w=YC%L$l+sMuB zHNAm8eV=s#1;W)SxD{xRct{;V$mx zkn;GB?>Wp7j`9P?IL--vhpJkpHR6gu?bcCNY^QJit_@F`XIAWEQiT!(1L@9`jkiKg&NQ@J|W+Qv&~# lz&|DMPYL`}0{@i2KPB)_3H(z6|CGQ#CGbxP{Ld_b{{=5#;N}1T literal 0 HcmV?d00001 diff --git a/Start_WM/test6.sln b/Start_WM/test6.sln new file mode 100755 index 00000000..6223065f --- /dev/null +++ b/Start_WM/test6.sln @@ -0,0 +1,30 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test6", "test6\test6.vcproj", "{C7D031E8-B513-4310-A29D-E50069448615}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4) + Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) + Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4) + Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C7D031E8-B513-4310-A29D-E50069448615}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4) + {C7D031E8-B513-4310-A29D-E50069448615}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4) + {C7D031E8-B513-4310-A29D-E50069448615}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4) + {C7D031E8-B513-4310-A29D-E50069448615}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) + {C7D031E8-B513-4310-A29D-E50069448615}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) + {C7D031E8-B513-4310-A29D-E50069448615}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) + {C7D031E8-B513-4310-A29D-E50069448615}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4) + {C7D031E8-B513-4310-A29D-E50069448615}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4) + {C7D031E8-B513-4310-A29D-E50069448615}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4) + {C7D031E8-B513-4310-A29D-E50069448615}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) + {C7D031E8-B513-4310-A29D-E50069448615}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) + {C7D031E8-B513-4310-A29D-E50069448615}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Start_WM/test6.suo b/Start_WM/test6.suo new file mode 100755 index 0000000000000000000000000000000000000000..ce060240b3d5a7d8924b60d3592d511a18f1c52a GIT binary patch literal 29696 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 literal 0 HcmV?d00001 diff --git a/Start_WM/test6/inc/GF.h b/Start_WM/test6/inc/GF.h new file mode 100755 index 00000000..3eb96011 --- /dev/null +++ b/Start_WM/test6/inc/GF.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GF.h + GFSDK top-level include header file. +*/ + +#ifndef __GF_H__ +#define __GF_H__ + +/* Device Interface Width */ +#define GF_DEVICE_INTERFACE_HOST_16 0x1 +#define GF_DEVICE_INTERFACE_HOST_32 0x2 + +/* Device Interface Type */ +#define GF_DEVICE_INTERFACE_TYPE_A 0x1 +#define GF_DEVICE_INTERFACE_TYPE_B 0x2 +#define GF_DEVICE_INTERFACE_TYPE_C 0x3 + +/* + * Device Addressing options and compile-time selection + */ +#define GF_DEVICE_ADDRESS_DIRECT 0x1 +#define GF_DEVICE_ADDRESS_INDIRECT16 0x2 +#define GF_DEVICE_ADDRESS_INDIRECT32 0x4 + +#include "nvcommon.h" +#include "GFDef.h" +#include "GFRmHelp.h" + +/** @mainpage GoForce 5500 Software Development Kit API Reference + + @image html nv_logo_horiz.gif +*/ + +#endif /* __GF_H__ */ + diff --git a/Start_WM/test6/inc/GF3D.h b/Start_WM/test6/inc/GF3D.h new file mode 100755 index 00000000..b06322c6 --- /dev/null +++ b/Start_WM/test6/inc/GF3D.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GF3D.h + GFSDK 3D API +*/ + +#ifndef __GF3D_H__ +#define __GF3D_H__ + +#include "GF.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup group3D 3DAPI 3D API +*/ +/*@{*/ + +// Typesafe functions for opening and closing this component +GF_RETTYPE GF3DOpen(GFRmHandle hRm, GF3DHandle *ph3D, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GF3DClose(GF3DHandle *ph3D); + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* __GF3D_H__ */ diff --git a/Start_WM/test6/inc/GFAudio.h b/Start_WM/test6/inc/GFAudio.h new file mode 100755 index 00000000..47ccbeda --- /dev/null +++ b/Start_WM/test6/inc/GFAudio.h @@ -0,0 +1,168 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFAudio.h + * GFSDK Audio Format API header file. + */ + +#ifndef __GFAudio_H__ +#define __GFAudio_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +//***************************************************************************** +// Audio Types +//***************************************************************************** +//#if defined GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS + +typedef struct _NvVectorS32 +{ + NvS32 x; + NvS32 y; + NvS32 z; + +} NvVectorS32; + +//#endif + + +//***************************************************************************** +// Audio Formats +//***************************************************************************** +// +// Note: FrameSize and Flags must be the first 2 entries in each parameter list below. + +typedef struct _GFMMPROC_PCM_PARAMETERS +{ + NvU32 FrameSize; + NvU32 Flags; + +} GFMMPROC_PCM_PARAMETERS; + +typedef struct _GFMMPROC_SBC_PARAMETERS +{ + NvU32 FrameSize; + NvU32 Flags; + NvU8 join; + NvU32 SampleRate; + NvU16 Bitpool; + NvU16 Channels; + NvU16 Channelmode; + NvU32 SamplesPerFrame; + NvU8 subbands; + NvU8 bitpool; + +} GFMMPROC_SBC_PARAMETERS; + +typedef struct _GFMMPROC_MP3_PARAMETERS +{ + NvU32 FrameSize; + NvU32 Flags; + + NvU32 SampleRate; + NvU16 BitsPerSample; + NvU16 Channels; + NvU32 SamplesPerFrame; + +} GFMMPROC_MP3_PARAMETERS; + +typedef struct _GFAUDIO_AAC_PARAMETERS +{ + NvU32 FrameSize; + NvU32 Flags; + + NvU16 BitsPerSample; + NvU16 Channels; + + NvU32 SamplingRate; + NvU32 ExtensionSamplingRate; + NvU32 BitRate; + NvU32 ChannelConfig; + NvU32 AudioObjectType; + + NvS16 CntBits; + NvS16 frameOK; + NvU32 CRC_Check; + NvU32 CRC_Reg; + +} GFMMPROC_AAC_PARAMETERS; + +typedef struct _GFAUDIO_AMRNB_PARAMETERS +{ + NvU32 FrameSize; + NvU32 Flags; + + NvU32 SamplingRate; + NvU16 BitsPerSample; + NvU16 Channels; + NvU32 format; +// NvU32 SamplesPerFrame; +// NvU32 ExtensionSamplingRate; + NvU32 Mode; + NvU32 NumberOfFrames; +} GFMMPROC_AMRNB_PARAMETERS; + +typedef struct _GFAUDIO_WMA_PARAMETERS +{ + NvU32 FrameSize; + NvU32 Flags; + + NvU16 FormatTag; + NvU16 Channels; + NvU32 SamplingRate; + NvU32 AvgBytesPerSec; + NvU16 BlockAlign; + NvU16 BitsPerSample; + NvU32 ChannelMask; + NvU16 EncodeOpt; + NvU16 AdvancedEncodeOpt; + + // Stuff for playerInfo + NvU16 PlayerOpt; + NvS32 PeakAmplitudeRef; + NvS32 RmsAmplitudeRef; + NvS32 PeakAmplitudeTarget; + NvS32 RmsAmplitudeTarget; + NvS16 DRCSetting; + NvS32 *rgiMixDownMatrix; + + NvU32 AuParserState; + +} GFMMPROC_WMA_PARAMETERS; + +typedef struct _GFAUDIO_AMRWB_PARAMETERS +{ + NvU32 FrameSize; + NvU32 Flags; + + NvU32 SamplingRate; + NvU16 BitsPerSample; + NvU16 Channels; + NvU32 format; +// NvU32 SamplesPerFrame; +// NvU32 ExtensionSamplingRate; + NvU32 Mode; +} GFMMPROC_AMRWB_PARAMETERS; + +typedef struct _GFMMPROC_MIDI_PARAMETERS +{ + NvU32 FrameSize; + NvU32 Flags; +} GFMMPROC_MIDI_PARAMETERS; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Start_WM/test6/inc/GFBDev.h b/Start_WM/test6/inc/GFBDev.h new file mode 100755 index 00000000..ccbd4513 --- /dev/null +++ b/Start_WM/test6/inc/GFBDev.h @@ -0,0 +1,189 @@ +/* + * Copyright 2003-2005 NVIDIA Corporation. All Rights Reserved. + * + * BY INSTALLING THE SOFTWARE THE USER AGREES TO THE TERMS BELOW. + * + * User agrees to use the software under carefully controlled conditions + * and to inform all employees and contractors who have access to the software + * that the source code of the software is confidential and proprietary + * information of NVIDIA and is licensed to user as such. User acknowledges + * and agrees that protection of the source code is essential and user shall + * retain the source code in strict confidence. User shall restrict access to + * the source code of the software to those employees and contractors of user + * who have agreed to be bound by a confidentiality obligation which + * incorporates the protections and restrictions substantially set forth + * herein, and who have a need to access the source code in order to carry out + * the business purpose between NVIDIA and user. The software provided + * herewith to user may only be used so long as the software is used solely + * with NVIDIA products and no other third party products (hardware or + * software). The software must carry the NVIDIA copyright notice shown + * above. User must not disclose, copy, duplicate, reproduce, modify, + * publicly display, create derivative works of the software other than as + * expressly authorized herein. User must not under any circumstances, + * distribute or in any way disseminate the information contained in the + * source code and/or the source code itself to third parties except as + * expressly agreed to by NVIDIA. In the event that user discovers any bugs + * in the software, such bugs must be reported to NVIDIA and any fixes may be + * inserted into the source code of the software by NVIDIA only. User shall + * not modify the source code of the software in any way. User shall be fully + * responsible for the conduct of all of its employees, contractors and + * representatives who may in any way violate these restrictions. + * + * NO WARRANTY + * THE ACCOMPANYING SOFTWARE (INCLUDING OBJECT AND SOURCE CODE) PROVIDED BY + * NVIDIA TO USER IS PROVIDED "AS IS." NVIDIA DISCLAIMS ALL WARRANTIES, + * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. + + * LIMITATION OF LIABILITY + * NVIDIA SHALL NOT BE LIABLE TO USER, USER'S CUSTOMERS, OR ANY OTHER PERSON + * OR ENTITY CLAIMING THROUGH OR UNDER USER FOR ANY LOSS OF PROFITS, INCOME, + * SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT + * OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A + * WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. IN NO EVENT SHALL NVIDIA'S + * AGGREGATE LIABILITY TO USER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH + * OR UNDER USER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY USER TO NVIDIA + * FOR THE SOFTWARE PROVIDED HEREWITH. + */ + +/* + * File: GFBDev.h + * GFSDK Block Device API header file. + */ + +#ifndef GF_BDEV_H +#define GF_BDEV_H + +#include "GF.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupBDev BDevAPI Block Device API + */ +/*@{*/ + +/** Block Device Capability definitions + Low 12 bits are for device types. + Matches GFFDEV_CAP_DEVICE_xxx in GFFDev.h + */ +#define GFBDEV_CAP_SD GFFDEV_CAP_DEVICE_SD /**< SD Storage Supported */ +#define GFBDEV_CAP_SDIO GFFDEV_CAP_DEVICE_SDIO /***< SDIO Supported */ +#define GFBDEV_CAP_MOUNT 0x00010000 /**< Mount/Unmount Supported */ +#define GFBDEV_CAP_DEVICE_MASK 0x00000FFF + +/** GFDRV_INFO: File system run-time struct. + Created when the volume is mounted via GFBDevMount (@see GFBDevMount()). + sec_total, sec_size, read, and write are filled in by + GFBDevMount() (or its lower level out-calls). + + read is mapped to BDevSDRead + write is mapped to BDevSDWrite + -- see GFBDevSD.c for details. + */ +typedef struct _GFDRV_INFO +{ + NvU32 dev; + NvU32 fat_type; + NvU32 sec_size; + NvU32 sec_total; + NvU32 cluster_size; + NvU32 cluster_total; + NvU32 rel_sec; + NvU32 data_sec_count; + NvU32 fat_sec_count; + NvU32 dir_count; + NvU32 root_sec_count; + NvU32 boot_sec; + NvU32 fat1_sec; + NvU32 fat2_sec; + NvU32 root_sec; + NvU32 data_sec; + NvU32 reFormat; + + NvU32 (*upd_fat)( struct _GFDRV_INFO *drv, NvU32 ndx, NvU32 data ); + NvU32 (*new_fat)( struct _GFDRV_INFO *drv, NvU32 ndx ); + NvU32 (*next_fat)( struct _GFDRV_INFO *drv, NvU32 ndx ); + NvU32 (*get_fat)( struct _GFDRV_INFO *drv, NvU32 ndx ); + NvU32 (*read)( NvU32 dev, NvU32 sec, NvU32 secSize, NvU32 count, + NvU32 buf ); + NvU32 (*write)( NvU32 dev, NvU32 sec, NvU32 secSize, NvU32 count, + NvU32 buf ); + + unsigned char *part_tab; + unsigned char *boot_tab; + unsigned char *fat_tab; + unsigned char *dir_tab; +} GFDRV_INFO; + +/* Publicly exposed Block Device API function in the table */ +/** @internal */ +typedef struct _GFBDEVTABLE +{ + GF_RETTYPE (* BDevGetProperty)( GFBDevHandle BDevHandle, + PGFPROPERTY pBDevProp ); + + GF_RETTYPE (* BDevMount)( GFBDevHandle BDevHandle, + GFDRV_INFO **pDrvInfo ); + + GF_RETTYPE (* BDevUnmount)( GFBDevHandle BDevHandle ); + +} GFBDEVTABLE, *PGFBDEVTABLE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFBDevSDOpen(GFRmHandle hRm, GFBDevHandle *phBDev, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFBDevClose(GFRmHandle hRm, GFBDevHandle *phBDev); + +/** @name Functions +@{*/ + +/** Gets BDev API properties. + @param BDevHandle (#GFBDevHandle) Handle to the Block Device API + @param pBDevProp (#PGFPROPERTY) pointer to property struct. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +#define GFBDevGetProperty( BDevHandle, pBDevProp ) \ + ((PGFBDEVTABLE)BDevHandle)->BDevGetProperty( BDevHandle, pBDevProp ) + +/** Initializes the SD device and run-time support structure. + @param BDevHandle (#GFBDevHandle) Handle to the Block Device API + @param pDrvInfo (#GFDRV_INFO) run-time support struct + + This creates and assigns a #GFDRV_INFO into + the given BDevHandle (actually a #BDEVSDTABLE). + Read and Write functions are assinged into the #GFDRV_INFO which + should be used by higher-level file systems to access the SD + device. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +#define GFBDevMount( BDevHandle, pDrvInfo ) \ + ((PGFBDEVTABLE)BDevHandle)->BDevMount( BDevHandle, pDrvInfo ) + +/** Uninitializes the SD device. + @param BDevHandle (#GFBDevHandle) Handle to the Block Device API + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +#define GFBDevUnmount( BDevHandle ) \ + ((PGFBDEVTABLE)BDevHandle)->BDevUnmount( BDevHandle ) + +/*@}*/ +/*@}*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* GF_BDEV_H */ + diff --git a/Start_WM/test6/inc/GFBitmap.h b/Start_WM/test6/inc/GFBitmap.h new file mode 100755 index 00000000..22286e00 --- /dev/null +++ b/Start_WM/test6/inc/GFBitmap.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFBitmap.h + * GFSDK Bitmap header file. + */ + + +#ifndef __GFBITMAP_H__ +#define __GFBITMAP_H__ + +/* Bitmap Color Format - Follow Surface Format GF_SURFACE_xxx */ +#define GF_BITMAP_YUV420 0x00000001 +#define GF_BITMAP_YUV422 0x00000002 +#define GF_BITMAP_YUYV (GF_BITMAP_YUV422|0x00000004) +#define GF_BITMAP_YVYU (GF_BITMAP_YUV422|0x00000008) +#define GF_BITMAP_UYVY (GF_BITMAP_YUV422|0x00000010) +#define GF_BITMAP_VYUY (GF_BITMAP_YUV422|0x00000020) +#define GF_BITMAP_MPEGDEC (GF_BITMAP_YUV420|0x00000040) +#define GF_BITMAP_RGB565 0x00010000 +#define GF_BITMAP_RGB8 0x00070000 +#define GF_BITMAP_ARGB8888 0x00030000 +#define GF_BITMAP_ARGB6666 0x000F0000 + +/* Bitmap */ +typedef struct _GFBITMAP +{ + NvU16 width; + NvU16 height; + NvS32 stride; + NvU32 format; + NvU8 bpp; // Bits per pixel + NvU8 reserved; + NvU16 offset; // Offset from beginning of bitmap to data + NvU8 data; // Real data starts from "Offset" location +} GFBITMAP, *PGFBITMAP; + +#endif /* __GFBITMAP_H__ */ diff --git a/Start_WM/test6/inc/GFCamera.h b/Start_WM/test6/inc/GFCamera.h new file mode 100755 index 00000000..f7730b5a --- /dev/null +++ b/Start_WM/test6/inc/GFCamera.h @@ -0,0 +1,367 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFCamera.h + GFSDK Camera API header file. +*/ + +#ifndef __CAMERA_H__ +#define __CAMERA_H__ + +#include "GF.h" +#include "GFVx.h" +#include "GFCameraScr.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupCamera CameraAPI Camera API +
        +
      • @ref pageCameraAppNotes +
          +
        • @ref pageCameraAppNotes1 +
        +
      +*/ +/*@{*/ + + +/* Helper Macros - Do not assume bytes are properly aligned! */ +#ifndef MAKENvU8S16 +#define MAKENvU8S16( data16 ) \ + (NvU8)((data16) & 0xFF), (NvU8)(((data16) >> 8) & 0xFF) +#endif /* MAKENvU8S16 */ +#ifndef MAKENvU8S32 +#define MAKENvU8S32( data32 ) \ + (NvU8)((data32) & 0xFF), \ + (NvU8)(((data32) >> 8) & 0xFF), \ + (NvU8)(((data32) >> 16) & 0xFF), \ + (NvU8)(((data32) >> 24) & 0xFF) +#endif /* MAKENvU8S32 */ +#ifndef MAKE16 +#define MAKE16( ptr ) \ + ((NvU16)(*ptr) | ((NvU16)(*(ptr+1)) << 8)) +#endif /* MAKE16 */ +#ifndef MAKE32 +#define MAKE32( ptr ) \ + ((NvU32)MAKE16( ptr ) | (NvU32)MAKE16( (ptr+2) ) << 16) +#endif /* MAKE32 */ + +/* GFCAMERA instruction (special) */ +#define GFCAMERA_NONE 0x00 +#define GFCAMERA_NORMAL_WRITE 0x01 +#define GFCAMERA_DELAY_MSEC 0x02 +#define GFCAMERA_NEED_MCLOCK 0x03 + +/* GFCameraSetResolution Options */ +#define GFCAMERA_POWERON_OPTION 0x00000001 + +/* GFCAMERA Error codes */ +#define GFCAM_ERROR_ILLEGAL_PARAMETER (GFCAM_ERROR | 0x00000001L) +#define GFCAM_ERROR_ALLOC_FAILED (GFCAM_ERROR | 0x00000002L) +#define GFCAM_ERROR_VM_ALLOC_FAILED (GFCAM_ERROR | 0x00000003L) +#define GFCAM_ERROR_SCRIPT_ACCESS_FAILED (GFCAM_ERROR | 0x00000004L) +#define GFCAM_ERROR_NATIVE_FUNCTION_FAILED (GFCAM_ERROR | 0x00000005L) +#define GFCAM_ERROR_GETTING_COMPONENT (GFCAM_ERROR | 0x00000006L) +#define GFCAM_ERROR_VM_BUFFER_ALLOC_FAILED (GFCAM_ERROR | 0x00000007L) +#define GFCAM_ERROR_CAMERA_SCRIPT_NOT_PRESENT (GFCAM_ERROR | 0x00000008L) +#define GFCAM_ERROR_FUNCTION_NOT_SUPPORTED (GFCAM_ERROR | 0x00000009L) + +/* GFCAMERAINSTRTYPE */ +typedef struct _GFCAMERAINSTRTYPE +{ + NvU16 skip; // IMPORTANT: Multiple instructions + // must be in ascending skip order + NvU8 type; + NvU16 size; + NvU32 data; +} GFCAMERAINSTRTYPE, *PGFCAMERAINSTRTYPE; + +/* GFCAMERABAYERINFO - BayerInfo struct */ +typedef struct _GFCAMERABAYERINFO +{ + NvU16 ScanWidth; + NvU16 ScanHeight; + + NvU16 ActiveLineStart; + NvU16 ActiveLineWidth; + NvU16 ActiveFrameStart; + NvU16 ActiveFrameHeight; + NvU8 hSyncEdge; + NvU8 vSyncEdge; + NvU16 bayerSel; + +} GFCAMERABAYERINFO, *PGFCAMERABAYERINFO; + +/* GFCAMERARESOLUTIONTYPE - Resolution struct */ +typedef struct _GFCAMERARESOLUTIONTYPE +{ + NvU16 x; + NvU16 y; + NvU8 numInstr; + GFCAMERAINSTRTYPE *pInstr; + GFCAMERABAYERINFO *pBayerInfo; +} GFCAMERARESOLUTIONTYPE, *PGFCAMERARESOLUTIONTYPE; + + + +/* GFCAMERATABLETYPE - Camera Table */ +#define GFCAMERA_NAME_SIZE 32 +typedef struct _GFCAMERATABLETYPE +{ + NvU16 id; + NvU16 ver; + NvU32 scriptSubID; + char name[GFCAMERA_NAME_SIZE]; + // variable name char string always + // ends with a '0' + NvU32 VIPFlag; + NvU32 VIPNewTiming; + NvU32 VIPColorFormat; + NvU8 VIPHOffset; + NvU8 VIPVOffset; + NvU8 numI2CBytes; //bytes per transfer/packet + NvU8 numRes; + GFCAMERARESOLUTIONTYPE *pResData; + NvU16 initDataSize; + NvU8 *pInitData; +// GFCAMERABAYERINFO *pBayerInfo; + struct _GFCAMERATABLETYPE *pNext; +} GFCAMERATABLETYPE, *PGFCAMERATABLETYPE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFCameraOpen(GFRmHandle hRm, GFCameraHandle *phCamera, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFCameraClose(GFCameraHandle *phCamera); + +/** This routine returns the camera's properties and capabilities. + These properties are returned in the GFPROPERTY structure. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param pProp (PGFPROPERTY) Pointer to GFPROPERTY structure. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see GFPROPERTY +*/ +GF_RETTYPE GFCameraGetProperty(GFCameraHandle CameraHandle, + PGFPROPERTY pProp); + +/** This routine programs the camera's registers based on the data + contained in the camera table. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param resX (NvU16) Horizontal resolution + @param resY (NvU16) Vertical resolution + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see PGFCAMERATABLETYPE +*/ +GF_RETTYPE GFCameraSetup(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + NvU16 resX, + NvU16 resY ); + +/** This routine programs the camera's registers for a resolution change. + The main difference from GFCameraSetup() is the lack of camera power on. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param resX (NvU16) Horizontal resolution + @param resY (NvU16) Vertical resolution + @param poweron (NvU32) flag indicates whether camera power on should be executed + @param option (NvU32) flag passed to camera script SetResolution function + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see PGFCAMERATABLETYPE +*/ +GF_RETTYPE GFCameraSetResolution(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + NvU16 resX, + NvU16 resY, + NvU32 poweron, + NvU32 option); + +/** This routine allocates the run-time camera table structure from the + camera scripts. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pTable (NvU8) Pointer to camera configuration table, ignored for GFSDK SC15. + Camera configurations are passed via scripts. + @param *ppCamera (PGFCAMERATABLETYPE) Returns pointer to linked list of camera description tables + + @return On success the number of cameras in the linked list is returned. This can be 0. + On failure an error code is returned. To distinguish between success and failure, + use macro #ISGFERROR() or #ISGFSUCCESS(). + + @see PGFCAMERATABLETYPE +*/ +GF_RETTYPE GFCameraTableAlloc(GFCameraHandle CameraHandle, + NvU8 *pTable, + PGFCAMERATABLETYPE *ppCamera); + +/** This routine frees the camera table structure created by + GFCameraTableAlloc(). + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *ppCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see PGFCAMERATABLETYPE +*/ +GF_RETTYPE GFCameraTableFree(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE *ppCamera); + +GF_RETTYPE GFCameraTableDump(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera); + +/** This routine finds a camera that is contained in the camera table structure. + It does so using various parameters that refer to entries in the table. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param *pWanted (PGFCAMERATABLETYPE) Pointer to the found PGFCAMERATABLETYPE structure. + @param id (NvU32) Unique I2C slave ID for the camera. + @param *name (Char) pointer to name. + @param resX (NvU16) Horizontal resolution + @param resY (NvU16) Vertical resolution + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFCameraFind(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + PGFCAMERATABLETYPE *pWanted, + NvU32 id, + char *name, + NvU16 resX, + NvU16 resY ); + +/** This routine scans for a camera that is contained in the + table structure created by GFCameraTableAlloc(). + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pTable (NvU8) Pointer to camera table. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFCameraScan(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera); + +/** This routine uses the script subID parameter to find a camera + that is contained in the camera table structure. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param *pWanted (PGFCAMERATABLETYPE) Pointer to the found PGFCAMERATABLETYPE structure. + @param subID (NvU32) Camera script subID. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFCameraScriptFind(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + PGFCAMERATABLETYPE *pWanted, + NvU32 subID); + +/** This routine calls the camera script function to operate on a user defined + camera attribute. A shared buffer is used to pass parameters to and from + the camera script function. + + The shared buffer and may contain data used by the script function + to perform the requested operation. The first data should indicate + the primary setting of the operation. The convention is to use ranges + that are normalized from 0 to 100. Where specific data is required, + that data must match that which is allowable by the camera in use. + If not, the error code GFCAM_ERROR_ILLEGAL_PARAMETER is returned. + + The attribute may be one of the defined flags listed below. + GFCAMERA_CAMERACONTROL_PAN + GFCAMERA_CAMERACONTROL_TILT + GFCAMERA_CAMERACONTROL_ROLL + GFCAMERA_CAMERACONTROL_ZOOM + GFCAMERA_CAMERACONTROL_EXPOSURE + GFCAMERA_CAMERACONTROL_IRIS + GFCAMERA_CAMERACONTROL_FOCUS + GFCAMERA_CAMERACONTROL_FLASH + GFCAMERA_VIDEOPROCAMP_BRIGHTNESS + GFCAMERA_VIDEOPROCAMP_CONTRAST + GFCAMERA_VIDEOPROCAMP_HUE + GFCAMERA_VIDEOPROCAMP_SATURATION + GFCAMERA_VIDEOPROCAMP_SHARPNESS + GFCAMERA_VIDEOPROCAMP_GAMMA + GFCAMERA_VIDEOPROCAMP_COLORENABLE + GFCAMERA_VIDEOPROCAMP_WHITEBALANCE + GFCAMERA_VIDEOPROCAMP_BACKLIGHT_COMPENSATION + GFCAMERA_VIDEOPROCAMP_GAIN + + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param attribute (NvU32) Attribute flag indicates operation. + @param *sharedBuffer (NvU32) pointer to a shared buffer. + @param bufferSize (NvU32) Size of shared buffer. + @param *readValue (NvU32) pointer to the returned value from the camera script function. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GFCAM_ERROR_FUNCTION_NOT_SUPPORTED Attribute not supported + @retval #GFCAM_ERROR_ILLEGAL_PARAMETER Parameter out of range + +*/ +GF_RETTYPE GFCameraScriptSetAttribute(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + NvU32 attribute, + NvU32 *sharedBuffer, + NvU32 bufferSize, + NvU32 *readValue); + +/** This routine uses the camera script function to execute a powerup or + powerdown sequence. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param poweron (NvU32) If set to '0' execute powerdown, if '1', execute powerup. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFCameraPower(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + NvU32 poweron); + +/*@}*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** @page pageCameraAppNotes CameraAPI Application Notes + + @section pageCameraAppNotes1 Todo + +*/ + +#endif /* __CAMERA_H__ */ + diff --git a/Start_WM/test6/inc/GFCameraScr.h b/Start_WM/test6/inc/GFCameraScr.h new file mode 100755 index 00000000..b34eb21b --- /dev/null +++ b/Start_WM/test6/inc/GFCameraScr.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#if !defined (__GFCAMERASCR_INC__) +#define __GFCAMERASCR_INC__ + +/* Camera Script error codes */ +#define GFCAMERA_NOT_SUPPORTED 0x80000000 //return error code for attribute +#define GFCAMERA_PARAMETER_ERROR 0x80000001 //return out of range parameter + +/** Camera script attribute flags, for camera control functions + @see GFCameraScriptSetAttribute() +*/ +#define GFCAMERA_CAMERACONTROL_PAN 0x00000001 +#define GFCAMERA_CAMERACONTROL_TILT 0x00000002 +#define GFCAMERA_CAMERACONTROL_ROLL 0x00000003 +#define GFCAMERA_CAMERACONTROL_ZOOM 0x00000004 +#define GFCAMERA_CAMERACONTROL_EXPOSURE 0x00000005 +#define GFCAMERA_CAMERACONTROL_IRIS 0x00000006 +#define GFCAMERA_CAMERACONTROL_FOCUS 0x00000007 +#define GFCAMERA_CAMERACONTROL_FLASH 0x00000008 +#define GFCAMERA_VIDEOPROCAMP_BRIGHTNESS 0x00000009 +#define GFCAMERA_VIDEOPROCAMP_CONTRAST 0x0000000a +#define GFCAMERA_VIDEOPROCAMP_HUE 0x0000000b +#define GFCAMERA_VIDEOPROCAMP_SATURATION 0x0000000c +#define GFCAMERA_VIDEOPROCAMP_SHARPNESS 0x0000000d +#define GFCAMERA_VIDEOPROCAMP_GAMMA 0x0000000e +#define GFCAMERA_VIDEOPROCAMP_COLORENABLE 0x0000000f +#define GFCAMERA_VIDEOPROCAMP_WHITEBALANCE 0x00000010 +#define GFCAMERA_VIDEOPROCAMP_BACKLIGHT_COMPENSATION 0x00000011 +#define GFCAMERA_VIDEOPROCAMP_GAIN 0x00000012 + +#endif + diff --git a/Start_WM/test6/inc/GFDef.h b/Start_WM/test6/inc/GFDef.h new file mode 100755 index 00000000..c7a9df55 --- /dev/null +++ b/Start_WM/test6/inc/GFDef.h @@ -0,0 +1,254 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFDef.h + * GFSDK Definition header file + */ + +#ifndef __GFDEF_H__ +#define __GFDEF_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "GFDefScr.h" + +/* Register field manipulation using xxx_RANGE macros defined in hardware + * header files. + */ +#define GF_LOWBIT(x) (0?x) +#define GF_HIGHBIT(x) (1?x) +#define GF_SIZE(x) (GF_HIGHBIT(x)-GF_LOWBIT(x)+1) +#define GF_SHIFT(x) ((0?x)%32) +#define GF_MASK(x) (0xFFFFFFFFUL>>(31-((1?x)%32)+((0?x)%32))) +#define GF_BITS(val, x) (((val) & GF_MASK(x))<> GF_SHIFT(d##_##r##_0_##f##_RANGE))& GF_MASK(d##_##r##_0_##f##_RANGE)) + +#define GF_FLD_SET_DRF_NUM(d,r,f,n,v) ((v & ~GF_SHIFTMASK(d##_##r##_0_##f##_RANGE)) | GF_DRF_NUM(d,r,f,n)) +#define GF_FLD_SET_DRF_DEF(d,r,f,c,v) (((v) & ~GF_SHIFTMASK(d##_##r##_0_##f##_RANGE)) | GF_DRF_DEF(d,r,f,c)) + +#define GF_RESETVAL(d,r) (d##_##r##_0_RESET_VAL) + +#define OP_DRF_DEF(o,f,c) ((o##_##f##_##c) << GF_SHIFT(o##_##f##_RANGE)) +#define OP_DRF_NUM(o,f,n) (((n)& GF_MASK(o##_##f##_RANGE))<< GF_SHIFT(o##_##f##_RANGE)) +#define OP_DRF_VAL(o,f,v) (((v)>> GF_SHIFT(o##_##f##_RANGE))& GF_MASK(o##_##f##_RANGE)) + +#define OP_FLD_SET_DRF_NUM(o,f,n,v) ((v & ~GF_SHIFTMASK(o##_##f##_RANGE)) | GF_DRF_NUM(o,f,n)) +#define OP_FLD_SET_DRF_DEF(o,f,c,v) (((v) & ~GF_SHIFTMASK(o##_##f##_RANGE)) | GF_DRF_DEF(o,f,c)) + +/* Default Return Codes */ +/* - All errors has MSB set, indicate a negative val. */ + +/** Macro to test if an error code of type GF_RETTYPE signals failure. + @param code (GF_RETTYPE) Error code + @return Evaluates to \a true on failure, \a false on success. +*/ +#define ISGFERROR(code) ((GF_RETTYPE)(code) < GF_SUCCESS) + +/** Macro to test if an error code of type GF_RETTYPE signals success. + @param code (GF_RETTYPE) Error code + @return Evaluates to \a true on success, \a false on failure. +*/ +#define ISGFSUCCESS(code) ((GF_RETTYPE)(code) >= GF_SUCCESS) + +/** Common error code: Generic error. */ +#define GF_ERROR 0x80000000L +/** Common error code: Success (not an error). */ +#define GF_SUCCESS 0x00000000L +/** Common error code: Busy (not an error). */ +#define GF_ERROR_BUSY 0x80000001L +/** Common error code: Out of memory. This can be CPU heap memory, or GPU memory. */ +#define GF_ERROR_OUT_MEMORY 0x80000003L +/** Common error code: Bad parameter. */ +#define GF_ERROR_BAD_PARAMETER 0x80000005L + + +#define GF_COMPONENT_ERROR_SHIFT 24 +/** Macro to reverse bits of the 7 bit component ID. + See GF_RETTYPE for explanation. +*/ +#define GF_COMPONENT_REVERSE(c) ((((c)&64)>>6)|(((c)&32)>>4)|(((c)&16)>>2)|((c)&8)|(((c)&4)<<2)|(((c)&2)<<4)|(((c)&1)<<6)) + +#define GX_ERROR (GF_COMPONENT_REVERSE(GF_GXAPI)< + +/** Utility macro */ +#define CHECK_STATUS_CLEANUP(f) \ + do { \ + if(ISGFERROR( ( status = (f) ) )) \ + goto Cleanup; \ + } while(0) + + + +#if !defined(NV_MODS) + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * READ THIS FIRST: + * + * None of these funtions should be called directly by an application. The + * macros below should be used instead. + */ + +/** Diag context structure */ +typedef struct _GFDIAGCONTEXT +{ + NvU32 processID; + NvU32 threadID; +} GFDIAGCONTEXT, *PGFDIAGCONTEXT; + + +/** Public exposed DIAG API functions in the table */ +typedef struct _GFDIAGTABLE +{ + /** + @see GF_DIAG_INITIALIZE + */ + GF_RETTYPE ( *DiagInitialize)( GFDiagHandle DiagHandle, int argc, char **argv ); + + /** + @see GF_DIAG_GET_VERSION + */ + GF_RETTYPE ( *DiagGetVersion)( GFDiagHandle DiagHandle, char *versionStr, int bufferLen ); + + /** + @see GF_DIAG_SET_RENDER_SURFACE + */ + GF_RETTYPE ( *DiagSetRenderSurface)( GFDiagHandle DiagHandle, PGFRMSURFACE surface ); + + /** + @see GF_DIAG_SET_IDLE_CHIP_CALLBACK + */ + GF_RETTYPE ( *DiagSetIdleChipCallback)( GFDiagHandle DiagHandle, + GF_RETTYPE (*pIdleCallback)(void *idleCallbackData), void *data ); + + /** + @see GF_DIAG_FRAME_DONE + */ + GF_RETTYPE ( *DiagFrameDone)( GFDiagHandle DiagHandle ); + + /** + @see GF_DIAG_CLEANUP + */ + GF_RETTYPE ( *DiagCleanup)( GFDiagHandle DiagHandle ); + + /** + @see GF_DIAG_RUN_TEST + */ + GF_RETTYPE (* DiagRunTest)( GFDiagHandle DiagHandle, char *testName, + const char *pCmdLine, NvU8 flag, GFDiagHandle *pDiagChildHandle ); + + /** + @see GF_DIAG_WAIT_FOR_TEST + */ + GF_RETTYPE (* DiagWaitForTest)( GFDiagHandle DiagHandle ); + + /** + @see GF_DIAG_PRINT + */ + GF_RETTYPE (* DiagPrint)( GFDiagHandle DiagHandle, const char *msg ); + + /** + @see GF_DIAG_GET_CONTEXT + */ + GF_RETTYPE (* DiagGetContext)( GFDiagHandle DiagHandle, GFDIAGCONTEXT *pContext ); +} GFDIAGTABLE, *PGFDIAGTABLE; + +/* +***************************************************************************** +* MACROS - Apps should use these to communicate with GFDiag +***************************************************************************** +*/ + +// Function documentation goes here to bypass #ifdef problems + +/** @name Functions +@{*/ + +/** @def GF_DIAG_MAIN + Replace your standard definition of "int main" with with this macro + for use with GFDiag. + + @param unused1 (int) Unused -- obsolete argument, to be removed + @param unused2 (char**) Unused -- obsolete argument, to be removed + @param testName (char*) Name of the test + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_INITIALIZE + Control things like storing vs checking, HW vs SW crcs via this function. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param argc (int) Argument count + @param argv (char**) Argument data + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Will read in the stored CRCs if applicable. +*/ + +/** @def GF_DIAG_GET_VERSION + Query the GFDiag version. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param str (char*) Pointer to a buffer that will be filled with the GFDiag version + @param len (int) Length of the buffer, versionStr + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The application allocates a buffer and passes it + (along with its length) to GFDiag. +*/ + +/** @def GF_DIAG_SET_IDLE_CHIP_CALLBACK +Allow the test to idle the chip in its own way. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param callbackFn (GF_RETTYPE (void *idleCallbackData)) Function pointer to call on idle + @param callbackData (void*) Data to pass to pIdleCallback when it is called + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_SET_RENDER_SURFACE + Tell GFDiag what surface we want to CRC etc. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param surface (#PGFRMSURFACE) Surface we want to CRC + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_FRAME_DONE + Announce the completion of a frame. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFDiag has the option to: + + Calculate a CRC on the primary surface. This function calls the callback + function set by GFDiagSetIdleChipCallback (or a default if no idle chip + callback is supplied) to idle the chip before calculating CRCs + + In "storing mode" this will store the CRC in some DB that gets written + to file later. + + In "checking mode" this checks the CRC against the one we read in from file. +*/ + +/** @def GF_DIAG_CLEANUP + Perform any necessary cleanup operations before the test exits and write + CRCs to file if applicable. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_PRINT + Prints to GFDiag. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param x (const char*) Message to print + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_RUN_TEST +Starts a test executing. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param testName (char*) Name of the test to execute + @param pCmdLine (const char*) The command line to execute the test + @param flag (NvU8) This is an option specifying how the test should be run. May contain one of: GF_DIAG_RUN_NEW_PROCESS, GF_DIAG_RUN_NEW_THREAD or GF_DIAG_RUN_NORMAL + @param pDiagChildHandle (#GFDiagHandle) This is a pointer to a GFDiagHandle that will be filled in with the handle of the child process + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_WAIT_FOR_TEST + Waits for test to complete, return value will be result of test. + + @param DiagHandle (#GFDiagHandle) Handle to Diag of test to run (probably the handle placed in pDiagChildHandle from GF_DAIG_RUN_TEST) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see GF_DIAG_RUN_TEST +*/ + +/** @def GF_DIAG_GET_CONTEXT +Gets context from GFDiag. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param pContext (#GFDIAGCONTEXT) Points to a structure that will be filled with the current context + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_PRINTF + Format prints a message. + + @param x (bracketed printf string) Message to print +*/ + +/*@}*/ + +/* Run flags */ + +/** Test is run in same thread */ +#define GF_DIAG_RUN_NORMAL 1 +#define GF_DIAG_RUN_NEW_THREAD 2 +#define GF_DIAG_RUN_NEW_PROCESS 4 + + +/** @def GF_DIAG_CRC_STATUS + Helper macro to check the status of a call to GF_DIAG_FRAME_DONE + and increment a fail count if the status was a failure. + + eg: + @code GF_DIAG_CRC_STATUS(GF_DIAG_FRAME_DONE("DxTest"), GF_Diag_CrcFailCount); + @endcode + + @param status The status of a call to GF_DIAG_FRAME_DONE + @param gf_diag_crcFailCount The var containing the current failure count + + @see GF_DIAG_FRAME_DONE +*/ +#define GF_DIAG_CRC_STATUS(status, gf_diag_crcFailCount) + +#ifdef GF_DIAG_ENABLED + +/* + * See doxygen comments above for info on the following macros + */ +#define GF_DIAG_MAIN(unused1, unused2, testName) \ + int TestMain(int argc, char *argv[], GFDiagHandle handle) + +#define GF_DIAG_INITIALIZE(handle, argc, argv) \ + ((PGFDIAGTABLE)handle)->DiagInitialize((handle), (argc), (argv)) + +#define GF_DIAG_GET_VERSION(handle, str, len) \ + ((PGFDIAGTABLE)handle)->DiagGetVersion((handle), (str), (len)) + +#define GF_DIAG_SET_IDLE_CHIP_CALLBACK(handle, callbackFn, callbackData) \ + ((PGFDIAGTABLE)handle)->DiagSetIdleChipCallback(handle, callbackFn, callbackData) + +#define GF_DIAG_SET_RENDER_SURFACE(handle, surface) \ + ((PGFDIAGTABLE)handle)->DiagSetRenderSurface((handle), (surface)) + +#define GF_DIAG_FRAME_DONE(handle) \ + ((PGFDIAGTABLE)handle)->DiagFrameDone((handle)) + +#define GF_DIAG_CLEANUP(handle) \ + ((PGFDIAGTABLE)handle)->DiagCleanup((handle)) + +#define GF_DIAG_PRINT(handle, x) \ + ((PGFDIAGTABLE)handle)->DiagPrint(handle, x) + +#define GF_DIAG_RUN_TEST(handle, testName, pCmdLine, flag, pDiagChildHandle) \ + ((PGFDIAGTABLE)handle)->DiagRunTest(handle, testName, pCmdLine, flag, pDiagChildHandle) + +#define GF_DIAG_WAIT_FOR_TEST(handle) \ + ((PGFDIAGTABLE)handle)->DiagWaitForTest(handle) + +#define GF_DIAG_GET_CONTEXT(handle, pContext) \ + ((PGFDIAGTABLE)handle)->DiagGetContext(handle, pContext) + + +static void +GFDiagPrintf( GFDiagHandle handle, const char *fmt, ... ) +{ + char buf[1024]; + va_list list; + + va_start(list, fmt); + + GFSprintfVAL(buf, fmt, list); + + GF_DIAG_PRINT(handle, buf); + + va_end(list); +} + +#define GF_DIAG_PRINTF(x) GFDiagPrintf x + +#else + +/* + * Do this exactly like nvplat...so this will have an OS specific + * implementation in the final GFDiag.h + */ +#if NVOS_IS_LINUX || NVOS_IS_WINDOWS +#define GF_DIAG_MAIN(unused1, unused2, testName) \ + int TestMain(int argc, char *argv[]) +#define GF_DIAG_MAIN_DEFAULT_1ARG(unused1, unused2, testName, arg1) \ + int TestMain(int argc, char *argv[]) +#define GF_DIAG_MAIN_DEFAULT_2ARGS(unused1, unused2, testName, arg1, arg2) \ + int TestMain(int argc, char *argv[]) +#define GF_DIAG_MAIN_DEFAULT_3ARGS(unused1, unused2, testName, arg1, arg2, arg3) \ + int TestMain(int argc, char *argv[]) +#else +#define GF_DIAG_MAIN(unused1, unused2, testName) \ + int argc = 1; \ + char *argv[] = { #testName }; \ + int main() +#define GF_DIAG_MAIN_DEFAULT_1ARG(unused1, unused2, testName, arg1) \ + int argc = 2; \ + char *argv[] = { #testName, arg1 }; \ + int main() +#define GF_DIAG_MAIN_DEFAULT_2ARGS(unused1, unused2, testName, arg1, arg2) \ + int argc = 3; \ + char *argv[] = { #testName, arg1, arg2 }; \ + int main() +#define GF_DIAG_MAIN_DEFAULT_3ARGS(unused1, unused2, testName, arg1, arg2, arg3) \ + int argc = 4; \ + char *argv[] = { #testName, arg1, arg2, arg3 }; \ + int main() +#endif + +#define GF_DIAG_INITIALIZE(testName, argc, argv) GF_SUCCESS +#define GF_DIAG_CLEANUP(testName) GF_SUCCESS + +/* These should be removed once all the Apps & MODS are updated */ +#define GF_DIAG_GET_VERSION(testName, str, len) GF_SUCCESS +#define GF_DIAG_SET_IDLE_CHIP_CALLBACK(testName, callbackFn, callbackData) GF_SUCCESS +#define GF_DIAG_SET_RENDER_SURFACE(testName, surface) GF_SUCCESS +#define GF_DIAG_FRAME_DONE(testName) GF_SUCCESS +#define GF_DIAG_PRINT(handle, x) GF_SUCCESS +#define GF_DIAG_RUN_TEST(handle, testName, pCmdLine, flag, pDiagChildHandle) GF_SUCCESS +#define GF_DIAG_WAIT_FOR_TEST(handle) GF_SUCCESS +#define GF_DIAG_GET_CONTEXT(handle, pContext) GF_SUCCESS + +#define GF_DIAG_PRINTF(x) GFPrintf x + +#endif /* GF_DIAG_ENABLED */ + +#ifdef __cplusplus +} +#endif + +/* NV_MODS */ +#else + +/* GFDiag is always enabled in NV_MODS builds */ +#define GF_DIAG_ENABLED 1 + +#ifndef INCLUDED_GFMODS_H +#include "../GFMods/src/GFMods.h" +#endif + +#endif /* NV_MODS */ + +#define CHECK_STATUS_MSG(f,TEXT) \ + do { \ + if(ISGFERROR( ( status = (f) ) )) \ + { \ + GF_DIAG_PRINTF((TEXT)); \ + } \ + } while(0) + + +#define CHECK_STATUS_CLEANUP_MSG(f , TEXT) \ + do { \ + if(ISGFERROR( ( status = (f) ) )) \ + { \ + GF_DIAG_PRINTF(TEXT); \ + goto Cleanup; \ + } \ + } while(0) + +#define CHECK_STATUS_AND_DISPLAY_CLEANUP_MSG(f , TEXT) \ + do { \ + if(ISGFERROR( ( status = (f) ) )) \ + { \ + GF_DIAG_PRINTF((TEXT,f)); \ + goto Cleanup; \ + } \ + } while(0) +#endif /* __GFDIAG_H__ */ diff --git a/Start_WM/test6/inc/GFDispCmdData.h b/Start_WM/test6/inc/GFDispCmdData.h new file mode 100755 index 00000000..5106900b --- /dev/null +++ b/Start_WM/test6/inc/GFDispCmdData.h @@ -0,0 +1,1740 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#if !defined __GFDISPCMDDATA_H__ +#define __GFDISPCMDDATA_H__ + +// Display Signal Options 0 + +#define GF_DEFAULT_TABLE 0x01 // Display Default Table Support +#define GF_DXAPI_SUPPORT 0x02 // DxAPI Support +#define GF_FMARK_SUPPORT 0x04 // FMARK Supported by panel + +#define GFSDXAPI_PROC0 0x80000000 // PROC0 in Display DxAPI table in Script +#define GFSDXAPI_PROC1 0x80000001 // PROC1 in Display DxAPI table in Script +#define GFSDXAPI_PROC2 0x80000002 // PROC2 in Display DxAPI table in Script +#define GFSDXAPI_PROC3 0x80000003 // PROC3 in Display DxAPI table in Script +#define GFSDXAPI_PROC4 0x80000004 // PROC4 in Display DxAPI table in Script +#define GFSDXAPI_PROC5 0x80000005 // PROC5 in Display DxAPI table in Script +#define GFSDXAPI_PROC6 0x80000006 // PROC6 in Display DxAPI table in Script +#define GFSDXAPI_PROC7 0x80000007 // PROC7 in Display DxAPI table in Script +#define GFSDXAPI_PROC8 0x80000008 // PROC8 in Display DxAPI table in Script +#define GFSDXAPI_PROC9 0x80000009 // PROC9 in Display DxAPI table in Script +#define GFSDXAPI_PROC10 0x8000000A // PROC10 in Display DxAPI table in Script +#define GFSDXAPI_PROC11 0x8000000B // PROC11 in Display DxAPI table in Script +#define GFSDXAPI_PROC12 0x8000000C // PROC12 in Display DxAPI table in Script +#define GFSDXAPI_PROC13 0x8000000D // PROC13 in Display DxAPI table in Script +#define GFSDXAPI_PROC14 0x8000000E // PROC14 in Display DxAPI table in Script +#define GFSDXAPI_PROC15 0x8000000F // PROC14 in Display DxAPI table in Script +#define GFSDXAPI_PROC16 0x80000010 // PROC16 in Display DxAPI table in Script +#define GFSDXAPI_PROC17 0x80000011 // PROC17 in Display DxAPI table in Script +#define GFSDXAPI_PROC18 0x80000012 // PROC18 in Display DxAPI table in Script +#define GFSDXAPI_PROC19 0x80000013 // PROC19 in Display DxAPI table in Script +#define GFSDXAPI_PROC20 0x80000014 // PROC20 in Display DxAPI table in Script +#define GFSDXAPI_PROC21 0x80000015 // PROC21 in Display DxAPI table in Script +#define GFSDXAPI_PROC22 0x80000016 // PROC22 in Display DxAPI table in Script +#define GFSDXAPI_PROC23 0x80000017 // PROC23 in Display DxAPI table in Script +#define GFSDXAPI_PROC24 0x80000018 // PROC24 in Display DxAPI table in Script +#define GFSDXAPI_PROC25 0x80000019 // PROC25 in Display DxAPI table in Script +#define GFSDXAPI_PROC26 0x8000001A // PROC26 in Display DxAPI table in Script +#define GFSDXAPI_PROC27 0x8000001B // PROC27 in Display DxAPI table in Script +#define GFSDXAPI_PROC28 0x8000001C // PROC28 in Display DxAPI table in Script +#define GFSDXAPI_PROC29 0x8000001D // PROC29 in Display DxAPI table in Script +#define GFSDXAPI_PROC30 0x8000001E // PROC30 in Display DxAPI table in Script +#define GFSDXAPI_PROC31 0x8000001F // PROC31 in Display DxAPI table in Script +#define GFSDXAPI_PROC_END 0x8000FFFF // PROC End in Display DxAPI table in Script + +#define OFFSET_DISP_SIGNAL_OPTIONS0 0x00000101 + +#define GFSCMD_H_PULSE0 0x00088101 +#define GFSCMD_H_PULSE1 0x000A8101 +#define GFSCMD_H_PULSE2 0x000C8101 +#define GFSCMD_V_PULSE0 0x00108101 +#define GFSCMD_V_PULSE1 0x00128101 +#define GFSCMD_V_PULSE2 0x00138101 +#define GFSCMD_V_PULSE3 0x00148101 +#define GFSCMD_M0 0x00188101 +#define GFSCMD_M1 0x001A8101 + +#define GF_H_PULSE0_DISABLE 0x00000000 +#define GF_H_PULSE0_ENABLE 0x00000100 +#define GF_H_PULSE1_DISABLE 0x00000000 +#define GF_H_PULSE1_ENABLE 0x00000400 +#define GF_H_PULSE2_DISABLE 0x00000000 +#define GF_H_PULSE2_ENABLE 0x00001000 +#define GF_V_PULSE0_DISABLE 0x00000000 +#define GF_V_PULSE0_ENABLE 0x00010000 +#define GF_V_PULSE1_DISABLE 0x00000000 +#define GF_V_PULSE1_ENABLE 0x00040000 +#define GF_V_PULSE2_DISABLE 0x00000000 +#define GF_V_PULSE2_ENABLE 0x00080000 +#define GF_V_PULSE3_DISABLE 0x00000000 +#define GF_V_PULSE3_ENABLE 0x00100000 +#define GF_M0_DISABLE 0x00000000 +#define GF_M0_ENABLE 0x01000000 +#define GF_M1_DISABLE 0x00000000 +#define GF_M1_ENABLE 0x02000000 + + +// Display Signal Options 1 + +#define OFFSET_DISP_SIGNAL_OPTIONS1 0x00000102 +#define GFSCMD_DI 0x00108102 +#define GFSCMD_PP 0x00128102 + +#define GF_DI_DISABLE 0x00000000 +#define GF_DI_ENABLE 0x00010000 +#define GF_PP_DISABLE 0x00000000 +#define GF_PP_ENABLE 0x00040000 + +#define OFFSET_H_PULSE0_CONTROL 0x0000010c + +#define GFSCMD_H_PULSE0_MODE 0x0003810c +#define GFSCMD_H_PULSE0_POLARITY 0x0004810c +#define GFSCMD_H_PULSE0_V_QUAL 0x0006810c +#define GFSCMD_H_PULSE0_LAST 0x0008810c + +#define GF_H_PULSE0_MODE_NORMAL 0x00000000 +#define GF_H_PULSE0_MODE_ONE_CLOCK 0x00000008 +#define GF_H_PULSE0_POLARITY_HIGH 0x00000000 +#define GF_H_PULSE0_POLARITY_LOW 0x00000010 +#define GF_H_PULSE0_V_QUAL_ALWAYS 0x00000000 +#define GF_H_PULSE0_V_QUAL_VACTIVE 0x00000080 +#define GF_H_PULSE0_V_QUAL_VACTIVE1 0x000000A0 +#define GF_H_PULSE0_LAST_START_A 0x00000000 +#define GF_H_PULSE0_LAST_END_A 0x00000100 +#define GF_H_PULSE0_LAST_START_B 0x00000200 +#define GF_H_PULSE0_LAST_END_B 0x00000300 +#define GF_H_PULSE0_LAST_START_C 0x00000400 +#define GF_H_PULSE0_LAST_END_C 0x00000500 +#define GF_H_PULSE0_LAST_START_D 0x00000600 +#define GF_H_PULSE0_LAST_END_D 0x00000700 + +#define OFFSET_H_PULSE0_POSITION_A 0x0000010d +#define GFSCMD_H_PULSE0_POSITION_A 0x0000810d + +#define OFFSET_H_PULSE1_CONTROL 0x00000111 + +#define GFSCMD_H_PULSE1_MODE 0x00038111 +#define GFSCMD_H_PULSE1_POLARITY 0x00048111 +#define GFSCMD_H_PULSE1_V_QUAL 0x00068111 +#define GFSCMD_H_PULSE1_LAST 0x00088111 + +#define GF_H_PULSE1_MODE_NORMAL 0x00000000 +#define GF_H_PULSE1_MODE_ONE_CLOCK 0x00000008 +#define GF_H_PULSE1_POLARITY_HIGH 0x00000000 +#define GF_H_PULSE1_POLARITY_LOW 0x00000010 +#define GF_H_PULSE1_V_QUAL_ALWAYS 0x00000000 +#define GF_H_PULSE1_V_QUAL_VACTIVE 0x00000080 +#define GF_H_PULSE1_V_QUAL_VACTIVE1 0x000000A0 +#define GF_H_PULSE1_LAST_START_A 0x00000000 +#define GF_H_PULSE1_LAST_END_A 0x00000100 +#define GF_H_PULSE1_LAST_START_B 0x00000200 +#define GF_H_PULSE1_LAST_END_B 0x00000300 +#define GF_H_PULSE1_LAST_START_C 0x00000400 +#define GF_H_PULSE1_LAST_END_C 0x00000500 +#define GF_H_PULSE1_LAST_START_D 0x00000600 +#define GF_H_PULSE1_LAST_END_D 0x00000700 + +#define OFFSET_H_PULSE1_POSITION_A 0x00000112 +#define GFSCMD_H_PULSE1_POSITION_A 0x00008112 + +#define OFFSET_H_PULSE2_CONTROL 0x00000116 +#define GFSCMD_H_PULSE2_MODE 0x00038116 +#define GFSCMD_H_PULSE2_POLARITY 0x00048116 +#define GFSCMD_H_PULSE2_V_QUAL 0x00068116 +#define GFSCMD_H_PULSE2_LAST 0x00088116 + +#define GF_H_PULSE2_MODE_NORMAL 0x00000000 +#define GF_H_PULSE2_MODE_ONE_CLOCK 0x00000008 +#define GF_H_PULSE2_POLARITY_HIGH 0x00000000 +#define GF_H_PULSE2_POLARITY_LOW 0x00000010 +#define GF_H_PULSE2_V_QUAL_ALWAYS 0x00000000 +#define GF_H_PULSE2_V_QUAL_VACTIVE 0x00000080 +#define GF_H_PULSE2_V_QUAL_VACTIVE1 0x000000A0 +#define GF_H_PULSE2_LAST_START_A 0x00000000 +#define GF_H_PULSE2_LAST_END_A 0x00000100 +#define GF_H_PULSE2_LAST_START_B 0x00000200 +#define GF_H_PULSE2_LAST_END_B 0x00000300 +#define GF_H_PULSE2_LAST_START_C 0x00000400 +#define GF_H_PULSE2_LAST_END_C 0x00000500 +#define GF_H_PULSE2_LAST_START_D 0x00000600 +#define GF_H_PULSE2_LAST_END_D 0x00000700 + +#define OFFSET_H_PULSE2_POSITION_A 0x00000117 +#define GFSCMD_H_PULSE2_POSITION_A 0x00008117 + +#define GFSCMD_V_PULSE0_POLARITY 0x0004811b +#define GFSCMD_V_PULSE0_DELAY_CNTRL 0x0006811b +#define GFSCMD_V_PULSE0_LAST 0x0008811b + +#define GF_V_PULSE0_POLARITY_HIGH 0x00000000 +#define GF_V_PULSE0_POLARITY_LOW 0x00000010 +#define GF_V_PULSE0_NODELAY 0x00000000 +#define GF_V_PULSE0_DELAY 0x00000040 +#define GF_V_PULSE0_DELAY1 0x00000080 +#define GF_V_PULSE0_LAST_START_A 0x00000000 +#define GF_V_PULSE0_LAST_END_A 0x00000100 +#define GF_V_PULSE0_LAST_START_B 0x00000200 +#define GF_V_PULSE0_LAST_END_B 0x00000300 +#define GF_V_PULSE0_LAST_START_C 0x00000400 +#define GF_V_PULSE0_LAST_END_C 0x00000500 + +#define OFFSET_V_PULSE0_POSITION_A 0x0000011c +#define GFSCMD_V_PULSE0_POSITION_A 0x0000811c + +#define GF_V_PULSE0_START_A 0x00000000 +#define GF_V_PULSE0_END_A 0x00010000 + +#define GFSCMD_V_PULSE1_POLARITY 0x0004811f +#define GFSCMD_V_PULSE1_DELAY_CNTRL 0x0006811f +#define GFSCMD_V_PULSE1_LAST 0x0008811f + +#define GF_V_PULSE1_POLARITY_HIGH 0x00000000 +#define GF_V_PULSE1_POLARITY_LOW 0x00000010 +#define GF_V_PULSE1_NODELAY 0x00000000 +#define GF_V_PULSE1_DELAY1 0x00000040 +#define GF_V_PULSE1_DELAY2 0x00000080 +#define GF_V_PULSE1_LAST_START_A 0x00000000 +#define GF_V_PULSE1_LAST_END_A 0x00000100 +#define GF_V_PULSE1_LAST_START_B 0x00000200 +#define GF_V_PULSE1_LAST_END_B 0x00000300 +#define GF_V_PULSE1_LAST_START_C 0x00000400 +#define GF_V_PULSE1_LAST_END_C 0x00000500 + +#define OFFSET_V_PULSE1_POSITION_A 0x00000120 +#define GFSCMD_V_PULSE1_POSITION_A 0x00008120 + +#define OFFSET_M0_CONTROL 0x00000127 +#define GFSCMD_M0_CLOCK_SELECT 0x00008127 +#define GFSCMD_M0_PHASE_CONTROL 0x00048127 +#define GFSCMD_M0_PHASE_RESET 0x00068127 +#define GFSCMD_M0_POLARITY 0x00078127 +#define GFSCMD_M0_PERIOD 0x00088127 +#define GFSCMD_M0_H_POSITION 0x00108127 + +#define GF_M0_CLOCK_SELECT_PCLK 0x00000000 +#define GF_M0_CLOCK_SELECT_LCLK 0x00000002 +#define GF_M0_CLOCK_SELECT_FCLK 0x00000003 +#define GF_M0_PHASE_CONTROL_FREE_RUN 0x00000000 +#define GF_M0_PHASE_CONTROL_VACTIVE_RESTART 0x00000020 +#define GF_M0_PHASE_CONTROL_FRAME_INVERT 0x00000030 +#define GF_M0_PHASE_RESET_NOT_RESET 0x00000000 +#define GF_M0_PHASE_RESET_RESET 0x00000040 +#define GF_M0_POLARITY_HIGH 0x00000000 +#define GF_M0_POLARITY_LOW 0x00000080 +#define GF_M0_PERIOD_VAL 0x00000100 +#define GF_M0_H_POSITION_VAL 0x00010000 + +#define OFFSET_M1_CONTROL 0x00000128 +#define GFSCMD_M1_CLOCK_SELECT 0x00008128 +#define GFSCMD_M1_PHASE_CONTROL 0x00048128 +#define GFSCMD_M1_PHASE_RESET 0x00068128 +#define GFSCMD_M1_POLARITY 0x00078128 +#define GFSCMD_M1_PERIOD 0x00088128 +#define GFSCMD_M1_H_POSITION 0x00108128 + +#define GF_M1_CLOCK_SELECT_PCLK 0x00000000 +#define GF_M1_CLOCK_SELECT_LCLK 0x00000002 +#define GF_M1_CLOCK_SELECT_FCLK 0x00000003 +#define GF_M1_PHASE_CONTROL_FREE_RUN 0x00000000 +#define GF_M1_PHASE_CONTROL_VACTIVE_RESTART 0x00000020 +#define GF_M1_PHASE_CONTROL_FRAME_INVERT 0x00000030 +#define GF_M1_PHASE_RESET_NOT_RESET 0x00000000 +#define GF_M1_PHASE_RESET_RESET 0x00000040 +#define GF_M1_POLARITY_HIGH 0x00000000 +#define GF_M1_POLARITY_LOW 0x00000080 +#define GF_M1_PERIOD_VAL 0x00000100 +#define GF_M1_H_POSITION_VAL 0x00010000 + +#define GF_DISP_CLOCK_CONTROL_0 0x0000012f + +#define GFSCMD_SHIFT_CLK_DIVIDER 0x0000812f +#define GFSCMD_PIXEL_CLK_DIVIDER 0x0008812f + +//#define GF_SHCLKD_1_256_VAL 0x00000000 +#define GF_PCD1 0x00000000 +#define GF_PCD1H 0x00000100 +#define GF_PCD2 0x00000200 +#define GF_PCD3 0x00000300 +#define GF_PCD4 0x00000400 +#define GF_PCD6 0x00000500 +#define GF_PCD8 0x00000600 +#define GF_PCD9 0x00000700 +#define GF_PCD12 0x00000800 +#define GF_PCD16 0x00000900 +#define GF_PCD13 0x00000a00 +#define GF_PCD18 0x00000b00 +#define GF_PCD24 0x00000c00 + +#define OFFSET_DISP_INTERFACE_CONTROL 0x00000130 +#define GFSCMD_DISP_DATA_FORMAT 0x00008130 + +#define GFSCMD_DISP_DATA_ALIGNMENT 0x00088130 +#define GFSCMD_DISP_DATA_ORDER 0x00098130 + +#define GF_DF1P1C_PRLL 0x00000000 +#define GF_DF1P2C24B_PRLL 0x00000001 +#define GF_DF1P2C18B_PRLL 0x00000002 +#define GF_DF1P2C16B_PRLL 0x00000003 +#define GF_DF1CNL_SRL 0x00000004 +#define GF_DF2CNL_SRL 0x00000005 +#define GF_DF3CNL_SRL 0x00000006 +#define GF_DF_SPI 0x00000007 +#define GF_MSB 0x00000000 +#define GF_LSB 0x00000100 +#define GF_RED_BLUE 0x00000000 +#define GF_BLUE_RED 0x00000200 + +#define OFFSET_DISP_COLOR_CONTROL 0x00000131 +#define GFSCMD_BASE_COLOR_SIZE 0x00008131 +#define GFSCMD_DITHER_CONTROL 0x00088131 +#define GFSCMD_ORD_DITHER_ROTATION 0x000C8131 +#define GFSCMD_DISP_COLOR_SWAP 0x00108131 +#define GFSCMD_BLANK_COLOR 0x00118131 +#define GFSCMD_NON_BASE_COLOR 0x00128131 +#define GFSCMD_LCD_MD0 0x00188131 + +#define GF_BASE666 0x00000000 +#define GF_BASE111 0x00000001 +#define GF_BASE222 0x00000002 +#define GF_BASE333 0x00000003 +#define GF_BASE444 0x00000004 +#define GF_BASE555 0x00000005 +#define GF_BASE565 0x00000006 +#define GF_BASE332 0x00000007 +#define GF_BASE888 0x00000008 +#define GF_DISABLE 0x00000000 +#define GF_ORDERED 0x00000200 +#define GF_ERRDIFF 0x00000300 +#define GF_ORD_DITHER_ROTATION_VAL 0x00000000 +#define GF_SWAP_RGB 0x00000000 +#define GF_SWAP_BGR 0x00010000 +#define GF_BLANK_ZERO 0x00000000 +#define GF_BLANK_ONES 0x00020000 +#define GF_NON_BASE_ZERO 0x00000000 +#define GF_NON_BASE_ONES 0x00040000 +#define GF_LCD_MD0_LOW 0x00000000 +#define GF_LCD_MD0_HIGH 0x01000000 + + +#define OFFSET_SHIFT_CLOCK_OPTIONS 0x00000132 + +#define GFSCMD_SC0_H_QUALIFIER 0x00008132 +#define GFSCMD_SC0_V_QUALIFIER 0x00038132 +#define GFSCMD_SC0_CLK_DIVIDER 0x00068132 +#define GFSCMD_SC1_H_QUALIFIER 0x00108132 +#define GFSCMD_SC1_V_QUALIFIER 0x00138132 +#define GFSCMD_SC1_CLK_DIVIDER 0x00158132 + +#define GF_SC0_H_DISABLE 0x00000000 +#define GF_SC0_H_NO_HQUAL 0x00000001 +#define GF_SC0_H_HACTIVE 0x00000002 +#define GF_SC0_H_EXT_HACTIVE 0x00000003 +#define GF_SC0_H_HPULSE0 0x00000004 +#define GF_SC0_H_EXT_HPULSE0 0x00000005 +#define GF_SC0_V_NO_VQUAL 0x00000000 +#define GF_SC0_V_RESERVED 0x00000008 +#define GF_SC0_V_VACTIVE 0x00000010 +#define GF_SC0_V_EXT_VACTIVE 0x00000018 +#define GF_SC0_V_VPULSE0 0x00000020 +#define GF_SC0_V_EXT_VPULSE0 0x00000028 +#define GF_SC0_DIV1 0x00000000 +#define GF_SC0_DIV2 0x00000040 +#define GF_SC0_DIV4 0x00000080 + +#define GF_SC1_H_DISABLE 0x00000000 +#define GF_SC1_H_NO_HQUAL 0x00010000 +#define GF_SC1_H_HACTIVE 0x00020000 +#define GF_SC1_H_EXT_HACTIVE 0x00030000 +#define GF_SC1_H_HPULSE1 0x00040000 +#define GF_SC1_H_EXT_HPULSE1 0x00050000 +#define GF_SC1_V_NO_VQUAL 0x00000000 +#define GF_SC1_V_RESERVED 0x00080000 +#define GF_SC1_V_VACTIVE 0x00100000 +#define GF_SC1_V_EXT_VACTIVE 0x00180000 +#define GF_SC1_V_VPULSE1 0x00200000 +#define GF_SC1_V_EXT_VPULSE1 0x00280000 +#define GF_SC1_DIV1 0x00000000 +#define GF_SC1_DIV2 0x00400000 +#define GF_SC1_DIV4 0x00800000 + +#define OFFSET_DATA_ENABLE_OPTIONS 0x00000133 + +#define GFSCMD_DE_SELECT_ACTIVE 0x00008133 +#define GFSCMD_DE_CONTROL 0x00038133 + +#define GF_DE_ACTIVE_ALL_LINES 0x00000000 +#define GF_DE_ACTIVE_NOBLANK 0x00000001 +#define GF_DE_ONECLK 0x00000000 +#define GF_DE_NORMAL 0x00000004 +#define GF_DE_ONE_CLK_PRECD_ACTIVE 0x00000008 +#define GF_DE_ONE_PIXEL_CLK_EARLY 0x0000000C + + +#define OFFSET_SERIAL_INTERFACE_OPTIONS 0x00000134 +#define GFSCMD_SDT_STP_MODE 0x00008134 +#define GFSCMD_SDT_STP_DURATION 0x00028134 +#define GFSCMD_STH_DURATION 0x00068134 +#define GFSCMD_STP_CONTRO 0x00078134 + +#define GF_SDT_STP_DISABLE 0x00000000 +#define GF_SDT_STP_RESERVED 0x00000001 +#define GF_SDT_STP_ENABLE_DUP 0x00000002 +#define GF_SDT_STP_ENABLE 0x00000003 +#define GF_SDT_STP_DURATION_VAL 0x00000000 +#define GF_ONE_CLOCK 0x00000000 +#define GF_TWO_CLOCK 0x00000040 +#define GF_STP_NORMAL 0x00000000 +#define GF_STP_EXTENDED 0x00000080 + + +#define OFFSET_LCD_LSPI_OPTIONS 0x00000135 +#define GFSCMD_LCD_SPI_CS_MAIN 0x00008135 +#define GFSCMD_LCD_SPI_DC 0x00018135 +#define GFSCMD_SPI_CS_CONTROL_LCD_IS_SPI 0x00028135 +#define GFSCMD_LCD_SPI_DIRECTION_LSB2MSB 0x00048135 + +#define GF_CS_MAIN 0x00000000 +#define GF_CS_SUB 0x00000001 +#define GF_LDC_LOW 0x00000000 +#define GF_LDC_HIGH 0x00000002 +#define GF_LCD_IS_SPI 0x00000000 +#define GF_LCD_SPI 0x00000004 +#define GF_IS_SPI 0x00000008 +#define GF_FORCED 0x0000000C +#define GF_MSB2LSB 0x00000000 +#define GF_LSB2MSB 0x00000010 + + +#define OFFSET_SIGNAL_RAISE 0x00000005 +#define GFSCMD_SIGNAL_RAISE_VECTOR 0x00008005 +#define GFSCMD_SIGNAL_RAISE_SELECT 0x00088005 +#define GFSCMD_SIGNAL_RAISE_CHANNEL_ID 0x00108005 + +#define GF_RAISE_VECTOR_VAL 0x00000000 +#define GF_RAISE_NONE 0x00000000 +#define GF_RAISE_FRAME_END 0x00000100 +#define GF_RAISE_VBLANK 0x00000200 +#define GF_RAISE_VPULSE3 0x00000300 +#define GF_RAISE_CHANNEL_ID_VAL 0x00000000 + + +#define OFFSET_SIGNAL_REFCOUNT 0x00000006 +#define GFSCMD_SIGNAL_REFCOUNT_VECTOR 0x00008006 +#define GFSCMD_SIGNAL_REFCOUNT_SELECT 0x00108006 + +#define GF_REFCOUNT_VECTOR_VAL 0x00000000 +#define GF_REFCOUNT_NONE 0x00000000 +#define GF_REFCOUNT_FRAME_END 0x00010000 + + + +// Display Power Control + +#define OFFSET_DISPLAY_POWER_CONTROL 0x00000009 +#define GFSCMD_PW0_CONTROL 0x00008009 +#define GFSCMD_PW1_CONTROL 0x00028009 +#define GFSCMD_PW2_CONTROL 0x00048009 +#define GFSCMD_PW3_CONTROL 0x00068009 +#define GFSCMD_PW4_CONTROL 0x00088009 +#define GFSCMD_PM0_CONTROL 0x00108009 +#define GFSCMD_PM1_CONTROL 0x00128009 +#define GFSCMD_SPI_CONTROL 0x00188009 +#define GFSCMD_HSPI_CONTROL 0x00198009 + +#define GF_PW0_DISABLE 0x00000000 +#define GF_PW0_ENABLE 0x00000001 +#define GF_PW1_DISABLE 0x00000000 +#define GF_PW1_ENABLE 0x00000004 +#define GF_PW2_DISABLE 0x00000000 +#define GF_PW2_ENABLE 0x00000010 +#define GF_PW3_DISABLE 0x00000000 +#define GF_PW3_ENABLE 0x00000040 +#define GF_PW4_DISABLE 0x00000000 +#define GF_PW4_ENABLE 0x00010000 +#define GF_PM0_DISABLE 0x00000000 +#define GF_PM0_ENABLE 0x00040000 +#define GF_PM1_DISABLE 0x00000000 +#define GF_PM1_ENABLE 0x00400000 +#define GF_SPI_DISABLE 0x00000000 +#define GF_SPI_ENABLE 0x01000000 +#define GF_HSPI_DISABLE 0x00000000 +#define GF_HSPI_ENABLE 0x02000000 + +// Pin Output Enable registers + +#define OFFSET_PIN_OUTPUT_ENABLE0 0x00000802 +#define GFSCMD_LD0_PIN_OUTPUT 0x00008802 +#define GFSCMD_LD1_PIN_OUTPUT 0x00028802 +#define GFSCMD_LD2_PIN_OUTPUT 0x00048802 +#define GFSCMD_LD3_PIN_OUTPUT 0x00068802 +#define GFSCMD_LD4_PIN_OUTPUT 0x00088802 +#define GFSCMD_LD5_PIN_OUTPUT 0x000a8802 +#define GFSCMD_LD6_PIN_OUTPUT 0x000c8802 +#define GFSCMD_LD7_PIN_OUTPUT 0x000e8802 +#define GFSCMD_LD8_PIN_OUTPUT 0x00108802 +#define GFSCMD_LD9_PIN_OUTPUT 0x00128802 +#define GFSCMD_LD10_PIN_OUTPUT 0x00148802 +#define GFSCMD_LD11_PIN_OUTPUT 0x00168802 +#define GFSCMD_LD12_PIN_OUTPUT 0x00188802 +#define GFSCMD_LD13_PIN_OUTPUT 0x001a8802 +#define GFSCMD_LD14_PIN_OUTPUT 0x001c8802 +#define GFSCMD_LD15_PIN_OUTPUT 0x001e8802 +#define GFSCMD_LD0_LD15_PIN_OUTPUT 0x00208802 + + +#define GF_LD0_OUTPUT_ENABLE 0x00000000 +#define GF_LD0_OUTPUT_DISABLE 0x00000001 +#define GF_LD1_OUTPUT_ENABLE 0x00000000 +#define GF_LD1_OUTPUT_DISABLE 0x00000004 +#define GF_LD2_OUTPUT_ENABLE 0x00000000 +#define GF_LD2_OUTPUT_DISABLE 0x00000010 +#define GF_LD3_OUTPUT_ENABLE 0x00000000 +#define GF_LD3_OUTPUT_DISABLE 0x00000040 +#define GF_LD4_OUTPUT_ENABLE 0x00000000 +#define GF_LD4_OUTPUT_DISABLE 0x00000100 +#define GF_LD5_OUTPUT_ENABLE 0x00000000 +#define GF_LD5_OUTPUT_DISABLE 0x00000400 +#define GF_LD6_OUTPUT_ENABLE 0x00000000 +#define GF_LD6_OUTPUT_DISABLE 0x00001000 +#define GF_LD7_OUTPUT_ENABLE 0x00000000 +#define GF_LD7_OUTPUT_DISABLE 0x00004000 +#define GF_LD8_OUTPUT_ENABLE 0x00000000 +#define GF_LD8_OUTPUT_DISABLE 0x00010000 +#define GF_LD9_OUTPUT_ENABLE 0x00000000 +#define GF_LD9_OUTPUT_DISABLE 0x00040000 +#define GF_LD10_OUTPUT_ENABLE 0x00000000 +#define GF_LD10_OUTPUT_DISABLE 0x00100000 +#define GF_LD11_OUTPUT_ENABLE 0x00000000 +#define GF_LD11_OUTPUT_DISABLE 0x00400000 +#define GF_LD12_OUTPUT_ENABLE 0x00000000 +#define GF_LD12_OUTPUT_DISABLE 0x01000000 +#define GF_LD13_OUTPUT_ENABLE 0x00000000 +#define GF_LD13_OUTPUT_DISABLE 0x04000000 +#define GF_LD14_OUTPUT_ENABLE 0x00000000 +#define GF_LD14_OUTPUT_DISABLE 0x10000000 +#define GF_LD15_OUTPUT_ENABLE 0x00000000 +#define GF_LD15_OUTPUT_DISABLE 0x40000000 +#define GF_LD0_LD15_OUTPUT_ENABLE 0x00000000 +#define GF_LD0_LD15_OUTPUT_DISABLE 0x55555555 + + +#define OFFSET_PIN_OUTPUT_ENABLE1 0x00000803 +#define GFSCMD_LD16_PIN_OUTPUT 0x00008803 +#define GFSCMD_LD17_PIN_OUTPUT 0x00028803 +#define GFSCMD_LPW0_PIN_OUTPUT 0x00108803 +#define GFSCMD_LPW1_PIN_OUTPUT 0x00128803 +#define GFSCMD_LPW2_PIN_OUTPUT 0x00148803 +#define GFSCMD_LSC0_PIN_OUTPUT 0x00188803 +#define GFSCMD_LSC1_PIN_OUTPUT 0x001a8803 +#define GFSCMD_LVS_PIN_OUTPUT 0x001c8803 +#define GFSCMD_LHS_PIN_OUTPUT 0x001e8803 +#define GFSCMD_LD16_LD17_PIN_OUTPUT 0x00208803 + +#define GF_LD16_OUTPUT_ENABLE 0x00000000 +#define GF_LD16_OUTPUT_DISABLE 0x00000001 +#define GF_LD17_OUTPUT_ENABLE 0x00000000 +#define GF_LD17_OUTPUT_DISABLE 0x00000004 +#define GF_LPW0_OUTPUT_ENABLE 0x00000000 +#define GF_LPW0_OUTPUT_DISABLE 0x00010000 +#define GF_LPW1_OUTPUT_ENABLE 0x00000000 +#define GF_LPW1_OUTPUT_DISABLE 0x00040000 +#define GF_LPW2_OUTPUT_ENABLE 0x00000000 +#define GF_LPW2_OUTPUT_DISABLE 0x00100000 +#define GF_LSC0_OUTPUT_ENABLE 0x00000000 +#define GF_LSC0_OUTPUT_DISABLE 0x01000000 +#define GF_LSC1_OUTPUT_ENABLE 0x00000000 +#define GF_LSC1_OUTPUT_DISABLE 0x04000000 +#define GF_LVS_OUTPUT_ENABLE 0x00000000 +#define GF_LVS_OUTPUT_DISABLE 0x10000000 +#define GF_LHS_OUTPUT_ENABLE 0x00000000 +#define GF_LHS_OUTPUT_DISABLE 0x40000000 +#define GF_LD16_LD17_OUTPUT_ENABLE 0x00000000 +#define GF_LD16_LD17_OUTPUT_DISABLE 0x00000005 + + +#define DC_PIN_OUTPUT_ENABLE2 0x00000804 +#define GFSCMD_LHP0_PIN_OUTPUT 0x00008804 +#define GFSCMD_LHP1_PIN_OUTPUT 0x00028804 +#define GFSCMD_LHP2_PIN_OUTPUT 0x00048804 +#define GFSCMD_LVP0_PIN_OUTPUT 0x00088804 +#define GFSCMD_LVP1_PIN_OUTPUT 0x000A8804 +#define GFSCMD_LM0_PIN_OUTPUT 0x00108804 +#define GFSCMD_LM1_PIN_OUTPUT 0x00128804 +#define GFSCMD_LDI_PIN_OUTPUT 0x00148804 +#define GFSCMD_LPP_PIN_OUTPUT 0x00168804 + +#define GF_LHP0_OUTPUT_ENABLE 0x00000000 +#define GF_LHP0_OUTPUT_DISABLE 0x00000001 +#define GF_LHP1_OUTPUT_ENABLE 0x00000000 +#define GF_LHP1_OUTPUT_DISABLE 0x00000004 +#define GF_LHP2_OUTPUT_ENABLE 0x00000000 +#define GF_LHP2_OUTPUT_DISABLE 0x00000010 +#define GF_LVP0_OUTPUT_ENABLE 0x00000000 +#define GF_LVP0_OUTPUT_DISABLE 0x00000100 +#define GF_LVP1_OUTPUT_ENABLE 0x00000000 +#define GF_LVP1_OUTPUT_DISABLE 0x00000404 +#define GF_LM0_OUTPUT_ENABLE 0x00000000 +#define GF_LM0_OUTPUT_DISABLE 0x00010000 +#define GF_LM1_OUTPUT_ENABLE 0x00000000 +#define GF_LM1_OUTPUT_DISABLE 0x00040000 +#define GF_LDI_OUTPUT_ENABLE 0x00000000 +#define GF_LDI_OUTPUT_DISABLE 0x00100000 +#define GF_LPP_OUTPUT_ENABLE 0x00000000 +#define GF_LPP_OUTPUT_DISABLE 0x00400000 + +#define OFFSET_OUTPUT_ENABLE3 0x00000805 +#define GFSCMD_LSCK_PIN_OUTPUT 0x00008805 +#define GFSCMD_LSDA_PIN_OUTPUT 0x00028805 +#define GFSCMD_LCSN_PIN_OUTPUT 0x00048805 +#define GFSCMD_LDC_PIN_OUTPUT 0x00068805 +#define GFSCMD_LSPI_PIN_OUTPUT 0x00088805 + +#define GF_LSCK_OUTPUT_ENABLE 0x00000000 +#define GF_LSCK_OUTPUT_DISABLE 0x00000001 +#define GF_LSDA_OUTPUT_ENABLE 0x00000000 +#define GF_LSDA_OUTPUT_DISABLE 0x00000004 +#define GF_LCSN_OUTPUT_ENABLE 0x00000000 +#define GF_LCSN_OUTPUT_DISABLE 0x00000010 +#define GF_LDC_OUTPUT_ENABLE 0x00000000 +#define GF_LDC_OUTPUT_DISABLE 0x00000040 +#define GF_LSPI_OUTPUT_ENABLE 0x00000000 +#define GF_LSPI_OUTPUT_DISABLE 0x00000100 + + +// Pin Output Polarity registers + +#define OFFSET_PIN_OUTPUT_POLARITY0 0x00000806 +#define GFSCMD_LD0_PIN_POLARITY 0x00008806 +#define GFSCMD_LD1_PIN_POLARITY 0x00028806 +#define GFSCMD_LD2_PIN_POLARITY 0x00048806 +#define GFSCMD_LD3_PIN_POLARITY 0x00068806 +#define GFSCMD_LD4_PIN_POLARITY 0x00088806 +#define GFSCMD_LD5_PIN_POLARITY 0x000a8806 +#define GFSCMD_LD6_PIN_POLARITY 0x000c8806 +#define GFSCMD_LD7_PIN_POLARITY 0x000e8806 +#define GFSCMD_LD8_PIN_POLARITY 0x00108806 +#define GFSCMD_LD9_PIN_POLARITY 0x00128806 +#define GFSCMD_LD10_PIN_POLARITY 0x00148806 +#define GFSCMD_LD11_PIN_POLARITY 0x00168806 +#define GFSCMD_LD12_PIN_POLARITY 0x00188806 +#define GFSCMD_LD13_PIN_POLARITY 0x001a8806 +#define GFSCMD_LD14_PIN_POLARITY 0x001c8806 +#define GFSCMD_LD15_PIN_POLARITY 0x001e8806 +#define GFSCMD_LD0_LD15_PIN_POLARITY 0x00208806 + + +#define GF_LD0_POLARITY_HIGH 0x00000000 +#define GF_LD0_POLARITY_LOW 0x00000001 +#define GF_LD1_POLARITY_HIGH 0x00000000 +#define GF_LD1_POLARITY_LOW 0x00000004 +#define GF_LD2_POLARITY_HIGH 0x00000000 +#define GF_LD2_POLARITY_LOW 0x00000010 +#define GF_LD3_POLARITY_HIGH 0x00000000 +#define GF_LD3_POLARITY_LOW 0x00000040 +#define GF_LD4_POLARITY_HIGH 0x00000000 +#define GF_LD4_POLARITY_LOW 0x00000100 +#define GF_LD5_POLARITY_HIGH 0x00000000 +#define GF_LD5_POLARITY_LOW 0x00000400 +#define GF_LD6_POLARITY_HIGH 0x00000000 +#define GF_LD6_POLARITY_LOW 0x00001000 +#define GF_LD7_POLARITY_HIGH 0x00000000 +#define GF_LD7_POLARITY_LOW 0x00004000 +#define GF_LD8_POLARITY_HIGH 0x00000000 +#define GF_LD8_POLARITY_LOW 0x00010000 +#define GF_LD9_POLARITY_HIGH 0x00000000 +#define GF_LD9_POLARITY_LOW 0x00040000 +#define GF_LD10_POLARITY_HIGH 0x00000000 +#define GF_LD10_POLARITY_LOW 0x00100000 +#define GF_LD11_POLARITY_HIGH 0x00000000 +#define GF_LD11_POLARITY_LOW 0x00400000 +#define GF_LD12_POLARITY_HIGH 0x00000000 +#define GF_LD12_POLARITY_LOW 0x01000000 +#define GF_LD13_POLARITY_HIGH 0x00000000 +#define GF_LD13_POLARITY_LOW 0x04000000 +#define GF_LD14_POLARITY_HIGH 0x00000000 +#define GF_LD14_POLARITY_LOW 0x10000000 +#define GF_LD15_POLARITY_HIGH 0x00000000 +#define GF_LD15_POLARITY_LOW 0x40000000 +#define GF_LD0_LD15_POLARITY_HIGH 0x00000000 +#define GF_LD0_LD15_POLARITY_LOW 0x55555555 + +#define OFFSET_PIN_OUTPUT_POLARITY1 0x00000807 +#define GFSCMD_LD16_PIN_POLARITY 0x00008807 +#define GFSCMD_LD17_PIN_POLARITY 0x00028807 +#define GFSCMD_LPW0_PIN_POLARITY 0x00108807 +#define GFSCMD_LPW1_PIN_POLARITY 0x00128807 +#define GFSCMD_LPW2_PIN_POLARITY 0x00148807 +#define GFSCMD_LSC0_PIN_POLARITY 0x00188807 +#define GFSCMD_LSC1_PIN_POLARITY 0x001a8807 +#define GFSCMD_LVS_PIN_POLARITY 0x001c8807 +#define GFSCMD_LHS_PIN_POLARITY 0x001e8807 +#define GFSCMD_LD16_LD17_PIN_POLARITY 0x00208807 + +#define GF_LD16_POLARITY_HIGH 0x00000000 +#define GF_LD16_POLARITY_LOW 0x00000001 +#define GF_LD17_POLARITY_HIGH 0x00000000 +#define GF_LD17_POLARITY_LOW 0x00000004 +#define GF_LPW0_POLARITY_HIGH 0x00000000 +#define GF_LPW0_POLARITY_LOW 0x00010000 +#define GF_LPW1_POLARITY_HIGH 0x00000000 +#define GF_LPW1_POLARITY_LOW 0x00040000 +#define GF_LPW2_POLARITY_HIGH 0x00000000 +#define GF_LPW2_POLARITY_LOW 0x00100000 +#define GF_LSC0_POLARITY_HIGH 0x00000000 +#define GF_LSC0_POLARITY_LOW 0x01000000 +#define GF_LSC1_POLARITY_HIGH 0x00000000 +#define GF_LSC1_POLARITY_LOW 0x04000000 +#define GF_LVS_POLARITY_HIGH 0x00000000 +#define GF_LVS_POLARITY_LOW 0x10000000 +#define GF_LHS_POLARITY_HIGH 0x00000000 +#define GF_LHS_POLARITY_LOW 0x40000000 +#define GF_LD16_LD17_POLARITY_HIGH 0x00000000 +#define GF_LD16_LD17_POLARITY_LOW 0x00000005 + +#define DC_PIN_OUTPUT_POLARITY2 0x00000808 +#define GFSCMD_LHP0_PIN_POLARITY 0x00008808 +#define GFSCMD_LHP1_PIN_POLARITY 0x00028808 +#define GFSCMD_LHP2_PIN_POLARITY 0x00048808 +#define GFSCMD_LVP0_PIN_POLARITY 0x00088808 +#define GFSCMD_LVP1_PIN_POLARITY 0x000A8808 +#define GFSCMD_LM0_PIN_POLARITY 0x00108808 +#define GFSCMD_LM1_PIN_POLARITY 0x00128808 +#define GFSCMD_LDI_PIN_POLARITY 0x00148808 +#define GFSCMD_LPP_PIN_POLARITY 0x00168808 + +#define GF_LHP0_POLARITY_HIGH 0x00000000 +#define GF_LHP0_POLARITY_LOW 0x00000001 +#define GF_LHP1_POLARITY_HIGH 0x00000000 +#define GF_LHP1_POLARITY_LOW 0x00000004 +#define GF_LHP2_POLARITY_HIGH 0x00000000 +#define GF_LHP2_POLARITY_LOW 0x00000010 +#define GF_LVP0_POLARITY_HIGH 0x00000000 +#define GF_LVP0_POLARITY_LOW 0x00000100 +#define GF_LVP1_POLARITY_HIGH 0x00000000 +#define GF_LVP1_POLARITY_LOW 0x00000404 +#define GF_LM0_POLARITY_HIGH 0x00000000 +#define GF_LM0_POLARITY_LOW 0x00010000 +#define GF_LM1_POLARITY_HIGH 0x00000000 +#define GF_LM1_POLARITY_LOW 0x00040000 +#define GF_LDI_POLARITY_HIGH 0x00000000 +#define GF_LDI_POLARITY_LOW 0x00100000 +#define GF_LPP_POLARITY_HIGH 0x00000000 +#define GF_LPP_POLARITY_LOW 0x00400000 + +#define OFFSET_OUTPUT_POLARITY3 0x00000809 +#define GFSCMD_LSCK_PIN_POLARITY 0x00008809 +#define GFSCMD_LSDA_PIN_POLARITY 0x00028809 +#define GFSCMD_LCSN_PIN_POLARITY 0x00048809 +#define GFSCMD_LDC_PIN_POLARITY 0x00068809 +#define GFSCMD_LSPI_PIN_POLARITY 0x00088809 + +#define GF_LSCK_POLARITY_HIGH 0x00000000 +#define GF_LSCK_POLARITY_LOW 0x00000001 +#define GF_LSDA_POLARITY_HIGH 0x00000000 +#define GF_LSDA_POLARITY_LOW 0x00000004 +#define GF_LCSN_POLARITY_HIGH 0x00000000 +#define GF_LCSN_POLARITY_LOW 0x00000010 +#define GF_LDC_POLARITY_HIGH 0x00000000 +#define GF_LDC_POLARITY_LOW 0x00000040 +#define GF_LSPI_POLARITY_HIGH 0x00000000 +#define GF_LSPI_POLARITY_LOW 0x00000100 + +// Pin Output data registers + +#define OFFSET_PIN_OUTPUT_DATA0 0x0000080a +#define GFSCMD_LD0_PIN_OUTPUT_DATA 0x0000880a +#define GFSCMD_LD1_PIN_OUTPUT_DATA 0x0002880a +#define GFSCMD_LD2_PIN_OUTPUT_DATA 0x0004880a +#define GFSCMD_LD3_PIN_OUTPUT_DATA 0x0006880a +#define GFSCMD_LD4_PIN_OUTPUT_DATA 0x0008880a +#define GFSCMD_LD5_PIN_OUTPUT_DATA 0x000a880a +#define GFSCMD_LD6_PIN_OUTPUT_DATA 0x000c880a +#define GFSCMD_LD7_PIN_OUTPUT_DATA 0x000e880a +#define GFSCMD_LD8_PIN_OUTPUT_DATA 0x0010880a +#define GFSCMD_LD9_PIN_OUTPUT_DATA 0x0012880a +#define GFSCMD_LD10_PIN_OUTPUT_DATA 0x0014880a +#define GFSCMD_LD11_PIN_OUTPUT_DATA 0x0016880a +#define GFSCMD_LD12_PIN_OUTPUT_DATA 0x0018880a +#define GFSCMD_LD13_PIN_OUTPUT_DATA 0x001a880a +#define GFSCMD_LD14_PIN_OUTPUT_DATA 0x001c880a +#define GFSCMD_LD15_PIN_OUTPUT_DATA 0x001e880a +#define GFSCMD_LD0_LD15_PIN_OUTPUT_DATA 0x0020880a + + +#define GF_LD0_DATA_LOW 0x00000002 +#define GF_LD0_DATA_HIGH 0x00000003 +#define GF_LD1_DATA_LOW 0x00000008 +#define GF_LD1_DATA_HIGH 0x0000000c +#define GF_LD2_DATA_LOW 0x00000020 +#define GF_LD2_DATA_HIGH 0x00000030 +#define GF_LD3_DATA_LOW 0x00000080 +#define GF_LD3_DATA_HIGH 0x000000c0 +#define GF_LD4_DATA_LOW 0x00000200 +#define GF_LD4_DATA_HIGH 0x00000300 +#define GF_LD5_DATA_LOW 0x00000800 +#define GF_LD5_DATA_HIGH 0x00000c00 +#define GF_LD6_DATA_LOW 0x00002000 +#define GF_LD6_DATA_HIGH 0x00003000 +#define GF_LD7_DATA_LOW 0x00008000 +#define GF_LD7_DATA_HIGH 0x0000c000 +#define GF_LD8_DATA_LOW 0x00020000 +#define GF_LD8_DATA_HIGH 0x00030000 +#define GF_LD9_DATA_LOW 0x00080000 +#define GF_LD9_DATA_HIGH 0x000c0000 +#define GF_LD10_DATA_LOW 0x00200000 +#define GF_LD10_DATA_HIGH 0x00300000 +#define GF_LD11_DATA_LOW 0x00800000 +#define GF_LD11_DATA_HIGH 0x00c00000 +#define GF_LD12_DATA_LOW 0x02000000 +#define GF_LD12_DATA_HIGH 0x03000000 +#define GF_LD13_DATA_LOW 0x08000000 +#define GF_LD13_DATA_HIGH 0x0c000000 +#define GF_LD14_DATA_LOW 0x20000000 +#define GF_LD14_DATA_HIGH 0x30000000 +#define GF_LD15_DATA_LOW 0x80000000 +#define GF_LD15_DATA_HIGH 0xc0000000 +#define GF_LD0_LD15_DATA_LOW 0xaaaaaaaa +#define GF_LD0_LD15_DATA_HIGH 0xffffffff + +#define OFFSET_PIN_OUTPUT_DATA1 0x0000080b +#define GFSCMD_LD16_PIN_OUTPUT_DATA 0x0000880b +#define GFSCMD_LD17_PIN_OUTPUT_DATA 0x0002880b +#define GFSCMD_LPW0_PIN_OUTPUT_DATA 0x0010880b +#define GFSCMD_LPW1_PIN_OUTPUT_DATA 0x0012880b +#define GFSCMD_LPW2_PIN_OUTPUT_DATA 0x0014880b +#define GFSCMD_LSC0_PIN_OUTPUT_DATA 0x0018880b +#define GFSCMD_LSC1_PIN_OUTPUT_DATA 0x001a880b +#define GFSCMD_LVS_PIN_OUTPUT_DATA 0x001c880b +#define GFSCMD_LHS_PIN_OUTPUT_DATA 0x001e880b +#define GFSCMD_LD16_LD17_PIN_OUTPUT_DATA 0x0020880b + +#define GF_LD16_DATA_LOW 0x00000002 +#define GF_LD16_DATA_HIGH 0x00000003 +#define GF_LD17_DATA_LOW 0x00000008 +#define GF_LD17_DATA_HIGH 0x0000000c +#define GF_LPW0_DATA_LOW 0x00020000 +#define GF_LPW0_DATA_HIGH 0x00030000 +#define GF_LPW1_DATA_LOW 0x00080000 +#define GF_LPW1_DATA_HIGH 0x000c0000 +#define GF_LPW2_DATA_LOW 0x00200000 +#define GF_LPW2_DATA_HIGH 0x00300000 +#define GF_LSC0_DATA_LOW 0x02000000 +#define GF_LSC0_DATA_HIGH 0x03000000 +#define GF_LSC1_DATA_LOW 0x08000000 +#define GF_LSC1_DATA_HIGH 0x0c000000 +#define GF_LVS_DATA_LOW 0x20000000 +#define GF_LVS_DATA_HIGH 0x30000000 +#define GF_LHS_DATA_LOW 0x80000000 +#define GF_LHS_DATA_HIGH 0xc0000000 +#define GF_LD16_LD17_DATA_LOW 0x0000000a +#define GF_LD16_LD17_DATA_HIGH 0x0000000f + + +#define OFFSET_PIN_OUTPUT_DATA2 0x0000080c +#define GFSCMD_LHP0_PIN_OUTPUT_DATA 0x0000880c +#define GFSCMD_LHP1_PIN_OUTPUT_DATA 0x0002880c +#define GFSCMD_LHP2_PIN_OUTPUT_DATA 0x0004880c +#define GFSCMD_LVP0_PIN_OUTPUT_DATA 0x0008880c +#define GFSCMD_LVP1_PIN_OUTPUT_DATA 0x000A880c +#define GFSCMD_LM0_PIN_OUTPUT_DATA 0x0010880c +#define GFSCMD_LM1_PIN_OUTPUT_DATA 0x0012880c +#define GFSCMD_LDI_PIN_OUTPUT_DATA 0x0014880c +#define GFSCMD_LPP_PIN_OUTPUT_DATA 0x0016880c + +#define GF_LHP0_DATA_LOW 0x00000002 +#define GF_LHP0_DATA_HIGH 0x00000003 +#define GF_LHP1_DATA_LOW 0x00000008 +#define GF_LHP1_DATA_HIGH 0x0000000c +#define GF_LHP2_DATA_LOW 0x00000020 +#define GF_LHP2_DATA_HIGH 0x00000030 +#define GF_LVP0_DATA_LOW 0x00000200 +#define GF_LVP0_DATA_HIGH 0x00000300 +#define GF_LVP1_DATA_LOW 0x00000800 +#define GF_LVP1_DATA_HIGH 0x00000c00 +#define GF_LM0_DATA_LOW 0x00020000 +#define GF_LM0_DATA_HIGH 0x00030000 +#define GF_LM1_DATA_LOW 0x00080000 +#define GF_LM1_DATA_HIGH 0x000c0000 +#define GF_LDI_DATA_LOW 0x00200000 +#define GF_LDI_DATA_HIGH 0x00300000 +#define GF_LPP_DATA_LOW 0x00800000 +#define GF_LPP_DATA_HIGH 0x00c00000 + +#define OFFSET_OUTPUT_DATA3 0x0000080d +#define GFSCMD_LSCK_PIN_OUTPUT_DATA 0x0000880d +#define GFSCMD_LSDA_PIN_OUTPUT_DATA 0x0002880d +#define GFSCMD_LCSN_PIN_OUTPUT_DATA 0x0004880d +#define GFSCMD_LDC_PIN_OUTPUT_DATA 0x0006880d +#define GFSCMD_LSPI_PIN_OUTPUT_DATA 0x0008880d + +#define GF_LSCK_DATA_LOW 0x00000002 +#define GF_LSCK_DATA_HIGH 0x00000003 +#define GF_LSDA_DATA_LOW 0x00000008 +#define GF_LSDA_DATA_HIGH 0x0000000c +#define GF_LCSN_DATA_LOW 0x00000020 +#define GF_LCSN_DATA_HIGH 0x00000030 +#define GF_LDC_DATA_LOW 0x00000080 +#define GF_LDC_DATA_HIGH 0x000000c0 +#define GF_LSPI_DATA_LOW 0x00000200 +#define GF_LSPI_DATA_HIGH 0x00000300 + +// Pin Input Enable + +#define GFSCMD_LSPI_PIN_INPUT 0x00088811 +#define GF_LSPI_INPUT_ENABLE 0x00000000 +#define GF_LSPI_INPUT_DISABLE 0x00000100 + +#define GFSCMD_LDC_PIN_INPUT 0x00088411 +#define GF_LDC_INPUT_ENABLE 0x00000000 +#define GF_LDC_INPUT_DISABLE 0x00000040 + +#define GFSCMD_LPP_PIN_INPUT 0x00168811 +#define GF_LPP_INPUT_ENABLE 0x00000000 +#define GF_LPP_INPUT_DISABLE 0x00400000 + +// Pin Output Select + +#define DC_PIN_OUTPUT_SELECT0 0x00000814 +#define GFSCMD_LD0_OUTPUT_SELECT 0x00008814 +#define GFSCMD_LD1_OUTPUT_SELECT 0x00048814 +#define GFSCMD_LD2_OUTPUT_SELECT 0x00088814 +#define GFSCMD_LD3_OUTPUT_SELECT 0x000C8814 +#define GFSCMD_LD4_OUTPUT_SELECT 0x00108814 +#define GFSCMD_LD5_OUTPUT_SELECT 0x00148814 +#define GFSCMD_LD6_OUTPUT_SELECT 0x00188814 +#define GFSCMD_LD7_OUTPUT_SELECT 0x001C8814 +#define GFSCMD_LD0_LD7_OUTPUT_SELECT 0x00208814 + +#define GF_LD0_PIN_FOR_LD0 0 +#define GF_LD0_PIN_FOR_LD0_OUT 1 +#define GF_LD0_PIN_FOR_SC_ 4 +#define GF_LD1_PIN_FOR_LD1 0 +#define GF_LD1_PIN_FOR_LD1_OUT 1 +#define GF_LD1_PIN_FOR_SC 4 +#define GF_LD2_PIN_FOR_LD2 0 +#define GF_LD2_PIN_FOR_LD2_OUT 1 +#define GF_LD2_PIN_FOR_SD0_ 4 +#define GF_LD3_PIN_FOR_LD3 0 +#define GF_LD3_PIN_FOR_LD3_OUT 1 +#define GF_LD3_PIN_FOR_SD0 4 +#define GF_LD4_PIN_FOR_LD4 0 +#define GF_LD4_PIN_FOR_LD4_OUT 1 +#define GF_LD4_PIN_FOR_SD1_ 4 +#define GF_LD5_PIN_FOR_LD5 0 +#define GF_LD5_PIN_FOR_LD5_OUT 1 +#define GF_LD5_PIN_FOR_SD1 4 +#define GF_LD6_PIN_FOR_LD6 0 +#define GF_LD6_PIN_FOR_LD6_OUT 1 +#define GF_LD6_PIN_FOR_STH 4 +#define GF_LD7_PIN_FOR_LD7 0 +#define GF_LD7_PIN_FOR_LD7_OUT 1 +#define GF_LD7_PIN_FOR_SDT 4 +#define GF_LD0_LD7_PIN_FOR_LD0_LD7 0x00000000 +#define GF_LD0_LD7_PIN_FOR_LD0_LD7_OUT 0x11111111 +#define GF_LD0_LD7_PIN_FOR_LPD0_LPD7_OUT 0x22222222 + +#define DC_PIN_OUTPUT_SELECT1 0x00000815 +#define GFSCMD_LD8_OUTPUT_SELECT 0x00008815 +#define GFSCMD_LD9_OUTPUT_SELECT 0x00048815 +#define GFSCMD_LD10_OUTPUT_SELECT 0x00088815 +#define GFSCMD_LD11_OUTPUT_SELECT 0x000C8815 +#define GFSCMD_LD12_OUTPUT_SELECT 0x00108815 +#define GFSCMD_LD13_OUTPUT_SELECT 0x00148815 +#define GFSCMD_LD14_OUTPUT_SELECT 0x00188815 +#define GFSCMD_LD15_OUTPUT_SELECT 0x001C8815 +#define GFSCMD_LD8_LD15_OUTPUT_SELECT 0x00208815 + +#define GF_LD8_PIN_FOR_LD8 0 +#define GF_LD8_PIN_FOR_LD8_OUT 1 +#define GF_LD8_PIN_FOR_LPD8_OUT 2 +#define GF_LD8_PIN_FOR_STP 4 +#define GF_LD9_PIN_FOR_LD9 0 +#define GF_LD9_PIN_FOR_LD9_OUT 1 +#define GF_LD9_PIN_FOR_LPD9_OUT 2 +#define GF_LD9_PIN_FOR_SD2_ 4 +#define GF_LD10_PIN_FOR_LD10 0 +#define GF_LD10_PIN_FOR_LD10_OUT 1 +#define GF_LD10_PIN_FOR_SD2 4 +#define GF_LD11_PIN_FOR_LD11 0 +#define GF_LD11_PIN_FOR_LD11_OUT 1 +#define GF_LD12_PIN_FOR_LD12 0 +#define GF_LD12_PIN_FOR_LD12_OUT 1 +#define GF_LD13_PIN_FOR_LD13 0 +#define GF_LD13_PIN_FOR_LD13_OUT 1 +#define GF_LD14_PIN_FOR_LD14 0 +#define GF_LD14_PIN_FOR_LD14_OUT 1 +#define GF_LD15_PIN_FOR_LD15 0 +#define GF_LD15_PIN_FOR_LD15_OUT 1 +#define GF_LD8_LD15_PIN_FOR_LD8_LD15 0x00000000 +#define GF_LD8_LD15_PIN_FOR_LD8_LD15_OUT 0x11111111 +#define GF_LD8_LD15_PIN_FOR_LPD8_LPD15_OUT 0x22222222 + +#define DC_PIN_OUTPUT_SELECT2 0x00000816 +#define GFSCMD_LD16_OUTPUT_SELECT 0x00008816 +#define GFSCMD_LD17_OUTPUT_SELECT 0x00048816 + +#define GF_LD16_PIN_FOR_LD16 0 +#define GF_LD16_PIN_FOR_LD16_OUT 1 +#define GF_LD17_PIN_FOR_LD17 0 +#define GF_LD17_PIN_FOR_LD17_OUT 1 + +#define OFFSET_PIN_OUTPUT_SELECT3 0x00000817 +#define GFSCMD_LPW0_OUTPUT_SELECT 0x00008817 +#define GFSCMD_LPW1_OUTPUT_SELECT 0x00048817 +#define GFSCMD_LPW2_OUTPUT_SELECT 0x00088817 +#define GFSCMD_LSC0_OUTPUT_SELECT 0x00108817 +#define GFSCMD_LSC1_OUTPUT_SELECT 0x00148817 +#define GFSCMD_LVS_OUTPUT_SELECT 0x00188817 +#define GFSCMD_LHS_OUTPUT_SELECT 0x001c8817 + +#define GF_LPW0_PIN_FOR_PW0 0 +#define GF_LPW0_PIN_FOR_PW0_OUT 1 +#define GF_LPW0_PIN_FOR_PW1 2 +#define GF_LPW0_PIN_FOR_PM0 3 +#define GF_LPW0_PIN_FOR_PW2 4 +#define GF_LPW1_PIN_FOR_PW1 0 +#define GF_LPW1_PIN_FOR_PW1_OUT 1 +#define GF_LPW1_PIN_FOR_PW2 2 +#define GF_LPW1_PIN_FOR_PM1 3 +#define GF_LPW1_PIN_FOR_PW3 4 +#define GF_LPW2_PIN_FOR_PW2 0 +#define GF_LPW2_PIN_FOR_PW2_OUT 1 +#define GF_LPW2_PIN_FOR_PW3 2 +#define GF_LPW2_PIN_FOR_PM0 3 +#define GF_LPW2_PIN_FOR_PW4 4 +#define GF_LSC0_PIN_FOR_LSC0 0 +#define GF_LSC0_PIN_FOR_LSC0_OUT 1 +#define GF_LSC1_PIN_FOR_LSC1 0 +#define GF_LSC1_PIN_FOR_LSC1_OUT 1 +#define GF_LSC1_PIN_FOR_LSC1_DE 2 +#define GF_LVS_PIN_FOR_VSYNC 0 +#define GF_LVS_PIN_FOR_LVS_OUT 1 +#define GF_LVS_PIN_FOR_PM1 3 +#define GF_LHS_PIN_FOR_HSYNC 0 +#define GF_LHS_PIN_FOR_LHS_OUT 1 +#define GF_LHS_PIN_FOR_PM0 3 + +#define OFSSET_PIN_OUTPUT_SELECT4 0x00000818 +#define GFSCMD_LHP0_OUTPUT_SELECT 0x00008818 +#define GFSCMD_LHP1_OUTPUT_SELECT 0x00048818 +#define GFSCMD_LHP2_OUTPUT_SELECT 0x00088818 +#define GFSCMD_LVP0_OUTPUT_SELECT 0x00108818 +#define GFSCMD_LVP1_OUTPUT_SELECT 0x00148818 + +#define GF_LHP0_PIN_FOR_LHP0 0 +#define GF_LHP0_PIN_FOR_LHP0_OUT 1 +#define GF_LHP0_PIN_FOR_LD21 2 +#define GF_LHP0_PIN_FOR_PM0 3 +#define GF_LHP1_PIN_FOR_LHP1 0 +#define GF_LHP1_PIN_FOR_LHP1_OUT 1 +#define GF_LHP1_PIN_FOR_LD18 2 +#define GF_LHP1_PIN_FOR_PM1 3 +#define GF_LHP2_PIN_FOR_LHP2 0 +#define GF_LHP2_PIN_FOR_LHP2_OUT 1 +#define GF_LHP2_PIN_FOR_LD19 2 +#define GF_LHP2_PIN_FOR_PM0 3 +#define GF_LHP2_PIN_FOR_LVP2 4 +#define GF_LVP0_PIN_FOR_LVP0 0 +#define GF_LVP0_PIN_FOR_LVP0_OUT 1 +#define GF_LVP0_PIN_FOR_PM0 3 +#define GF_LVP1_PIN_FOR_LVP1 0 +#define GF_LVP1_PIN_FOR_LVP1_OUT 1 +#define GF_LVP1_PIN_FOR_LD20 2 +#define GF_LVP1_PIN_FOR_PM1 3 +#define GF_LVP1_PIN_FOR_PW4 4 + +#define OFFSET_PIN_OUTPUT_SELECT5 0x00000819 +#define GFSCMD_LM0_OUTPUT_SELECT 0x00008819 +#define GFSCMD_LM1_OUTPUT_SELECT 0x00048819 +#define GFSCMD_LDI_OUTPUT_SELECT 0x00088819 +#define GFSCMD_LPP_OUTPUT_SELECT 0x000c8819 + +#define GF_LM0_PIN_FOR_LM0 0 +#define GF_LM0_PIN_FOR_LM0_OUT 1 +#define GF_LM0_PIN_FOR_SCS 2 +#define GF_LM0_PIN_FOR_PM0 3 +#define GF_LM0_PIN_FOR_LVP2 4 +#define GF_LM1_PIN_FOR_M1 0 +#define GF_LM1_PIN_FOR_LM1_OUT 1 +#define GF_LM1_PIN_FOR_LD21 2 +#define GF_LM1_PIN_FOR_PM1 3 +#define GF_LM1_PIN_FOR_LVP3 4 +#define GF_LDI_PIN_FOR_DI 0 +#define GF_LDI_PIN_FOR_LDI_OUT 1 +#define GF_LDI_PIN_FOR_LD22 2 +#define GF_LDI_PIN_FOR_PM0 3 +#define GF_LDI_PIN_FOR_SCS 4 +#define GF_LPP_PIN_FOR_PP 0 +#define GF_LPP_PIN_FOR_LPP_OUT 1 +#define GF_LPP_PIN_FOR_LD23 2 +#define GF_LPP_PIN_FOR_PM1 3 +#define GF_LPP_PIN_FOR_LVP3 4 + +#define OFFSET_PIN_OUTPUT_SELECT6 0x0000081a +#define GFSCMD_LSCK_OUTPUT_SELECT 0x0000881a +#define GFSCMD_LSDA_OUTPUT_SELECT 0x0004881a +#define GFSCMD_LCSN_OUTPUT_SELECT 0x0008881a +#define GFSCMD_LDC_OUTPUT_SELECT 0x000c881a +#define GFSCMD_LSPI_OUTPUT_SELECT 0x0010881a + +#define GF_LSCK_PIN_FOR_SCK 0 +#define GF_LSCK_PIN_FOR_LSCK_OUT 1 +#define GF_LSCK_PIN_FOR_PM0 3 +#define GF_LSDA_PIN_FOR_SDA 0 +#define GF_LSDA_PIN_FOR_LSDA_OUT 1 +#define GF_LSDA_PIN_FOR_SCS 2 +#define GF_LSDA_PIN_FOR_PM1 3 +#define GF_LCS_PIN_FOR_MCS 0 +#define GF_LCS_PIN_FOR_LCS_OUT 1 +#define GF_LCS_PIN_FOR_PM0 3 +#define GF_LDC_PIN_FOR_SDC 0 +#define GF_LDC_PIN_FOR_LDC_OUT 1 +#define GF_LDC_PIN_FOR_LD22 2 +#define GF_LDC_PIN_FOR_PM1 3 +#define GF_LSPI_PIN_FOR_SPI 0 +#define GF_LSPI_PIN_FOR_LSPI_OUT 1 +#define GF_LSPI_PIN_FOR_DE 2 +#define GF_LSPI_PIN_FOR_PM0 3 +#define GF_LSPI_PIN_FOR_PCLK 4 + + +//#define OFFSET_PIN_MISC_CONTROL 0x0000081b +//#define DISP_CLOCK_OUTPUT_MASK +//#define DISP_CLOCK_OUTPUT_SHIFT +//#define DISP_CLOCK_OUTPUT_DISABLE +//#define DISP_CLOCK_OUTPUT_ENABLE + +#define OFFSET_PM0_CONTROL 0x0000081c +#define GFSCMD_PM0_CLOCK_SELECT 0x0000881c +#define GFSCMD_PM0_CLOCK_DIVIDER 0x0004881c +#define GFSCMD_PM0_PERIOD 0x0012881c + +#define GF_PM0_SHIFT_CLOCK 0x00000000 +#define GF_PM0_PIXEL_CLOCK 0x00000001 +#define GF_PM0_LINE_CLOCK 0x00000002 +#define GF_PM0_FRAME_CLOCK 0x00000003 +#define GF_PM0_CLOCK_DIVIDER_VAL 0x00000010 +#define GF_PM0_PERIOD_VAL 0x00040000 + +#define OFFSET_PM0_DUTY_CYCLE 0x0000081d +#define GFSCMD_PM0_DUTY_CYCLE 0x0000881d + +#define GF_PM0_DUTY_CYCLE_VAL 0x00000000 + +#define OFFSET_PM1_CONTROL 0x0000081e +#define GFSCMD_PM1_CLOCK_SELECT 0x0000881e +#define GFSCMD_PM1_CLOCK_DIVIDER 0x0004881e +#define GFSCMD_PM1_PERIOD 0x0012881e + +#define GF_PM1_SHIFT_CLOCK 0x00000000 +#define GF_PM1_PIXEL_CLOCK 0x00000001 +#define GF_PM1_LINE_CLOCK 0x00000002 +#define GF_PM1_FRAME_CLOCK 0x00000003 +#define GF_PM1_CLOCK_DIVIDER_VAL 0x00000010 +#define GF_PM1_PERIOD_VAL 0x00040000 + +#define OFFSET_PM1_DUTY_CYCLE 0x0000081f +#define GFSCMD_PM1_DUTY_CYCLE 0x0000881f + +#define GF_PM1_DUTY_CYCLE_VAL 0x00000000 + +//////////////////////// +#define OFFSET_SPI_CONTROL 0x00000820 +#define GFSCMD_SPI_SERIAL_CLK_CONTROL 0x00008820 +#define GFSCMD_SPI_DATA_DIRECTION 0x00038820 +#define GFSCMD_SPI_BITS_PER_CYCLE 0x00048820 +#define GFSCMD_SPI_CLK_DIVIDER_1_32 0x00108820 +#define GFSCMD_SPI_STATUS 0x00188820 + +#define GF_SPI_1SCLK_CS_RISING_EDGE_ACTV 0x00000000 +#define GF_SPI_2SCLK_CS_RISING_EDGE_ACTV 0x00000001 +#define GF_SPI_1SCLK_CS_FALLING_EDGE_ACTV 0x00000002 +#define GF_SPI_2SCLK_CS_FALLING_EDGE_ACTV 0x00000003 +#define GF_SPI_MSB2LSB 0x00000000 +#define GF_SPI_LSB2MSB 0x00000008 +#define GF_SPI8 0x00000000 +#define GF_SPI8DC 0x00000010 +#define GF_SPI12 0x00000020 +#define GF_SPI16 0x00000030 +#define GF_SPI16DC 0x00000040 +#define GF_START_BYTE_PLUS_SPI16 0x00000050 +#define GF_SPI18 0x00000060 +#define GF_SPI24 0x00000070 +//#define GF_SPI_CLK_DIVIDER_1_32_VAL +#define GF_SPI_STATUS_DISABLE 0x00000000 +#define GF_STATUS_ENABLE_HOST_SPI 0x01000000 +#define GF_STATUS_ENABLE_HOST_IS_SPI 0x02000000 +#define GF_STATUS_ENABLE_ALL_SPI_CYCL 0x03000000 + +//#define OFFSET_HSPI_START_BYTE 0x00000821 +#define GFSCMD_HSPI_DATA_START_BYTE 0x00008821 +#define GFSCMD_HSPI_START_BYTE 0x00008821 +//#define GFSCMD_HSPI_COMMAND_START_BYTE 0x00088821 + +//#define OFFSET_HSPI_WRITE_DATA_CD 0x00000822 +#define GFSCMD_HSPI_WRITE_DATA_A 0x00008822 +#define GFSCMD_HSPI_WRITE_DATA_B 0x00088822 +#define GFSCMD_HSPI_WRITE_DATA_AB 0x00208822 + +//#define OFFSET_HSPI_WRITE_DATA_CD 0x00000823 +#define GFSCMD_HSPI_WRITE_DATA_C 0x00008823 +#define GFSCMD_HSPI_WRITE_DATA_D 0x00088823 +#define GFSCMD_HSPI_WRITE_DATA_CD 0x00208823 + +#define GF_HSPI_CMD_CYCLE1 0 +#define GF_HSPI_CMD_CYCLE2 0 +#define GF_HSPI_CMD_CYCLE3 0 +#define GF_HSPI_CMD_CYCLE4 0 + +#define GF_HSPI_DATA_CYCLE1 1 +#define GF_HSPI_DATA_CYCLE2 2 +#define GF_HSPI_DATA_CYCLE3 4 +#define GF_HSPI_DATA_CYCLE4 8 + +#define GF_HSPI_MAIN_CS_CYCLE1 1 +#define GF_HSPI_MAIN_CS_CYCLE2 2 +#define GF_HSPI_MAIN_CS_CYCLE3 4 +#define GF_HSPI_MAIN_CS_CYCLE4 8 + +#define GF_HSPI_SUB_CS_CYCLE1 1 +#define GF_HSPI_SUB_CS_CYCLE2 2 +#define GF_HSPI_SUB_CS_CYCLE3 4 +#define GF_HSPI_SUB_CS_CYCLE4 8 + +////////////////////////// + +#if 0 +// LCD SPI interface signals + +#define DC_P_LCD_SPI_OPTIONS 0x00000135 +#define GF_LCD_SPI_CS 0x00008135 +#define GF_LCD_SPI_DC 0x00018135 +#define GF_SPI_CS_CONTROL 0x00028135 +#define GF_LCD_SPI_DIRECTION 0x00048135 + +#define GF_LCD_SPI_CS_MAIN 0x00000000 +#define GF_LCD_SPI_CS_SUB 0x00000001 +#define GF_LCD_SPI_DC_LOW 0x00000000 +#define GF_LCD_SPI_DC_HIGH 0x00000002 +#define GF_SPI_CS_CONTROL_LCD_IS_SPI 0x00000000 +#define GF_SPI_CS_CONTROL_LCD_SPI 0x00000004 +#define GF_SPI_CS_CONTROL_IS_SPI 0x00000008 +#define GF_SPI_CS_CONTROL_FORCED 0x0000000C +#define GF_LCD_SPI_DIRECTION_MSB2LSB 0x00000000 +#define GF_LCD_SPI_DIRECTION_LSB2MSB 0x00000010 +#endif + +// Class: Initialization Sequence (IS) + +#define OFSSET_P_INIT_SEQ_CONTROL 0x00000141 +#define GFSCMD_SEND_INIT_SEQUENCE 0x00008141 +#define GFSCMD_INIT_SEQUENCE_MODE_PLCD 0x00018141 +#define GFSCMD_INIT_SEQ_DC_SIGNAL_NODC 0x00048141 +#define GFSCMD_INIT_SEQ_DC_CONTROL 0x00078141 +#define GFSCMD_FRAME_INIT_SEQ_CYCLES 0x00088141 + +#define GF_SEND_INIT_SEQUENCE_DISABLE 0x00000000 +#define GF_SEND_INIT_SEQUENCE_ENABLE 0x00000001 +#define GF_INIT_SEQUENCE_MODE_PLCD_INIT 0x00000000 +#define GF_INIT_SEQUENCE_MODE_SPI_INIT 0x00000002 +#define GF_INIT_SEQ_SIGNAL_NODC 0x00000000 +#define GF_INIT_SEQ_SIGNAL_VSYNC 0x00000010 +#define GF_INIT_SEQ_SIGNAL_VPULSE0 0x00000020 +#define GF_INIT_SEQ_SIGNAL_VPULSE1 0x00000030 +#define GF_INIT_SEQ_SIGNAL_VPULSE2 0x00000040 +#define GF_INIT_SEQ_SIGNAL_VPULSE3 0x00000050 +#define GF_INIT_SEQ_CONTROL 0x00000080 + +//#define GF_FRAME_INIT_SEQ_CYCLES 0x00000100 + + +// SPI Init Sequence Write Data bits 31-0 +#define DC_P_SPI_INIT_SEQ_DATA_A 0x00000142 +#define GFSCMD_SPI_INIT_SEQ_DATA_A 0x00008142 + +// SPI Init Sequence Write Data bits 63-32 +#define DC_P_SPI_INIT_SEQ_DATA_B 0x00000143 +#define GFSCMD_SPI_INIT_SEQ_DATA_B 0x00008143 + +// SPI Init Sequence Write Data bits 95-64 +#define DC_P_SPI_INIT_SEQ_DATA_C 0x00000144 +#define GFSCMD_SPI_INIT_SEQ_DATA_C 0x00008144 + +// SPI Init Sequence Write Data bits 127-96 +#define DC_P_SPI_INIT_SEQ_DATA_D 0x00000145 +#define GFSCMD_SPI_INIT_SEQ_DATA_D 0x00008145 + +#define OFFSET_DISPLAY_COMMAND 0x00000003 +#define GFSCMD_DISPLAY_CTRL_MODE 0x00058003 + +#define GF_CTRL_MODE_STOP 0x00000000 +#define GF_CTRL_MODE_C_DISPLAY 0x00000020 +#define GF_CTRL_MODE_NC_DISPLAY 0x00000040 +#define GF_CTRL_MODE_NOCHANGE 0x000000C0 + + +/* Other Commands */ + +#define GF_NO_DATA 0x00000000 +#define GFSCMD_LVDD_ON 0x01020000 +#define GFSCMD_LVDD_OFF 0x01020001 + +#define GFSCMD_RESET_LHP2 0x0104880c +#define GFSCMD_RESET_LVP0 0x0108880c +#define GFSCMD_MS_DELAY 0x01005A5A +#define GFSCMD_WAIT_VBLANK 0x01005555 +#define GFSCMD_END_OF_TABLE 0x0100ffff +#define GFSCMD_I2C_A_PAL_PLL2_CLK 0x0100F000 + +#define GFSDEFAULT_CMD 0x10000000 // Default settings +#define GFSDEFAULT_BACKLIGHT0 0x10000001 +#define GF_ON_LPW2 0x00000000 +#define GF_ON_LPW0 0x00000001 + +#define GFSDEFAULT_BACKLIGHT1 0x10000002 +#define GF_ON_LM1 0x00000000 +#define GF_ON_LPW1 0x00000001 + +#define GFPDRV_CMD 0x20000000 +#define GFHOST_CMD 0x40000000 +#define GFSCMD_PANEL_PKT_HEADER_START 0x40000000 + +#define GF_DLY_AFTR_DATA_SENT_MASK 0x00002000 +#define GF_A_2MS_DLY_AFTR_DATA_SENT 0x00000000 +#define GF_A_NO_DLY_AFTR_DATA_SENT 0x00002000 + +#define GF_RAISE_WAIT_AFTR_DATA_SENT_MASK 0x00001000 +#define GF_A_RAISE_WAIT_AFTR_DATA_SENT 0x00001000 + +#define GF_DATA_BURST_MASK 0x000000ff +#define GF_A_DATA_BURST0 0x00000000 +#define GF_A_DATA_BURST1 0x00000001 +#define GF_A_DATA_BURST2 0x00000002 +#define GF_A_DATA_BURST3 0x00000003 +#define GF_A_DATA_BURST4 0x00000004 +#define GF_A_DATA_BURST5 0x00000005 +#define GF_A_DATA_BURST6 0x00000006 +#define GF_A_DATA_BURST7 0x00000007 +#define GF_A_DATA_BURST8 0x00000008 + +#define GF_CS_MASK 0x000f0000 +#define GF_A_MCS_ACTVH 0x00010000 +#define GF_A_MCS_ACTVL 0x00020000 +#define GF_A_SCS_ACTVH 0x00030000 +#define GF_A_SCS_ACTVL 0x00040000 + +#define GF_RS_DC_MASK 0x00f00000 +#define GF_A_RS_DC_IXH_DATAL 0x00100000 +#define GF_A_RS_DC_IXL_DATAL 0x00200000 +#define GF_A_RS_DC_IXL_DATAH 0x00300000 +#define GF_A_RS_DC_IXH_DATAH 0x00400000 + +#define GF_IFACE_MASK 0x00008f00 +#define GF_A_IFACE_PRLL 0x00008000 + +#define GF_A_IFACE_PRLL_8 0x00008100 +#define GF_A_IFACE_PRLL_9 0x00008200 +#define GF_A_IFACE_PRLL_16 0x00008300 +#define GF_A_IFACE_PRLL_18 0x00008400 +#define GF_A_IFACE_SPI_8 0x00000100 +#define GF_A_IFACE_SPI_8DC 0x00000200 +#define GF_A_IFACE_SPI_12 0x00000300 +#define GF_A_IFACE_SPI_16 0x00000400 +#define GF_A_IFACE_SPI_16DC 0x00000500 +#define GF_A_IFACE_SPI_16_START8 0x00000600 +#define GF_A_IFACE_SPI_18 0x00000700 +#define GF_A_IFACE_SPI_24 0x00000800 +#define GF_A_IF_LSB_ALINED 0x00004000 +#define GF_A_IF_MSB_ALINED 0x00000000 +#define GF_IF_ALINED_MASK 0x00004000 + +#define GF_CLK_PER_PIXEL_MASK 0x3f000000 +#define GF_A_1CLK_PIXEL 0x01000000 +#define GF_A_2CLK_PIXEL 0x02000000 +#define GF_A_3CLK_PIXEL 0x03000000 +#define GF_A_4CLK_PIXEL 0x04000000 +#define GF_A_24CLK_PIXEL 0x18000000 + +// Parellel +#define GF_A_DATA_VLD_MASK 0xC0000000 +#define GF_A_DATA_VLD_CLK_RISE 0x40000000 +#define GF_A_DATA_VLD_CLK_FALL 0x80000000 + +// Serial + +#define GF_SPI_SCLK_CS_EDGE_ACTV_MASK 0xC0000000 +#define GF_A_SPI_1SCLK_CS_RISING_EDGE_ACTV 0x40000000 +#define GF_A_SPI_2SCLK_CS_RISING_EDGE_ACTV 0x00000000 +#define GF_A_SPI_1SCLK_CS_FALLING_EDGE_ACTV 0xC0000000 +#define GF_A_SPI_2SCLK_CS_FALLING_EDGE_ACTV 0x80000000 + +#define GF_A_SPI_CS_ACTVH 0x00010000 +#define GF_A_SPI_CS_ACTVL 0x00020000 + +#define GF_SPI_RS_DC_MASK 0x00f00000 +#define GF_A_SPI_RS_DC_IXH_DATAL 0x00100000 +#define GF_A_SPI_RS_DC_IXL_DATAL 0x00200000 +#define GF_A_SPI_RS_DC_IXL_DATAH 0x00300000 +#define GF_A_SPI_RS_DC_IXH_DATAH 0x00400000 + + +#define GF_B_ 0x00000000 +#define GF_C_ 0x00000000 + +#define GF_SPI_DATA_START_BYTE 0x00000000 +#define GF_SPI_CMD_START_BYTE 0x00000000 +#define GF_PANEL_DRV_CMD_DATA ~0x0000ffff +#define GFSCMD_PANEL_PKT_HEADER_END 0x40008000 + +#define GFPERIODIC_CMD 0x4000C000 +#define GFSCMD_PERIODIC_PKT_HEADER_START 0x4000C000 +#define GFSCMD_PERIODIC_PKT_HEADER_SIZE 0x0000000A + +#define GF_IS_PERDC_MSB9_LSB9_SWAP_MASK 0x00800000 +#define GF_IS_PERDC_MSB9_LSB9_SWAP 0x00800000 + +#define GF_IS_PERDC_PARLL_CYCLE_MASK 0x0000000f +#define GF_IS_PERDC_PARLL_CYCLE0 0x00000000 +#define GF_IS_PERDC_PARLL_CYCLE1 0x00000001 +#define GF_IS_PERDC_PARLL_CYCLE2 0x00000002 +#define GF_IS_PERDC_PARLL_CYCLE3 0x00000003 +#define GF_IS_PERDC_PARLL_CYCLE4 0x00000004 +#define GF_IS_PERDC_PARLL_CYCLE5 0x00000005 +#define GF_IS_PERDC_PARLL_CYCLE6 0x00000006 +#define GF_IS_PERDC_PARLL_CYCLE7 0x00000007 +#define GF_IS_PERDC_PARLL_CYCLE8 0x00000008 +#define GF_IS_PERDC_PARLL_CYCLE9 0x00000009 +#define GF_IS_PERDC_PARLL_CYCLE10 0x0000000A +#define GF_IS_PERDC_PARLL_CYCLE11 0x0000000B +#define GF_IS_PERDC_PARLL_CYCLE12 0x0000000C + +#define GF_IS_PERDC_PARLL_IF_MASK 0xf0000000 +#define GF_IS_PERDC_PARLL_IF_8 0x00000000 +#define GF_IS_PERDC_PARLL_IF_9 0x10000000 +#define GF_IS_PERDC_PARLL_IF_18 0x20000000 +#define GF_IS_PERDC_PARLL_IF_16 0x30000000 + +#define GF_IS_PERDC_PARLL_MAX_DATA_MASK 0x0000ff00 +#define GF_IS_PERDC_PARLL_MAX_DATA_IF_8 0x00005900 +#define GF_IS_PERDC_PARLL_MAX_DATA_IF_9 0x00005900 +#define GF_IS_PERDC_PARLL_MAX_DATA_IF_16 0x00006B00 +#define GF_IS_PERDC_PARLL_MAX_DATA_IF_18 0x00006B00 + +#define GFIS_PRLL_EN_RS_DC_C 0 +#define GFIS_PRLL_EN_RS_DC_D 0 + +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_1_D (1 << (108-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_2_D (1 << (111-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_3_D (1 << (114-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_4_D (1 << (117-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_5_D (1 << (120-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_6_D (1 << (123-96)) + +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_1_D (1 << (109-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_2_D (1 << (112-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_3_D (1 << (115-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_4_D (1 << (118-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_5_D (1 << (121-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_6_D (1 << (124-96)) + +#define GFIS_PRLL_RS_CD_18_CYCLE_1_H_D (1 << (110-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_1_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_2_H_D (1 << (113-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_2_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_3_H_D (1 << (116-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_3_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_4_H_D (1 << (119-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_4_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_5_H_D (1 << (122-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_5_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_6_H_D (1 << (125-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_6_L_D 0x00000000 + +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_1_C (1 << (90-64)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_2_C (1 << (93-64)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_3_D (1 << (96-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_4_D (1 << (99-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_5_D (1 << (102-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_6_D (1 << (105-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_7_D (1 << (108-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_8_D (1 << (111-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_9_D (1 << (114-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_10_D (1 << (117-96)) + +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_1_C (1 << (91-64)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_2_C (1 << (94-64)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_3_D (1 << (97-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_4_D (1 << (100-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_5_D (1 << (103-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_6_D (1 << (106-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_7_D (1 << (109-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_8_D (1 << (112-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_9_D (1 << (115-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_10_D (1 << (118-96)) + +#define GFIS_PRLL_RS_CD_9_CYCLE_1_H_C (1 << (92-64)) +#define GFIS_PRLL_RS_CD_9_CYCLE_1_L_C 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_2_H_C (1 << (95-64)) +#define GFIS_PRLL_RS_CD_9_CYCLE_2_L_C 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_3_H_D (1 << (98-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_3_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_4_H_D (1 << (101-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_4_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_5_H_D (1 << (104-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_5_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_6_H_D (1 << (107-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_6_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_7_H_D (1 << (110-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_7_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_8_H_D (1 << (113-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_8_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_9_H_D (1 << (116-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_9_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_10_H_D (1 << (119-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_10_L_D 0x00000000 + +// Serial + +#define GF_IS_PERDC_SERIAL_CYCLE_MASK 0x0000000f +#define GF_IS_PERDC_SERIAL_CYCLE0 0x00000000 +#define GF_IS_PERDC_SERIAL_CYCLE1 0x00000001 +#define GF_IS_PERDC_SERIAL_CYCLE2 0x00000002 +#define GF_IS_PERDC_SERIAL_CYCLE3 0x00000003 +#define GF_IS_PERDC_SERIAL_CYCLE4 0x00000004 +#define GF_IS_PERDC_SERIAL_CYCLE5 0x00000005 +#define GF_IS_PERDC_SERIAL_CYCLE6 0x00000006 +#define GF_IS_PERDC_SERIAL_CYCLE7 0x00000007 +#define GF_IS_PERDC_SERIAL_CYCLE8 0x00000008 +#define GF_IS_PERDC_SERIAL_CYCLE9 0x00000009 +#define GF_IS_PERDC_SERIAL_CYCLE10 0x0000000A +#define GF_IS_PERDC_SERIAL_CYCLE11 0x0000000B +#define GF_IS_PERDC_SERIAL_CYCLE12 0x0000000C + +#define GF_IS_PERDC_SERIAL_IF_MASK 0xf0000000 +#define GF_IS_PERDC_SERIAL_IF_8 0x80000000 +#define GF_IS_PERDC_SERIAL_IF_9 0x90000000 +#define GF_IS_PERDC_SERIAL_IF_12 0xA0000000 +#define GF_IS_PERDC_SERIAL_IF_16 0xB0000000 +#define GF_IS_PERDC_SERIAL_IF_18 0xC0000000 +#define GF_IS_PERDC_SERIAL_IF_24 0xD0000000 + +#define GF_IS_PERDC_SERIAL_MAX_DATA_MASK 0x0000ff00 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_8 0x00005900 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_9 0x00005900 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_12 0x00006A00 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_16 0x00006B00 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_18 0x00006C00 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_24 0x00006D00 + +#define GFIS_SERIAL_EN_RS_DC_C 0 +#define GFIS_SERIAL_EN_RS_DC_D 0 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_24_CYCLE_1_D (1 << (96-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_24_CYCLE_2_D (1 << (98-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_24_CYCLE_3_D (1 << (100-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_24_CYCLE_4_D (1 << (102-96)) + +#define GFIS_SERIAL_RS_CD_24_CYCLE_1_H_D (1 << (97-96)) +#define GFIS_SERIAL_RS_CD_24_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_24_CYCLE_2_H_D (1 << (99-96)) +#define GFIS_SERIAL_RS_CD_24_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_24_CYCLE_3_H_D (1 << (101-96)) +#define GFIS_SERIAL_RS_CD_24_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_24_CYCLE_4_H_D (1 << (103-96)) +#define GFIS_SERIAL_RS_CD_24_CYCLE_4_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_1_D (1 << (108-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_2_D (1 << (110-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_3_D (1 << (112-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_4_D (1 << (114-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_5_D (1 << (116-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_6_D (1 << (118-96)) + +#define GFIS_SERIAL_RS_CD_18_CYCLE_1_H_D (1 << (109-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_2_H_D (1 << (111-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_3_H_D (1 << (113-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_4_H_D (1 << (115-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_5_H_D (1 << (117-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_6_H_D (1 << (119-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_6_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_1_D (1 << (112-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_2_D (1 << (114-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_3_D (1 << (116-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_4_D (1 << (118-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_5_D (1 << (120-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_6_D (1 << (122-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_7_D (1 << (124-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_7_D (1 << (124-96)) + +#define GFIS_SERIAL_RS_CD_16_CYCLE_1_H_D (1 << (113-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_2_H_D (1 << (115-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_3_H_D (1 << (117-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_4_H_D (1 << (119-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_5_H_D (1 << (121-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_6_H_D (1 << (123-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_6_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_7_H_D (1 << (125-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_7_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_1_D (1 << (109-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_2_D (1 << (111-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_3_D (1 << (113-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_4_D (1 << (115-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_5_D (1 << (117-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_6_D (1 << (119-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_7_D (1 << (121-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_8_D (1 << (123-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_9_D (1 << (125-96)) + +#define GFIS_SERIAL_RS_CD_12_CYCLE_1_H_D (1 << (110-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_2_H_D (1 << (112-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_3_H_D (1 << (114-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_4_H_D (1 << (116-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_5_H_D (1 << (118-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_6_H_D (1 << (120-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_6_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_7_H_D (1 << (122-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_7_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_8_H_D (1 << (124-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_8_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_9_H_D (1 << (126-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_9_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_1_D (1 << (99-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_2_D (1 << (101-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_3_D (1 << (103-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_4_D (1 << (105-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_5_D (1 << (107-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_6_D (1 << (109-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_7_D (1 << (111-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_8_D (1 << (113-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_9_D (1 << (115-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_10_D (1 << (117-96)) + +#define GFIS_SERIAL_RS_CD_9_CYCLE_1_H_D (1 << (100-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_2_H_D (1 << (102-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_3_H_D (1 << (104-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_4_H_D (1 << (106-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_5_H_D (1 << (108-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_6_H_D (1 << (110-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_6_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_7_H_D (1 << (112-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_7_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_8_H_D (1 << (114-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_8_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_9_H_D (1 << (116-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_9_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_10_H_D (1 << (118-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_10_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_1_D (1 << (96-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_2_D (1 << (98-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_3_D (1 << (100-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_4_D (1 << (102-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_5_D (1 << (104-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_6_D (1 << (106-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_7_D (1 << (108-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_8_D (1 << (110-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_9_D (1 << (112-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_10_D (1 << (114-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_11_D (1 << (116-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_12_D (1 << (118-96)) + +#define GFIS_SERIAL_RS_CD_8_CYCLE_1_H_D (1 << (97-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_2_H_D (1 << (99-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_3_H_D (1 << (101-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_4_H_D (1 << (103-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_5_H_D (1 << (105-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_6_H_D (1 << (107-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_6_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_7_H_D (1 << (109-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_7_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_8_H_D (1 << (111-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_8_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_9_H_D (1 << (113-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_9_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_10_H_D (1 << (115-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_10_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_11_H_D (1 << (117-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_11_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_12_H_D (1 << (119-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_12_L_D 0x00000000 + +#define GFSCMD_PERIODIC_PKT_HEADER_END 0x4000E000 + +#define GFSCMD_I2C_PKT_HEADER_START 0x4000A000 + +#define GF_I2C_DATA_BURST_MASK 0x000000ff +#define GF_I2C_A_DATA_BURST0 0x00000000 +#define GF_I2C_A_DATA_BURST1 0x00000001 +#define GF_I2C_A_DATA_BURST2 0x00000002 +#define GF_I2C_A_DATA_BURST3 0x00000003 +#define GF_I2C_A_DATA_BURST4 0x00000004 +#define GF_I2C_A_DATA_BURST5 0x00000005 +#define GF_I2C_A_DATA_BURST6 0x00000006 +#define GF_I2C_A_DATA_BURST7 0x00000007 +#define GF_I2C_A_DATA_BURST8 0x00000008 + +#define GF_HW_SW_I2C_MASK 0x00000300 +#define GF_HW_I2C 0x00000000 +#define GF_SW_I2C 0x00000100 +#define GF_I2C_B_WRITE_ID 0x00000000 +#define GF_I2C_C_READ_ID 0x00000000 +#define GFSCMD_I2C_PKT_HEADER_END 0x4000B000 + + +//SDIO GPIOs + +#define GFSCMD_GPIO_SD_INIT 0x00008f00 //One time Init SD GPIO +#define GF_NO_DATA 0x00000000 + +#define GFSCMD_GPIO_SD_PIN_SDGP0 0x00008f01 +#define GFSCMD_GPIO_SD_PIN_SDGP1 0x00018f01 +#define GFSCMD_GPIO_SD_PIN_CMD 0x00028f02 +#define GFSCMD_GPIO_SD_PIN_CLK 0x00038f02 +#define GFSCMD_GPIO_SD_PIN_DATA0 0x00048f00 +#define GFSCMD_GPIO_SD_PIN_DATA1 0x00048f01 +#define GFSCMD_GPIO_SD_PIN_DATA2 0x00048f02 +#define GFSCMD_GPIO_SD_PIN_DATA3 0x00048f03 + +#define GF_GPIO_PIN_OUTPUT_ENABLE 0x00000000 +#define GF_GPIO_PIN_INPUT_ENABLE 0x00000001 +#define GF_GPIO_PIN_DISABLE 0x00000002 +#define GF_GPIO_PIN_HIGH 0x00000003 +#define GF_GPIO_PIN_LOW 0x00000004 + +#endif //__GFDISPCMDDATA_H__ diff --git a/Start_WM/test6/inc/GFDx.h b/Start_WM/test6/inc/GFDx.h new file mode 100755 index 00000000..cca38e76 --- /dev/null +++ b/Start_WM/test6/inc/GFDx.h @@ -0,0 +1,1847 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFDx.h + GFSDK Display Initialization API header file. + */ + +#ifndef GF_DX_H +#define GF_DX_H + +#include "GFDispCmdData.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupDx DxAPI Display Initialization API +
        +
      • @ref pageDxAppNotes +
          +
        • @ref pageDxAppNotes1 +
        +
      +*/ +/*@{*/ + +/** GFDxAPI color info to be used during programming GFDxErase*/ +#define GFDX_COLOR_RED 0xF800F800 +#define GFDX_COLOR_GREEN 0x07E007E0 +#define GFDX_COLOR_BLUE 0x001F001F + + + +/** GFDxAPI error code: Function not supported. */ +#define GFDX_ERROR_NO_SUPPORT (GFDX_ERROR | 2) +/** GFDxAPI error code: Invalid attribute ID for GFDxSetAttribute() / GFDxGetAttribute(). */ +#define GFDX_ERROR_INVALID_ATTRIBUTE (GFDX_ERROR | 6) + +/** + This struct is used by GFDxGetProperty(). + * */ +typedef struct _GFDXPROPERTY +{ + /** standard GF property, following info is available as cap */ + GFPROPERTY Prop; + /** Not supported */ + NvU16 LcdWidth; + /** Not supported */ + NvU16 LcdHeight; + /** Not supported */ + NvU16 LcdIndex; + /** Not supported */ + char LcdName[18]; + /** Not supported */ + NvU16 SubLcdWidth; + /** Not supported */ + NvU16 SubLcdHeight; + /** Not supported */ + NvU16 SubLcdIndex; + /** Not supported */ + char SubLcdName[18]; + +} GFDXPROPERTY, *PGFDXPROPERTY; + +#define DC_P_A_BLEND_2WIN_B DC_P_B_BLEND_2WIN_A +#define DC_P_A_BLEND_2WIN_C DC_P_B_BLEND_2WIN_C + +#define DC_P_C_BLEND_2WIN_A DC_P_B_BLEND_2WIN_A +#define DC_P_C_BLEND_2WIN_B DC_P_B_BLEND_2WIN_C + +//#define DC_P_B_BLEND_2WIN_B DC_P_B_BLEND_2WIN_C +#define P_B_CKEY_ENABLE_2WIN_B_CKEY0 P_B_CKEY_ENABLE_2WIN_C_CKEY0 +#define P_B_CKEY_ENABLE_2WIN_B_CKEY1 P_B_CKEY_ENABLE_2WIN_C_CKEY1 +#define P_B_BLEND_CONTROL_2WIN_B_MASK P_B_BLEND_CONTROL_2WIN_C_MASK +#define P_B_BLEND_CONTROL_2WIN_B_ALPHA_WEIGHT P_B_BLEND_CONTROL_2WIN_C_ALPHA_WEIGHT +#define P_B_BLEND_CONTROL_2WIN_B_DEPENDENT_WEIGHT P_B_BLEND_CONTROL_2WIN_C_DEPENDENT_WEIGHT +#define P_B_BLEND_WEIGHT0_2WIN_B_MASK P_B_BLEND_WEIGHT0_2WIN_C_MASK +#define P_B_BLEND_WEIGHT0_2WIN_B_SHIFT P_B_BLEND_WEIGHT0_2WIN_C_SHIFT +#define P_B_BLEND_WEIGHT1_2WIN_B_MASK P_B_BLEND_WEIGHT1_2WIN_C_MASK +#define P_B_BLEND_WEIGHT1_2WIN_B_SHIFT P_B_BLEND_WEIGHT1_2WIN_C_SHIFT + +//#define DC_P_B_BLEND_3WIN_AB DC_P_B_BLEND_3WIN_AC +#define DC_P_A_BLEND_3WIN_BC DC_P_B_BLEND_3WIN_AC +#define P_B_CKEY_ENABLE_3WIN_AB_CKEY0 P_B_CKEY_ENABLE_3WIN_AC_CKEY0 +#define P_B_CKEY_ENABLE_3WIN_AB_CKEY1 P_B_CKEY_ENABLE_3WIN_AC_CKEY1 +#define P_B_BLEND_CONTROL_3WIN_AB_MASK P_B_BLEND_CONTROL_3WIN_AC_MASK +#define P_B_BLEND_CONTROL_3WIN_AB_ALPHA_WEIGHT P_B_BLEND_CONTROL_3WIN_AC_ALPHA_WEIGHT +#define P_B_BLEND_CONTROL_3WIN_AB_DEPENDENT_WEIGHT P_B_BLEND_CONTROL_3WIN_AC_DEPENDENT_WEIGHT +#define P_B_BLEND_WEIGHT0_3WIN_AB_MASK P_B_BLEND_WEIGHT0_3WIN_AC_MASK +#define P_B_BLEND_WEIGHT0_3WIN_AB_SHIFT P_B_BLEND_WEIGHT0_3WIN_AC_SHIFT +#define P_B_BLEND_WEIGHT1_3WIN_AB_MASK P_B_BLEND_WEIGHT1_3WIN_AC_MASK +#define P_B_BLEND_WEIGHT1_3WIN_AB_SHIFT P_B_BLEND_WEIGHT1_3WIN_AC_SHIFT + +//#define DC_P_B_BLEND_3WIN_BC DC_P_B_BLEND_3WIN_AC +#define DC_P_C_BLEND_3WIN_AB DC_P_B_BLEND_3WIN_AC +#define P_B_CKEY_ENABLE_3WIN_BC_CKEY0 P_B_CKEY_ENABLE_3WIN_AC_CKEY0 +#define P_B_CKEY_ENABLE_3WIN_BC_CKEY1 P_B_CKEY_ENABLE_3WIN_AC_CKEY1 +#define P_B_BLEND_CONTROL_3WIN_BC_MASK P_B_BLEND_CONTROL_3WIN_AC_MASK +#define P_B_BLEND_CONTROL_3WIN_BC_ALPHA_WEIGHT P_B_BLEND_CONTROL_3WIN_AC_ALPHA_WEIGHT +#define P_B_BLEND_CONTROL_3WIN_BC_DEPENDENT_WEIGHT P_B_BLEND_CONTROL_3WIN_AC_DEPENDENT_WEIGHT +#define P_B_BLEND_WEIGHT0_3WIN_BC_MASK P_B_BLEND_WEIGHT0_3WIN_AC_MASK +#define P_B_BLEND_WEIGHT0_3WIN_BC_SHIFT P_B_BLEND_WEIGHT0_3WIN_AC_SHIFT +#define P_B_BLEND_WEIGHT1_3WIN_BC_MASK P_B_BLEND_WEIGHT1_3WIN_AC_MASK +#define P_B_BLEND_WEIGHT1_3WIN_BC_SHIFT P_B_BLEND_WEIGHT1_3WIN_AC_SHIFT + +/** + Definition of attribute ids for Set/GetAttributes() + */ +typedef enum _GFDXATTRIBUTES + { + /** Width of the LCD fixed (240 for a 240x320 panel) */ + GFDX_ATTR_LCDWIDTH, + /** Height of the LCD fixed (320 for a 240x320 panel) */ + GFDX_ATTR_LCDHEIGHT, + /** NVIDIA panel index, This function overwrites environment panel Index setting */ + GFDX_ATTR_LCDTYPE, + /** Name of the panel (upto 16 chars,"PHILIPS_LP7123A") */ + GFDX_ATTR_LCDNAME, + /** Width of the display area usually same as LCDWIDTH, + Parameters: W[15:0] */ + GFDX_ATTR_WIDTH, + /** Height of the display area, can be less if emulating smaller size, + Parameters: H[15:0] */ + GFDX_ATTR_HEIGHT, + /** set/gets width height together to avoid artifacts, + Parameters: W[15:0], H[31:16] */ + GFDX_ATTR_WH_WA, + /** set/gets x, y start position of window A, + Parameters: X[15:0], Y[31:16] */ + GFDX_ATTR_XY_POS_WA, + /** Color Depth Bits per pixel: 1,2,4,8,12,15(RGB555),16(RGB565), 32(ARGB888), + GFDX_COLOR_DEPTH_YCbCr422, + GFDX_COLOR_DEPTH_YUV422, + GFDX_COLOR_DEPTH_YCbCr420P, + GFDX_COLOR_DEPTH_YUV420P, + GFDX_COLOR_DEPTH_YUV422P, + GFDX_COLOR_DEPTH_YCbCr422P, + GFDX_COLOR_DEPTH_YCbCr422R, + GFDX_COLOR_DEPTH_YUV422R, + GFDX_COLOR_DEPTH_YCbCr422RA, + GFDX_COLOR_DEPTH_YUV422RA, + */ + GFDX_ATTR_BPP_WA, + /** On/Off Horizontal & Vertical Pixel Doubling for window A, + Parameters: GFDXA_PIX_DBL_H, GFDXA_PIX_DBL_V or 0-Disable */ + GFDX_ATTR_PIXEL_DBL_WA, + /** Start Address for Window A Buffer 0 */ + GFDX_ATTR_ADDR_WA_B0, + /** Start Address for Window A Buffer 1 */ + GFDX_ATTR_ADDR_WA_B1, + /** Stride for Window A Buffer 0 */ + GFDX_ATTR_STRIDE_WA_B0, + /** Stride for Window A Buffer 1 */ + GFDX_ATTR_STRIDE_WA_B1, + /** Enable/Disable Windows A, Parameters: 1-Enable 0-Disable */ + GFDX_ATTR_ENABLE_WA, + /** Enable/Disable Buf0, Buf1, VI, GE Double Buffer (see def), + Parameters: GFDXA_DB_BUF0, GFDXA_DB_BUF1, GFDXA_DB_GE, GFDXA_DB_VI, + GFDXA_DB_EPP, GFDXA_DB_MPEGE, GFDXA_DB_HOST + */ + GFDX_ATTR_DBL_BUF_WA, + /** Sets/Gets GC Rotate bits for window A, for internal use only */ + GFDX_ATTR_ROTATE_BIT_WA, + /** Set/Get H Direction Increment/Decrement for window A, for internal use only */ + GFDX_ATTR_H_DIRECTION_WA, + /** Set/Get V Direction Increment/Decrement for window A, for internal use only */ + GFDX_ATTR_V_DIRECTION_WA, + /** Enable/Disable Palette for WinA */ + GFDX_ATTR_PALETTE_EN_WA, + /** Set/Get Palette 666 R[31-24], G[23-16], B[15-8], Index[7-0] WinA */ + GFDX_ATTR_PALETTE_WA, + /** Set/Get Palette 888 R[31-24], G[23-16], B[15-8], Index[7-0] WinA */ + GFDX_ATTR_PALETTE888_WA, + /** Enable/Disable DV WinA , + Parameters: GFDX_ATTR_DV_ENABLE, GFDX_ATTR_DV_DISABLE + */ + GFDX_ATTR_DV_CONTROL_EN_WA, + /** Set/Get DV Control R[26-24], G[18-16], B[10-8] WinA */ + GFDX_ATTR_DV_CONTROL_WA, + /** Color Key0 Lower range for overlay, there are two sets of color keys KEY0 & KEY1, + Parameters: R[23-16],G[15-8],B[7-0], Each KEY has Lower and Upper range */ + GFDX_ATTR_COLOR_KEY0_LOWER_RANGE, + /** Color Key0 Upper range for overlay, there are two sets of color keys KEY0 & KEY1, + Parameters: R[23-16],G[15-8],B[7-0], Each KEY has Lower and Upper range */ + GFDX_ATTR_COLOR_KEY0_UPPER_RANGE, + /** Color Key1 Lower range for overlay, there are two sets of color keys KEY0 & KEY1, + Parameters: R[23-16],G[15-8],B[7-0], Each KEY has Lower and Upper range */ + GFDX_ATTR_COLOR_KEY1_LOWER_RANGE, + /** Color Key1 Upper range for overlay, there are two sets of color keys KEY0 & KEY1, + Parameters: R[23-16],G[15-8],B[7-0], Each KEY has Lower and Upper range */ + GFDX_ATTR_COLOR_KEY1_UPPER_RANGE, + /** Color Key enbled but pixel color is not in range, + Parameters: GFDXA_BLEND_CONTROL_NOKEY_ALPHA_WEIGHT else 0 for Fix Weight */ + GFDX_ATTR_COLOR_NOKEY_WA, + /** Weight0 for Color Key not match area, + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT0_WA, + /** Weight1 for Color Key not match area, + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT1_WA, + /** Color Key0 Enble/Disable for WinA, + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE or GFDXA_BLEND_COLOR_KEY0_DISABLE */ + GFDX_ATTR_COLOR_KEY0_1WIN_WA, + /** Color Key1 Enble/Disable for WinA, + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE or GFDXA_BLEND_COLOR_KEY1_DISABLE */ + GFDX_ATTR_COLOR_KEY1_1WIN_WA, + /** Blend Control for WinA where does not Overlap with other Window, + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or 0 for Fix Weight */ + GFDX_ATTR_COLOR_1WIN_WA, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0, + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT0_WA, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1, + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT1_WA, + /** Color Key0 Enble/Disable for WinA, Overlap with WinB, + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY01 + else 2WIN_A_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY1 + else 2WIN_A_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_B_WA, + /** Color Key1 Enble/Disable for WinA, Overlap with WinB, + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY01 + else 2WIN_A_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY0 + else 2WIN_A_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_B_WA, + /** Blend Control for WinA area that overlap with WinB only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_B_WA, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_B_WEIGHT0_WA, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_B_WEIGHT1_WA, + /** Color Key0 Enble/Disable for WinA, Overlap with WinC + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY01 + else 2WIN_A_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY1 + else 2WIN_A_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_C_WA, + /** Color Key1 Enble/Disable for WinA, Overlap with WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY01 + else 2WIN_A_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY0 + else 2WIN_A_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_C_WA, + /** Blend Control for WinA area that overlap with WinC only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_C_WA, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_C_WEIGHT0_WA, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_C_WEIGHT1_WA, + /** Color Key0 Enble/Disable for WinA, Overlap with WinA & WinC Only + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 3WIN_AC_CKEY1 enbled then ENABLE_3WIN_AC_CKEY01 + else 3WIN_AC_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 3WIN_AC_CKEY1 enbled then ENABLE_3WIN_AC_CKEY1 + else 3WIN_AC_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_3WIN_BC_WA, + /** Color Key1 Enble/Disable for WinA, Overlap with WinA & WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 3WIN_AC_CKEY1 enbled then ENABLE_3WIN_AC_CKEY01 + else 3WIN_AC_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 3WIN_AC_CKEY1 enbled then ENABLE_3WIN_AC_CKEY0 + else 3WIN_AC_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_3WIN_BC_WA, + /** Blend Control for WinA area that overlap with WinA & WinC only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_3WIN_BC_WA, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_3WIN_BC_WEIGHT0_WA, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_3WIN_BC_WEIGHT1_WA, + /** set/gets width height together to avoid artifacts */ + GFDX_ATTR_WH_WB, + /** set/gets source width height together to avoid artifacts, + Parameters: W[15:0], H[31:16] */ + GFDX_ATTR_SRC_WH_WB, + /** set/gets x, y start position of window B, + Parameters: X[15:0], Y[31:16] */ + GFDX_ATTR_XY_POS_WB, + /** Color Depth Bits per pixel: 1,2,4,8,12,15(RGB555),16(RGB565), 32(ARGB888), + GFDX_COLOR_DEPTH_YCbCr422, + GFDX_COLOR_DEPTH_YUV422, + GFDX_COLOR_DEPTH_YCbCr420P, + GFDX_COLOR_DEPTH_YUV420P, + GFDX_COLOR_DEPTH_YUV422P, + GFDX_COLOR_DEPTH_YCbCr422P, + GFDX_COLOR_DEPTH_YCbCr422R, + GFDX_COLOR_DEPTH_YUV422R, + GFDX_COLOR_DEPTH_YCbCr422RA, + GFDX_COLOR_DEPTH_YUV422RA, + */ + GFDX_ATTR_BPP_WB, + /** On/Off Horizontal & Vertical Pixel Doubling for Window B, + Parameters: GFDXA_PIX_DBL_H, GFDXA_PIX_DBL_V or 0-Disable */ + GFDX_ATTR_PIXEL_DBL_WB, + /** Upscales/Downscales window */ + GFDX_ATTR_SCALE_WB, + /** Start Address for Window B Buffer 0 */ + GFDX_ATTR_ADDR_WB_B0, + /** U Start Address for Window B Buffer 0 */ + GFDX_ATTR_ADDR_U_WB_B0, + /** V Start Address for Window B Buffer 0 */ + GFDX_ATTR_ADDR_V_WB_B0, + /** Stride for Window B Buffer 0 */ + GFDX_ATTR_STRIDE_WB_B0, + /** UV Stride for Window B Buffer 0 */ + GFDX_ATTR_STRIDE_UV_WB_B0, + /** Start Address for Window B Buffer 1 */ + GFDX_ATTR_ADDR_WB_B1, + /** U Start Address for Window B Buffer 1 */ + GFDX_ATTR_ADDR_U_WB_B1, + /** V Start Address for Window B Buffer 1 */ + GFDX_ATTR_ADDR_V_WB_B1, + /** Stride for Window B Buffer 1 */ + GFDX_ATTR_STRIDE_WB_B1, + /** UV Stride for Window B Buffer 1 */ + GFDX_ATTR_STRIDE_UV_WB_B1, + /** Enable/Disable Windows B, Parameters: 1-Enable 0-Disable */ + GFDX_ATTR_ENABLE_WB, + /** Enable/Disable Buf0, Buf1, VI, GE Double Buffer (see def), + Parameters: GFDXA_DB_BUF0, GFDXA_DB_BUF1, GFDXA_DB_GE, GFDXA_DB_VI, + GFDXA_DB_EPP, GFDXA_DB_MPEGE, GFDXA_DB_HOST + */ + GFDX_ATTR_DBL_BUF_WB, + /** Sets/Gets GC Rotate bits for window B, for internal use only */ + GFDX_ATTR_ROTATE_BIT_WB, + /** Set/Get H Direction Increment/Decrement for window B, for internal use only */ + GFDX_ATTR_H_DIRECTION_WB, + /** Set/Get V Direction Increment/Decrement for window B, for internal use only */ + GFDX_ATTR_V_DIRECTION_WB, + /** Enable/Disable Palette for WinB */ + GFDX_ATTR_PALETTE_EN_WB, + /** Set/Get Palette 666 R[31-24], G[23-16], B[15-8], Index[7-0] WinB */ + GFDX_ATTR_PALETTE_WB, + /** Set/Get Palette 888 R[31-24], G[23-16], B[15-8], Index[7-0] WinB */ + GFDX_ATTR_PALETTE888_WB, + /** Enable/Disable DV WinB , + Parameters: GFDX_ATTR_DV_ENABLE, GFDX_ATTR_DV_DISABLE + */ + GFDX_ATTR_DV_CONTROL_EN_WB, + /** Set/Get DV Control R[26-24], G[18-16], B[10-8] WinB */ + GFDX_ATTR_DV_CONTROL_WB, + /** Color Key enbled but pixel color is not in range + Parameters: GFDXA_BLEND_CONTROL_NOKEY_ALPHA_WEIGHT else 0 for Fix Weight */ + GFDX_ATTR_COLOR_NOKEY_WB, + /** Weight0 for Color Key not match area + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT0_WB, + /** Weight1 for Color Key not match area + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT1_WB, + /** Color Key0 Enble/Disable for WinB + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE or GFDXA_BLEND_COLOR_KEY0_DISABLE */ + GFDX_ATTR_COLOR_KEY0_1WIN_WB, + /** Color Key1 Enble/Disable for WinB + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE or GFDXA_BLEND_COLOR_KEY1_DISABLE */ + GFDX_ATTR_COLOR_KEY1_1WIN_WB, + /** Blend Control for WinB where does not Overlap with other Window + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or 0 for Fix Weight */ + GFDX_ATTR_COLOR_1WIN_WB, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT0_WB, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT1_WB, + /** Color Key0 Enble/Disable for WinB, Overlap with WinA + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY01 + else 2WIN_B_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY1 + else 2WIN_B_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_A_WB, + /** Color Key1 Enble/Disable for WinB, Overlap with WinA + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY01 + else 2WIN_B_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY0 + else 2WIN_B_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_A_WB, + /** Blend Control for WinB where does not Overlap with other Window + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_A_WB, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_A_WEIGHT0_WB, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_A_WEIGHT1_WB, + /** Color Key0 Enble/Disable for WinB, Overlap with WinC + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY01 + else 2WIN_B_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY1 + else 2WIN_B_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_C_WB, + /** Color Key1 Enble/Disable for WinB, Overlap with WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY01 + else 2WIN_B_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY0 + else 2WIN_B_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_C_WB, + /** Blend Control for WinB area that overlap with WinC only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_C_WB, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_C_WEIGHT0_WB, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_C_WEIGHT1_WB, + /** Color Key0 Enble/Disable for WinB, Overlap with WinA & WinC Only + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 3WIN_BC_CKEY1 enbled then ENABLE_3WIN_BC_CKEY01 + else 3WIN_BC_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 3WIN_BC_CKEY1 enbled then ENABLE_3WIN_BC_CKEY1 + else 3WIN_BC_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_3WIN_AC_WB, + /** Color Key1 Enble/Disable for WinB, Overlap with WinA & WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 3WIN_BC_CKEY1 enbled then ENABLE_3WIN_BC_CKEY01 + else 3WIN_BC_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 3WIN_BC_CKEY1 enbled then ENABLE_3WIN_BC_CKEY0 + else 3WIN_BC_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_3WIN_AC_WB, + /** Blend Control for WinB area that overlap with WinA & WinC only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_3WIN_AC_WB, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_3WIN_AC_WEIGHT0_WB, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_3WIN_AC_WEIGHT1_WB, + + /** set/gets width height together to avoid artifacts */ + GFDX_ATTR_WH_WC, + /** set/gets source width height together to avoid artifacts, + Parameters: W[15:0], H[31:16] */ + GFDX_ATTR_SRC_WH_WC, + /** set/gets x, y start position of window C, + Parameters: X[15:0], Y[31:16] */ + GFDX_ATTR_XY_POS_WC, + /** Color Depth Bits per pixel: 1,2,4,8,12,15(RGB555),16(RGB565), 32(ARGB888), + GFDX_COLOR_DEPTH_YCbCr422, + GFDX_COLOR_DEPTH_YUV422, + GFDX_COLOR_DEPTH_YCbCr420P, + GFDX_COLOR_DEPTH_YUV420P, + GFDX_COLOR_DEPTH_YUV422P, + GFDX_COLOR_DEPTH_YCbCr422P, + GFDX_COLOR_DEPTH_YCbCr422R, + GFDX_COLOR_DEPTH_YUV422R, + GFDX_COLOR_DEPTH_YCbCr422RA, + GFDX_COLOR_DEPTH_YUV422RA, + */ + GFDX_ATTR_BPP_WC, + /** Set Trigger for encode window, 0- Disable, 1- Enable, 2-single Shot*/ + GFDX_ATTR_TRIGGER_WENC, + /** On/Off Horizontal & Vertical Pixel Doubling for Window C, + Parameters: GFDXA_PIX_DBL_H, GFDXA_PIX_DBL_V or 0-Disable */ + GFDX_ATTR_PIXEL_DBL_WC, + /** Upscales/Downscales window */ + GFDX_ATTR_SCALE_WC, + /** Start Address for window C Buffer 0 */ + GFDX_ATTR_ADDR_WC_B0, + /** U Start Address for window C Buffer 0 */ + GFDX_ATTR_ADDR_U_WC_B0, + /** V Start Address for window C Buffer 0 */ + GFDX_ATTR_ADDR_V_WC_B0, + /** Stride for window C Buffer 0 */ + GFDX_ATTR_STRIDE_WC_B0, + /** UV Stride for window C Buffer 0 */ + GFDX_ATTR_STRIDE_UV_WC_B0, + /** Start Address for window C Buffer 1 */ + GFDX_ATTR_ADDR_WC_B1, + /** U Start Address for window C Buffer 1 */ + GFDX_ATTR_ADDR_U_WC_B1, + /** V Start Address for window C Buffer 1 */ + GFDX_ATTR_ADDR_V_WC_B1, + /** Stride for window C Buffer 1 */ + GFDX_ATTR_STRIDE_WC_B1, + /** UV Stride for window C Buffer 1 */ + GFDX_ATTR_STRIDE_UV_WC_B1, + /** Enable/Disable Windows C, Parameters: 1-Enable 0-Disable */ + GFDX_ATTR_ENABLE_WC, + /** Enable/Disable Buf0, Buf1, VI, GE Double Buffer (see def), + Parameters: GFDXA_DB_BUF0, GFDXA_DB_BUF1, GFDXA_DB_GE, GFDXA_DB_VI, + GFDXA_DB_EPP, GFDXA_DB_MPEGE, GFDXA_DB_HOST + */ + GFDX_ATTR_DBL_BUF_WC, + /** Sets/Gets GC Rotate bits for window C, for internal use only */ + GFDX_ATTR_ROTATE_BIT_WC, + /** Set/Get H Direction Increment/Decrement for window C, for internal use only */ + GFDX_ATTR_H_DIRECTION_WC, + /** Set/Get V Direction Increment/Decrement for window C, for internal use only */ + GFDX_ATTR_V_DIRECTION_WC, + /** Enable/Disable Palette for WinC */ + GFDX_ATTR_PALETTE_EN_WC, + /** Set/Get Palette 666 R[31-24], G[23-16], B[15-8], Index[7-0] WinC */ + GFDX_ATTR_PALETTE_WC, + /** Set/Get Palette 888 R[31-24], G[23-16], B[15-8], Index[7-0] WinC */ + GFDX_ATTR_PALETTE888_WC, + /** Enable/Disable DV WinC, + Parameters: GFDX_ATTR_DV_ENABLE, GFDX_ATTR_DV_DISABLE + */ + GFDX_ATTR_DV_CONTROL_EN_WC, + /** Set/Get DV Control R[26-24], G[18-16], B[10-8] WinA */ + GFDX_ATTR_DV_CONTROL_WC, + /** Color Key enbled but pixel color is not in range + Parameters: GFDXA_BLEND_CONTROL_NOKEY_ALPHA_WEIGHT else 0 for Fix Weight */ + GFDX_ATTR_COLOR_NOKEY_WC, + /** Weight0 for Color Key not match area + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT0_WC, + /** Weight1 for Color Key not match area + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT1_WC, + /** Color Key0 Enble/Disable for WinC + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE or GFDXA_BLEND_COLOR_KEY0_DISABLE */ + GFDX_ATTR_COLOR_KEY0_1WIN_WC, + /** Color Key1 Enble/Disable for WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE or GFDXA_BLEND_COLOR_KEY1_DISABLE */ + GFDX_ATTR_COLOR_KEY1_1WIN_WC, + /** Blend Control for WinC where does not Overlap with other Window + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or 0 for Fix Weight */ + GFDX_ATTR_COLOR_1WIN_WC, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT0_WC, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT1_WC, + /** Color Key0 Enble/Disable for WinC, Overlap with WinA + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY01 + else 2WIN_C_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY1 + else 2WIN_C_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_A_WC, + /** Color Key1 Enble/Disable for WinC, Overlap with WinA + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY01 + else 2WIN_C_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY0 + else 2WIN_C_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_A_WC, + /** Blend Control for WinC area that overlap with WinA only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_A_WC, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_A_WEIGHT0_WC, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_A_WEIGHT1_WC, + /** Color Key0 Enble/Disable for WinC, Overlap with WinB + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY01 + else 2WIN_C_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY1 + else 2WIN_C_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_B_WC, + /** Color Key1 Enble/Disable for WinC, Overlap with WinB + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY01 + else 2WIN_C_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY0 + else 2WIN_C_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_B_WC, + /** Blend Control for WinC area that overlap with WinB only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_B_WC, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_B_WEIGHT0_WC, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_B_WEIGHT1_WC, + /** Color Key0 Enble/Disable for WinC, Overlap with WinA & WinB Only + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 3WIN_AB_CKEY1 enbled then ENABLE_3WIN_AB_CKEY01 + else 3WIN_AB_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 3WIN_AB_CKEY1 enbled then ENABLE_3WIN_AB_CKEY1 + else 3WIN_AB_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_3WIN_AB_WC, + /** Color Key1 Enble/Disable for WinC, Overlap with WinA & WinB + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 3WIN_AB_CKEY1 enbled then ENABLE_3WIN_AB_CKEY01 + else 3WIN_AB_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 3WIN_AB_CKEY1 enbled then ENABLE_3WIN_AB_CKEY0 + else 3WIN_AB_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_3WIN_AB_WC, + /** Blend Control for WinC area that overlap with WinA & WinB only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_3WIN_AB_WC, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_3WIN_AB_WEIGHT0_WC, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_3WIN_AB_WEIGHT1_WC, + /** GC Color Key for overlay, Not supported */ + GFDX_ATTR_COLOR_KEY, + /** GC Color Key Mask for overlay, Not supported */ + GFDX_ATTR_COLOR_KEY_MASK, + /** Set overlap type (see def), Not supported */ + GFDX_ATTR_OVERLAP_TYPE, + /** Gets VDisplay End for GE Start Window programming, Not supported */ + GFDX_ATTR_V_DISPLAY_END, + /** Gets range for clock divider L=0:H=15 */ + GFDX_ATTR_PWM0_CLK_RANGE, + /** Gets range for duty cycle L=0:H=255 */ + GFDX_ATTR_PWM0_DTY_RANGE, + /** Controls Backlight0 clock divider for PWM0 Bits[5:0] */ + GFDX_ATTR_PWM0_CLOCK, + /** Controls Backlight0 duty cycle for PWM0 Bits[7:0] */ + GFDX_ATTR_PWM0_DUTYCY, + /** Gets range for clock divider L=0:H=15 */ + GFDX_ATTR_PWM1_CLK_RANGE, + /** Gets range for duty cycle L=0:H=255 */ + GFDX_ATTR_PWM1_DTY_RANGE, + /** Controls Backlight1 clock divider for PWM1 Bits[5:0] */ + GFDX_ATTR_PWM1_CLOCK, + /** Controls Backlight1 duty cycle for PWM1 Bits[7:0] */ + GFDX_ATTR_PWM1_DUTYCY, + /** LCD Type 0-Main Lcd, 1-Sub Lcd */ + GFDX_ATTR_DISP_TYPE, + /** SW register 1 for program usage */ + GFDX_ATTR_SW_REG_1, + /** SW register 2 for program usage */ + GFDX_ATTR_SW_REG_2, + /** set/gets width height of screen encode window, + Parameters: W[15:0], H[31:16] */ + GFDX_ATTR_WH_WENC, + /** set/gets x, y start position of screen encode window, + Parameters: X[15:0], Y[31:16] */ + GFDX_ATTR_XY_POS_WENC, + /** Enable/Disable screen encode window. Parameters: 1-Enable 0-Disable. + * Please note that this sets the encode rate to its maximum value of + * 1.000 so if you plan to change it after enabling, + * use attribute GFDX_ATTR_WENC_RATE. */ + GFDX_ATTR_ENABLE_WENC, + /** Get Device ID & Rev, Not supported */ + GFDX_ATTR_DEVICE_INFO, + /** Enable CRC, Set Wait 1 or 2 VSync + Parameters: GFDXA_CRC_WAIT_VSYNC1, GFDXA_CRC_WAIT_VSYNC2, GFDXA_CRC_DISABLE + */ + GFDX_ATTR_CRC_ENABLE, + /** Get Check Sum */ + GFDX_ATTR_CRC_CHECK_SUM, + /** Not supported, Not supported */ + GFDX_ATTR_HC_SHAPE, + /** load Hardware Cursor Image, Not supported */ + GFDX_ATTR_HC_SHAPE_EXT, + /** set cursor hot spot, Not supported */ + GFDX_ATTR_HC_HOTSPOT, + /** set foreground and background color, Not supported */ + GFDX_ATTR_HC_COLOR, + /** Set Hardware Cursor new Position, Not supported */ + GFDX_ATTR_HC_POSITION, + /** Enable, Disable Hardware Cursor, Not supported */ + GFDX_ATTR_HC_SHOW, + /** free internal buffer, Not supported */ + GFDX_ATTR_HC_RELEASE, + /** Set Start or Stop Frame + Parameters: GFDX_MAIN_START, GFDX_MAIN_STOP, GFDX_SUB_START, GFDX_SUB_STOP + */ + GFDX_ATTR_STOP_START, + /** Set Start or Stop Frame + Parameters: GFDX_MAIN_ONE_FRAME, GFDX_SUB_ONE_FRAME + */ + GFDX_ATTR_SEND_ONE_FRAME, + /** Set No change */ + GFDX_ATTR_NOCHANGE, + /** Get Pre Init LCD Resolution Bit[0-15] Width, Bit[16-31] Height*/ + GFDX_ATTR_PRE_INIT_LCD_RES, + /** NVIDIA panel index internal to API use */ + GFDX_ATTR_INTERNAL_LCDTYPE, + /** Setting this attribute will bypass any hardware writes in DxAPI which go through + * the GFDX_CHANNEL_xx macros. The runtime environment GFSDK_DXINIT_BYPASS uses + * this attribue to disable hardware writes during DxSetDisplay(). + * Parameters: GFDX_SET_WRITE_SHADOW or GFDX_CLR_WRITE_SHADOW + */ + GFDX_ATTR_WRITE_SHADOW_ONLY, + /** Backlight0 ON GPIO LPW2 Low */ + GFDX_ATTR_BACKLIGHT0_ON, + /** Backlight1 ON GPIO LM1 Low */ + GFDX_ATTR_BACKLIGHT1_ON, + /** Backlight0 OFF GPIO LPW2 High */ + GFDX_ATTR_BACKLIGHT0_OFF, + /** Backlight1 OFF GPIO LM1 High*/ + GFDX_ATTR_BACKLIGHT1_OFF, + /** configure BACKLIGHT0 as GPIO on LPW2*/ + GFDX_ATTR_BACKLIGHT0_CONFIGURE_GPIO, + /** configure BACKLIGHT1 as GPIO on LM1*/ + GFDX_ATTR_BACKLIGHT1_CONFIGURE_GPIO, + /** configure BACKLIGHT0 as PWM on LPW2*/ + GFDX_ATTR_BACKLIGHT0_CONFIGURE_PWM, + /** configure BACKLIGHT1 as PWM on LM1 */ + GFDX_ATTR_BACKLIGHT1_CONFIGURE_PWM, + + /** Set Stop Frame Options, + Parameters: GFDX_MAIN_STOP_POLARITY_HIGH, GFDX_MAIN_STOP_POLARITY_LOW, GFDX_SUB_STOP_POLARITY_HIGH + GFDX_SUB_STOP_POLARITY_LOW, GFDX_MAIN_STOP_INPUT_PIN_ENABLE, GFDX_MAIN_STOP_INPUT_PIN_DISABLE, + GFDX_SUB_STOP_INPUT_PIN_ENABLE, GFDX_SUB_STOP_INPUT_PIN_DISABLE, GFDX_STOP_WINDOW_A_NC_ENABLE, + GFDX_STOP_WINDOW_A_NC_DISABLE, GFDX_STOP_WINDOW_B_NC_ENABLE, GFDX_STOP_WINDOW_B_NC_DISABLE, + GFDX_STOP_WINDOW_B_NC_ENABLE, GFDX_STOP_WINDOW_B_NC_DISABLE + */ + GFDX_ATTR_STOP_FRAME_OPTIONS, + /** Set Non Continuos Display */ + GFDX_ATTR_NC_DISPLAY, + /** Horizontal and Vertical Filter Support Window B + Parameters: GFDX_H_FILTER_ENABLE, GFDX_H_FILTER_DISABLE, GFDX_V_FILTER_ENABLE, GFDX_V_FILTER_DISABLE + */ + GFDX_ATTR_H_V_FILTER_WB, + /** Horizontal and Vertical Filter Support Window C + Parameters: GFDX_H_FILTER_ENABLE, GFDX_H_FILTER_DISABLE, GFDX_V_FILTER_ENABLE, GFDX_V_FILTER_DISABLE + */ + GFDX_ATTR_H_V_FILTER_WC, + + /** Get Supported Display Script Options + Parameters: GFDX_DEFAULT_TABLE, GFDX_DXAPI_SUPPORT, GFDX_FMARK_SUPPORT + */ + GFDX_ATTR_DISPLAY_SCRIPT_OPTIONS, + /** Rate of window decode output frames when sending continuously. + * please note that the rate is overwritten with the maximum value (i.e. 1.000 + * which is represented by a fixed point fraction 16.16) if you use attribute + * GFDX_ATTR_ENABLE_WENC, so you need to overwrite with this attribute. + * Parameters: any number between 0x0 and 0x10000 (i.e. 0.0 an 1.000) + */ + GFDX_ATTR_WENC_RATE + +} GFDXATTRIBUTES; + +// Stop Frame Options +#define GFDX_MAIN_STOP_POLARITY_HIGH 0x00000001 +#define GFDX_MAIN_STOP_POLARITY_LOW 0x80000001 +#define GFDX_MAIN_STOP_INPUT_PIN_ENABLE 0x00000002 +#define GFDX_MAIN_STOP_INPUT_PIN_DISABLE 0x80000002 + +#define GFDX_SUB_STOP_POLARITY_HIGH 0x00000004 +#define GFDX_SUB_STOP_POLARITY_LOW 0x80000004 +#define GFDX_SUB_STOP_INPUT_PIN_ENABLE 0x00000006 +#define GFDX_SUB_STOP_INPUT_PIN_DISABLE 0x80000006 + +#define GFDX_STOP_WINDOW_A_NC_ENABLE 0x00000010 +#define GFDX_STOP_WINDOW_A_NC_DISABLE 0x80000010 +#define GFDX_STOP_WINDOW_B_NC_ENABLE 0x00000011 +#define GFDX_STOP_WINDOW_B_NC_DISABLE 0x80000011 +#define GFDX_STOP_WINDOW_C_NC_ENABLE 0x00000012 +#define GFDX_STOP_WINDOW_C_NC_DISABLE 0x80000012 + +// Horizontal and Vertical Filter Support Window B & C + +#define GFDX_H_FILTER_ENABLE 0x00000100 +#define GFDX_H_FILTER_DISABLE 0x80000100 +#define GFDX_V_FILTER_ENABLE 0x00004000 +#define GFDX_V_FILTER_DISABLE 0x80004000 +#define GFDX_V_FILTER_OPTIMIZE_ENABLE 0x00010000 +#define GFDX_V_FILTER_OPTIMIZE_DISABLE 0x80010000 + +// Display Script Options + +#define GFDX_DEFAULT_TABLE 0x00000001 +#define GFDX_DXAPI_SUPPORT 0x00000002 +#define GFDX_FMARK_SUPPORT 0x00000004 + + +/** Attribute value for GFDX_ATTR_WRITE_SHADOW_ONLY. + * Setting this attribute will disable all channel hardware writes in DxAPI. + * The runtime environment GFSDK_DXINIT_BYPASS uses this attribue to disable + * hardware writes in DxSetDisplay(). + */ +#define GFDX_SET_WRITE_SHADOW 0x00000001 +/** Attribute value for GFDX_ATTR_WRITE_SHADOW_ONLY. + * This attribute is used to clear the effect of #GFDX_SET_WRITE_SHADOW. + * It must be used explicitly to re-enable hardware writes in DxAPI. + */ +#define GFDX_CLR_WRITE_SHADOW 0x80000001 + + + +#define GFDX_COLOR_DEPTH_YCbCr422 (16UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV422 (17UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YCbCr420P (18UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV420P (19UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YCbCr422P (20UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV422P (21UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YCbCr422R (22UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV422R (23UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YCbCr422RA (24UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV422RA (25UL | 0x80000000) + +#define GFDX_SWAP_MASK 0x000f0000 +#define GFDX_NO_SWAP 0x00000000 +#define GFDX_BYTE_SWAP 0x00010000 +#define GFDX_ORDER_SWAP 0x00020000 +#define GFDX_WORD_SWAP 0x00030000 + +#define GFDX_COLOR_DEPTH_YUV422_YVYU (17UL | 0x80000000 | GFDX_NO_SWAP) +#define GFDX_COLOR_DEPTH_YUV422_VYUY (17UL | 0x80000000 | GFDX_BYTE_SWAP) +#define GFDX_COLOR_DEPTH_YUV422_UYVY (17UL | 0x80000000 | GFDX_ORDER_SWAP) +#define GFDX_COLOR_DEPTH_YUV422_YUYV (17UL | 0x80000000 | GFDX_WORD_SWAP) + +#define GFDX_COLOR_DEPTH_YCbCr422_YVYU (16UL | 0x80000000 | GFDX_NO_SWAP) +#define GFDX_COLOR_DEPTH_YCbCr422_VYUY (16UL | 0x80000000 | GFDX_BYTE_SWAP) +#define GFDX_COLOR_DEPTH_YCbCr422_UYVY (16UL | 0x80000000 | GFDX_ORDER_SWAP) +#define GFDX_COLOR_DEPTH_YCbCr422_YUYV (16UL | 0x80000000 | GFDX_WORD_SWAP) + + +// Horizontal Filter Coefficients + +#define GF_H_P00C0 0x0 +#define GF_H_P00C1 (0x0 << 3 ) +#define GF_H_P00C2 (0x80 << 8 ) +#define GF_H_P00C3 (0x0 << 16) +#define GF_H_P00C4 (0x0 << 24) +#define GF_H_P00C5 (0x0 << 29) +#define GF_H_P00CX GF_H_P00C0|GF_H_P00C1|GF_H_P00C2|GF_H_P00C3|GF_H_P00C4|GF_H_P00C5 + +#define GF_H_P01C0 0x1 +#define GF_H_P01C1 (0x1c << 3 ) +#define GF_H_P01C2 (0x7c << 8 ) +#define GF_H_P01C3 (0x8 << 16) +#define GF_H_P01C4 (0x1e << 24) +#define GF_H_P01C5 (0x1 << 29) +#define GF_H_P01CX GF_H_P01C0|GF_H_P01C1|GF_H_P01C2|GF_H_P01C3|GF_H_P01C4|GF_H_P01C5 + +#define GF_H_P02C0 0x1 +#define GF_H_P02C1 (0x18 << 3 ) +#define GF_H_P02C2 (0x7a << 8 ) +#define GF_H_P02C3 (0x11 << 16) +#define GF_H_P02C4 (0x1b << 24) +#define GF_H_P02C5 (0x1 << 29) +#define GF_H_P02CX GF_H_P02C0|GF_H_P02C1|GF_H_P02C2|GF_H_P02C3|GF_H_P02C4|GF_H_P02C5 + +#define GF_H_P03C0 0x2 +#define GF_H_P03C1 (0x15 << 3 ) +#define GF_H_P03C2 (0x73 << 8 ) +#define GF_H_P03C3 (0x1b << 16) +#define GF_H_P03C4 (0x19 << 24) +#define GF_H_P03C5 (0x2 << 29) +#define GF_H_P03CX GF_H_P03C0|GF_H_P03C1|GF_H_P03C2|GF_H_P03C3|GF_H_P03C4|GF_H_P03C5 + +#define GF_H_P04C0 0x2 +#define GF_H_P04C1 (0x13 << 3 ) +#define GF_H_P04C2 (0x6d << 8 ) +#define GF_H_P04C3 (0x25 << 16) +#define GF_H_P04C4 (0x17 << 24) +#define GF_H_P04C5 (0x2 << 29) +#define GF_H_P04CX GF_H_P04C0|GF_H_P04C1|GF_H_P04C2|GF_H_P04C3|GF_H_P04C4|GF_H_P04C5 + +#define GF_H_P05C0 0x3 +#define GF_H_P05C1 (0x11 << 3 ) +#define GF_H_P05C2 (0x66 << 8 ) +#define GF_H_P05C3 (0x2f << 16) +#define GF_H_P05C4 (0x15 << 24) +#define GF_H_P05C5 (0x2 << 29) +#define GF_H_P05CX GF_H_P05C0|GF_H_P05C1|GF_H_P05C2|GF_H_P05C3|GF_H_P05C4|GF_H_P05C5 + +#define GF_H_P06C0 0x3 +#define GF_H_P06C1 (0x11 << 3 ) +#define GF_H_P06C2 (0x5e << 8 ) +#define GF_H_P06C3 (0x38 << 16) +#define GF_H_P06C4 (0x13 << 24) +#define GF_H_P06C5 (0x3 << 29) +#define GF_H_P06CX GF_H_P06C0|GF_H_P06C1|GF_H_P06C2|GF_H_P06C3|GF_H_P06C4|GF_H_P06C5 + +#define GF_H_P07C0 0x3 +#define GF_H_P07C1 (0x10 << 3 ) +#define GF_H_P07C2 (0x55 << 8 ) +#define GF_H_P07C3 (0x43 << 16) +#define GF_H_P07C4 (0x12 << 24) +#define GF_H_P07C5 (0x3 << 29) +#define GF_H_P07CX GF_H_P07C0|GF_H_P07C1|GF_H_P07C2|GF_H_P07C3|GF_H_P07C4|GF_H_P07C5 + +#define GF_H_P08C0 0x3 +#define GF_H_P08C1 (0x11 << 3 ) +#define GF_H_P08C2 (0x4c << 8 ) +#define GF_H_P08C3 (0x4c << 16) +#define GF_H_P08C4 (0x11 << 24) +#define GF_H_P08C5 (0x3 << 29) +#define GF_H_P08CX GF_H_P08C0|GF_H_P08C1|GF_H_P08C2|GF_H_P08C3|GF_H_P08C4|GF_H_P08C5 + +#define GF_H_P09C0 0x3 +#define GF_H_P09C1 (0x12 << 3 ) +#define GF_H_P09C2 (0x43 << 8 ) +#define GF_H_P09C3 (0x55 << 16) +#define GF_H_P09C4 (0x10 << 24) +#define GF_H_P09C5 (0x3 << 29) +#define GF_H_P09CX GF_H_P09C0|GF_H_P09C1|GF_H_P09C2|GF_H_P09C3|GF_H_P09C4|GF_H_P09C5 + +#define GF_H_P0AC0 0x3 +#define GF_H_P0AC1 (0x13 << 3 ) +#define GF_H_P0AC2 (0x38 << 8 ) +#define GF_H_P0AC3 (0x5e << 16) +#define GF_H_P0AC4 (0x11 << 24) +#define GF_H_P0AC5 (0x3 << 29) +#define GF_H_P0ACX GF_H_P0AC0|GF_H_P0AC1|GF_H_P0AC2|GF_H_P0AC3|GF_H_P0AC4|GF_H_P0AC5 + +#define GF_H_P0BC0 0x2 +#define GF_H_P0BC1 (0x15 << 3 ) +#define GF_H_P0BC2 (0x2f << 8 ) +#define GF_H_P0BC3 (0x66 << 16) +#define GF_H_P0BC4 (0x11 << 24) +#define GF_H_P0BC5 (0x3 << 29) +#define GF_H_P0BCX GF_H_P0BC0|GF_H_P0BC1|GF_H_P0BC2|GF_H_P0BC3|GF_H_P0BC4|GF_H_P0BC5 + +#define GF_H_P0CC0 0x2 +#define GF_H_P0CC1 (0x17 << 3 ) +#define GF_H_P0CC2 (0x25 << 8 ) +#define GF_H_P0CC3 (0x6d << 16) +#define GF_H_P0CC4 (0x13 << 24) +#define GF_H_P0CC5 (0x2 << 29) +#define GF_H_P0CCX GF_H_P0CC0|GF_H_P0CC1|GF_H_P0CC2|GF_H_P0CC3|GF_H_P0CC4|GF_H_P0CC5 + +#define GF_H_P0DC0 0x2 +#define GF_H_P0DC1 (0x19 << 3 ) +#define GF_H_P0DC2 (0x1b << 8 ) +#define GF_H_P0DC3 (0x73 << 16) +#define GF_H_P0DC4 (0x15 << 24) +#define GF_H_P0DC5 (0x2 << 29) +#define GF_H_P0DCX GF_H_P0DC0|GF_H_P0DC1|GF_H_P0DC2|GF_H_P0DC3|GF_H_P0DC4|GF_H_P0DC5 + +#define GF_H_P0EC0 0x1 +#define GF_H_P0EC1 (0x1b << 3 ) +#define GF_H_P0EC2 (0x11 << 8 ) +#define GF_H_P0EC3 (0x7a << 16) +#define GF_H_P0EC4 (0x18 << 24) +#define GF_H_P0EC5 (0x1 << 29) +#define GF_H_P0ECX GF_H_P0EC0|GF_H_P0EC1|GF_H_P0EC2|GF_H_P0EC3|GF_H_P0EC4|GF_H_P0EC5 + +#define GF_H_P0FC0 0x1 +#define GF_H_P0FC1 (0x1e << 3 ) +#define GF_H_P0FC2 (0x8 << 8 ) +#define GF_H_P0FC3 (0x7c << 16) +#define GF_H_P0FC4 (0x1c << 24) +#define GF_H_P0FC5 (0x1 << 29) +#define GF_H_P0FCX GF_H_P0FC0|GF_H_P0FC1|GF_H_P0FC2|GF_H_P0FC3|GF_H_P0FC4|GF_H_P0FC5 + +// Vertical Filter Coefficients +#define GF_V_P00C0 0x80 +#define GF_V_P01C0 0x78 +#define GF_V_P02C0 0x70 +#define GF_V_P03C0 0x68 +#define GF_V_P04C0 0x60 +#define GF_V_P05C0 0x58 +#define GF_V_P06C0 0x50 +#define GF_V_P07C0 0x48 +#define GF_V_P08C0 0x40 +#define GF_V_P09C0 0x38 +#define GF_V_P0AC0 0x30 +#define GF_V_P0BC0 0x28 +#define GF_V_P0CC0 0x20 +#define GF_V_P0DC0 0x18 +#define GF_V_P0EC0 0x10 +#define GF_V_P0FC0 0x8 + +/** Hardware Cursor definition */ +typedef struct _HC_COLOR +{ + NvU32 foreground; + NvU32 background; +} HC_COLOR, *PHC_COLOR; + +typedef struct _HC_POSITION +{ + NvU32 x; + NvU32 y; +} HC_POSITION, *PHC_POSITION; + +typedef struct _HC_HOTSPOT +{ + NvU32 x; + NvU32 y; +} HC_HOTSPOT, *PHC_HOTSPOT; + +enum +{ + CD64X64, + CD32X32 +}; + +typedef struct _HC_MASK +{ + NvU32 *data; + NvU32 size; + NvU32 dimension; +} HC_MASK, *PHC_MASK; + +typedef struct _DisplayTimingEntry +{ + /** Horizontal Ref. Need not to be changed, set 0 for default setting */ + NvU16 usHRef; + /** Vertical Ref. Need not to be changed, set 0 for default setting */ + NvU16 usVRef; + /** Horizontal Sync Width, set 0 for default setting */ + NvU16 usHSyncWidth; + /** Vertical Sync Width, set 0 for default setting */ + NvU16 usVSyncWidth; + /** Horizontal Back Porch, set 0 for default setting */ + NvU16 usHBackPorch; + /** Vertical Back Porch, set 0 for default setting */ + NvU16 usVBackPorch; + /** Horizontal Active, Set same as Window Width */ + NvU16 usHActive; + /** Vertical Active, Set same as Window Height */ + NvU16 usVActive; + /** Horizontal Total, set 0 for default setting */ + NvU16 usHTotal; + /** Vertical Total, set 0 for default setting */ + NvU16 usVTotal; + /** Window Width */ + NvU16 usPanelVX; + /** Window Height */ + NvU16 usPanelVY; + /** Window Start X Position */ + NvU16 usPosX; + /** Window Start Y Position */ + NvU16 usPosY; + /** Window Sel 0-WinA (GFDX_DISPTMG_SEL_WINA), 1-WinB (GFDX_DISPTMG_SEL_WINB) */ + NvU16 SelWin; + NvU16 Reserved1; + NvU16 Reserved2; + NvU16 Reserved3; +} DISPLAYTIMINGENTRY, *PDISPLAYTIMINGENTRY; + +// Display Timing + +#define GFDX_DISPTMG_SEL_WINA 0 +#define GFDX_DISPTMG_SEL_WINB 1 + +/** redefine some of the constants for compatibility */ +#define GFDX_ATTR_WIDTH_HEIGHT GFDX_ATTR_WH_WA +#define GFDX_ATTR_XY_POSITION GFDX_ATTR_XY_POS_WA +#define GFDX_ATTR_BPP GFDX_ATTR_BPP_WA +#define GFDX_ATTR_PIXEL_DOUBLE GFDX_ATTR_PIXEL_DBL_WA +#define GFDX_ATTR_STARTADDR GFDX_ATTR_ADDR_WA_B0 +#define GFDX_ATTR_STRIDE GFDX_ATTR_STRIDE_WA_B0 + +/** definition of GFDX_ATTR_PIXEL_DOUBLE */ +#define GFDXA_PIX_DBL_H 0x01 /* Horizontal pixel doubling on */ +#define GFDXA_PIX_DBL_V 0x02 /* Vertical pixel doubling on */ + +/** definition of GFDX_ATTR_DOUBLE_BUF control (0,2,1,3 is same as hw) */ +#define GFDXA_DB_BUF0 0x00 /* GC display buffer address is from buf0 */ +#define GFDXA_DB_BUF1 0x02 /* GC display buffer address is from buf1 */ +#define GFDXA_DB_HOST 0x06 /* GC display buffer address is from Host */ +#define GFDXA_DB_GE 0x01 /* GC display buffer address is from GE */ +#define GFDXA_DB_VI 0x03 /* GC display buffer address is from VI */ +#define GFDXA_DB_EPP 0x04 +#define GFDXA_DB_MPEGE 0x05 + +/** definition of GFDX_ATTR_ROTATE_BIT_W? */ +#define GFDXA_ROTATE_BITS_0 0x00000000 // no rotation, x+,y+,startAddr = 0 +#define GFDXA_ROTATE_BITS_90 0x00000500 // +90 (anti-clock), x-, y+, start= stride-3 (TL) +#define GFDXA_ROTATE_BITS_180 0x00000300 // +180(anti-clock), x-, y-, start= height*stride-3 (BR) +#define GFDXA_ROTATE_BITS_270 0x00000600 // +270(anti-clock), x+, y-, start= (height-1)*stride (BL) + +/** definition of Color Key and Alpha Blending*/ +#define GFDXA_BLEND_CONTROL_NOKEY_ALPHA_WEIGHT 0x00000001 + +#define GFDXA_BLEND_COLOR_KEY0_ENABLE 0x00000001 +#define GFDXA_BLEND_COLOR_KEY1_ENABLE 0x00000002 +#define GFDXA_BLEND_COLOR_KEY0_DISABLE 0x00000000 +#define GFDXA_BLEND_COLOR_KEY1_DISABLE 0x00000000 +#define GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT 0x00000004 +#define GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT 0x00000008 + +/** Disable CRC capture. */ +#define GFDXA_CRC_DISABLE 0x00000000 +/** Wait for 1 VSYNC and capture CRC for one frame. */ +#define GFDXA_CRC_WAIT_VSYNC1 0x00000001 +/** Wait for 2 VSYNC and capture CRC for one frame. */ +#define GFDXA_CRC_WAIT_VSYNC2 0x00000003 + +/** Set Direction for Rotation*/ +#define GFDX_ATTR_H_DIRECTION_DECREMENT 0x00000001 +#define GFDX_ATTR_H_DIRECTION_INCREMENT 0x00000000 +#define GFDX_ATTR_V_DIRECTION_DECREMENT 0x00000004 +#define GFDX_ATTR_V_DIRECTION_INCREMENT 0x00000000 + +/** definition of Palette Enable/Disable*/ +#define GFDX_ATTR_PALETTE_ENABLE 0x00010000 +#define GFDX_ATTR_PALETTE_DISABLE 0x00000000 +#define GFDX_ATTR_DV_ENABLE 0x00100000 +#define GFDX_ATTR_DV_DISABLE 0x00000000 + +#define GFDX_ATTR_WENC_DISABLE 0x00000000 +#define GFDX_ATTR_WENC_ENABLE 0x00000001 +#define GFDX_ATTR_WENC_TRIG_DISABLE 0x00000000 +#define GFDX_ATTR_WENC_TRIG_ENABLE 0x00000001 +#define GFDX_ATTR_WENC_TRIG_ONE_SHOT 0x00000002 + +/** Read CRC Check Sum */ +#define GFDXA_CRC_READ_CHECK_SUM 0x00000001 + +/** + Sub-LCD support + */ +#define LCD_MAIN 0 +#define LCD_SUB 1 +#define MAX_LCD 2 + +/** + Start-Stop Frame support + */ +#define GFDX_MAIN_START 0x00000001 +#define GFDX_MAIN_STOP 0x00000002 +#define GFDX_SUB_START 0x00000003 +#define GFDX_SUB_STOP 0x00000004 +#define GFDX_MAIN_ONE_FRAME 0x00000001 +#define GFDX_SUB_ONE_FRAME 0x00000002 + +#define GF_DISPLAY_NORMAL 0x00000000 +#define GF_DISPLAY_PARTIAL 0x00000001 + +#ifdef PROJECT_SEC_G1 +#define GF_DISPLAY_NTSC_V570 0x00000002 +#define GF_DISPLAY_NTSC_V490 0x00000003 +#define GF_DISPLAY_NTSC_V700 0x00000004 +#define GF_DISPLAY_PAL 0x00000005 +#endif + +/** + DxEnableDisplay support + */ +#define GF_PANEL_DRV_ONOFF 0x00000100 +#define GF_PANEL_DRV_SLP_WKUP 0x00000200 + +/** + Clock selections, profile and options + */ +#define GFDX_OSC 0x00000001 +#define GFDX_ROSC 0x00000002 +#define GFDX_PLL1 0x00000003 +#define GFDX_PLL_QUERY 0x80000000 +#define GFDX_POWER 0x00010000 +#define GFDX_PERFORMANCE 0x00020000 + +/** + Option for GFDxVSync: Waits until vertical blank (default). + */ +#define GFDX_VSYNC_WAIT 0x0000 +/** + Option for GFDxVSync: Checks and immediately returns vertical blank status. + Returns GF_SUCCESS if in vertical blank, else returns GF_ERROR. + */ +#define GFDX_VSYNC_CHECK 0x0001 +/** + Option for GFDxVSync: Puts Wait token in the command FIFO and the CPU returns + immediately. Uses FRAME_END interrupt bit. + */ +#define GFDX_VSYNC_HW_WAIT 0x0002 +/** + Option for GFDxVSync: Raise and wait in the command fifo for VBLANK. + */ +#define GFDX_VBLANK_HW_WAIT 0x0003 +/** + Option for GFDxVSync: Raise and wait in the command fifo for VPULSE3. + */ +#define GFDX_VPULSE3_HW_WAIT 0x0004 + +/** Dx Hardware has multiple windows (some registers are replicated per + window - the window must be exlicitly selected to write to the correct + register in the window). Use this enum to select which window + to write to for APIs that support this - window selection is mostly + done through the attribute name, eg: _WA, _WB, etc. + */ +typedef enum _GFDXWINDOWSELECT +{ + DX_WINDOW_SELECT_NONE = 0, + DX_WINDOW_SELECT_NORMAL = 1, /* all windows */ + DX_WINDOW_SELECT_A = 2, + DX_WINDOW_SELECT_B = 4, + DX_WINDOW_SELECT_C = 8 +} GFDXWINDOWSELECT; + +/** Color Space Conversion coefficients. Use GFDxSetCSCCoeff() and + GFDxGetCSCCoeff() to write/read the coefficients to/from hardware. + */ +typedef struct _GFDXCSCCOEFF +{ + NvU32 YOF; + NvU32 KYRGB; + NvU32 KUR; + NvU32 KVR; + NvU32 KUG; + NvU32 KVG; + NvU32 KUB; + NvU32 KVB; +} GFDXCSCCOEF; + +typedef struct _DXSCRIPTCMD +{ + NvU32 ScriptCmdType; /** Script Command */ + NvU32 DataBurstCount; /** Burst count 0-255, not Valid for GFSCMD */ + NvU32 PanelDriverCmd; /** Valid Only if ScriptCmdType = GFPDRV_CMD */ + NvU32 *PanelIndexData; /** Data pointer */ + NvU32 GFData; /** Valid only if ScriptCmdType is GFSCMD */ + NvU32 reserved1; +} DXSCRIPTCMD, *PDXSCRIPTCMD; + +typedef struct _GFLCDTABLE { + /** For usage see GFDxSetDisplay()*/ + GF_RETTYPE (* DxSetDisplay)(GFDxHandle DxHandle, int lcdSel, NvU32 ulStartAddr, + NvU32 ulStride, unsigned bpp); + /** For usage see GFDxEnableDisplay()*/ + GF_RETTYPE (* DxEnableDisplay)(GFDxHandle DxHandle, int lcdSel, unsigned bOn); + /** For usage see GFDxSetAttribute()*/ + GF_RETTYPE (* DxSetAttribute)(GFDxHandle DxHandle, int lcdSel, unsigned aid, NvU32 attr); + /** For usage see GFDxGetAttribute()*/ + GF_RETTYPE (* DxGetAttribute)(GFDxHandle DxHandle, int lcdSel, unsigned aid, NvU32 *attr); + /** For usage see GFDxSetAttributeWithCS()*/ + GF_RETTYPE (* DxSetAttributeWithCS)(GFDxHandle DxHandle, int lcdSel, unsigned aid, NvU32 attr); + /** For usage see GFDxGetAttributeWithCS()*/ + GF_RETTYPE (* DxGetAttributeWithCS)(GFDxHandle DxHandle, int lcdSel, unsigned aid, NvU32 *attr); + /** For usage see GFDxRotate()*/ + GF_RETTYPE (* DxRotate)(GFDxHandle DxHandle, int lcdSel, unsigned nRotate, NvU32 ulStartAddr); + /** For usage see GFDxErase()*/ + GF_RETTYPE (* DxErase)(GFDxHandle DxHandle, int lcdSel, NvU32 ulStartAddr, NvU32 color); + /** For usage see GFDxSwitchLCD()*/ + GF_RETTYPE (* DxSwitchLCD)(GFDxHandle DxHandle, int lcdSel, int Option); + /** LCD Configurations */ + void * pLcdConfig; + /** For usage see GFDxScriptCmd()*/ + GF_RETTYPE (* DxScriptCmd)(GFDxHandle DxHandle, int lcdSel, PDXSCRIPTCMD pDxScriptCmd, NvU32 Option); + /** For usage see GFDxScriptCmdWithCS()*/ + GF_RETTYPE (* DxScriptCmdWithCS)(GFDxHandle DxHandle, int lcdSel, PDXSCRIPTCMD pDxScriptCmd, NvU32 Option); + /** For usage see GFDxDisplayTiming()*/ + GF_RETTYPE (* DxDisplayTiming)(GFDxHandle DxHandle, int lcdSel, PDISPLAYTIMINGENTRY pDxTiming, NvU32 Option); + /** For usage see GFDxDisplayTimingWithCS()*/ + GF_RETTYPE (* DxDisplayTimingWithCS)(GFDxHandle DxHandle, int lcdSel, PDISPLAYTIMINGENTRY pDxTiming, NvU32 Option); + /** For usage see GFDxSetDisplayEx()*/ + GF_RETTYPE (* DxSetDisplayEx)(GFDxHandle DxHandle, int lcdSel, NvU32 ulStartAddr, + NvU32 ulStride, unsigned bpp, unsigned bOn); +} GFLCDTABLE; + +/* Publicly exposed DX API function table */ +typedef struct _GFDXTABLE +{ + /** For usage see GFDxGetProperty()*/ + GF_RETTYPE (* DxGetProperty)(GFDxHandle DxHandle, PGFDXPROPERTY pDxProp); + /** For usage see GFDxVSync()*/ + GF_RETTYPE (* DxVSync)(GFDxHandle DxHandle, NvU16 option); + /** For usage see GFDxSetDisplayWithCS()*/ + GF_RETTYPE (* DxSetDisplayWithCS)(GFDxHandle DxHandle, int lcdSel, + NvU32 ulStartAddr, NvU32 ulStride, unsigned bpp); + /** For usage see GFDxEnableDisplayWithCS()*/ + GF_RETTYPE (* DxEnableDisplayWithCS)(GFDxHandle DxHandle, int lcdSel, + unsigned bOn); +// Removed to make the WinCE dll binary compatible with SC4 dll. +// GF_RETTYPE (* DxHSync)(GFDxHandle DxHandle, NvU16 option); + + /** For per LCD functions. ()*/ + GFLCDTABLE Lcd[MAX_LCD]; + /** For usage see GFDxEraseWithCS()*/ + GF_RETTYPE (* DxEraseWithCS)(GFDxHandle DxHandle, int lcdSel, + NvU32 ulStartAddr, NvU32 color); + /** For usage see GFDxSetCSCCoeff()*/ + GF_RETTYPE (* DxSetCSCCoeff)( GFDxHandle DxHandle, GFDXWINDOWSELECT window, + GFDXCSCCOEF *coef ); + /** For usage see GFDxGetCSCCoeff()*/ + GF_RETTYPE (* DxGetCSCCoeff)( GFDxHandle DxHandle, GFDXWINDOWSELECT window, + GFDXCSCCOEF *coef ); + /** For usage see GFDxVSyncWithCS()*/ + GF_RETTYPE (* DxVSyncWithCS)(GFDxHandle DxHandle, NvU16 option); + /** For usage see GFDxSetCSCCoeffWithCS()*/ + GF_RETTYPE (* DxSetCSCCoeffWithCS)( GFDxHandle DxHandle, GFDXWINDOWSELECT window, + GFDXCSCCOEF *coef ); + /** For usage see GFDxGetCSCCoeffWithCS()*/ + GF_RETTYPE (* DxGetCSCCoeffWithCS)( GFDxHandle DxHandle, GFDXWINDOWSELECT window, + GFDXCSCCOEF *coef ); + /** For usage see GFDxSetDisplayExWithCS()*/ + GF_RETTYPE (* DxSetDisplayExWithCS)(GFDxHandle DxHandle, int lcdSel, + NvU32 ulStartAddr, NvU32 ulStride, unsigned bpp, unsigned bOn); +} GFDXTABLE, *PGFDXTABLE; + +/** Filter coefficients */ +typedef struct GFDxHorizontalFilter_t +{ + NvU32 filter[16]; +} GFDxHorizontalFilter; + +typedef struct GFDxVerticalFilter_t +{ + NvU32 filter[16]; +} GFDxVerticalFilter; + +/** + Typesafe function for opening Dx component. + This function is implicitly called by the resource manager (GFRm) in response + to an application’s call to GFRmComponentGet() for the GFDxAPI + component. It is not supposed to be called by an application. It is included + here only for the purpose of GFDxAPI source code customization. + + @param hrm (GFRmHandle) Handle to Rm component. + @param phDx (GFDxHandle *) Handle to Dx component. + @param state (GF_STATE_TYPE) + @param hCh (GFRmChHandle) Handle to Channel. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +GF_RETTYPE GFDxOpen(GFRmHandle hRm, GFDxHandle *phDx, + GF_STATE_TYPE state, GFRmChHandle hCh); + +/** + Typesafe function for closing Dx component. + This function is implicitly called by the resource manager (GFRm) in response + to an application’s call to GFRmComponentGet() for the GFDxAPI + component. It is included here only for the purpose of GFDxAPI source code + customization. + + @param phDx (GFDxHandle *) Handle to Dx component. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + * +*/ +void GFDxClose(GFDxHandle *phDx); + +/** + This funtion returns the fixed properties of the display hardware. + + @param DxHandle (GFDxHandle) Handle to Dx Component + @param pDxProp (PGFDXPROPERTY) See #GFDXPROPERTY + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxGetProperty( handle, pDxProp ) \ + ((PGFDXTABLE)handle)->DxGetProperty( handle, pDxProp ) + +/** + This functions waits for a vertical sync and returns to the caller. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param option (NvU16) Search for Option for GFDxVSync for more info. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxVSync(handle, option) \ + ((PGFDXTABLE)handle)->DxVSync( handle, option ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxVSync(). + */ +#define GFDxVSyncWithCS(handle, option) \ + ((PGFDXTABLE)handle)->DxVSyncWithCS( handle, option ) + +/** + IMPORTANT NOTE: This function is not available. + */ +#define GFDxHSync(handle, option) \ + ((PGFDXTABLE)handle)->DxHSync( handle, option ) + +/** + This function initializes the main LCD or sub-LCD display. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param Handle (DxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param ulStartAddr (NvU32) display start address for main or sub-LCD (should be set to 0). + GFDxSetAttribute() should be called to set the display start + address for the main LCD or sub-LCD. + @param ulStride (NvU32) Default stride if 0; otherwise use the passed value. + GFDxSetAttribute() should be called to set the display stride + for the main LCD or sub-LCD. + @param bpp (unsigned) Default should be 16 bits/pixel for main LCD or sub-LCD. + GFDxSetAttribute() should be called to set the display bpp for + the main LCD or sub-LCD. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSetDisplay( handle, lcdSel, ulStartAddr, ulStride, bpp ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSetDisplay( handle, lcdSel, ulStartAddr, ulStride, bpp ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxSetDisplay(). + */ +#define GFDxSetDisplayWithCS( handle, lcdSel, ulStartAddr, ulStride, bpp ) \ + ((PGFDXTABLE)handle)->DxSetDisplayWithCS( handle, lcdSel, ulStartAddr, \ + ulStride, bpp ) + +/** + This function initializes the main LCD or sub-LCD display. + IMPORTANT NOTE: This function extends GFDxSetDisplay() function by adding an option to enable/disable + the LCD display. + + @param Handle (DxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param ulStartAddr (NvU32) display start address for main or sub-LCD (should be set to 0). + GFDxSetAttribute() should be called to set the display start + address for the main LCD or sub-LCD. + @param ulStride (NvU32) Default stride if 0; otherwise use the passed value. + GFDxSetAttribute() should be called to set the display stride + for the main LCD or sub-LCD. + @param bpp (unsigned) Default should be 16 bits/pixel for main LCD or sub-LCD. + GFDxSetAttribute() should be called to set the display bpp for + the main LCD or sub-LCD. + @param bOn (unsigned) 1 to Enable Display, + 0 to disable Display. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSetDisplayEx( handle, lcdSel, ulStartAddr, ulStride, bpp, bOn ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSetDisplayEx( handle, lcdSel, ulStartAddr, ulStride, bpp, bOn ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxSetDisplayEx(). + */ +#define GFDxSetDisplayExWithCS( handle, lcdSel, ulStartAddr, ulStride, bpp, bOn ) \ + ((PGFDXTABLE)handle)->DxSetDisplayExWithCS( handle, lcdSel, ulStartAddr, \ + ulStride, bpp, On) + +/** + This function enables/disables LCD display with proper power sequencing. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param Handle (DxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param bOn (unsigned) Bit0: 1 to Enable Display, + 0 to disable Display. + Also Option for Panel Driver On/Off + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxEnableDisplay( handle, lcdSel, bOn ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxEnableDisplay( handle, lcdSel, bOn ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxEnableDisplay(). + */ +#define GFDxEnableDisplayWithCS( handle, lcdSel, bOn ) \ + ((PGFDXTABLE)handle)->DxEnableDisplayWithCS( handle, lcdSel, bOn ) + +/** + GFDxSetAttribute() sets the display attributes for a main panel or + subpanel. All the GFDxAPI attributes should be set after the + GFDxSetDisplay() + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param aid (unsigned) Attribute IDs. See #GFDXATTRIBUTES Enumeration Type + @param attr (NvU32) Attribute value for main LCD or sub-LCD. Should be + written with attribute ID in aid. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSetAttribute( handle, lcdSel, aid, attr) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSetAttribute( handle, lcdSel, aid, attr ) + +/** + Execute script command from DxApiTable. Send cmd/data to panel. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param ScriptCmdType (PDXSCRIPTCMD) Script Command + @param Option (NvU32) Reserved, not used. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxScriptCmd( handle, lcdSel, pDxScriptCmd, Option) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxScriptCmd( handle, lcdSel, pDxScriptCmd, Option ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxScriptCmd(). + */ +#define GFDxScriptCmdWithCS( handle, lcdSel, pDxScriptCmd, Option) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxScriptCmdWithCS( handle, lcdSel, pDxScriptCmd, Option ) + +/** Sets the timing registers. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param pDxTiming (PDISPLAYTIMINGENTRY) See #PDISPLAYTIMINGENTRY. + @param Option (NvU32) GF_DISPLAY_PARTIAL or GF_DISPLAY_NORMAL. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxDisplayTiming( handle, lcdSel, pDxTiming, Option) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxDisplayTiming( handle, lcdSel, pDxTiming, Option ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxDisplayTiming(). + */ +#define GFDxDisplayTimingWithCS( handle, lcdSel, pDxTiming, Option) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxDisplayTimingWithCS( handle, lcdSel, pDxTiming, Option ) + +/** + This function returns the bit depth, the destination stride, the start address, + the associated surface of the display buffer, or the graphics command + execution control. The location of the returned attribute value is pointed to by + attr. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param aid (unsigned) Attribute ID. see #GFDXATTRIBUTES. + @param attr (NvU32 *) pointer to attribute value. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxGetAttribute( handle, lcdSel, aid, pAttr) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxGetAttribute( handle, lcdSel, aid, pAttr ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxSetAttribute(). + */ +#define GFDxSetAttributeWithCS( handle, lcdSel, aid, attr) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSetAttributeWithCS( handle, lcdSel, aid, attr ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxGetAttribute(). + */ +#define GFDxGetAttributeWithCS( handle, lcdSel, aid, pAttr) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxGetAttributeWithCS( handle, lcdSel, aid, pAttr ) + +/** + IMPORTANT NOTE: this function is not available. + */ +#define GFDxRotate( handle, lcdSel, nRotate, ulStartAddr ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxRotate( handle, lcdSel, nRotate, ulStartAddr ) + +/** + This function clears the main or subdisplay screen with the given color. It also + clears the display buffer of the main or subpanel window. Window A buffer 0 + is used as a display buffer. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param ulStartAddr (NvU32) Start Address. (The offset in bytes of the + display frame buffer.) + @param color (NvU32) Clear screen with this color. The 32-bit value + has a 16-bit color duplicated in the upper and + lower parts. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxErase( handle, lcdSel, ulStartAddr, color ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxErase( handle, lcdSel, ulStartAddr, color ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxErase(). + */ +#define GFDxEraseWithCS( handle, lcdSel, ulStartAddr, color ) \ + ((PGFDXTABLE)handle)->DxEraseWithCS( handle, lcdSel, ulStartAddr, color ) + +/** + This function enables swithcing between the main LCD and sub-LCD. + IMPORTANT NOTE: This function has critical sections and is thread-safe. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param Option (NvU32) 0 for switch (Must be set to 0) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSwitchLCD( handle, lcdSel, Option ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSwitchLCD( handle, lcdSel, Option ) + +/** + This function sets the hardware Color Space Conversion (CSC) Coefficients. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param window (GFDXWINDOWSELECT) Controller window. see #GFDXWINDOWSELECT. + @param coef (GFDXCSCCOEF *) CSC coefficients. see #GFDXCSCCOEF. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSetCSCCoeff( handle, window, coef ) \ + ((PGFDXTABLE)handle)->DxSetCSCCoeff( handle, window, coef ) + +/** + This function gets the hardware Color Space Conversion (CSC) Coefficients. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param window (GFDXWINDOWSELECT) Controller window. see #GFDXWINDOWSELECT. + @param coef (GFDXCSCCOEF *) CSC coefficients. see #GFDXCSCCOEF. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxGetCSCCoeff( handle, window, coef ) \ + ((PGFDXTABLE)handle)->DxGetCSCCoeff( handle, window, coef ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxSetCSCCoeff(). + */ +#define GFDxSetCSCCoeffWithCS( handle, window, coef ) \ + ((PGFDXTABLE)handle)->DxSetCSCCoeffWithCS( handle, window, coef ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxGetCSCCoeff(). + */ +#define GFDxGetCSCCoeffWithCS( handle, window, coef ) \ + ((PGFDXTABLE)handle)->DxGetCSCCoeffWithCS( handle, window, coef ) +/*@}*/ + +/** GFDxSetDefaultPanelMode - sets the default mode for multi-mode panels. + + @param handle A handle to a Dx instance + @param mode The panel mode + + Some panels support multiple modes. To support mode switching, the + default panel mode must be known. + */ +GF_RETTYPE +GFDxSetDefaultPanelMode( GFDxHandle handle, NvU32 mode ); + +/** GFDxSwitchPanelMode - switch from the current mode to a new mode. + + @param handle A handle to a Dx instance + @param mode The panel mode + + This switches from the current mode to a new mode. This calls a display + script with the name "SwitchMode__to_" where x is the current mode + and y is the new mode. + */ +GF_RETTYPE +GFDxSwitchPanelMode( GFDxHandle handle, NvU32 mode ); + +/** GFDxSPIRegEnable - enable register reads and writes over SPI. + + @param handle A handle to a Dx instance + @param enable Either enable or disable register read/writes. + + Enabling SPI register reads/writes may change the pin mapping which + may prevent the rest of the display api from behaving properly (pixel + data may no longer output to the panel). Disabling will restore + the pin mapping. + */ +void +GFDxSpiRegEnable( GFDxHandle handle, NvBool enable ); + +/** GFDxSPIRegWrite - write a 16 bit register over SPI. + + @param handle A handle to a Dx instance + @param address The address to write + @param data The data to write + */ +GF_RETTYPE +GFDxSpiRegWrite( GFDxHandle handle, NvU16 address, NvU16 data ); + +/** GFDxSPIRegRead - read a 16 bit register over SPI. + + @param handle A handle to a Dx instance + @param address The address to read from + @param data The data to read (out param) + */ +GF_RETTYPE +GFDxSpiRegRead( GFDxHandle handle, NvU16 address, NvU16 *data ); + +/** GFDxSpiPixelInit - send init sequence to the panel and setup the pixel + write hardware. + + @param handle A handle to a Dx instance + @param seq_data_a The first 32 bits of init data + @param seq_data_b The second 32 bits of init data + @param seq_data_c The third 32 bits of init data + @param seq_data_d The fourth 32 bits of init data + + Note that this only support SPI16 mode, msb2lsb data ordering. + + Some panels may need the init sequence before every frame, in which + case, this should always be called before GFDxSpiPixelWrite(). + */ +GF_RETTYPE +GFDxSpiPixelInit( GFDxHandle handle, NvU32 seq_data_a, + NvU32 seq_data_b, NvU32 seq_data_c, NvU32 seq_data_d ); + +/** GFDxSpiPixelWrite - writes the given pixel to the panel over SPI. + + @param handle A handle to a Dx instance + @param pixel The pixels to write + */ +GF_RETTYPE +GFDxSpiPixelWrite( GFDxHandle handle, NvUPtr pixels ); + +/** GFDxSpiScript - send commands to the spi hardware via an in-memory script. + + @param handle A handle to a Dx instance + @param script The script to execute + */ +GF_RETTYPE +GFDxSpiScript( GFDxHandle handle, NvU32 *script ); + +/** GFDxSetPixelClock - sets the pixel clock divider in half step increments. + + @param handle A handle to the Dx instance + @param divider The pixel clock divider (actually shift clock - pixel clock + will be the same as shift clock) + + Note: the divider is in half step increments: 1 = 1, 2 = 1.5, 3 = 2, etc. + */ +GF_RETTYPE +GFDxSetPixelClock( GFDxHandle handle, NvU32 divider ); + +/** GFDxGetPixelClock - gets the current shift clock divider value. + + @param handle A handle to the Dx instance + @param divider The pixel clock divider (actually shift clock - pixel clock + will be the same as shift clock) + + */ +GF_RETTYPE +GFDxGetPixelClock( GFDxHandle handle, NvU32 *divider ); + +/** GFDxSetFilter - sets the window filtering coefficients. + + @param handle A handle to the Dx instance + @param window The target window for the new coefficients + @param hfilter The horizontal filtering coefficients + @param vfilter The vertical filtering coefficients + + Window A does NOT support filtering. + Window C only supports horizontal filtering (the vfilter param must be + null) + Window B supports both h and v filtering + + Passing null to both h and v filter will disabling filtering. + + DX_WINDOW_SELECT_NONE and DX_WINDOW_SELECT_NORMAL should not be used. + */ +GF_RETTYPE +GFDxSetFilter( GFDxHandle handle, GFDXWINDOWSELECT window, + GFDxHorizontalFilter *hfilter, GFDxVerticalFilter *vfilter ); + +#ifdef PROJECT_SEC_G1 +/** GFDxSetFilter - sets the clock and timing to support focus TV encoder. + + @param handle A handle to the Dx instance + @param option The Normal/NTSC/PAL mode to set + */ +GF_RETTYPE +GFDxSetMode( GFDxHandle handle, NvU32 option ); +#endif + +#ifdef __cplusplus +} +#endif + +/** @page pageDxAppNotes DxAPI Application Notes + + @section pageDxAppNotes1 Todo + +*/ + +#endif /* GF_DX_H */ diff --git a/Start_WM/test6/inc/GFEPP.h b/Start_WM/test6/inc/GFEPP.h new file mode 100755 index 00000000..36d28219 --- /dev/null +++ b/Start_WM/test6/inc/GFEPP.h @@ -0,0 +1,89 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFEPP.h + GFSDK EPP API +*/ + +#ifndef __GFEPP_H__ +#define __GFEPP_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupEPP EPPAPI EPP API +*/ +/*@{*/ + +typedef struct _GFEPPBUFFERINFO +{ + NvU32 flag; + PGFRECT pSrcRect; + void *pLine; + NvU32 alphaValue; + NvU32 numofSurfs; + PGFRMSURFACE *ppSurf; +} GFEPPBUFFERINFO, *PEPPBUFFERINFO; + + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFEPPOpen(GFRmHandle hRm, GFEPPHandle *phEPP, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFEPPClose(GFEPPHandle *phEPP); + +GF_RETTYPE GFEPPSetBuffers(GFEPPHandle EPPHandle, PEPPBUFFERINFO pBuf); +GF_RETTYPE GFEPPRaiseBuffer(GFEPPHandle EPPHandle, NvU32, NvU32* pCmdS, NvU32* pIndex); +GF_RETTYPE GFEPPRaiseFrame(GFEPPHandle EPPHandle, NvU32, NvU32* pCmdS, NvU32* pIndex); + + +#define EPPBUFFERINFO_FLAG_SRC_VI 0x00000001 + //incoming video from VI +#define EPPBUFFERINFO_FLAG_SRC_SB 0x00000002 + //incoming video from SB +#define EPPBUFFERINFO_FLAG_SRC_GC 0x00000003 + //incoming video from display +#define EPPBUFFERINFO_FLAG_SRC_MASK 0x0000000F + +#define EPPBUFFERINFO_FLAG_SRC_VI_YUV444 0x00000010 + //incoming video from VI +#define EPPBUFFERINFO_FLAG_SRC_VI_BAYER 0x00000020 + //incoming video from VI, Raw Bayer data +#define EPPBUFFERINFO_FLAG_SRC_VI_RGB 0x00000030 + //incoming video from VI, Raw RGB data +#define EPPBUFFERINFO_FLAG_SRC_VI_MASK 0x000000F0 + +#define EPPBUFFERINFO_FLAG_PRE_PROC 0x00000100 + //pre process filter enable +#define EPPBUFFERINFO_FLAG_AVERAGE 0x00000200 + //enable average for 420 planar or 444 to 422 conversion. +#define EPPBUFFERINFO_FLAG_C_SIGN 0x00000400 + //chroma sign +#define EPPBUFFERINFO_FLAG_DMA 0x00000800 + //enable DMA +#define EPPBUFFERINFO_FLAG_DUP 0x00001000 + //duplicate +#define EPPBUFFERINFO_FLAG_H_DIRECTION 0x00002000 +#define EPPBUFFERINFO_FLAG_V_DIRECTION 0x00004000 +#define EPPBUFFERINFO_FLAG_XY_SWAP 0x00008000 + +#define EPPBUFFERINFO_FLAG_SRC_SB_YUV 0x00010000 +#define EPPBUFFERINFO_FLAG_SRC_SB_RGB 0x00020000 +#define EPPBUFFERINFO_FLAG_SRC_SB_MASK 0x000F0000 + + //BE CAREFUL WITH THE STRIDE PROGRAMMING! + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif // _GFEPP_H_ diff --git a/Start_WM/test6/inc/GFFDev.h b/Start_WM/test6/inc/GFFDev.h new file mode 100755 index 00000000..6826085b --- /dev/null +++ b/Start_WM/test6/inc/GFFDev.h @@ -0,0 +1,321 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFFDev.h + GFSDK File Device API header file. +*/ + +#ifndef __GFFDEV_H__ +#define __GFFDEV_H__ + +#include "nvtypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupFDev FDevAPI File Device API +
        +
      • @ref pageFDevAppNotes +
          +
        • @ref pageFDevAppNotes1 +
        +
      +*/ +/*@{*/ + +/** FDev capability flag. + @see GFFDevMount() + */ +#define GFFDEV_CAP_STANDARD 0x00010000 /**< Standard C Library */ + +/** FDev capability flag. + @see GFFDevMount() + */ +#define GFFDEV_CAP_DEVICE_SD 0x00000001 /**< SD Device Supported */ + +/** FDev capability flag. + @see GFFDevMount() + */ +#define GFFDEV_CAP_FAT 0x00020000 /**< Fat FileSystem */ + +/** FDev capability flag. + @see GFFDevMount() + */ +#define GFFDEV_CAP_DEVICE_MASK 0x00000FFF + +/** FDev capability flag - default on the selected OS. + Linux, Windows -> Standard, else -> SD + @see GFFDevMount() + */ +#if !NVOS_IS_WINDOWS && !NVOS_IS_LINUX +#define GFFDEV_CAP_DEFAULT_FOR_OS GFFDEV_CAP_DEVICE_SD +#else +#define GFFDEV_CAP_DEFAULT_FOR_OS GFFDEV_CAP_STANDARD +#endif + +/** Parameter enum for GFFDevSeekFile. + @see GFFDevSeekFile + */ +typedef enum +{ + GFFDEV_SEEK_SET = 0, /**< Set fileHandle relative to beginning of file */ + GFFDEV_SEEK_CUR, /**< Set fileHandle relative to specified offset location */ + GFFDEV_SEEK_END /**< Set fileHandle relative to end of file */ +} GFFDEVSEEKTYPE; + +/** Public File Info structure. + Matches Microsoft's struct _finddata_t . + + @see FDevFindFirstFile() + @see FDevFindNextFile() + */ +typedef struct _GFFDEVFILEINFO +{ + unsigned attrib; + NvU32 time_create; /**< -1 for FAT file systems */ + NvU32 time_access; /**< -1 for FAT file systems */ + NvU32 time_write; + NvU32 size; + char name[260]; +} GFFDEVFILEINFO, *PGFFDEVFILEINFO; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFFDevOpen(GFRmHandle hRm, GFFDevHandle *phFDev, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFFDevClose(GFFDevHandle *phFDev); + +/** @name Functions +@{*/ + +/** Mounts a filesystem. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param capType (NvU32) capability type + + The filesystem pointed to by #FDevHandle will be mounted based on + the #capType. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevMount(GFFDevHandle FDevHandle, NvU32 capType); + +/** Unmounts a mounted filesystem. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error +*/ +GF_RETTYPE GFFDevUnmount(GFFDevHandle FDevHandle); + +/** Opens a file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (const char *) name of the file + @param fileSpec (const char *) read/write/etc flags + @param pFileHandle (#GFFDevFileHandle) Pointer to the handle of the opened file - + will be filled in by #GFFDevOpenFile() + + Opens a file on the mounted filesystem with #fileName. Open flags, + given by #fileSpec, are the same as libc's fopen. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevOpenFile(GFFDevHandle FDevhandle, + const char *fileName, + const char *fileSpec, + GFFDevFileHandle *pFileHandle); + +/** Closes an open file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param pFileHandle (#GFFDevFileHandle *) Pointer to the open file + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevCloseFile(GFFDevHandle FDevhandle, + GFFDevFileHandle *pFileHandle); + +/** Reads data from a file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileHandle (#GFFDevFileHandle) Handle to the open file + @param pReadBuf (void *) Buffer for file bytes + @param pCount (NvU32 *) Pointer to number of bytes to read, will be + written to the actual number of bytes read. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevReadFile(GFFDevHandle FDevhandle, + GFFDevFileHandle fileHandle, + void * pReadBuf, + NvU32 *pCount); + +/** Writes data to an open file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileHandle (#GFFDevFileHandle) Handle to open file + @param pWriteBuf (void *) pointer to bytes to write to the file + @param pCount (NvU32 *) pointer to number of bytes to write, will + be written to actual number of bytes written. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevWriteFile(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle, + void * pWriteBuf, + NvU32 *pCount ); + +/** Sets the file read/write position. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileHandle (#GFFDevFileHandle) Handle to open file + @param offset (NvS32) offset to be used with #where + @param where (#GFFDEVSEEKTYPE) file offset base + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevSeekFile(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle, + NvS32 offset, + GFFDEVSEEKTYPE where); + +/** Gets the current file position. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileHandle (#GFFDevFileHandle) Handle to open file + @param pOffset (NvU32 *) pointer to offset, will be filled in + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevTellFile(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle, + NvU32 *pOffset); + +/** Gets the file size. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (#GFFDevFileHandle) Handle of open file + @param pSize (NvU32 *) pointer to file size, will be filled in. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevGetFileSize(GFFDevHandle FDevHandle, + const char *fileName, + NvU32 *pSize); + +/** Renames a file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param oldFileName (const char *) name of existing file + @param newFileName (const char *) name to which to rename the file + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevRenameFile(GFFDevHandle FDevHandle, + const char *oldFileName, + const char *newFileName); + +/** Removes a file from the filesystem + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (#GFFDevFileHandle) Handle of open file + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevDeleteFile(GFFDevHandle FDevHandle, + const char *fileName); + +/** Gets the first file in a directory. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param dirName (const char *) Name of the directory to enumerate + @param pFileInfo (#GFFDEVFILEINFO *) pointer to the file info for the + first file + @param pDirHandle (#GFFDevDirHandle *) pointer to the handle to the directory + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevFindFirstFile(GFFDevHandle FDevHandle, + const char *dirName, + GFFDEVFILEINFO *pFileInfo, + GFFDevDirHandle *pDirHandle); + +/** Gets the next file in the directory. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param pFileInfo (#GFFDEVFILEINFO *) pointer ot the info for the next file + @param pDirHandle (#GFFDevDirHandle *) pointer to the directory handle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevFindNextFile(GFFDevHandle FDevHandle, + GFFDEVFILEINFO *pFileInfo, + GFFDevDirHandle *pDirHandle); + +/** Closes the directory. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param pDirHandle (#GFFDevDirHandle *) pointer to the directory handle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevFindCloseFile(GFFDevHandle FDevHandle, + GFFDevDirHandle *pdirHandle); + +/** Flushes all buffered data to the file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (#GFFDevFileHandle) Handle of open file + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevFlushFile(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle); + +/** Gets the filesystem blocks for the file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (#GFFDevFileHandle) Handle of open file + @param size (NvU32) size of the file + @param ppBlockList (#PGFBLOCKLIST *) block list to be allocated + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevBlockListAlloc(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle, + NvU32 size, + PGFBLOCKLIST *ppBlockList ); + +/** Gets the FDev API properties + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param pBlockList (#PGFBLOCKLIST) Block list to deallocate + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevBlockListFree(GFFDevHandle FDevHandle, + PGFBLOCKLIST pBlockList ); + +/*@}*/ +/*@}*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** @page pageFDevAppNotes FDevAPI Application Notes + + @section pageFDevAppNotes1 Todo + +*/ + +#endif /* __GFFDEV_H__ */ + diff --git a/Start_WM/test6/inc/GFGx.h b/Start_WM/test6/inc/GFGx.h new file mode 100755 index 00000000..5a974df4 --- /dev/null +++ b/Start_WM/test6/inc/GFGx.h @@ -0,0 +1,1927 @@ +/* + * Copyright (c) 2005 - 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software and related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ +/** @file GFGx.h + GFSDK Graphics API header file. +*/ + +#ifndef __GFGx_H__ +#define __GFGx_H__ + +#include "GFRm.h" + +/* GFGxAPI error codes */ +#include "GFGxError.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +/** @addtogroup groupGx GxAPI Graphics API +*/ + /*
        +
      • @ref pageGxAppNotes +
          +
        • @ref pageGxAppNotes1 +
        +
      + */ + +/*@{*/ + +/**** GX CAPABILITIES DEFINITIONS ****/ + +/** GFGxAPI capability definition : bitblt support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_BLT 0x00000001UL // BitBlt +/** GFGxAPI capability definition : linedraw support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_LINE 0x00000002UL // Line draw +/** GFGxAPI capability definition : clipping support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_CLIP 0x00000004UL // Clipping +/** GFGxAPI capability definition : stretchblt support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_STRETCHBLT 0x00000008UL // StretchBlt +/** GFGxAPI capability definition : alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHABLENDING 0x00000010UL // Alpha blending +/** GFGxAPI capability definition : alphablending and transparency support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_COLOR_CMP 0x00000020UL // Alpha blending + +/* NEW CAPABILITY FLAGS */ + +/** GFGxAPI capability definition : fast rotation support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_FAST_ROTATION 0x00000040UL // Fast Rotation + +/** GFGxAPI capability definition : inside clipping support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_CLIPPING_INSIDE 0x00000100UL // Inside Clipping +/** GFGxAPI capability definition : fadeblt support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_FADE_BLT 0x00000200UL // Fade Blt + +/** GFGxAPI capability definition : color pattern support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_COLOR_PATTERN 0x00001000UL // Color Pattern +/** GFGxAPI capability definition : color pattern transparency support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_CLR_PAT_TRANSPARENT 0x00002000UL // Color Pattern Transparency +/** GFGxAPI capability definition : alphablending and fading support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_AND_FADING 0x00004000UL // ALpha Blending & fading +/** GFGxAPI capability definition : 1BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_1BPP 0x00008000UL // Planar 1 BPP Alpha +/** GFGxAPI capability definition : 2BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_2BPP 0x00010000UL // Planar 2 BPP Alpha +/** GFGxAPI capability definition : 4BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_4BPP 0x00020000UL // Planar 4 BPP Alpha +/** GFGxAPI capability definition : 8BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_8BPP 0x00040000UL // Planar 8 BPP Alpha +/** GFGxAPI capability definition : SRC4DST4BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_SRC4DST4 0x00080000UL // Planar 44 BPP Alpha + // 8 bpp plane, src * 4 + dst*4 +/** GFGxAPI capability definition : 32BPP to 16BPP alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_32BLEND16 0x00200000UL // 32 bits source blending +/** GFGxAPI capability definition : src 1555 alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_SRC1555 0x00400000UL // Src alpha 1555 +/** GFGxAPI capability definition : src 4444 alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_SRC4444 0x00800000UL // Src alpha 4444 +/** GFGxAPI capability definition : src fixed alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_FIXED 0x01000000UL // Fixed alpha + +/**** CLIPPING FLAGS ****/ + +/* disable clipping */ +/** GFGxAPI CLIPPING flags : disable clipping. + @see GFGxSetClip() +*/ +#define GFGX_SETCLIP_DISABLE 0x00000000UL + +/* enable clipping */ +/** GFGxAPI CLIPPING flags : enable clipping. + @see GFGxSetClip() +*/ +#define GFGX_SETCLIP_ENABLE 0x00000001UL + +/* set clipping rectangle */ +/** GFGxAPI CLIPPING flags : set clipping rectangle. + @see GFGxSetClip() +*/ +#define GFGX_SETCLIP_SETRECT 0x00000002UL + +/* set inside clipping - default is outside clipping*/ +/** GFGxAPI CLIPPING flags : set inside clipping, default is outside. + @see GFGxSetClip() +*/ +#define GFGX_SETCLIP_INSIDE 0x00000004UL + + +/**** LINE DRAW FLAGS ****/ + +/* don't draw last pixel */ +/** GFGxAPI LINE DRAW flags : do not draw last pixel. + @see GFGxLine() +*/ +#define GFGX_LINE_NOT_DRAW_LAST_PIXEL 0x00000001UL + +/**** BITBLT - SOURCE FLAGS ****/ + +/* source is screen */ +/** GFGxAPI BITBLT Source flags : source comes from video mem. + @see GFGxBlt() +*/ +#define GFGX_BLT_SRC_VIDEO 0x00000000UL + +/* color source in system memory */ +/** GFGxAPI BITBLT Source flags : colour source comes from system mem. + @see GFGxBlt() +*/ +#define GFGX_BLT_SRC_SYSMEM_COLOR 0x00000001UL + +/* mono source in system memory */ +/** GFGxAPI BITBLT Source flags : mono source comes from system mem. + @see GFGxBlt() +*/ +#define GFGX_BLT_SRC_SYSMEM_MONO 0x00000002UL + +/* source is solid color */ +/** GFGxAPI BITBLT Source flags : source is solid (unique color). + @see GFGxBlt() +*/ +#define GFGX_BLT_SRC_SOLID 0x00000004UL + + +/**** BITBLT - PATTERN FLAGS ****/ + +/* pattern is mono */ +/** GFGxAPI BITBLT Pattern flags : pattern is mono. + @see GFGxBlt() +*/ +#define GFGX_BLT_PAT_MONO 0x00000008UL + +/* pattern is color */ +/** GFGxAPI BITBLT Pattern flags : pattern is color. + @see GFGxBlt() +*/ +#define GFGX_BLT_PAT_COLOR 0x00000010UL + +/* pattern is solid color */ +/** GFGxAPI BITBLT Pattern flags : pattern is solid (unique color). + @see GFGxBlt() +*/ +#define GFGX_BLT_PAT_SOLID 0x00000020UL + +/* pattern is cached */ +/** GFGxAPI BITBLT Pattern flags : pattern is cached in video mem. + The pattern ID for the cached pattern is returned in the pPatID + field in GFGXBLTPARAM sruct. User needs to make sure that a valid + pointer is passed in pPatID. + @see GFGxBlt() +*/ +#define GFGX_BLT_PAT_CACHE 0x00000040UL + + +/**** BITBLT - MODE FLAGS ****/ +/**** Linear / XY Mode / Surface Flag ****/ + +/* XY Mode Blt */ +/** GFGxAPI BITBLT Mode flags : X/Y mode is used. + @see GFGxBlt() +*/ +#define GFGX_BLT_MODE_XY 0x00000000UL + +/* Linear Mode Blt */ +/** GFGxAPI BITBLT Mode flags : linear mode is used. + @see GFGxBlt() +*/ +#define GFGX_BLT_MODE_LINEAR 0x00000080UL + +/* Surface to Surface blt */ +/** GFGxAPI BITBLT Mode flags : surface to surface mode is used. + @see GFGxBlt() +*/ +#define GFGX_BLT_SURFACE 0x00000100UL + + +/**** BITBLT - CLIPPING FLAGS ****/ + +/* enable clipping */ +/** GFGxAPI BITBLT Clipping flags : enable clipping. + @see GFGxBlt() +*/ +#define GFGX_BLT_CLIP 0x00000200UL + +/**** BITBLT - SOURCE TRANSPARENCY FLAGS ****/ + +/* color source transparent blt (if source pixel matches colorCompare, +do not overwrite) */ +/** GFGxAPI BITBLT Source Transparency flags : enable color source transparency + (if source pixel matches colorCompare, do not overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_SRC_COLOR 0x00000400UL + +/* color source inverse transparent blt (if source pixel matches +colorCompare, overwrite) */ +/** GFGxAPI BITBLT Source Transparency flags : enable color source inverse + transparency (if source pixel matches colorCompare, overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_SRC_COLOR_INV 0x08000000UL + + +/* mono source transparent blt (if source bit is 0, no +overwrite on corresponding destination location) */ +/** GFGxAPI BITBLT Source Transparency flags : enable mono source transparency + (if source bit is 0, no overwrite on corresponding destination location). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_SRC_MONO 0x00000800UL + +/* mono source inverted transparent blt (if source bit +is 1, no overwrite on corresponding destination location) */ +/** GFGxAPI BITBLT Source Transparency flags : enable mono source inverse + transparency (if source bit is 1, no overwrite on corresponding destination + location). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_SRC_MONO_INV 0x00001000UL + + +/**** BITBLT - DESTINATION TRANSPARENCY FLAGS ****/ + +/* destination transparent blt (if destination pixel matches colorCompare, +overwrite) */ +/** GFGxAPI BITBLT Destination Transparency flags : enable destination + transparency (if destination pixel matches colorCompare, overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_DST 0x00002000UL + +/* destination transparent inverse blt (if destination pixel matches +colorCompare, donot overwrite) */ +/** GFGxAPI BITBLT Destination Transparency flags : enable destination inverse + transparency (if destination pixel matches colorCompare, do not overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_DST_INV 0x10000000UL + +/**** BITBLT - PATTERN TRANSPARENCY FLAGS ****/ + +/* Mono pattern transparent Blt */ +/** GFGxAPI BITBLT Pattern Transparency flags : enable mono pattern transparency + (if pattern bit is 0, no overwrite on corresponding destination location). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_PAT_MONO 0x00004000UL + +/* Mono pattern inverted transparent Blt */ +/** GFGxAPI BITBLT Pattern Transparency flags : enable mono pattern inverse + transparency (if pattern bit is 1, no overwrite on corresponding destination + location). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_PAT_MONO_INV 0x00008000UL + +/* Color pattern transparency Blt */ +/** GFGxAPI BITBLT Pattern Transparency flags : enable color pattern transparency + (if pattern pixel matches colorCompare, do not overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_PAT_COLOR 0x00010000UL + +/* Color pattern transparency Blt */ +/** GFGxAPI BITBLT Pattern Transparency flags : enable color pattern inverse + transparency (if pattern pixel matches colorCompare, overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_PAT_COLOR_INV 0x20000000UL + +/**** Fade Blt ****/ +/** GFGxAPI BITBLT flags : enable fade blt. + @see GFGxBlt() +*/ +#define GFGX_BLT_FADE_BLT 0x00020000UL + +/* Enable alpha blending */ +/** GFGxAPI BITBLT flags : enable alphablending. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_BLENDING 0x00080000UL + + + +/**** ALPHABLENDING FLAGS ****/ + +/* Fixed alpha operation */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is fixed value. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_FIXED ( 0x00200000UL) + +/* Inverse Fixed alpha */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse fixed value. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_FIXED_INV (0x00400000UL) + +/* Source alpha ARGB1555 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB1555. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_SRC_1555_T (0x00800000UL) + +/* Inverse Source alpha ARGB1555 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB1555. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_SRC_1555_T_INV (0x01000000UL) + +/* Source alpha ARGB4444 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB4444. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_SRC_4444 (0x02000000UL) + +/* Inverse Source ARGB4444 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB4444. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_SRC_4444_INV (0x04000000UL) + +/* new flags */ + +/** GFGxAPI BITBLT Alphablending mask. + @see GFGxBlt() +*/ +#define GFGXEX1_MASK 0x3FFFFFFF + +/* Fixed alpha operation */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is fixed value. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_FIXED (0x40000000 | 0x00000001UL) + +/* Inverse Fixed alpha */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse fixed value. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_FIXED_INV (0x40000000 | 0x00000002UL) + +/* Source alpha ARGB1555 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB1555. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_1555_T (0x40000000 | 0x00000004UL) + +/* Inverse Source alpha ARGB1555 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB1555. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_1555_T_INV (0x40000000 | 0x00000008UL) + +/* Source alpha ARGB4444 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB4444. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_4444 (0x40000000 | 0x00000010UL) + +/* Inverse Source ARGB4444 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB4444. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_4444_INV (0x40000000 | 0x00000020UL) + +/* Source alpha ARGB8888 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB8888. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_8888 (0x40000000 | 0x00000040UL) + +/* Inverse source alpha ARGB8888 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB8888. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_8888_INV (0x40000000 | 0x00000080UL) + +/* Destination alpha ARGB8888 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is destination ARGB8888. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_DST_8888 (0x40000000 | 0x00000100UL) + +/* Inverse Destination alpha 8888 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse destination ARGB8888. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_DST_8888_INV (0x40000000 | 0x00000200UL) + +/* Planar 1BPP alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 1BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_1BPP (0x40000000 | 0x00000400UL ) + +/* Planar 1BPP Inv alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 1BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_1BPP_INV (0x40000000 | 0x00000800UL) + +/* Planar 2BPP alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 2BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_2BPP (0x40000000 | 0x00001000UL) + +/* Planar 2BPP Inv alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 2BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_2BPP_INV (0x40000000 | 0x00002000UL) + +/* Planar 4BPP alpha Blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 4BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_4BPP (0x40000000 | 0x00004000UL) + +/* Planar 4BPP Inv alpha Blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 4BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_4BPP_INV (0x40000000 | 0x00008000UL) + +/* Planar 8BPP alpha Blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 8BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_8BPP (0x40000000 | 0x00010000UL) + +/* Planar 8Bpp Inv alpha Blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 8BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_8BPP_INV (0x40000000 | 0x00020000UL) + +/* Planar 44BPP alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is SRC4DST4BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_44BPP (0x40000000 | 0x00040000UL) + +/* Planar 32 bpp src blending 16 bpp dst */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 32BPP src to 16BPP dst. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_32BPP16 (0x40000000 | 0x00080000UL) + +/*Planar Inv 32 bpp src blending 16 bpp dst */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 32BPP src to + 16BPP dst. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_32BPP16_INV (0x40000000 | 0x00100000UL) + +/* Alpha planar is already in video mem, no need to transfer it from sys mem */ +#define GFGXEX1_BLT_PLANAR_NOTRANSFER (0x40000000 | 0x00200000UL) + +/**** FAST ROTATION FLAGS ****/ +/** GFGxAPI BITBLT Fast Rotation mask. + @see GFGxFastRotate() +*/ +#define GFGXEX2_MASK 0x3FFFFFFF + +/* Fast Rotation Modes */ + +/* Square (in place rotation) */ +/** GFGxAPI BITBLT Fast Rotation flags : dst is same than src. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_SQUARE (0x80000000 | 0x00000001UL) + +/* Source to Destination Rotation ( 2 buffers) */ +/** GFGxAPI BITBLT Fast Rotation flags : dst is different than src. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_SRC_DST_COPY (0x80000000 | 0x00000002UL) + +/* Disable Fast Rotation */ +/** GFGxAPI BITBLT Fast Rotation flags : disable fast rotation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_DISABLE (0x80000000 | 0x00000004UL) + +/* Fast Rotation Types */ + +/* Flip-X */ +/** GFGxAPI BITBLT Fast Rotation flags : FLIP-X transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_FLIP_X (0x80000000 | 0x00000008UL) + +/* Flip-Y */ +/** GFGxAPI BITBLT Fast Rotation flags : FLIP-Y transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_FLIP_Y (0x80000000 | 0x00000010UL) + +/* Trans-LR */ +/** GFGxAPI BITBLT Fast Rotation flags : TRANSPOSE LEFT-RIGHT transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_TRANS_LR (0x80000000 | 0x00000020UL) + +/* Trans-RL */ +/** GFGxAPI BITBLT Fast Rotation flags : TRANSPOSE RIGHT-LEFT transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_TRANS_RL (0x80000000 | 0x00000040UL) + +/* 90 deg Rotation */ +/** GFGxAPI BITBLT Fast Rotation flags : 90° rotation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_ROT_90 (0x80000000 | 0x00000080UL) + +/* 180 deg Rotation */ +/** GFGxAPI BITBLT Fast Rotation flags : 180° rotation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_ROT_180 (0x80000000 | 0x00000100UL) + +/* 270 deg Rotation */ +/** GFGxAPI BITBLT Fast Rotation flags : 270° rotation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_ROT_270 (0x80000000 | 0x00000200UL) + +/* Identity */ +/** GFGxAPI BITBLT Fast Rotation flags : identity transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_IDENTITY (0x80000000 | 0x00000400UL) + + +/** GFGXAPI STRETCHBLT flag in GFGXBLTPARAM struct + This flag waits for the StretchBlt engine to be idle. + If enabled it will block the CPU thread until the StretchBlt is done. + It is effective only for GFGxStretchBlt(). + For other api's it is ignored. + @see GFGxBlt() +*/ +#define GFGX_STRETCHBLT_WAITFOR_FINISH 0x00100000UL + + +/* + * Definition of attribute ids for Set/GetAttributes() + */ + +/** GFGxAPI attributes definition. + @see GFGxGetAttribute(), GFGxSetAttribute() +*/ +typedef enum _GFGXATTRIBUTES + { + /** Current bits per pixel. */ + GFGX_ATTR_BPP, + /** Frame buffer line width in bytes. */ + GFGX_ATTR_STRIDE, + /** Ptr to start address of the display frame buffer. */ + GFGX_ATTR_ADDR_PTR, + /** Start address offset. */ + GFGX_ATTR_ADDR, + /** Surface for GFGxAPI operations. */ + GFGX_ATTR_SURFACE, + /** Palette RGB888. */ + GFGX_ATTR_PALETTE_RGB888 +} GFGXATTRIBUTES; + +/* Blt parameter struct */ +/** GFGxAPI BLT parameter structure. + @see GFGxBlt() +*/ +typedef struct _GFGXBLTPARAM +{ + /** Destination x in pixels (relative to left). */ + NvS16 dx; + /** Destination y in scan lines (relative to top). */ + NvS16 dy; + /** Width of the source rectangle in pixels. */ + NvS16 w; + /** Height of the source rectangle in pixels. */ + NvS16 h; + /** Source x in pixels (relative to left). */ + NvS16 sx; + /** Source y in scan lines (relative to top). */ + NvS16 sy; + /** Width of the source rectangle in pixels (for Stretch Blt only). */ + NvS16 sw; + /** Height of the source rectangle in scan lines (for Stretch Blt only). */ + NvS16 sh; + /** Color depth */ + NvU16 bpp; + /** Number of bytes per scanline for bitmap. */ + NvS16 stride; + /** Foreground color (used if pixel data is 1 on 1BPP source bitmap). */ + NvU32 fgColor; + /** Background color (used if pixel data is 0 on 1BPP source bitmap). */ + NvU32 bgColor; + /** Pointer to source bitmap. */ + NvU8 *pBits; + /** Pattern offset in x direction. */ + NvS16 px; + /** Pattern offset in y direction. */ + NvS16 py; + /** Pattern foreground color (used if pixel data is 1 on 1BPP pattern bitmap).*/ + NvU32 patFgColor; + /** Pattern background color (used if pixel data is 0 on 1BPP pattern bitmap).*/ + NvU32 patBgColor; + /** Pattern color key for transparent blt.*/ + NvU32 patColorCmp; + /** Pointer to pattern bitmap. */ + NvU8 *pPatBits; + /** Number of bytes per scanline for pattern. */ + NvU32 patStride; + /** Width of pattern. */ + NvU32 patW; + /** Height of pattern. */ + NvU32 patH; + + /** pointer to Pattern ID when GFGX_BLT_PAT_CACHE flag is set. */ + /** GFGxBlt() will return the patID in this field */ + NvU32 *pPatID; + + // Miscellaneous parameters + /** Color key for transparent blt. */ + NvU32 colorCompare; + /** Main flags setting. */ + NvU32 flags; + /** Raster operation code (ROP3). */ + NvU16 rop3; + + // Surface parameters + /** Pointer to dst surface pointer. */ + PGFRMSURFACE *ppDestSurf; + /** Pointer to src surface pointer. */ + PGFRMSURFACE *ppSrcSurf; + /** Source start address. */ + NvU32 srcStartAddr; + /** Destination start address. */ + NvU32 dstStartAddr; + /** Number of bytes per scanline for destination. */ + NvS16 dstStride; + + // alpha blending parameters + /** Alpha value for GFGX_BLT_ALPHA_FIXED or alphaFg for GFGX_BLT_ALPHA_SRC_1555_T. */ + NvU16 alpha; + /** Background alpha for GFGX_BLT_ALPHA_SRC_1555_T. */ + NvU16 alphaBg; + /** Pointer to alpha plane. */ + NvU8 *pAlphaplane; + + // Fading parameters + /** Fading coefficient. */ + NvU32 fadeCoeff; + /** Fading offset. */ + NvU32 fadeOffset; + + /** Alphablending flag. */ + NvU32 flagex1; + + /** Fast rotation flag. */ + NvU32 flagex2; + +} GFGXBLTPARAM; + + +/** @name Functions +@{*/ + +/** This function returns version and capabilities of API and hardware. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pGxProp (PGFPROPERTY) Pointer to property structure to be filled in + + @retval #GF_SUCCESS pGxProp filled in successfully + @retval #GF_ERROR Some error occured + + The #GFPROPERTY structure passed with parameter pGxProp will be + filled in on successfull return. + + The GFPROPERTY::Capability field will hold a combination of flagbits + indicating capabilities specific to the GFGxAPI : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFGX_CAP_BLT BitBlt supported.
      #GFGX_CAP_LINE Line Draw supported.
      #GFGX_CAP_CLIP Clipping supported.
      #GFGX_CAP_STRETCHBLTStretchblt supported.
      #GFGX_CAP_ALPHABLENDING Alphablending supported.
      #GFGX_CAP_ALPHA_COLOR_CMPAlphablending and transparency supported.
      #GFGX_CAP_FAST_ROTATION Fast rotation supported.
      #GFGX_CAP_CLIPPING_INSIDE Inside clipping supported.
      #GFGX_CAP_FADE_BLT Fadeblt supported.
      #GFGX_CAP_COLOR_PATTERN Color pattern supported.
      #GFGX_CAP_CLR_PAT_TRANSPARENTColor pattern transparency supported.
      #GFGX_CAP_ALPHA_AND_FADING Alphablending and fading supported.
      #GFGX_CAP_ALPHA_PLANAR_1BPP 1BPP alpha planar supported.
      #GFGX_CAP_ALPHA_PLANAR_2BPP 2BPP alpha plane supported.
      #GFGX_CAP_ALPHA_PLANAR_4BPP 4BPP alpha plane supported.
      #GFGX_CAP_ALPHA_PLANAR_8BPP 8BPP alpha plane supported.
      #GFGX_CAP_ALPHA_PLANAR_SRC4DST4SRC4DST4BPP alpha plane supported.
      #GFGX_CAP_ALPHA_PLANAR_32BLEND16 32BPP to 16BPP alphablending supported.
      #GFGX_CAP_ALPHA_SRC1555Src 1555 alphablending supported.
      #GFGX_CAP_ALPHA_SRC4444 Src 4444 alphablending supported.
      #GFGX_CAP_ALPHA_FIXED Src fixed alphablending supported.
      + + It is recommended, but not mandatory, that you call this function to query + for the GFGxAPI version and capabilities before proceeding to call any of + the other GFGxAPI functions. + + @see GFPROPERTY +*/ +GF_RETTYPE GFGxGetProperty(GFGxHandle GxHandle, + PGFPROPERTY pGxProp); +/** This function fills a rectangle in video memory with the specified solid color. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param x,y (NvS16) left-top corner of the rectangle (x in pixels, y in scan lines) + @param w,h (NvS16) width & height of the rectangle (w in pixels, h in scan lines) + @param color (NvU32) color to be filled (8BPP index, or 16BPP-32BPP TrueColor) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxFillRectEx() +*/ +GF_RETTYPE GFGxFillRect(GFGxHandle GxHandle, + NvS16 x, NvS16 y, + NvS16 w, NvS16 h, + NvU32 color); +/** This function is commonly used in scrolling an image in video memory. It copies + a rectangular image in the video memory to another location in the same video + memory. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle (dx in pixels, dy in scan lines) + @param w,h (NvS16) width & height of rectangles (w in pixels, h in scan lines) + @param sx,sy (NvS16) left-top corner of source rectangle (sx in pixels, sy in scan lines) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFGxCopyRect() checks for the destruction of the copied image in video memory + caused by overlapping source and destination locations. + + Also, if the destination for the rectangle exceeds the limit of the video memory, + wrapping is done in hardware and no error code is returned. + + + @see GFGxCopyRectEx(), GFGxCopyRectDirect() +*/ +GF_RETTYPE GFGxCopyRect(GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy); + +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap is specified in monochrome (1BPP) pixels. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle (dx in pixels, dy in scan lines) + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle (sx in pixels, sy in scan lines) + @param fgColor (NvU16) color applied to source data bit 1 (The color depth should be same as the frame buffer) + @param bgColor (NvU16) color applied to source data bit 0 (The color depth should be same as the frame buffer) + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to monochome (1bpp) bitmap + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransMonoBitmap() +*/ +GF_RETTYPE GFGxCopyMonoBitmap( GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvU32 fgColor, NvU32 bgColor, + NvS16 srcStride, + NvU8 *pMonoBits); +/** This function copies the bitmap from video memory to system memory. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle (dx in pixels, dy in scan lines) + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle (sx in pixels, sy in scan lines) + @param dstStride (NvS16) destination stride in bytes + @param pDstAddr (NvU8*) pointer to destination buffer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFGxReadBlt( GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvS16 dstStride, + NvU8 *pDstStartAddr); +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap is specified in monochrome (1BPP) pixels and can be transparent. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param color (NvU16) color applied to non-transparent source data bit + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to monochome (1bpp) bitmap + @param selectTrans (NvS16) transparency select: 0 or 1 + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function is similar to GFGxCopyMonoBitmap() except for the selectTrans parameter. + This parameter indicates whether bit data equal to 0 or 1 is going to be transparent. + This function could be used for drawing a transparent text string or character. + + + @see GFGxCopyMonoBitmap() +*/ +GF_RETTYPE GFGxCopyTransMonoBitmap( GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvU32 color, + NvS16 srcStride, + NvU8 *pMonoBits, + NvS16 selectTrans ); +/** This function is used to blit/blend a given source rectangle to/with the given + destination location in the video memory. + + Overlap rectangles are handled properly. Source and destination rectangles must + have same size. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pBltParam (#GFGXBLTPARAM*) refer to structure definition + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + This routine is more generic. It supports System Memory to Video Memory Blts and + Video to Video Memory Blts involving Source and Pattern data.The Source and Pattern + data can be either Color or Monochrome(1 Bpp). Monochrome Blts are supported by performing + a Monochrome to Color Expansion. + + Tiling mode is also supported for Mono Patttern Blts. The size of the pattern in this case + should be 16x16. Tiling is not supported for Color Patterns. + + The following features can also be enabled during Blts : + + - Color Source and Mono Source Transparency + - Destination Transparency, + - Color Pattern and Mono Pattern Transparency + - Alphablending ( Both Planar and Source Alpha) + - Fading + - Microsoft Windows compatible ROP3 + - Clipping + + GFGxBlt() supports both raster operations and alpha blending operations.The two types + of operations are mutually exclusive. + + Please refer to the supported GFGxBlt() flags starting with GFGX_BLT_* and GFGXEX1_BLT_*. + + + @see GFGxCopyRect(), GFGxCopyRectDirect(), GFGxBltSurface(), GFGxCopyMonoBitmap(), + GFGxCopyTransMonoBitmap(), GFGxCopyColorBitmap() +*/ +GF_RETTYPE GFGxBlt( GFGxHandle GxHandle, + const GFGXBLTPARAM *pBltParam ); + +/** + This function performs a surface-to-surface blit. The color depth of the source + surface must match that of the destination. Also, the width and height of the + source must be the same as the destination's width and height. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param ppDestSurf (#PGFRMSURFACE*) pointer to destination surface pointer + @param ppSrcSurf (#PGFRMSURFACE) pointer so source surface pointer + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param rop3 (NvU16) raster operation code + @param srcStartAddr (NvU32) start address relative to the source surface + @param dstStartAddr (NvU32) start address relative to the destination surface + @param flags (NvU32) Transparent blit flag. See Below + @param colorCompare (NvU32) color key for transparent blit. If there is no transparent blit, colorCompare = 0 + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Transparent blit flag is one of the following: + - GFGX_BLT_TRANSPARENT_SRC_COLOR + - GFGX_BLT_TRANSPARENT_SRC_MONO + - GFGX_BLT_TRANSPARENT_SRC_MONO_INV + - GFGX_BLT_TRANSPARENT_DST + - GFGX_BLT_TRANSPARENT_PAT_COLOR + - GFGX_BLT_TRANSPARENT_PAT_COLOR_INV + - GFGX_BLT_TRANSPARENT_PAT_MONO + - GFGX_BLT_TRANSPARENT_PAT_MONO_INV + Refer to GFGX_BLT_X flag definitions for further information. If no transparent blit, flag = 0 + + Alphablending is not supported. + + + @see GFGxCopyRect(), GFGxCopyRectDirect(), GFGxBltSurface(), GFGxCopyMonoBitmap(), + GFGxCopyTransMonoBitmap(), GFGxCopyColorBitmap() +*/ +GF_RETTYPE GFGxBltSurface( GFGxHandle GxHandle, PGFRMSURFACE *ppDestSurf, + PGFRMSURFACE *ppSrcSurf, + NvS16 w, NvS16 h, NvU16 rop3, + NvU32 srcStartAddr, NvU32 dstStartAddr, + NvU32 flags, NvU32 colorCompare); + +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap's color depth must match the destination's video memory's color depth. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyMonoBitmap() +*/ +GF_RETTYPE GFGxCopyColorBitmap( GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits ); + +/** This function draws a line from a point x1, y1 to another point x2, y2 with a specified color + and ROP2 code. GFGxSetClip() should be called before calling GFGxLine(). If clipping is needed, + it is assumed that clipping is enabled and clipping rectangle was set by GFGxSetClip(). If + clipping is not set, the line wraps if it is too long, and no error code is returned. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param x1,y1 (NvU16) (x,y) destination point coords (in pixels, scan lines) + @param x2,y2 (NvU16) (x,y) source point coords in (pixels, scan lines) + @param rop2 (NvU16) ROP2 code + @param color (NvU16) color key for transparent blt or pattern color + @param flags (NvU16) refer to GFGX_LINE_X flag definitions + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Set flags to GFGX_LINE_NOT_DRAW_LAST_PIXEL if the last pixel is not to be + drawn. + +*/ +GF_RETTYPE GFGxLine( GFGxHandle GxHandle, + NvU16 x1, NvU16 y1, NvU16 x2, NvU16 y2, + NvU16 rop2, NvU32 color, NvU16 flags ); + +/** This function enables or disables clipping and also sets the clipping rectangle for subsequent + blit and line drawing functions. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pClipRect (#PGFRECT) pointer to the clipping rectangle + @param clipFlag (NvU32) See below + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Set clipFlag to one of the following: + - GFGX_SETCLIP_DISABLE + - GFGX_SETCLIP_ENABLE + - GFGX_SETCLIP_SETRECT + Refer to GFGX_SETCLIP_X flag definitions + + Clipping Sample Code + // Initialize clipping and rectangle parameters. + clipRect.top = 10; + clipRect.left = 10; + clipRect.right = 60; + clipRect.bottom = 60; + // Set the clipping rectangle and enable clipping. + GFGxSetClip( GxHandle, &clipRect, (GFGX_SETCLIP_SETRECT| + GFGX_SETCLIP_ENABLE) ); + // Call drawing function: Rectangle Fill, Pattern Fill, etc. + GFGXFillRect( GxHandle, 20, 20, 30, 30, 0x07E0 ); + // Disable clipping. + GFGxSetClip( GxHandle, NULL, GFGX_SETCLIP_DISABLE ); + + +*/ +GF_RETTYPE GFGxSetClip( GFGxHandle GxHandle, + PGFRECT pClipRect, NvU32 clipFlag); + +/** This function ensures synchronization between 2D operations and others modules operations. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param timeout (NvU32) obsolete parameter + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + When several modules share the same channel (like 3D,2D), it may be necessary to + synchronize the command flow with the 2D module execution. Putting a GFGxNotBusy() + call after a 2D operation ensures that commands which follow the 2D command are + executed after full completion of the 2D command. + + As opposed to GFGxWaitNotBusy(), this function doesn't block the CPU thread. + Graphics engine may not be idle when returning from the function. Control returns + to the CPU right after a wait command is placed in the graphics engine command FIFO. + The GoForce hardware begins executing the commands following the engine idle + command only after the graphics engine becomes idle. + + + @see GFGxWaitNotBusy() +*/ +GF_RETTYPE GFGxNotBusy( GFGxHandle GxHandle, + NvU32 timeout ); +/** This function sets the new value into the palette entry at index location. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param palVal (NvU32) New palette entry value + @param index (NvU16) Index of the palette entry + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The index value ranges from [0..255] inclusively. Parameter palVal is in RGB format, + where bits [0-7] represent the red value, bits [8-15] the green value, and bits [16-23] + the blue value. + + When this function is called, the physical palette entry is modified permanently. + + This function is used only for the 8-bits per-pixel mode and does not apply to the RGB 16 and + 32-bits mode. + + + @see GFGxGetPal(), GFGxSetPalRange(), GFGxGetPalRange() +*/ +GF_RETTYPE GFGxSetPal(GFGxHandle GxHandle, + NvU32 palVal, NvU16 index); + +/** This function sets the a range of new values pointed by pPalRange into the palette entries + starting at startIndex location and ending at endIndex inclusively. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pPalRange (NvU32*) Pointer to a range of palette entry values + @param startIndex (NvU16) Starting index of palette entries + @param endIndex (NvU16) Ending index of palette entries + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The index value ranges from [0..255] inclusively. Each palette entry value is in RGB format, + where bits [0-7] represent the red value, bits [8-15] the green value, and bits [16-23] + the blue value. + + When this function is called, the physical palette entry is modified permanently. + + This function is used only for the 8-bits per-pixel mode and does not apply to the RGB 16 and + 32-bits mode. + + + @see GFGxGetPal(), GFGxSetPalRange(), GFGxGetPalRange() +*/ +GF_RETTYPE GFGxSetPalRange(GFGxHandle GxHandle, + NvU32 * palRange, + NvU16 startIndex, NvU16 endIndex); + +/** This function returns the palette entry value at index location. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pPalVal (NvU32*) pointer to palette entry value + @param index (NvU16) index of the palette entry + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The index value ranges from [0..255] inclusively. The returned palette entry value is stored + in the location pointed to by pPalVal. + + This function is used only for the 8-bits per-pixel mode and does not apply to the RGB 16 and + 32-bits mode. + + + @see GFGxSetPal(), GFGxSetPalRange(), GFGxGetPalRange() +*/ +GF_RETTYPE GFGxGetPal(GFGxHandle GxHandle, + NvU32 * pPalVal, + NvU16 index); +/** This function returns the palette entry values starting from location startIndex to endIndex + inclusively. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pPalArray (NvU32*) Pointer to a range of palette entry values + @param startIndex (NvU16) Starting index of palette entries + @param endIndex (NvU16) Ending index of palette entries + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The index value ranges from [0..255] inclusively. The returned values are stored into + variables pointed to by pPalArray. + + This function is used only for the 8-bits per-pixel mode and does not apply to the RGB 16 and + 32-bits mode. + + + @see GFGxSetPal(), GFGxGetPal(), GFGxSetPalRange() +*/ + +GF_RETTYPE GFGxGetPalRange(GFGxHandle GxHandle, + NvU32 * pPalArray, + NvU16 startIndex, NvU16 endIndex); +/** This function transfers a color bitmap of exact full screen size from system memory to video memory. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pBltParam (#GFGXBLTPARAM*) refere to structure definition + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxBlt() +*/ + +GF_RETTYPE GFGxBltFullScreen(GFGxHandle GxHandle, + const GFGXBLTPARAM *pBltParam); +/** This function copies a rectangular image in the video memory to another location in the same video + memory without taking care of overlapping cases. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of rectangles + @param sx,sy (NvS16) left-top corner of source rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This is a special case of GxCopyRect(). It does not check on destructions of copied image + on video memory due to overlapping source and destination locations. + + + @see GFGxCopyRectEx(), GFGxCopyRect() +*/ +GF_RETTYPE GFGxCopyRectDirect(GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy); +/** This function copies a source bitmap from system memory to the video memory with + certain restrictions. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param bitmapPtr (NvU32*) Pointer to color bitmap + @param size_in_bytes (NvU16) Total bytes to transfer + @param rect (#GFRECT) Destination rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This is a special case of GxCopyColorBitmap(). Conditions below must be verified : + - The source bitmap pointer, pColorBits, has to be a 32-bit (DWORD) aligned address. + - The size of each line of the source bitmap must be 64-bits (8 bytes, QWORD) aligned. + - There must not be any skipping bytes between lines. + - Total bitmap size has to be smaller than or equal to 2K (2048) bytes. + - The source bitmap's color depth MUST match the destination video memory's color depth. + + + @see GxCopyColorBitmap() +*/ +GF_RETTYPE GFGxCopyPackedColorBitmap(GFGxHandle GxHandle, + NvU32 *pColorBits, + NvU16 bitmapSize, + GFRECT rect); +/** This function sets a given attribute. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param aid (NvU32) Attribute id, such as width, height etc + @param attr (NvU32) Attribute value + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Attribute id can be one of the following : + + + + + + + + + + + + + +
      #GFGX_ATTR_BPP Current bits per pixel.
      #GFGX_ATTR_STRIDE Frame buffer line width in bytes.
      #GFGX_ATTR_ADDR_PTR Ptr to start address of the display frame buffer.
      #GFGX_ATTR_ADDRStart address offset.
      #GFGX_ATTR_SURFACE Surface for GFGxAPI operations.
      #GFGX_ATTR_PALETTE_RGB888 Palette RGB888.
      + + + @see GFGxGetAttribute() +*/ + +GF_RETTYPE GFGxSetAttribute(GFGxHandle GxHandle, + NvU32 aid,NvU32 attr); +/** This function gets an attribute. Certain attributes are fixed. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param aid (NvU32) attribute id, such as width, height etc + @param attr (NvU32*) pointer to returned attribute value + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Attribute id can be one of the following : + + + + + + + + + + + + + + +
      #GFGX_ATTR_BPP Current bits per pixel.
      #GFGX_ATTR_STRIDE Frame buffer line width in bytes.
      #GFGX_ATTR_ADDR_PTR Ptr to start address of the display frame buffer.
      #GFGX_ATTR_ADDRStart address offset.
      #GFGX_ATTR_SURFACE Surface for GFGxAPI operations.
      #GFGX_ATTR_PALETTE_RGB888 Palette RGB888.
      + + @see GFGxSetAttribute() +*/ +GF_RETTYPE GFGxGetAttribute(GFGxHandle GxHandle, + NvU32 aid, NvU32 *attr); +/** This function checks whether the graphics engine is busy or idle. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param timeout (NvU32) obsolete parameter + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The function will wait until the graphics engine is idle. For example, if you want + to write to the frame buffer but the graphics engine is busy the function can be used + to wait until it is idle. + + As opposed to GFGxNotBusy(), this function blocks the CPU thread while waiting for + the graphics engine to become idle. + + + @see GFGxNotBusy() +*/ +GF_RETTYPE GFGxWaitNotBusy( GFGxHandle GxHandle, + NvU32 timeout ); +/** This function is used to stretch or shrink an image, which can be in system memory or video memory. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pBltParam (#GFGXBLTPARAM*) refere to structure definition + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The function has these limitations : + - supports 16 and 32BPP color depths, + + @see GFGxBlt() +*/ + +GF_RETTYPE GFGxStretchBlt( GFGxHandle GxHandle, + const GFGXBLTPARAM *pBltParam ); +/*******************************New API's based on enhancing old API's****************************/ + +/** This function fills a rectangle in the video memory with the specified solid color. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param x,y (NvS16) left-top corner of the rectangle + @param w,h (NvS16) width & height of the rectangle + @param color (NvU32) color to be filled (8BPP index, or 16BPP-32BPP TrueColor) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxFillRect() +*/ + /* Old API's with enhancement */ +GF_RETTYPE GFGxFillRectEx(GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 x, NvS16 y, + NvS16 w, NvS16 h, + NvU32 color); +/** This function copies a rectangular image in the video memory to another location in the same + video memory. It is commonly used in scrolling an image in video memory. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of rectangles + @param sx,sy (NvS16) left-top corner of source rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFGxCopyRectEx() checks for the destruction of the copied image in video memory + caused by overlapping source and destination locations. Also, if the destination + for the rectangle exceeds the limit of the video memory, wrapping is done in hardware + and no error code is returned. + + + @see GFGxCopyRect(), GFGxCopyRectDirect() +*/ +GF_RETTYPE GFGxCopyRectEx(GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy); +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap is specified in monochrome (1BPP) pixels. + Video memory location is specified by the surface parameter. + + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param fgColor (NvU16) color applied to source data bit 1 + @param bgColor (NvU16) color applied to source data bit 0 + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to monochome (1bpp) bitmap + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransMonoBitmap() +*/ +GF_RETTYPE GFGxCopyMonoBitmapEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvU32 fgColor, NvU32 bgColor, + NvS16 srcStride, + NvU8 *pMonoBits); +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap is specified in monochrome (1BPP) pixels and can be transparent. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param color (NvU16) color applied to non-transparent source data bit + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to monochome (1bpp) bitmap + @param selectTrans (NvS16) transparency select: 0 or 1 + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function is similar to GFGxCopyMonoBitmapEx() except for the selectTrans + parameter. This parameter indicates whether bit data equal to 0 or 1 is going to be + transparent. + + This function could be used for drawing a transparent text string or character. + + + @see GFGxCopyMonoBitmapEx() +*/ +GF_RETTYPE GFGxCopyTransMonoBitmapEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvU32 color, + NvS16 srcStride, + NvU8 *pMonoBits, + NvS16 selectTrans); + +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap's color depth must match the destination's video memory's color depth. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyMonoBitmap() +*/ +GF_RETTYPE GFGxCopyColorBitmapEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits + ); + +/** This function draws a line from a point x1, y1 to another point x2, y2 with a specified color + and ROP2 code. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param x1,y1 (NvU16) (x,y) destination point coords + @param x2,y2 (NvU16) (x,y) source point coords + @param rop2 (NvU16) ROP2 code + @param color (NvU16) color key for transparent blt or pattern color + @param flags (NvU16) refere to GFGX_LINE_X flag definitions + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxLine() +*/ +GF_RETTYPE GFGxLineEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvU16 x1, NvU16 y1, + NvU16 x2, NvU16 y2, + NvU16 rop2, NvU32 color, + NvU16 flags); + +GF_RETTYPE GFGxBltFullScreenEx(GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + const GFGXBLTPARAM *pBltParam); +/** This function copies a rectangular image in the video memory to another location in the same video + memory without taking care of overlapping cases. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of rectangles + @param sx,sy (NvS16) left-top corner of source rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This is a special case of GxCopyRect(). It does not check on destructions + of copied image on video memory due to overlapping source and destination locations. + + + @see GFGxCopyRectEx(), GFGxCopyRect(), GFGxCopyRectDirect() +*/ +GF_RETTYPE GFGxCopyRectDirectEx(GFGxHandle GxHandle, + PGFRMSURFACE pSurfNvS16, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy); + +/** This function copies a source bitmap from system memory to the video memory with + certain restrictions. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param pColorBits (NvU32*) pointer to color bitmap + @param bitmapSize (NvU16) total bytes to transfer + @param rect (#GFRECT) destination rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This is a special case of GxCopyColorBitmap(). Conditions below must be verified : + - The source bitmap pointer, pColorBits, has to be a 32-bit (DWORD) aligned address. + - The size of each line of the source bitmap must be 64-bits (8 bytes, QWORD) aligned. + - There must not be any skipping bytes between lines. + - Total bitmap size has to be smaller than or equal to 2K (2048) bytes. + - The source bitmap's color depth MUST match the destination video memory's color depth. + + + @see GxCopyColorBitmap(), GFGxCopyPackedColorBitmap() +*/ +GF_RETTYPE GFGxCopyPackedColorBitmapEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvU32 *pColorBits, + NvU16 bitmapSize, + GFRECT rect +/** This function performs a surface-to-surface blit. The color depth of the source + surface must match that of the destination. Also, the width and height of the + source must be the same as the destination's width and height. + Alphablending parameters can be specified. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param ppDestSurf (#PGFRMSURFACE*)pointer to destination surface pointer + @param ppSrcSurf (#PGFRMSURFACE) pointer so source surface pointer + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param rop3 (NvU16) raster operation code + @param srcStartAddr (NvU32) start address relative to the source surface + @param dstStartAddr (NvU32) start address relative to the destination surface + @param flags (NvU32) refer to GFGX_BLT_X flag definitions + @param flagex1 (NvU32) refer to alphablending flag definitions GFGXEX1_BLT_X + @param colorCompare (NvU32) color key for transparent blit + @param alpha (NvU16) alpha value for GFGX_BLT_ALPHA_FIXED or alphaFg + @param alphaBg (NvU16) background alpha + + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyRect(), GFGxCopyRectDirect(), GFGxBltSurface(), GFGxCopyMonoBitmap(), + GFGxCopyTransMonoBitmap(), GFGxCopyColorBitmap() +*/ ); +GF_RETTYPE GFGxBltSurfaceEx( GFGxHandle GxHandle, PGFRMSURFACE *ppDestSurf, + PGFRMSURFACE *ppSrcSurf, + NvS16 w, NvS16 h, NvU16 rop3, + NvU32 srcStartAddr, NvU32 dstStartAddr, + NvU32 flags, NvU32 flagex1, NvU32 colorCompare, + NvU16 alpha, NvU16 alphaBg); + + /* New API's based on new features */ + +/*******************************New API's based on New Features***********************************/ + +/** This function is used to transform a given source rectangle to the given destination + location in the video memory. + + Rotation takes place in counterclockwise direction. + + Destination rectangle can be same than source rectangle or different.

      + Both source and destination must be in video memory. + + Common input data requirements : + + - the data buffer must be aligned on all edges (top, bottom, left, right), which also implies + that stride is
      multiple of 16 bytes, + - the base address of both source and destination must be aligned at a 128-bit word aligned, + - in GFGX_BLT_SURFACE mode, source and destination must be same format : GF_SURFACE_RGB8,
      + GF_SURFACE_RGB565, GF_SURFACE_ARGB8888, or GF_SURFACE_YUV420, + - GFGX_BLT_MODE_LINEAR and X/Y modes are also supported for GF_SURFACE_RGB8,
      GF_SURFACE_RGB565 + and GF_SURFACE_ARGB8888, + - width and height must be multiple of 16 pixels in 8bpp mode, 8 in 16bpp and 4 in 32bpp for
      + GF_SURFACE_RGB8, GF_SURFACE_RGB565 and GF_SURFACE_ARGB8888 surfaces, + - in GFGXEX2_FAST_ROTATE_SQUARE mode, width should be equal to height for 90, 270,
      + TRANS_LR and TRANS_RL modes. Also the destination surface should be same as source + surface. + + Specific GF_SURFACE_YUV420 input data requirements : + + - only GFGX_BLT_SURFACE mode is supported, with no offsets defined for both source and +
      destination (dstStartAddr = srcStartAddr = 0). + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pBltParam (#GFGXBLTPARAM*) refere to structure definition + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + This function can be used the same way than GFGxBlt, adding flagex2 information. + + The following transformations are supported : + + + + + + + + + + + + + + + + + +
      #GFGXEX2_FAST_ROTATE_FLIP_X FLIP-X.
      #GFGXEX2_FAST_ROTATE_FLIP_Y FLIP-Y.
      #GFGXEX2_FAST_ROTATE_TRANS_LR TRANSPOSE LEFT-RIGHT.
      #GFGXEX2_FAST_ROTATE_TRANS_RLTRANSPOSE RIGHT-LEFT.
      #GFGXEX2_FAST_ROTATE_ROT_90 90° rotation.
      #GFGXEX2_FAST_ROTATE_ROT_180180° rotation.
      #GFGXEX2_FAST_ROTATE_ROT_270 270° rotation.
      + + + @see GFGxBlt() +*/ +GF_RETTYPE GFGxFastRotate(GFGxHandle GxHandle, + const GFGXBLTPARAM *pBltParam); +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap's color depth must match the destination's video memory's color depth. + Source transparency is supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + @param pSrcColorKey (NvU32*) pointer to source color key. If NULL no transparency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyMonoBitmap(), GFGxCopyColorBitmap() +*/ +GF_RETTYPE GFGxCopyTransColorBitmap(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits, + NvU32 *pSrcColorKey); +/** This function copies a source bitmap from system memory to the video memory with a mono + pattern buffer combination. + The source bitmap's color depth must match the destination's video memory's color depth. + Source and mono pattern transparencies are supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + @param pSrcColorKey (NvU32*) pointer to source color key. If NULL no transparency. + @param rop3 (NvU8) raster operation code + @param pPatBuffer (NvU8*) pointer to pattern buffer + @param patFgColor (NvU32) pattern foreground color + @param patBgColor (NvU32) pattern background color + @param patW, patH (NvU32) width & height of pattern buffer + @param patStride (NvU32) pattern stride in bytes + @param pSelectPatTrans (NvU16*) pointer to pattern color key. If NULL no transparency. + + Depending of pattern size, replicated mode is used or not. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransColorBitmap(), GFGxCopyColorBitmap() +*/ +GF_RETTYPE GFGxCopyTransColorBitmapWithMonoPattern(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits, + NvU32 *pSrcColorKey, + NvU8 rop3, + NvU8 *pPatBuffer, + NvU32 patFgColor, + NvU32 patBgColor, + NvU32 patW, + NvU32 patH, + NvU32 patStride, + NvU16 *pSelectPatTrans); +/** This function copies a source bitmap from system memory to the video memory with a colour + pattern buffer combination. + The source bitmap and pattern's color depth must match the destination's video memory's color depth. + Source and color pattern transparencies are supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + @param pSrcColorKey (NvU32*) pointer to source color key. If NULL no transparency. + @param rop3 (NvU8) raster operation code + @param pPatBuffer (NvU8*) pointer to pattern buffer + @param patW, patH (NvU32) width & height of pattern buffer + @param patStride (NvU32) pattern stride in bytes + @param pPatColorKey (NvU32*) pointer to pattern color key. If NULL no transparency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransColorBitmap(), GFGxCopyColorBitmap(), GFGxCopyTransColorBitmapWithMonoPattern() +*/ +GF_RETTYPE GFGxCopyTransColorBitmapWithColorPattern(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits, + NvU32 *pSrcColorKey, + NvU8 rop3, + NvU8 *pPatBuffer, + NvU32 patW, + NvU32 patH, + NvU32 patStride, + NvU32 *pPatColorKey); +/** This function copies a source bitmap from system memory to the video memory with a mono + pattern buffer combination. + The source bitmap and pattern are mono (1BPP). + Mono source and mono pattern transparencies are supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcFgColor (NvU32) source foreground color + @param srcBgColor (NvU32) source background color + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to source bitmap + @param pSelectSrcTrans (NvU16*) pointer to source color key. If NULL no transparency. + @param rop3 (NvU8) raster operation code + @param pPatBuffer (NvU8*) pointer to pattern buffer + @param patFgColor (NvU32) pattern foreground color + @param patBgColor (NvU32) pattern background color + @param patW, patH (NvU32) width & height of pattern buffer + @param patStride (NvU32) pattern stride in bytes + @param pSelectPatTrans (NvU16*) pointer to pattern color key. If NULL no transparency. + + Depending of pattern size, replicated mode is used or not. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransColorBitmap(), GFGxCopyTransMonoBitmap() +*/ +GF_RETTYPE GFGxCopyTransMonoBitmapWithMonoPattern(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvU32 srcFgColor, + NvU32 srcBgColor, + NvS16 srcStride, + NvU8 *pMonoBits, + NvU16 *pSelectSrcTrans, + NvU8 rop3, + NvU8 *pPatBuffer, + NvU32 patFgColor, + NvU32 patBgColor, + NvU32 patW, + NvU32 patH, + NvU32 patStride, + NvU16 *pSelectPatTrans); +/** This function copies a source bitmap from system memory to the video memory with a color + pattern buffer combination. + The source bitmap is mono (1BPP). + Mono source and color pattern transparencies are supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcFgColor (NvU32) source foreground color + @param srcBgColor (NvU32) source background color + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to source bitmap + @param pSelectSrcTrans (NvU16*) pointer to source color key. If NULL no transparency. + @param rop3 (NvU8) raster operation code + @param pPatBuffer (NvU8*) pointer to pattern buffer + @param patW, patH (NvU32) width & height of pattern buffer + @param patStride (NvU32) pattern stride in bytes + @param pPatColorKey (NvU32*) pointer to pattern color key. If NULL no transparency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransMonoBitmap(), GFGxCopyTransMonoBitmapWithMonoPattern() +*/ +GF_RETTYPE GFGxCopyTransMonoBitmapWithColorPattern(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvU32 srcFgColor, + NvU32 srcBgColor, + NvS16 srcStride, + NvU8 *pMonoBits, + NvU16 *pSelectSrcTrans, + NvU8 rop3, + NvU8 *pPatBuffer, + NvU32 patW, + NvU32 patH, + NvU32 patStride, + NvU32 *pPatColorKey); + +/** This function purges the graphics cache used to store pattern buffers when + GFGX_BLT_PAT_CACHE is used. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + + @retval #GF_SUCCESS Success + @retval #GFGX_ERROR_NULL_PARAMETER Invalid GxHandle + + @see GFGxBlt() +*/ +GF_RETTYPE GFGxCachePurge(GFGxHandle GxHandle); + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFGxOpen(GFRmHandle hRm, GFGxHandle *phGx, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFGxClose(GFGxHandle *phGx); + +/*@}*/ +/*@}*/ + +#ifdef __cplusplus +} +#endif + +/** @page pageGxAppNotes GxAPI Application Notes + + @section pageGxAppNotes1 Todo + +*/ + +#endif // _GFGx_H_ diff --git a/Start_WM/test6/inc/GFGxError.h b/Start_WM/test6/inc/GFGxError.h new file mode 100755 index 00000000..64e84624 --- /dev/null +++ b/Start_WM/test6/inc/GFGxError.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFGxError.h + * GFSDK Gx Graphics API header file. + */ + +#ifndef __GFGXERROR_H__ +#define __GFGXERROR_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** GFGxAPI error code: Bad parameter. */ +#define GFGX_ERROR_ILLEGAL_PARAMETER (GFGX_ERROR | 0x00000001L) +#define GFGX_ERROR_NULL_SURFACE (GFGX_ERROR | 0x00000002L) +/** GFGxAPI error code: Color depth not supported. */ +#define GFGX_ERROR_COLORDEPTH_NOT_SUPPORTED (GFGX_ERROR | 0x00000003L) +#define GFGX_ERROR_ILLEGAL_ALPHA_MODE (GFGX_ERROR | 0x00000004L) +#define GFGX_ERROR_ILLEGAL_ROTATION_FLAG (GFGX_ERROR | 0x00000005L) +#define GFGX_ERROR_GETTING_COMPONENT (GFGX_ERROR | 0x00000006L) +#define GFGX_ERROR_NO_PRIMARY_SURFACE (GFGX_ERROR | 0x00000007L) +#define GFGX_ERROR_NO_COLORCONVERT_SUPPORT (GFGX_ERROR | 0x00000008L) +#define GFGX_ERROR_NULL_PARAMETER (GFGX_ERROR | 0x00000009L) +/** GFGxAPI error code: Function not supported. */ +#define GFGX_ERROR_NOT_SUPPORTED (GFGX_ERROR | 0x0000000AL) + + + +#ifdef __cplusplus +} +#endif + +#endif // __GFGXERROR_H__ + + + diff --git a/Start_WM/test6/inc/GFI2C.h b/Start_WM/test6/inc/GFI2C.h new file mode 100755 index 00000000..458a21c0 --- /dev/null +++ b/Start_WM/test6/inc/GFI2C.h @@ -0,0 +1,314 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFI2C.h + GFSDK I2C API header file. +*/ + +#ifndef __I2C_H__ +#define __I2C_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup groupI2C I2CAPI I2C API +*/ +/*@{*/ + +/** GFI2C Error code: Function was passed an illegal parameter. */ +#define GFI2C_ERROR_ILLEGAL_PARAMETER (GFI2C_ERROR | 0x00000001L) +/** GFI2C Error code: I2C slave device did not respond with ack signal. */ +#define GFI2C_ERROR_ACKNOWLEDGE_FAILURE (GFI2C_ERROR | 0x00000002L) +/** GFI2C Error code: Polling routine generated a timeout error. */ +#define GFI2C_ERROR_TIMEOUT_ERROR (GFI2C_ERROR | 0x00000003L) + +/** Enum specifies attribute ids for GFI2CSetAttribute() + @see GFI2CSetAttribute() +*/ +typedef enum _GFI2CATTRIBUTES +{ + GFI2C_ATTR_PULLUP, /**< Set internal I2C pullups, see GFI2C_ATTR_PULLUP_FLAGS. */ + GFI2C_ATTR_SW, /**< Set to use GPIO for SW I2C */ + GFI2C_ATTR_HW, /**< Set to use HW I2C (default) */ + GFI2C_ATTR_TIMING, /**< I2C timing mode, valid for GFI2C_ATTR_HW mode only, see GFI2C_TIMING */ + GFI2C_ATTR_RESPTIMEOUT /**< Set I2C Ack response timeout in ms */ + +} GFI2CATTRIBUTES; + +/** Flag bits for for GFI2C_ATTR_PULLUP attribute. + + Usage example: +
      +    attr = (SP_SCL_PULLUP_DISABLE | SP_SDA_PULLUP_DISABLE)
      +    GFI2CSetAttribute(I2CHandle, GFI2C_ATTR_PULLUP, attr)
      +    
      + + @see GFI2CSetAttribute(), GFI2CATTRIBUTES +*/ +typedef enum _GFI2C_ATTR_PULLUP_FLAGS +{ + SDA_PULLDOWN_DISABLE = 0, //!< Flag to disable I2C data pull down + SDA_PULLDOWN_ENABLE = 1, //!< Flag to enable I2C data pull down + SDA_PULLUP_DISABLE = 0, //!< Flag to disable I2C data pull up + SDA_PULLUP_ENABLE = 1, //!< Flag to enable I2C data pull up + SCL_PULLDOWN_DISABLE = 0, //!< Flag to disable I2C clock pull down + SCL_PULLDOWN_ENABLE = 1, //!< Flag to enable I2C clock pull down + SCL_PULLUP_DISABLE = 0, //!< Flag to disable I2C data pull up + SCL_PULLUP_ENABLE = 0, //!< Flag to enable I2C clock pull up + SCL_DEFAULT = 0, //!< Flag sets I2C clock back to default + SDA_DEFAULT = 0 //!< Flag sets I2C data back to default + +} GFI2C_ATTR_PULLUP_FLAGS; + +/** Timing modes for GFI2C_ATTR_TIMING attribute. + + The timing mode has effect for I2C HW mode (GFI2C_ATTR_HW) only. + + It affects the programming of IC_IC_CONFIG_0/THDCTL and + IC_TCOMMAND_0/SPEED_CTL registers. +*/ +typedef enum _GFI2C_TIMING +{ + /** Standard timing (default). + IC_TCOMMAND_0, SPEED_CTL is programmed to STD_MODE (standard timing). + */ + GFI2C_TIMING_STANDARD = 0, + + /** Fast mode with 2 clocks extended hold time. + IC_TCOMMAND_0, SPEED_CTL is programmed to FAST_MODE. + IC_IC_CONFIG_0, THDCTL is programmed to b'10 (add 2 clocks to hold time). + */ + GFI2C_TIMING_FASTADD2CLK + +} GFI2C_TIMING; + +typedef struct _GFI2CTABLE +{ + GF_RETTYPE (* I2CWrite)( GFI2CHandle I2CHandle, + NvU32 slaveAddr, + NvU8 *pDataBytes, + NvU32 len, + NvU32 delayInMSec ); + + GF_RETTYPE (* I2CRead)( GFI2CHandle I2CHandle, + NvU32 slaveAddr, + NvU8 *pDataBytes, + NvU32 len, + NvU32 delayInMSec ); + + GF_RETTYPE (* I2CRestartRead)( GFI2CHandle I2CHandle, + NvU32 slaveAddr, + NvU32 index, + NvU8 *pDataBytes, + NvU32 len, + NvU32 delayInMSec ); + + GF_RETTYPE (* I2CScan)( GFI2CHandle I2CHandle, + NvU16 slaveAddr ); + + GF_RETTYPE (* I2CPowerSwitch)( GFI2CHandle I2CHandle, NvU8 status); + + GF_RETTYPE (* I2CGetProperty)( GFI2CHandle I2CHandle, + PGFPROPERTY pI2CProp ); + + GF_RETTYPE (* I2CSetAttribute)(GFI2CHandle I2CHandle, NvU32 aid, NvU32 attr); + GF_RETTYPE (* I2CSetClock)( GFI2CHandle I2CHandle, NvU32 selectclock); + GF_RETTYPE (* I2CWritePrepare)( GFI2CHandle I2CHandle, + NvU32 slaveAddr, + NvU32 *pData, + NvU32 len, + NvU32 *pBuffer, + NvU32 *bufferSize); + GF_RETTYPE (* I2CRestartWrite)( GFI2CHandle I2CHandle, + NvU32 slaveAddr1, + NvU8 *pIndexBytes, + NvU32 lenIndex, + NvU32 slaveAddr2, + NvU8 *pDataBytes, + NvU32 lenData, + NvU32 delayInMSec ); + +} GFI2CTABLE, *PGFI2CTABLE; + +/** Open GFI2C component. + @param hRm RM handle + @param phI2C Returns I2C component handle on success + @param state Channel allocation mode + @param hCh Channel to use, or NULL to allocate new +*/ +GF_RETTYPE GFI2COpen(GFRmHandle hRm, GFI2CHandle *phI2C, GF_STATE_TYPE state, GFRmChHandle hCh); + +/** Close GFi@c component. + @param phI2C I2C component handle, will be reset to NULL. Can be NULL. +*/ +void GFI2CClose(GFI2CHandle *phI2C); + +/** This routine writes out len bytes of data during one I2C transfer. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + @param pDataBytes (NvU8) Pointer to data bytes to be written + @param len (NvU32) Number of bytes of data to be written + @param delayInMSec (NvU32) Optional delay inserted after transfer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CWrite(I2CHandle, slaveAddr, pDataBytes, len, delayInMSec) \ + ((PGFI2CTABLE)I2CHandle)->I2CWrite(I2CHandle, slaveAddr, pDataBytes, len, delayInMSec) + +/** This routine reads len bytes of data during one I2C transfer. A typical I2C slave + device requires its address already be set by a preceding GFI2CWrite() function. + These functions should be executed together with no other activity in between. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + @param pDataBytes (NvU8) Pointer to data bytes read from device + @param len (NvU32) Number of bytes of data to be read + @param delayInMSec (NvU32) Optional delay inserted after transfer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CRead(I2CHandle, slaveAddr, pDataBytes, len, delayInMSec) \ + ((PGFI2CTABLE)I2CHandle)->I2CRead(I2CHandle, slaveAddr, pDataBytes, len, delayInMSec) + +/** This function reads in len or fewer bytes of data from an I2C slave device. It differs + from the GFI2CRead() function in that it does so with a combination of an I2C write and + read. There is an I2C write of the slave address and index byte then followed by a START + condition. There is no STOP condition in-between the write and read transactions. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + @param index (NvU32) 2nd byte index of slave device register + @param pDataBytes (NvU8) Pointer to data bytes read from device + @param len (NvU32) Number of bytes of data to be read + @param delayInMSec (NvU32) Optional delay inserted after transfer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CRestartRead(I2CHandle, slaveAddr, index, pDataBytes, len, delayInMSec) \ + ((PGFI2CTABLE)I2CHandle)->I2CRestartRead(I2CHandle, slaveAddr, index, pDataBytes, len, delayInMSec) + +/** This routine writes out a I2C slave address and checks for an ACK. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CScan(I2CHandle, slaveAddr) \ + ((PGFI2CTABLE)I2CHandle)->I2CScan(I2CHandle, slaveAddr) + +/** This function has been replaced by camera scripting. Camera power is now + controlled by a function in the camera scripts. +*/ +#define GFI2CPowerSwitch(I2CHandle, status) \ + ((PGFI2CTABLE)I2CHandle)->I2CPowerSwitch(I2CHandle, status) + +/** This routine sets various I2C attributes. The aid parameter passes an + enumeration GFI2CATTRIBUTES that selects the attribute operation. Each + attribute has a set of defined values passed in the parameter attr, that + it will operate on. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param aid (NvU32) attribute flag + @param attr (NvU32) attribute data value + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see GFI2CATTRIBUTES + +*/ +#define GFI2CSetAttribute( I2CHandle, aid, attr) \ + ((PGFI2CTABLE)I2CHandle)->I2CSetAttribute(I2CHandle, aid, attr ) + +/** This routine sets the I2C clock output on the SCL pin. The parameter + selectclock specifies the new I2C clock in kilohertz. The default + is 100. If selectclock = 0, then the default will be set. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param selectclock (NvU32) new clock value in kHz. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CSetClock(I2CHandle, selectclock) \ + ((PGFI2CTABLE)I2CHandle)->I2CSetClock(I2CHandle, selectclock) + +/** This routine Provide properties about I2C. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param pProp (GFPROPERTY) pointer to GFPROPERTY struct. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +#define GFI2CGetProperty(I2CHandle, pProp) \ + ((PGFI2CTABLE)I2CHandle)->I2CGetProperty(I2CHandle, pProp) + +/** This function prepares a buffer that contains the command sequence for an + I2C write. This may concatenated onto another command sequence and written + to the channel as a combination of two transactions. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + @param pData (NvU8) Pointer to data bytes to be written + @param len (NvU32) Number of bytes of data to be read + @param pBuffer (NvU8) Pointer to command sequence for I2C write + @param bufferSize (NvU32) Number of commands returned + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CWritePrepare(I2CHandle, slaveAddr, pData, len, pBuffer, bufferSize) \ + ((PGFI2CTABLE)I2CHandle)->I2CWritePrepare(I2CHandle, slaveAddr, pData, len, pBuffer, bufferSize) + +/** This function writes lenData bytes of data to an I2C slave device. It differs + from the GFI2CWrite() function in that it does so with a combination of two I2C writes + There is an I2C write of the slave address and index bytes then followed by a START + condition. There is no STOP condition in-between the write and write transactions. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr1 (NvU32) I2C address of 1st slave device + @param pDataIndex (NvU8) Pointer to index data to be written to the 1st device + @param lenIndex (NvU32) index data length + @param slaveAddr2 (NvU32) I2C address of 2nd slave device + @param pDataBytes (NvU8) Pointer to data bytes written to 2nd device + @param lenData (NvU32) Number of bytes of data to be read + @param delayInMSec (NvU32) Optional delay inserted after transfer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CRestartWrite(I2CHandle, slaveAddr1, pIndexBytes, lenIndex, \ + slaveAddr2, pDataBytes, lenData, delayInMSec) \ + ((PGFI2CTABLE)I2CHandle)->I2CRestartWrite(I2CHandle, slaveAddr1, pIndexBytes, lenIndex, \ + slaveAddr2, pDataBytes, lenData, delayInMSec) + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* __I2C_H__ */ + diff --git a/Start_WM/test6/inc/GFI2S.h b/Start_WM/test6/inc/GFI2S.h new file mode 100755 index 00000000..bbfd876e --- /dev/null +++ b/Start_WM/test6/inc/GFI2S.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* +* File: GFi2s.h +* I2S header file. +*/ + + +#ifndef __I2S_H__ +#define __I2S_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFI2SOpen(GFRmHandle hRm, GFI2SHandle *phI2S, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFI2SClose(GFI2SHandle *phI2S); + +GF_RETTYPE GFI2SSetTransmitBuffer(GFI2SHandle I2SHandle, + NvU32 startAddr, + NvU32 sizeBytes, + NvU32 numBuffers); + +GF_RETTYPE GFI2SSetTransmitState(GFI2SHandle I2SHandle, + NvU32 state); + +GF_RETTYPE GFI2SSetReceiveBuffer(GFI2SHandle I2SHandle, + NvU32 startAddr, + NvU32 sizeBytes, + NvU32 numBuffers); + +GF_RETTYPE GFI2SSetReceiveState(GFI2SHandle I2SHandle, + NvU32 state); + +#ifdef __cplusplus +} +#endif + +#endif /* __I2S_H__ */ diff --git a/Start_WM/test6/inc/GFINTx.h b/Start_WM/test6/inc/GFINTx.h new file mode 100755 index 00000000..2b45eb76 --- /dev/null +++ b/Start_WM/test6/inc/GFINTx.h @@ -0,0 +1,114 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFINTx.h + GFSDK Interrupt API header file. +*/ + +#ifndef __GFINTx_H__ +#define __GFINTx_H__ + +#include "GFRmOEM.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupINTx INTxAPI Interrupt API +*/ +/*@{*/ + +#define GF_INTR_START 0 +#define GF_INTR_END 15 + +/* Embedded memory controller interrupt */ +#define GF_EMC_INTR (15) + +/* MC interrupt. */ +#define GF_MC_INTR (14) + +/* SD interrupt. */ +#define GF_SD_INTR (13) + +/* I2C interrupt. */ +#define GF_IC_INTR (12) + +/* I2s interrupt. */ +#define GF_I2S_INTR (11) + +/* Display interrupt. */ +#define GF_DISPLAY_INTR (10) + +/* 3d interrupt. */ +#define GF_GR3D_INTR (9) + +/* 2d interrupt. */ +#define GF_GR2D_INTR (8) + +/* DSP interrupt. */ +#define GF_DSP_INTR (7) + +/* ISP interrupt. */ +#define GF_ISP_INTR (6) + +/* SDGP1 input falling edge interrupt. */ +#define GF_EPP_INTR (5) + +/* VI interrupt. */ +#define GF_VI_INTR (4) + +/* JPEG Encoder interrupt. */ +#define GF_JPEGE_INTR (3) + +/* Mpeg Encoder interrupt. */ +#define GF_ME_INTR (2) + +/* Graphics MPD interrupt. */ +#define GF_GRMPD_INTR (1) + +/* Host interface interrupt. */ +#define GF_HOST_INTR (0) + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFINTxOpen(GFRmHandle hRm, GFINTxHandle *phINTx, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFINTxClose(GFINTxHandle *phINTx); + +/* ### Helper Macros ### */ +GF_RETTYPE GFINTxGetProperty(GFINTxHandle INTxHandle, + PGFPROPERTY pINTxProp); + + +GF_RETTYPE GFINTxDisable(GFINTxHandle INTxHandle, + NvU32 idInt); + +GF_RETTYPE GFINTxEnable(GFINTxHandle INTxHandle, + NvU32 idInt); + +/** Wait for system level interrupt request. + @param handle Handle to INTx API + @param idInt System level interrupt ID + @param timeout Timeout in miliseconds, or 0 to wait endlessly + @retval GF_SUCCESS Interrupt request received + @retval GF_WAIT_TIME_OUT Timeout without interrupt request received +*/ +GF_RETTYPE GFINTxWaitForIRQ(GFINTxHandle INTxHandle, + NvU32 idInt, + NvU32 timeout); + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif // __GFINTx_H__ +/* End of file. */ + diff --git a/Start_WM/test6/inc/GFIsp.h b/Start_WM/test6/inc/GFIsp.h new file mode 100755 index 00000000..b3c7e512 --- /dev/null +++ b/Start_WM/test6/inc/GFIsp.h @@ -0,0 +1,1654 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFIsp.h + GFSDK Image Signal Processing API header file. +*/ + +#ifndef _GF_ISP__ +#define _GF_ISP__ + +//#define DVS_DEVELOPMENT + +#include "GFCamera.h" +#include "GFVx.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupIsp IspAPI Image Signal Processing API + + As image resolution increases (three megapixels and up), image signal + processing inside the imager module becomes complex and costly, and the + required bandwidth to transfer processed data to the GPU increases. + + One solution to this problem is to incorporate image signal processing (ISP1) + capabilities inside the GPU, and let the imager send raw Bayer Pattern Data + from the CMOS or CCD sensor to the GPU. This reduces bandwidth as ISP + programming is easier and much faster compared to having the ISP unit + inside the imager. + + The ISP pipeline consists of various stages of image processing operations to + enhance the image so that its digital representation is as close to the natural + look as possible. The ISP pipeline consists of the following stages: + - Optical Black Compensation (OB) + - De-Knee Linearization + - Lens Shading Compensation + - White Balance Gain Adjustment (M1, M2, M3 statistics gathering) + - Bad Pixel Compensation + - Noise Reduction + - Demosaicing + - Edge Enhancement (M4 statistics gathering) + - Color Noise Reduction + - Color Correction + - Gamma Correction + - RGB to YUV conversion + + Besides these pipeline stages, the ISP module also provides a statistics + collection mechanism that can be applied to multiple regions of the image. + Image statistics information can be used to compute Auto Exposure (AE), + Auto White Balance (AWB) and Auto Focus (AF). + + The GFISPAPI sets up parameters for each pipeline functional block. If + needed, the user can also choose to bypass each individual functional block. + Once all blocks are set up, image data flows through them automatically. + + Figure 1, "Block Diagram of the ISP Interface," shows the ISP with + respect to other input blocks such as video input (VI) and the encoder + preprocessor (EPP). + + @image html ISPFigure1.bmp + + Figure 2, "Internal ISP Data Flow," shows the data flow inside the + ISP. + + @image html ISPFigure2.bmp + +*/ +/*@{*/ + +/** @defgroup groupIspCapability ISP Capability Flags + These flags represent the various capabilities of the ISP. + @see GFISPPROPERTY +*/ +/*@{*/ + +/** IspAPI property flag: Bayer format input supported. + @see GFISPGetProperty() +*/ +#define GFISP_CAP_FORMAT_BAYER 0x00000001 + +/** IspAPI property flag: Stacked format input supported. + @see GFISPGetProperty() +*/ +#define GFISP_CAP_FORMAT_STACKED 0x00000002 + +/** IspAPI property flag: Three optical black regions supported. + @see GFISPGetProperty(), GFISPOBCONTROL +*/ +#define GFISP_CAP_THREE_OB_REGIONS 0x00000004 + +/** IspAPI property flag: Four optical black regions supported. + @see GFISPGetProperty(), GFISPOBCONTROL +*/ +#define GFISP_CAP_FOUR_OB_REGIONS 0x00000008 + +/** IspAPI property flag: Frame-based optical black supported. + @see GFISPGetProperty(), GFISPOBCONTROL +*/ +#define GFISP_CAP_FRAME_OB 0x00000010 + +/** IspAPI property flag: Line-based optical black supported. + @see GFISPGetProperty(), GFISPOBCONTROL +*/ +#define GFISP_CAP_LINE_OB 0x00000020 + +/** IspAPI property flag: Column-based optical black supported. + @see GFISPGetProperty() +*/ +#define GFISP_CAP_COLUMN_OB 0x00000040 + +/** IspAPI property flag: Deknee (input linearization) supported. + @see GFISPGetProperty(), GFISPDEKNEECONTROL +*/ +#define GFISP_CAP_DE_KNEE 0x00000100 + +/** IspAPI property flag: Lens shading supported. + @see GFISPGetProperty(), GFISPLENSSHADING +*/ +#define GFISP_CAP_LENSSHADING 0x00000200 + +/** IspAPI property flag: White balance supported. + @see GFISPGetProperty(), GFISPWBCONTROL +*/ +#define GFISP_CAP_WB 0x00000400 + +/** IspAPI property flag: Demosaic supported. + @see GFISPGetProperty(), GFISPDEMOSAICCONTROL +*/ +#define GFISP_CAP_DEMOSIAC 0x00000800 + +/** IspAPI property flag: Edge enhancement supported. + @see GFISPGetProperty(), GFISPEDGEENHANCECONTROL +*/ +#define GFISP_CAP_EDGEENHANCE 0x00001000 + +/** IspAPI property flag: Bad pixel concealment supported. + @see GFISPGetProperty(), GFISPBADPIXELCONTROL +*/ +#define GFISP_CAP_BADPIXEL 0x00002000 + +/** IspAPI property flag: Noise reduction supported. + @see GFISPGetProperty(), GFISPNOISECONTROL1 +*/ +#define GFISP_CAP_NOISEREDUCTION1 0x00004000 + +/** IspAPI property flag: Color noise reduction supported. + @see GFISPGetProperty(), GFISPNOISECONTROL2 +*/ +#define GFISP_CAP_NOISEREDUCTION2 0x00008000 + +/** IspAPI property flag: Color correction supported. + @see GFISPGetProperty(), GFISPCOLORCORRECTION +*/ +#define GFISP_CAP_COLORCORRECTION 0x00100000 + +/** IspAPI property flag: Gamma correction supported. + @see GFISPGetProperty(), GFISPGAMMACONTROL +*/ +#define GFISP_CAP_GAMMACORRECTION 0x00200000 + +/** IspAPI property flag: YUV conversion supported. + @see GFISPGetProperty(), GFISPYUVCONVERSION +*/ +#define GFISP_CAP_YUVCONVERSION 0x00400000 + +/** IspAPI property flag: M1 window statistics supported. + @see GFISPGetProperty(), GFISPM1WINDOW +*/ +#define GFISP_CAP_M1 0x01000000 + +/** IspAPI property flag: M2 window statistics supported. + @see GFISPGetProperty(), GFISPM2WINDOW +*/ +#define GFISP_CAP_M2 0x02000000 + +/** IspAPI property flag: M3 window statistics supported. + @see GFISPGetProperty(), GFISPM3WINDOW +*/ +#define GFISP_CAP_M3 0x04000000 + +/** IspAPI property flag: M4 window statistics supported. + @see GFISPGetProperty(), GFISPM4WINDOW +*/ +#define GFISP_CAP_M4 0x08000000 + +/** IspAPI property flag: Negative effect supported. + @see GFISPGetProperty() +*/ +#define GFISP_CAP_NEGATIVEEFFECT 0x80000000 +/*@}*/ + +//#define MANUAL_ENABLE_WAIT_FOR_OUTPUT_END 1 + +/** Struct for ISP version and capabilities. + @see GFISPGetProperty +*/ +typedef struct _GFISPPROPERTY +{ + NvU32 size; /**< Actual size of GFISPPROPERTY data structure. */ + NvU32 version; /**< Version of GFISPAPI. */ + + NvU32 cap; /**< Combination of @ref groupIspCapability. Each bit corresponds to one ISP capability. */ + NvU32 maxWidth, /**< Maximum supported image width. */ + maxHeight; /**< Maximum image height. */ + NvU32 supportedScriptVersion; /**< Version of script supported by ISP API. Incorrect script version may cause some API calls to fail. */ +} GFISPPROPERTY, *PGFISPPROPERTY; + + +/** Definition of attribute ids for GFISPGetAttribute() and GFISPSetAttribute(). +*/ +typedef enum _GFISPATTRIBUTES { + GFISP_ATTR_ENABLE_ISP, /**< The master switch of ISP. 1 = Enable ISP processing, 0 = Disable */ + GFISP_ATTR_ENABLE_OB, /**< The master switch for optical black. 1 = Enable OB, 0 = Disable */ + GFISP_ATTR_ENABLE_SENSOR_MANUAL_OB, /**< The master switch for SENSOR Manual optical black. 1 = Enable OB, 0 = Disable */ + GFISP_ATTR_ENABLE_SENSOR_AUTO_OB, /**< The master switch for SENSOR Auto optical black. 1 = Enable OB, 0 = Disable */ + GFISP_ATTR_ENABLE_FOB, /**< Switch for frame based optical black. 1 = Enable frame based optical black, 0 = Disable */ + GFISP_ATTR_ENABLE_FOB_SELFRESET, /**< Switch for self-reset for frame based optical black. 1 = Enable (reset every frame), 0 = Disable */ + GFISP_ATTR_ENABLE_FOB_TEMPORAL, /**< Switch for temporal filtering for frame based optical black. 1 = Enable temporal filtering, 0 = Disable */ + GFISP_ATTR_ENABLE_LOB, /**< Switch for line based optical black. 1 = Enable line based OB, 0 = Disable */ + GFISP_ATTR_ENABLE_DEKNEE, /**< Switch for deknee. 1 = Enable deknee, 0 = Disable */ + GFISP_ATTR_ENABLE_LENS_SHADING, /**< Switch for lens shading correction. 1 = Enable lens shading correction, 0 = Disable */ + GFISP_ATTR_ENABLE_WB, /**< The master switch for white balance. 1 = Enable white balance, 0 = Disable */ + GFISP_ATTR_ENABLE_AWB, /**< Switch for built-in automatic white balance. 1 = Automatic/dynamic (real-time) white balance, 0 = Preprogrammed mode white balance */ + GFISP_ATTR_AWB_HOLD, /**< Switch to pause automatic white balance. Only effective when GFISP_ATTR_ENABLE_AWB=1. 1 = Start applying current AWB gain value to all future frames, 0 = Restore normal AWB mode */ + GFISP_ATTR_ENABLE_DEMOSAIC, /**< Switch for demosaic processing. 1 = Enable demosaic processing, 0 = Disable */ + GFISP_ATTR_ENABLE_EDGE_ENHANCE, /**< Switch for edge enhancement. 1 = Enable edge enhancement, 0 = Disable */ + GFISP_ATTR_ENABLE_NOISE_CONTROL1, /**< Switch for noise control 1. Noise control method 1 is built in the demosaic unit. 1 = Enable noise control 1, 0 = Disable */ + GFISP_ATTR_ENABLE_BAD_PIXEL, /**< Switch for bad pixel concealment. 1 = Enable bad pixel detection and concealment, 0 = Disable */ + GFISP_ATTR_ENABLE_COLOR_CORRECTION, /**< Switch for color correction. 1 = Enable color correction, 0 = Disable */ + GFISP_ATTR_ENABLE_NOISE_CONTROL2, /**< Switch for noise control 2. Noise control method 2 is built in the color correction unit. 1 = Enable noise control 2, 0 = Disable */ + GFISP_ATTR_ENABLE_GAMMA_CORRECTION, /**< Switch for gamma correction. 1 = Enable gamma correction, 0 = Disable */ + GFISP_ATTR_ENABLE_YUV_CONVERSION, /**< Switch for RGB to YUV conversion. 1 = Enable RGB-YUV conversion, 0 = Disable */ + GFISP_ATTR_ENABLE_NEGATIVE_EFFECT, /**< Switch for negative effect. 1 = Negate whole output image, 0 = Normal image */ + GFISP_ATTR_ENABLE_M2, /**< Switch for M2 statistics. 1 = Enable M2 statistics gathering, 0 = Disable */ + GFISP_ATTR_ENABLE_M3, /**< Switch for M3 statistics. 1 = Enable M3 statistics gathering, 0 = Disable */ + GFISP_ATTR_ENABLE_M4, /**< Switch for M4 statistics. 1 = Enable M4 statistics gathering, 0 = Disable */ + GFISP_ATTR_ENABLE_STATS_RAISE, /**< Switch for statistics raise. 1 = Generate raise vector when statistics gathering is complete, 0 = Disable */ + GFISP_ATTR_ENABLE_STATS_INT, /**< Switch for statistics interrupt. 1 = Generate interrupt when statistics gathering is complete, 0 = Disable */ + GFISP_ATTR_STATS_LINE_END, /**< The line at which statistics gathering is complete. When the line counter reaches STATS_LINE_END, the raise vector and/or interrupt are generated (if enabled). */ +#ifdef MANUAL_ENABLE_WAIT_FOR_OUTPUT_END + GFISP_ATTR_ENABLE_WAIT_FOR_OUTPUT_END, /**< Temporary used to enable wait for OUTPUT_END. 1 = Wait for output end, 0 = Disable */ +#endif + /* Special effects */ + GFISP_ATTR_ENABLE_EMBOSS, /**< Switch for emboss special effect. 1 = Enable emboss special effect, 0 = Disable */ + GFISP_ATTR_ENABLE_SOLARIZE, /**< Switch for solarize special effect. 1 = Enable solarize special effect, 0 = Disable */ + GFISP_ATTR_ENABLE_SEPIA, /**< Switch for sepia special effect. 1 = Enable sepia special effect, 0 = Disable */ + GFISP_ATTR_ENABLE_MONOCHROME, /**< Switch for monochrome special effect. 1 = Enable monochrome special effect, 0 = Disable */ + /* Video settings */ + GFISP_ATTR_CONTRAST, /**< Contrast control. Acts as offset for Y data. Range is [0, 128]. */ + GFISP_ATTR_BRIGHTNESS, /**< Brightness control. Modifies slope of Y data. Range is [0, 256]. */ + GFISP_ATTR_HUE, /**< Hue control. Modifies slope of UV data. Range is [0, 128]. */ + GFISP_ATTR_SATURATION_U, /**< Hue control. Modifies slope of UV data. Range is [0, 256]. */ + GFISP_ATTR_SATURATION_V, /**< Hue control. Modifies slope of UV data. Range is [0, 256]. */ + /* Software 3A control */ + GFISP_ATTR_ENABLE_3A_AE, /**< Switch for software auto exposure. 1 = Enable auto exposure and disable sensor exposure, 0 = Disable */ + GFISP_ATTR_ENABLE_3A_AWB, /**< Switch for software auto white balance. 1 = Enable auto white balance and disable sensor exposure, 0 = Disable */ + GFISP_ATTR_ENABLE_3A_AF, /**< Switch for software auto focus. 1 = Enable auto focus and disable sensor auto focus, 0 = Disable */ + + GFISP_ATTR_ENABLE_SENSOR_AE, /**< Switch for sensor auto exposure. 1 = Enable sensor auto exposure and disable software expoture, 0 = Disable */ + GFISP_ATTR_ENABLE_SENSOR_AWB, /**< Switch for sensor auto white balance. 1 = Enable sensor auto white balance and disable software white balance, 0 = Disable */ + GFISP_ATTR_ENABLE_SENSOR_AF, /**< Switch for sensor auto focus. 1 = Enable sensor auto focus and disable software auto focus, 0 = Disable */ + GFISP_ATTR_ENABLE_AUTO_CC_VIVIDITY /**< Flag for auto vividity. 1 = Enable auto vividity, 0 = Disable auto vividity*/ +} GFISPATTRIBUTES; + + +/** Definition of parameter ids and data structures for #GFISPGetParameter and #GFISPSetParameter. +*/ +typedef enum _GFISPPARAMETERS { + GFISP_PARA_TIMING, /**< Get/Set timing parameters. @see GFISPIMGTIMING */ + GFISP_PARA_M1WINDOW, /**< Get/Set M1 statistics parameters. @see GFISPM1WINDOW */ + GFISP_PARA_M2WINDOW, /**< Get/Set M2 statistics parameters. @see GFISPM2WINDOW */ + GFISP_PARA_M3WINDOW, /**< Get/Set M3 statistics parameters. @see GFISPM3WINDOW */ + GFISP_PARA_M4WINDOW, /**< Get/Set M4 statistics parameters. @see GFISPM4WINDOW */ + GFISP_PARA_OB, /**< Get/Set optical black parameters. @see GFISPOBCONTROL */ + GFISP_PARA_DEKNEE, /**< Get/Set deknee parameters. @see GFISPDEKNEECONTROL */ + GFISP_PARA_LENSSHADING, /**< Get/Set lens shading parameters. @see GFISPLENSSHADING */ + GFISP_PARA_WB, /**< Get/Set white balance parameters. @see GFISPWBCONTROL */ + GFISP_PARA_DEMOSAIC, /**< Get/Set demosaic parameters. @see GFISPDEMOSAICCONTROL */ + GFISP_PARA_EDGEENHANCE, /**< Get/Set edge enhancement parameters. @see GFISPEDGEENHANCECONTROL */ + GFISP_PARA_NOISECONTROL1, /**< Get/Set noise control 1 parameters. @see GFISPNOISECONTROL1 */ + GFISP_PARA_NOISECONTROL2, /**< Get/Set noise control 2 parameters. @see GFISPNOISECONTROL2 */ + GFISP_PARA_BADPIXEL, /**< Get/Set bad pixel parameters. @see GFISPBADPIXELCONTROL */ + GFISP_PARA_COLORCORRECT, /**< Get/Set color correction parameters. @see GFISPCOLORCORRECTION */ + GFISP_PARA_GAMMACORRECT, /**< Get/Set gamma correction parameters. @see GFISPGAMMACONTROL */ + GFISP_PARA_YUVCONVERT, /**< Get/Set YUV conversion parameters. @see GFISPYUVCONVERSION */ + GFISP_PARA_SETMODE, /**< Get/Set ISP mode as specified in script. @see GFISPSETMODE */ + GFISP_PARA_3A_AE, /**< Get/Set 3A AE parameters. @see GFISP3AAE */ + GFISP_PARA_3A_AWB, /**< Get/Set 3A AWB parameters. @see GFISP3AAWB */ + GFISP_PARA_3A_AF , /**< Get/Set 3A AF parameters. @see GFISP3AAF */ + GFISP_PARA_3A_PREV_MODE_AWB, + GFISP_PARA_3A_AWB_SAT_Y_LIMITS, + GFISP_PARA_3A_FRAME_RATE_LOW_LIMIT, + GFISP_PARA_3A_FRAME_RATE_HIGH_LIMIT, + GFISP_PARA_3A_FRAME_RATE_CHOICE, + GFISP_PARA_ISO_SENSITIVITY, /**< Get/Set ISO Sensitivity for 3AAE. */ + GFISP_PARA_REDUCE_GAIN_COMPRESS_GAMMA, /**< Reduce/Restore sensor gain and compensate gain change through Gamma curve Compression/Restoration. + To be used only with SetParameter fn. @see GFISPGAINGAMMACTRL */ + GFISP_PARA_IMAGE_STABILIZATION, /**< Set Image Stabilization. 1 = Enable Image Stabilization, 0 = Disable */ + GFISP_PARA_EXPOSURE_CONTROL, /**< Get/Set exposure control parameters. @see GFISPEXPOSURECONTROL */ + GFISP_PARA_EXPOSURE, /**< Get/Set exposure manually. @see GFISPMANUALEXPOSURE */ + GFISP_ISP_SENSOR_CAPABILITY, /**< ISP 3A Capability >*/ + GFISP_PARA_SENSOR_REGISTER /**< SENSOR Register Read wrtie parameter>*/ + +} GFISPPARAMETERS; + +/** Number of fractional bits of fixed point parameters. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_FIXEDPOINTPARAMETER_FBITS 8 +/** Total number of bits of fixed point parameters. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_FIXEDPOINTPARAMETER_BITS 16 +/** Macro to convert floating point to fixed point. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_CONVERT_FLOAT_TO_FIXED_SIGNED(x) ((NvS16)(x * (2 << GFISP_FIXEDPOINTPARAMETER_FBITS))) +/** Macro to convert floating point to fixed point. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_CONVERT_FLOAT_TO_FIXED_UNSIGNED(x) ((NvU16)(x * (2 << GFISP_FIXEDPOINTPARAMETER_FBITS))) +/** Macro to convert fixed point to floating point. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_CONVERT_FIXED_TO_FLOAT(x) (((float)x) / (2 << GFISP_FIXEDPOINTPARAMETER_FBITS)) + + +/** Enum for which pixel of the R, G, G, B pattern the active frame starts on. + @see GFISPIMGTIMING +*/ +typedef enum +{ + GFISP_RGGB = 0, + GFISP_GRBG = 1, + GFISP_GBRG = 2, + GFISP_BGGR = 3 +} GFISP_BAYERPATTERN_SEL; + +/** Timing Generator Control. + + Whole timing frame consists of scanned part and idle parts (void periods in between lines + and frames). Overall scanned image frame is specified by H_SCAN_SIZE and V_SCAN_SIZE which + includes H and V blank periods. Line and pixel counters are set to 1 at transitions of active + edge of V and H sync input pulses. Note that coordinate in the whole frame starts with + (1,1) instead of (0,0). + + In horizotal direction, H sync active edge indicates start of scan line and it initiates + pixel count from 1 to H_SCAN_SIZE (end of line). After H_SCAN_SIZE pixels are received, + the ISP module goes into void period, in which it waits for next arrival of H sync active + edge. In practice, H blank period is composed of inactive period during H_SCAN SIZE and the + void period in between end of line and start next line. + + Same applies to vertical direction. + + Active part (non-blanking part) consists of "optical black" lines at top and bottom of the + image frame and left and right of image line, and active lines with active pixels in the + middle. + + @see GFISPGetParameter, GFISPSetParameter +*/ +typedef struct _GFISPIMGTIMING +{ + NvU16 hScanSize, /**< Number of pixel clock periods per scan line (including H blanking). */ + vScanSize; /**< Number of line periods per scan frame (including V blanking). */ + NvU8 hSyncEdge, /**< Active edge selection for horizontal sync. 0 = positive transition, 1 = negative transition. */ + vSyncEdge; /**< Active edge selection for vertical sync. 0 = positive transition, 1 = negative transition. */ + GFISP_BAYERPATTERN_SEL bayerSel; /**< Bayer timing format. Specifies which pixel of the R, G, G, B pattern the active frame starts on. */ + + GFRECT ActiveRect; /**< Active image area. */ + GFRECT OutputRect; /**< Output image area. */ +} GFISPIMGTIMING, *PGFISPIMGTIMING; + + +/** Enum for the number of samples to take across the M1 statistics window. + @see GFISPM1WINDOW +*/ +typedef enum +{ + GFISP_M1SAMPLE32 = 0, + GFISP_M1SAMPLE64 = 1 +} GFISP_M1_SAMPLE_SEL; + +/** M1 statistics window control. + + The GFISPAPI provides four methods that programmers can use to gather + statistics on pixel values. Based on the values, the programmer can take + appropriate compensating action as needed. The four methods are M1 + Window, M2 Window, M3 Window, and M4 Window. + + This structure describes the M1 Window method, which measures average/ + peak pixel values inside the specified area. It returns eight values—four + values (RGGB) represent average pixels, and four values represent peak + pixels. The measurement result can be used for white balance, either + automatically by AWB or manually by the programmer. + + Refer to the function #GFISPReadMWindowValues() for reading the + measured values. + + @see GFISPGetParameter, GFISPSetParameter, GFISPReadMWindowValues +*/ +typedef struct _GFISPM1WINDOW +{ + GFRECT M1WindowRect; /**< M1 Window size/position. */ + GFISP_M1_SAMPLE_SEL horzSampSel, /**< Horizontal sample density. */ + vertSampSel; /**< Vertical sample density. */ + NvU16 PeakMax; /**< Maximum limit of peak detection. */ + NvU16 TemporalFilterStrength; /**< Selects temporal filter coefficients. Valid range is [0-7]. Value 0 effectively turns off temporal filter. */ +} GFISPM1WINDOW, *PGFISPM1WINDOW; + + +/** M2 statistics window control. + + The GFISPAPI provides four methods that programmers can use to gather + statistics on pixel values. Based on the values, the programmer can take + appropriate compensating action as needed. The four methods are M1 + Window, M2 Window, M3 Window, and M4 Window. + + This structure describes the M2 Window method for gathering statistics on + pixel values. The M2 Window method measures the number of pixels at + specified ranges inside a specified area. A histogram with four bins is + generated. + + Refer to the function #GFISPReadMWindowValues() for reading the + measured values. + + @see GFISPGetParameter, GFISPSetParameter, GFISPReadMWindowValues, GFISP_ATTR_ENABLE_M2 +*/ +typedef struct _GFISPM2WINDOW +{ + GFRECT M2WindowRect; /**< M2 Window size/pos. */ + NvU16 HistBinL1, /**< Cut point of 1st bin. */ + HistBinL2, /**< Cut point of 2nd bin. */ + HistBinL3; /**< Cut point of 3rd bin. */ + NvU16 reserved; +} GFISPM2WINDOW, *PGFISPM2WINDOW; + + +/** M3 statistics window control. + + The GFISPAPI provides four methods that programmers can use to gather + statistics on pixel values. Based on the values, the programmer can take + appropriate compensating action as needed. The four methods are M1 + Window, M2 Window, M3 Window, and M4 Window. + + This structure describes the M3 Window method for gathering statistics on + pixel values, The M3 Window method generates a group of pixel samples + from the specified area. Each sub-window generates one 32-bit value. + + The horizontal interval of M3 sub-windows is derived from M3 window + line width divided by M3 window horizontal count, rounded down. + + The vertical interval of M3 sub-windows is derived from M3 window + frame height divided by M3 window vertical count, rounded down. + + Refer to the function #GFISPReadMWindowValues() for reading the + measured values. + + @see GFISPGetParameter, GFISPSetParameter, GFISPReadMWindowValues, GFISP_ATTR_ENABLE_M3 +*/ +typedef struct _GFISPM3WINDOW +{ + GFRECT M3WindowRect; /**< M3 Window size/pos. */ + NvU8 SubWindowCountH, /**< Number of sub-windows in horizontal direction. Can be {16,32,64}. */ + SubWindowCountV; /**< Number of sub-windows in vertical direction. Can be {16,32,64}. */ + NvU16 SubWindowWidth, /**< Width of sub-windows. Can be {2,4,8,16,32}. */ + SubWindowHeight; /**< Height of sub-windows. Can be {2,4,8,16,32}. */ + NvU16 reserved; +} GFISPM3WINDOW, *PGFISPM3WINDOW; + + +/** M4 statistics window control. + + The GFISPAPI provides four methods that programmers can use to gather + statistics on pixel values. Based on the values, the programmer can take + appropriate compensating action as needed. The four methods are M1 + Window, M2 Window, M3 Window, and M4 Window. + + This structure describes the M4 Window method for gathering statistics on + pixel values. The M4 Window method takes statistical measurements for + auto-focus control. It generates two values for each sub-window. One value + represents the high frequency factor inside the sub-window. The other value + represents sub-window luminance. + + There are {1, 2, 3, 4, 6, 9} sub-windows in {1,2,3}x{1,2,3} configurations. + + SC15 implementation has the following constraints + * SubWindowintervalH >= SubWindowWidth + * SubWindowintervalV >= SubWindowHeight + + Refer to the function #GFISPReadMWindowValues() for reading the + measured values. + + @see GFISPGetParameter, GFISPSetParameter, GFISPReadMWindowValues, GFISP_ATTR_ENABLE_M4 +*/ +typedef struct _GFISPM4WINDOW +{ + NvU32 Left, /**< Specifies left of first M4 sub-window. */ + Top; /**< Specifies top of first M4 sub-window. */ + NvU8 SubWindowCountH, /**< Specifies the number of sub-windows in the horizontal direction. Can be {1,2,3}. */ + SubWindowCountV; /**< Specifies the number of sub-windows in the vertical direction. Can be {1,2,3}. */ + NvU16 SubWindowWidth, /**< Specifies the width of each sub-window. */ + SubWindowHeight; /**< Specifies the height of each sub-window. */ + NvU16 SubWindowIntervalH, /**< Specifies the horizontal interval of sub-windows. */ + SubWindowIntervalV; /**< Specifies the vertical interval of sub-windows. */ + NvU8 CoreLimit; /**< Top limit of noise coring for M4 statistics gathering. Valid range is [0-63]. */ + NvU8 reserved; +} GFISPM4WINDOW, *PGFISPM4WINDOW; + + +/** Enum for the Optical Black Mode. + @see GFISPOBCONTROL +*/ +typedef enum +{ + OB_MODE_FRAME = 0, + OB_MODE_AVG_FRAME_LINE = 1, + OB_MODE_LINE = 2 +} GFISP_OB_MODE_SEL; + + +/** Optical black control. + + The very first ISP operation to be applied to the input pixel signal is to + establish "black" level. This anchors signal activities to a black reference level, + or "zero" level. + + There are two methods of accomplishing optical blacking. One method is + performed on each frame and is called Frame-based Optical Blacking (FOB). + The other method is performed on each scan line and is called Line-based + Optical Blacking (LOB). + + Under FOB, optical black level can be established in one of two ways--by + setting it manually, or more commonly by letting the ISP measure it + automatically. In the automatic method the user can specify black regions + which surround the active imaging area. The pixel levels from these regions + are used to determine the input signal level of reference black, which is + mapped to "zero" level in the subsequent pixel processing. + + LOB is applied to each scan line and is used to detect and compensate for + fluctuations in the imager input signal level of reference black. + + The user can choose to use either FOB, or LOB, or both. + + Four optical black regions are defined through 16 coordinates. + + If ISP's OB capability is GFISP_CAP_THREE_OB_REGIONS, then: + - Only six of the 16 OB coordinates are used: + - OBTopRegionStartV, OBTopRegionHeight, + - OBLeftRegionStartH, OBLeftRegionWidth, + - OBBottomRegionStartV, OBBottomRegionHeight + - Right OB region is not supported. + - Top region width is assumed equal to input width. + - Left region height is assumed equal to input height. + - Bottom region width is assumed equal to input width. + - Bottom region is only used if GFISP_ATTR_ENABLE_FOB_SELFRESET is disabled. + + If ISP's OB capability is GFISP_CAP_FOUR_OB_REGIONS, then all sixteen + OB coordinates are used. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_FOB, GFISP_ATTR_ENABLE_FOB_SELFRESET, GFISP_ATTR_ENABLE_FOB_TEMPORAL, GFISP_ATTR_ENABLE_MANUALOB, GFISP_ATTR_ENABLE_LOB +*/ +typedef struct _GFISPOBCONTROL +{ + NvU32 OBTopRegionStartV, OBTopRegionHeight, OBTopRegionStartH, OBTopRegionWidth; + NvU32 OBBottomRegionStartV, OBBottomRegionHeight, OBBottomRegionStartH, OBBottomRegionWidth; + NvU32 OBLeftRegionStartV, OBLeftRegionHeight, OBLeftRegionStartH, OBLeftRegionWidth; + NvU32 OBRightRegionStartV, OBRightRegionHeight, OBRightRegionStartH, OBRightRegionWidth; + + NvU8 FOBCoef; /**< Filter coefficient of FOB acquisition. Valid range is [0-15]. */ + NvU8 TOBCoef; /**< Temporal filter coefficient of FOB temporal filter. Valid range is [0-15]. */ + + NvU8 LOBWidth; /**< Width used for LOB. Valid values are {2, 4, 8}. */ + + NvU8 FOBAdjust; /**< Manual adjustment applied to the black level. Valid range is [0, 63]. */ + GFISP_OB_MODE_SEL OBMode; /**< Optical black mode vales {frame, avg of frame + line, line } */ +} GFISPOBCONTROL, *PGFISPOBCONTROL; + + +/** This structure describes one approximated linear segment for deknee. + @see GFISPDEKNEECONTROL +*/ +typedef struct _GFISPDEKNEEENTRY +{ + NvU16 start; /**< Start of a range. */ + NvU16 slope; /**< Slope of the linear. Unsigned fixed point format. Valid range is [0, 3 63/64] with precision of 1/64. */ +} GFISPDEKNEEENTRY, *PGFISPDEKNEEENTRY; + +/** Deknee control. + + Imagers tend to show some degree of non-linearity in their light-to-electric + transfer characteristics. Deknee unit attempts to improve the linearity. + + NVIDIA ISP implements Deknee as a piece-wise linear approximation of up + to 16 segments. + + This structure describes the start and slope values for the Deknee look-up + table. The caller may choose to divide the table into 4, 8, or 16 linear segments + (4, 8, or 16 entries in the table). + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_DEKNEE +*/ +typedef struct _GFISPDEKNEECONTROL +{ + NvU32 nEntries; /**< Number of entries in the pEntry table. Valid values are {4,8,16}. */ + GFISPDEKNEEENTRY *pEntries; /**< Deknee entry table. */ +} GFISPDEKNEECONTROL, *PGFISPDEKNEECONTROL; + + +/** Lens shading compensation control. + + An optical lens in front of the imager tends to introduce shading and + unevenness in the strength of incident light. It is strongest at the center and + diminishes as the distance from the center increases. Actual shading + characteristics vary depending on the choice of optics. + + This structure describes a method for compensating for this shading by + applying varying levels of gain to the pixel signal in the reverse function of + the shading. + + The GFISPAPI implements this as a second degree quadratic equation for + each color component at H and V: + + F = 1 + X * (Coef1 + Coef2 *X) + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_LENS_SHADING +*/ +typedef struct _GFISPLENSHADING +{ + NvU16 hCenter, /**< Horizontal center point of camera lens. */ + vCenter; /**< Vertical center point of camera lens. */ + + NvU16 rHorzCoef1, /**< First order coefficient for Horizontal Red. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + rHorzCoef2; /**< Second order coefficient for Horizontal Red. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 rVertCoef1, /**< First order coefficient for Vertical Red. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + rVertCoef2; /**< Second order coefficient for Vertical Red. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 gHorzCoef1, /**< First order coefficient for Horizontal Green. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + gHorzCoef2; /**< Second order coefficient for Horizontal Green. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 gVertCoef1, /**< First order coefficient for Vertical Green. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + gVertCoef2; /**< Second order coefficient for Vertical Green. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 bHorzCoef1, /**< First order coefficient for Horizontal Blue. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + bHorzCoef2; /**< Second order coefficient for Horizontal Blue. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 bVertCoef1, /**< First order coefficient for Vertical Blue. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + bVertCoef2; /**< Second order coefficient for Vertical Blue. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ +} GFISPLENSSHADING, *PGFISPLENSSHADING; + + + +/** White balance control. + + White Values + + RGB component signal levels are balanced to render white objects as white. + This is a normalization step of electronic signal of RGB color primaries. + Depending on the "color temperature" of the white reference, the relative + strength of RGB tri-stimulus values vary. In the electric signal, ER/EG/EB + corresponding to the RGB tri-stimulus values are normalized so that white (of + 100% strength) is represented by ER = EG = EB = 1. The original image in front + of the imager is reproduced only when a display device does precise reverse + conversion, which is a purely ideal case. Otherwise, the original image is + rendered in different shades of colors depending on the reference white for + which the display device is tuned. + + Gray Values + + RGB pixel values that represent "gray" objects may be obtained in various + ways. For example, a picture frame can be filled with a "white" object, or + average values for a large number of pixels can be calculated, or a set of + average values collected in many sampling spotscan be used to represent the + approximated "gray" object. + + Gain Factors and White Balance + + Digital gain values are dedicated to each of the four color channels (R, Gr, Gb, + B). + + Depending on how to set gain factors, there are two ways to use White + Balance. A commonly used method is called Dynamic WB, or AWB. Under + AWB, gain values are updated automatically by ISP internal AWB control + based on the average values and peak values in {R, G1, G2, B} color channels. + Refer to #GFISP_PARA_M1WINDOW. + + - If the frame exposure is high ("Top" level, controlled by ThresholdT2M/ + ThresholdM2T), gains are calculated from the average RGrGbB values. + - If the frame exposure is low ("Bottom" level, controlled by + ThresholdM2B/ThresholdB2M), gains are calculated from peak + RGrGbB values. + - If the frame exposure is in the middle range, gains are calculated from + both average and peak values. + + Under AWB, the user can send a command to freeze the current gain value by + setting GFISP_ATTR_AWB_HOLD to 1. Then the current AWB gain value is + applied to all future frames. + + The other method is called pre-programmed WB or Static WB. It sets preprogrammed + gain values and applies them all time. Under this mode, the + programmer determines the proper gain values based on the M1/M3 + measurement window output. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_WB, GFISP_ATTR_ENABLE_AWB, + GFISP_ATTR_AWB_HOLD, GFISPM1WINDOW +*/ +typedef struct _GFISPWBCONTROL +{ + // Static WB. + NvU16 RGain, /**< Static gain factor for Red. Only effective when GFISP_ATTR_ENABLE_AWB==0. */ + GrGain, /**< Static gain factor for Green on Red. Only effective when GFISP_ATTR_ENABLE_AWB==0. */ + BGain, /**< Static gain factor for Blue. Only effective when GFISP_ATTR_ENABLE_AWB==0. */ + GbGain; /**< Static gain factor for Green on Blue. Only effective when GFISP_ATTR_ENABLE_AWB==0. */ + + // Both statis and auto WB. + NvU16 TopClipLimit; /**< Lower limit of gain based clipping. Effective for both Static WB and Auto WB. Value 0 effectively turns off Top-clipping. */ + + // Auto WB. + NvU16 PeakRef; /**< White reference level for gain adjustment. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + + NvU16 RGainMax, RGainMin; /**< Max/Min Gain factor for Red. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + NvU16 GGainMax, GGainMin; /**< Max/Min Gain factor for Green. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + NvU16 BGainMax, BGainMin; /**< Max/Min Gain factor for Blue. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + + NvU16 ThresholdT2M, /**< Top-to-Middle transition level. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + ThresholdM2T, /**< Middle-to-Top transition level. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + ThresholdM2B, /**< Middle-to-Bottom transition level. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + ThresholdB2M; /**< Bottom-to-Middle transition level. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + +} GFISPWBCONTROL, *PGFISPWBCONTROL; + + +/** Demosaic mode enum for #GFISPDEMOSAICCONTROL. +*/ +typedef enum +{ + GFISP_DM3X3 = 0, // 3x3 one-shot demosaicing + GFISP_DM3X3BPNR = 1, // 3x3 demosaicing/bad-pixel/noise-reduction + GFISP_DM5X5 = 2, // 5x5 one-shot demosaicing + GFISP_DM5X5BP = 3, // 5x5 demosaicing/bad-pixel + GFISP_DM5X5BPNR = 4 // 5x5 demosaicing/bad-pixel/noise-reduction +} GFISP_DEMOSAIC_MODE_SEL; + +/** Demosaic control. + + This structure controls the demosaic process, which uses 2D interpolation to + convert Bayer format R/G/B pixel signals obtained from the imager to + generate R/G/B component values. + + Under the SC15 hardware implementation, the Demosaic unit is built with + bad pixel (BP) and noise reduction (NR) control inside, so picking demosaic + mode affects bad pixel and noise reduction control. Unless limited by + memory bandwidth, programmers should always pick BPNR modes. Otherwise, BP + and NR features are not available, even if you try to turn on BP or NR + controls with GFISPSetAttribute(). + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_DEMOSAIC, + GFISPBADPIXELCONTROL, GFISPNOISECONTROL1 +*/ +typedef struct _GFISPDEMOSAICCONTROL +{ + GFISP_DEMOSAIC_MODE_SEL DemosaicMode; /**< Demosaic mode selection. */ +} GFISPDEMOSAICCONTROL, *PGFISPDEMOSAICCONTROL; + + +/** Coring limit scaling selection enum for #GFISPEDGEENHANCECONTROL. */ +typedef enum +{ + GFISP_GCLIMIT_SCALE_4 = 0, // range [1,4.5] + GFISP_GCLIMIT_SCALE_8 = 1, // range [1,8.5] + GFISP_GCLIMIT_SCALE_16= 2, // range [1,16.5] + GFISP_GCLIMIT_SCALE_32= 3 // range [1,32.5] +} GFISP_GCORINGLIMIT_SCALE_SEL; + +/** Edge enhancement control. + + This structure controls the edge enhancement process, accomplished by the + following: + -# Extracting the high frequency component (HF) of the pixel + -# Amplifying HF if the extracted value is "large" (that is, coring) + -# Adding the amplified HF back to the Y channel of the pixel. + + In the SC15 implementation, edge enhancement control resides in the + Demosaic unit. It is effective only if DM3X3BPNR, DM5X5NR, or DM5X5BPNR + demosaic mode is selected. The threshold that's used for coring is not a predetermined + fixed value, but instead is adaptive depending on the brightness + level. If the pixel surround is bright (more visible), the coring threshold will + be larger, which means only stronger edges are enhanced. Weaker edges are + considered more noise-prone and therefore are not enhanced. + + Two control parameters are used to determine the adaptive coring threshold: + GCoringLimit and GCoreScaleSel. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_EDGE_ENHANCE +*/ +typedef struct _GFISPEDGEENHANCECONTROL +{ + NvU16 StrengthLevel; /**< How heavily the edge enhancement is applied. Unsigned fixed-point format. Valid range is [0, 3 7/8] with a precision of 1/8, plus [4, 15 1/2] with a precision of 1/2. */ + + NvU16 GCoringLimit; /**< Minimum coring level. The coring level increases when the pixel's surrounding brightness level goes up. Valid range is [0-63]. */ + GFISP_GCORINGLIMIT_SCALE_SEL GCoringScaleSel; /**< Scaling factor of GCoringLimit. Specifies the influence of the brightness level to the coring level. The higher the GCoreScaleSel is, the larger the coring level grows under the same brightness. */ +} GFISPEDGEENHANCECONTROL, *PGFISPEDGEENHANCECONTROL; + + +/** Noise Reduction 1 control. + + There are two noise reduction functions in ISP datapath: + -# 3D noise reduction + -# False color reduction + + GFISPNOISECONTROL1 applies to the first method. + It resides in Demosaic unit along with edge enhancement. It is effective + only if DM3X3BPNR, DM5X5NR, or DM5X5BPNR demosaic mode is selected. + + This method reduces noise not only in the image plane but also in the + intensity domain. In other words, low pass filtering is applied to pixels that + have a similar pixel value and are also close to the same location. + FilterStrengthLevel defines the filter kernel size on the intensity + domain. Larger FilterStrengthLevel generates a smoother but blurry + image. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_NOISE_CONTROL1 +*/ +typedef struct _GFISPNOISECONTROL1 +{ + NvU16 FilterStrengthLevel; /**< Weighted average scaling factor. Valid range is [0,7]. */ +} GFISPNOISECONTROL1, *PGFISPNOISECONTROL1; + + +/** Noise Reduction 2 control. + + There are two noise reduction functions in ISP datapath: + -# 3D noise reduction + -# False color reduction + + GFISPNOISECONTROL2 applies to the second method. + It resides in color correction unit. + + This method reduces the colorfulness of pixels at shadow region or at edges + to de-emphasize color noise and color aliasing effects. HighLimit and + TransitionWidth specify the pixels that will undergo the color reduction. + If the luminance level of the pixel is larger than (HighLimit + + TransitionWidth), the pixel's colorfulness is intact. If the luminance level + is smaller than HighLimit, the colorfulness is reduced to a minimum (i.e., no + color correction is applied). Pixels with luminance levels between these limits + pass through an intermediate colorfulness reduction factor. CCScaleFactor + specifies how much color reduction should be applied at edge pixels. Larger + CCScaleFactor creates a more noticeable color reduction at the edges. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_NOISE_CONTROL2 +*/ +typedef struct _GFISPNOISECONTROL2 +{ + NvU16 HighLimit; /**< Upper-limit level of noise reduction curve. */ + NvU16 TransitionWidth; /**< Width of noise reduction curve. Valid values are {16, 32, 64, 128}. */ + NvU16 CCScaleFactor; /**< Slope of noise reduction curve. Unsigned fixed point format. Valid range is [0, 31]. */ +} GFISPNOISECONTROL2, *PGFISPNOISECONTROL2; + + + +/** Bad pixel control. + + This structure controls a method to conceal bad pixels. + + The process resides in the Demosaic unit along with edge enhancement + and noise control 1. It is effective only if DM3X3BPNR or DM5X5BPNR demosaic + mode is selected. + + If a pixel value deviates greatly from its surrounding pixels, the pixel is + considered to be a bad pixel. The deviation is defined in terms of the + percentage of the average value of the surrounding pixels. + + Two ratio coefficients are used: + - If the pixel is within a flat area, LowCoef is used, + - If the pixel is at an edge region, UpCoef is used. + If the average of the surrounding pixels is lower than DarkLevel, it is + considered to be at a shadow region, and DarkLevel instead of the average + value will be used to calculate the deviation threshold. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_BAD_PIXEL +*/ +typedef struct _GFISPBADPIXELCONTROL +{ + NvU16 DarkLevel; /**< Bad-pixel dark level. */ + NvU16 UpCoef, /**< Coefficient for upper threshold. Unsigned fixed point format. Valid range is [0, 1 7/8] with precision of 1/8. */ + LowCoef; /**< Coefficient for lower threshold. Unsigned fixed point format. Valid range is [0, 1 7/8] with precision of 1/8. */ +} GFISPBADPIXELCONTROL, *PGFISPBADPIXELCONTROL; + + +/** Color correction control. + + This structure controls the color correction process. + + In a strict sense, the color correction module transforms a given color space + (based on the optical characteristics of the imager) to a specific color space + such as described by the CCIR 601 standard. The color component signals are + then handled according to that standard color space from that point on. + + For high-end cameras, color correction is used to match some sensitive colors + such as flesh tone to a desired shade of colors, and is handled primarily by + experts who know what they are doing. + + In practice, there may be a simpler means with fewer control parameters, + where the color shade of images is adjusted to suit the viewer's taste. So, gain + and offset of R, G, and B pixels are individually adjusted. + + GFISP color correction consists of 3x3 matrix factors for the camera RGB + (cRGB) to standard RGB (sRGB) conversion. Subjective adjustment of color + can also be included. + - Coefficients on the main diagonal are unsigned. Valid range is [0, 7 255/256]. + - Off-diagonal coefficients are unsigned. Valid range is [-7 255/256, 7 255/256]. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_COLOR_CORRECTION +*/ +typedef struct _GFISPCOLORCORRECTION +{ + NvU16 R2R; /**< Red-to-red coefficient. Unsigned fixed point format. Valid range is [0, 7 255/256]. */ + NvS16 R2G; /**< Red-to-green coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvS16 R2B; /**< Red-to-blue coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvS16 G2R; /**< Green-to-red coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvU16 G2G; /**< Green-to-green coefficient. Unsigned fixed point format. Valid range is [0, 7 255/256]. */ + NvS16 G2B; /**< Green-to-blue coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvS16 B2R; /**< Blue-to-red coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvS16 B2G; /**< Blue-to-green coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvU16 B2B; /**< Blue-to-blue coefficient. Unsigned fixed point format. Valid range is [0, 7 255/256]. */ + NvS16 Vividity; /**< Multiplier to boost the diagonal elements. Signed fixed point format. Valid Range [-64/256, 64/256]. */ + NvS16 VividityScaleFactor; /**< Multiplier to boost the diagonal elements. Signed fixed point format. Valid Range [-OffDiagona/64, OffDiagonal/64]. */ + NvU16 GainStart; /**< Starting Gain for Auto Vividity . */ + NvU16 GainEnd; /**< End Gain for Auto Vividity. */ +} GFISPCOLORCORRECTION, *PGFISPCOLORCORRECTION; + + +/** This structure describes one approximated linear segment for gamma. + @see GFISPGAMMACONTROL +*/ +typedef struct _GFISPGAMMAENTRY +{ + NvU16 inputStart; /**< Input start value of line segment. Valid range is [0, 1023]. */ + NvU16 outputStart; /**< Output start value of line segment. Valid range is [0, 255]. */ + NvS16 slope; /**< Slope of the line segment. Signed fixed point format. Valid range is [-7 63/64, 7 63/64]. */ + NvU16 reserved; +} GFISPGAMMAENTRY, *PGFISPGAMMAENTRY; + +/** Gamma correction control. + + This structure controls the gamma correction process. + + Gamma correction applies non-linear characteristics to compensate for the + non-linear characteristics of display devices such as cathode ray tubes driven + by R, G, B primary color signals. So, in a strict sense, this must be applied to + R, G, B signals. + + In SC15 implementation, gamma correction is approximated using up to 16 + line segments. Each line entry must be provided in ascending order (within + the input range). + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_GAMMA_CORRECTION +*/ +typedef struct _GFISPGAMMACONTROL +{ + NvU32 nEntries; /**< Number of entries in the pEntries table. Valid range is [1-16]. */ + GFISPGAMMAENTRY *pEntries; /**< Gamma entry table. */ +} GFISPGAMMACONTROL, *PGFISPGAMMACONTROL; + + +/** Y signal range selection enum for #GFISPYUVCONVERSION. +*/ +typedef enum +{ + GFISP_YRANGE_FULL = 0, /**< Range of [0,255]. */ + GFISP_YRANGE_NEARFULL = 1, /**< Rage of [1,254] (exclude 00 and FF). */ + GFISP_YRANGE_ITU601 = 2 /**< ITU601 standard. */ +} GFISP_YRANGE_SEL; + +/** RGB to YUV conversion control. + This structure controls the YUV conversion process, which converts RGB + color space to corresponding YUV color space, based on the 3x3 matrix. + + {Y, U, V} shall have offset values that are not shown in the formula above. +*/ +typedef struct _GFISPYUVCONVERSION +{ + GFISP_YRANGE_SEL YRangeSel; /**< YUV output signal range. */ + NvS16 YOff; /**< Y value offset. Valid range is [-128, 127]. */ + + // 3x3 YUV conversion matrix. + // G2Y is unsigned fixed point format. Valid range is [0, 1 255/256]. + // R2Y and B2Y are unsigned fixed point format. Valid range is [0, 255/256]. + // R2U, G2U, B2U, R2V, G2V, B2V are signed fixed point format. + // Valid range is [-255/256, 255/256]. + NvS16 R2Y; /**< Red-to-Y coefficient. Unsigned fixed point format. Valid range is [0, 255/256]. */ + NvS16 G2Y; /**< Green-to-Y coefficient. Unsigned fixed point format. Valid range is [0, 1 255/256]. */ + NvS16 B2Y; /**< Blue-to-Y coefficient. Unsigned fixed point format. Valid range is [0, 1 255/256]. */ + NvS16 R2U; /**< Red-to-U coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 G2U; /**< Green-to-U coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 B2U; /**< Blue-to-U coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 R2V; /**< Red-to-V coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 G2V; /**< Green-to-V coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 B2V; /**< Blue-to-V coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ +} GFISPYUVCONVERSION, *PGFISPYUVCONVERSION; + +/** Isp set mode + This structure set ISP parameters to the specified mode, as specidied in the ISP script. +*/ +typedef struct _GFISPSETMODE +{ + NvS32 Mode; /**< Mode number. */ +} GFISPSETMODE, *PGFISPSETMODE; + +/** 3A AE parameter + These enum contains 3A AE control parameters. +*/ + +typedef enum +{ + GFISP_AE_FRAME_CHOICE_FIXED = 0, /**< fixed frame rate. At lowlux AE will use only digital gain to increase brightness */ + GFISP_AE_FRAME_CHOICE_FLEXIBLE = 1 /**< At lowlux AE will increase frame height first (i.e., lower frame rate) to increase brightness Frame height is bounded by FrameHeight at GFISP_AE_SENSORINFO. */ +}GFISP_AE_FRAME_CHOICE; + +typedef enum +{ + GFISP_AE_METERING_CHOICE_EVALUATIVE = 0, /**< calculate luminance average by propriotary algorithm */ + GFISP_AE_METERING_CHOICE_SPOT = 1, /**< calculate luminance average from center window only */ + GFISP_AE_METERING_CHOICE_CENTER = 2, /**< GFISP_AE_METERING_CHOICE_CENTER: calculate luminance average from weighted sum of center window and whole frame */ + GFISP_AE_METERING_CHOICE_MATRIX = 3 /**< calculate luminance average from weighted sum of 3x3 sub-windows */ +}GFISP_AE_METERING_CHOICE; + +typedef enum +{ + GFISP_AE_ANTIFLICKER_CHOICE_50HZ = 0, /**< use AEStep_50Hz in GFISP_AE_SENSORINFO as exposure steps */ + GFISP_AE_ANTIFLICKER_CHOICE_60HZ = 1, /**< use AEStep_60Hz in GFISP_AE_SENSORINFO as exposure steps */ + GFISP_AE_ANTIFLICKER_CHOICE_MANUAL = 2, /**< use ManualAntiFlickerStep in GFISP_AE_CONTROL1 as exposure steps */ + GFISP_AE_ANTIFLICKER_CHOICE_AUTO = 3 /**< enable auto anti-flickering */ +}GFISP_AE_ANTIFLICKER_CHOICE; + +/** 3A AE parameter + This structure contains 3A AE parameters. +*/ +typedef struct _GFISP3AAE +{ + NvU16 AETarget; /**< [0..255]. Target average luminance value for AE convergence. Higher value renders brighter image. */ + NvU16 AEToleranceIn; /**< [0..255]. Convergence tolerance from AESTATE_OUT to AESTATE_IN */ + NvU16 AEToleranceOut; /**< [0..255]. Convergence tolerance from AESTATE_OUT to AESTATE_IN. Normally AEToleranceOut >= AEToleranceIn */ + GFISP_AE_FRAME_CHOICE FrameRateChoice; /**< GFISP_AE_FRAME_CHOICE */ + GFISP_AE_METERING_CHOICE MeteringChoice; /**< GFISP_AE_METERING_CHOICE */ + GFISP_AE_ANTIFLICKER_CHOICE AntiFlickerChoice; /**< GFISP_AE_ANTIFLICKER_CHOICE */ + NvU8 ConvergeSpeed; /**< [1..15]. AE convergence speed. 1 being the fastest (immediate update) */ + NvS32 Status; /**< 3A AE Status. Read only */ + + NvU32 ManualAntiFlickerStep; // manual exposure step. Used when AntiFlickerChoice=GFISP_AE_ANTIFLICKER_CHOICE_MANUAL + NvS32 CenterWeight, FrameWeight; // weights for MeteringChoice=GFISP_AE_METERING_CHOICE_CENTER + NvS32 Metering11, Metering12, Metering13,// weights for MeteringChoice=GFISP_AE_METERING_CHOICE_MATRIX + Metering21, Metering22, Metering23, + Metering31, Metering32, Metering33; + NvU16 AdditionalLumaIncreaseForFlatScene;// [0..255]. give final exposure additional increase if scene is flat. + NvU16 BacklightTbright; // [0..255]. Threshold for determining "bright regions" (for backlight checking) + NvU16 BacklightTdark; // [0..255]. Threshold for determining "dark regions" (for backlight checking) + NvU16 TOverexposed; // [0..255]. Threshold for determining overexposed condition. + NvU16 TDark; // [0..255]. Threshold for determining dark condition. + NvU8 AutoNoiseControl; /**< Auto Noise Control */ +} GFISP3AAE, *PGFISP3AAE; + +/* Exposure parameter USED for Manual Exposure and Gain settings +*/ +typedef struct _GFISPEXPOSURECONTROL +{ + NvU32 MaxFrameHeight; // longest exposure time allowed. >= DefaultFrameHeight, in unit + // of per scanline. + // For constant framerate application, set MaxFrameHeight=FrameHeight. + + NvU32 DefaultFrameHeight; // sensor's default time difference betwee two consecutive VSYNC pulses, + // in unit of per scanline. + NvU32 DefaultFrameHeightIS; // Limit the frame height corresponding to ET of 1/60 sec + + NvU16 MaxGain; // [1..128]. max digital gains allowed. Normally set to 2 (=200%) + // if anti-flickering is on. If larger sensitivity boost is needed + // at lowlux condition set MaxGain to higher value. + NvU16 MinGain; //Minimum Exposure Gain in ISP Format + + NvU16 MaxGainIS; // max digital gain allowed in the case of image stabilization + +}GFISPEXPOSURECONTROL, *PGFISPEXPOSURECONTROL; + +/* Manual Exposure and Gain settings +*/ +typedef struct _GFISPMANUALEXPOSURE +{ + NvU32 Exposure; // exposure time + NvU32 Gain; // digital gain +}GFISPMANUALEXPOSURE, *PGFISPMANUALEXPOSURE; + + +/** 3A AWB parameter + This structure contains 3A AWB parameters. +*/ + +typedef enum +{ + GFISP_AWB_WBMODE_CLOUDY = 0, /**<: for cloudy conditions (7,000K - 8,000K) */ + GFISP_AWB_WBMODE_SUNNY = 1, /**<: for sunny conditions (5,500K - 6,000K) */ + GFISP_AWB_WBMODE_FLASH = 2, /**<: for strobe or xenon flashes (~5,000K) */ + GFISP_AWB_WBMODE_FLUORESCENT = 3, /**<: for indoor office conditions (~3,000K) */ + GFISP_AWB_WBMODE_INCANDESCENT = 4, /**<: for indoor home conditions (~2,800K) */ +}GFISP_AWB_WBCUSTOM; + +typedef enum +{ + GFISP_AWB_COPLEXITY_HIGH = 0, /***/ + GFISP_AWB_COPLEXITY_MEDIUM = 1, /***/ + GFISP_AWB_COPLEXITY_LOW = 2 /***/ +}GFISP_AWB_COMPLEXITY; + +typedef struct _GFISP3AAWB +{ + NvU8 fWBCustom; // =0 when WB Custom Setting OFF + // =1 when WB Custom Setting ON + GFISP_AWB_WBCUSTOM WBCustomK; // Choose one of the defined illum class when fWBCustom=1 + // GFISP_AWB_WBMODE_CLOUDY = 0, /**<: for cloudy conditions (7,000K - 8,000K) */ + // GFISP_AWB_WBMODE_SUNNY = 1, /**<: for sunny conditions (5,500K - 6,000K) */ + // GFISP_AWB_WBMODE_FLASH = 2 /**<: for strobe or xenon flashes (~5,000K) */ + // GFISP_AWB_WBMODE_FLUORESCENT = 3, /**<: for indoor office conditions (~3,000K) */ + // GFISP_AWB_WBMODE_INCANDESCENT = 4, /**<: for indoor home conditions (~2,800K) */ + // Must be < NumWBCustom + + GFISP_AWB_COMPLEXITY ComplexityMode; + NvS8 WBShift; /**< Moves up or down illuminant class. For white balance bracketing. */ + /**< timing and stability control */ + NvU8 ConvergeSpeed; /**< [0..6], 6 being the fastest (immediate update) */ + NvU8 ToleranceIn; /**< [0..255], tolerance for convergence. */ + NvU8 ToleranceOut; /**< [0..255], threshold for triggering new AWB update. Normally ToleranceIn < ToleranceOut, and both toelrances are small (e.g., 5 to 10). */ + NvU32 FilterCoefficient; /**< [0-20] Filter coefficient used for scene change detection . */ + NvU32 M3FilterCoefficient; /**< [0-60] Filter coefficient used for temporal low pass filtering of M3 Buffer . */ + NvU32 UseM3LPFilter; /**< Flag for M3 Low Pass Filter. 1 = Enable LPF, 0 = Disable */ + NvU32 KXYCorrelation; /**< To be used for scene change detection. */ + + NvS32 Status; /**< 3A AWB Status. Read only */ +} GFISP3AAWB, *PGFISP3AAWB; + +typedef enum +{ + GFISP_AFSTATE_IN = 0, + GFISP_AFSTATE_OUT = 1, + GFISP_AFSTATE_INIT = 2 +}GFISP_AF_STATE; + +typedef enum +{ + GFISP_AF_TYPE_CENTER = 1, + GFISP_AF_TYPE_AUTO_EVALUATE = 2, + GFISP_AF_TYPE_FACE_PRIORITY = 3 +}GFISP_AF_TYPE; + +typedef enum +{ + GFISP_AF_MODE_CONTINUOUS = 0, + GFISP_AF_MODE_SINGLE = 1 +}GFISP_AF_MODE; + +/** 3A AF parameter + This structure contains 3A AF parameters. +*/ +typedef struct _GFISP3AAF +{ + GFISP_AF_STATE Status; /**< 3A AF Status. Read only */ + GFISP_AF_MODE Mode; + NvU8 Speed; + NvU8 LockTillAE; + NvU8 LockTillAWB; + NvU8 TakeSnapshot; +} GFISP3AAF, *PGFISP3AAF; + +/** ISP 3A Capability. +To get the 3A capability for a particular sensor. +*/ +typedef struct _GFISPSENSORCAPABILITY +{ + NvU8 AWBCapability; /***/ + NvU8 AECapability; /***/ + NvU8 AFCapability; /***/ + NvU8 ManualOBCapability; /***/ + NvU8 AutoOBCapability; /***/ +}GFISPSENSORCAPABILITY, *PGFISPSENSORCAPABILITY; + + + +typedef enum +{ + GFISP_SENSOR_I2C_8_BIT_REGISTER = 0, + GFISP_SENSOR_I2C_16_BIT_REGISTER = 1, +} REGISTERTYPE; + +typedef struct _GFISPSENSORRWREGISTER +{ + REGISTERTYPE RegisterType; //0: 8-bit register , 1: 16-bit register + NvU32 Addr; /**< Address : data read-write address>*/ + NvU32 Data; /**< Value of data at that address >*/ +}GFISPSENSORRWREGISTER, *PGFISPSENSORRWREGISTER; + +/** 3A algorithm type + These enum contains 3A algorithm type required for checking convergence. +*/ +typedef enum +{ + GFISP_CB_REGISTER_3A_AWB = 0, + GFISP_CB_REGISTER_3A_AE = 1, + GFISP_CB_REGISTER_3A_AF = 2 +} GFISP3ATYPE; + +/** Enabling or disabling the "gain reduction and gamma compression" property for reducing noise introduced due to high gain +* in case of Image Stabilization. +*/ +typedef enum +{ + GFISP_REDUCE_GAIN_COMPRESS_GAMMA_ON, + GFISP_REDUCE_GAIN_COMPRESS_GAMMA_OFF +} GFISPGAINGAMMACTRL; +/** Public exposed ISP API function table. See @ref groupIspFunctions. */ +typedef struct _GFISPTABLE +{ + GF_RETTYPE (* ISPGetProperty) ( GFIspHandle ISPHandle, PGFISPPROPERTY pIspProp ); + +#if defined(DVS_DEVELOPMENT) + GF_RETTYPE (* ISPSetup) ( GFIspHandle ISPHandle, GFVxHandle VxHandle, PGFCAMERARESOLUTIONTYPE pCameraResolution, GFVXBLT vxBlt ); +#else + GF_RETTYPE (* ISPSetup) ( GFIspHandle ISPHandle, PGFCAMERARESOLUTIONTYPE pCameraResolution ); +#endif + + GF_RETTYPE (* ISPSetResolution) ( GFIspHandle ISPHandle, PGFCAMERARESOLUTIONTYPE pCameraResolution ); + + GF_RETTYPE (* ISPGetAttribute) ( GFIspHandle ISPHandle, + GFISPATTRIBUTES aid, + NvU32 *attr); + GF_RETTYPE (* ISPSetAttribute) ( GFIspHandle ISPHandle, + GFISPATTRIBUTES aid, + NvU32 attr); + + GF_RETTYPE (* ISPSetAttributeToDefault) (GFIspHandle ISPHandle, GFISPATTRIBUTES aid); + + GF_RETTYPE (* ISPGetParameter) ( GFIspHandle ISPHandle, + GFISPPARAMETERS pid, + NvU32 *pSize, + void *pPara); + GF_RETTYPE (* ISPSetParameter) ( GFIspHandle ISPHandle, + GFISPPARAMETERS pid, + NvU32 size, + void *pPara); + + GF_RETTYPE (* ISPSetParameterToDefault) (GFIspHandle ISPHandle, GFISPPARAMETERS pid); + + GF_RETTYPE (* ISPTriggerMWindowGather) (GFIspHandle ISPHandle); + + GF_RETTYPE (* ISPReadMWindowValues) ( GFIspHandle ISPHandle, + NvS32 szM1Buffer, + NvU32 *pM1Buffer, + NvS32 szM2Buffer, + NvU32 *pM2Buffer, + NvS32 szM3Buffer, + NvU32 *pM3Buffer, + NvS32 szM4Buffer, + NvU32 *pM4Buffer); + + GF_RETTYPE (* ISPOEMScriptFunc) (GFIspHandle ISPHandle, + NvU32 ScriptFuncTag, + NvU32 size, + NvU32 *pBuffer); + + GF_RETTYPE (* ISP3APeriodicTrigger)(GFIspHandle ISPHandle); + + GF_RETTYPE (* ISPAeBracketingSetET) (NvS32 mode, NvU32 *pRetExposure, NvS32 *pRetGain); + + GF_RETTYPE (* ISPAwbBracketingSetIllum) (NvS32 mode, NvU16 *pRetCCT); + + GF_RETTYPE (* ISPRegister3ACallback) (GFIspHandle ISPHandle, GFISP3ATYPE type, void (*func)(void *), void *pParameter); + +} GFISPTABLE, *PGFISPTABLE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFIspOpen(GFRmHandle hRm, GFIspHandle *phIsp, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFIspClose(GFIspHandle *phIsp); + +/** @defgroup groupIspFunctions ISP Function macros + These function macros represent the function calls for GFISPAPI. +*/ +/*@{*/ + +/** Returns information about the GFISPAPI. + + @param handle Valid handle to GFISPAPI component. + @param pIspProp Pointer to a #GFISPPROPERTY struct. + For the sake of future expansion, the caller should put the size of + the structure into the #GFISPPROPERTY::size field; GFISPAPI will not + fill the structure beyond this size. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_SIZE_TOO_SMALL Error: size parameter is too small to fit even partial results. + + This function returns information about the GFISPAPI, including the + following: + - GFISPAPI module version + - ISP capability + - ISP limit parameters + It is good practice to use this function to query for the API version and + capabilities before using other GFISPAPI functions. + + @see GFISPPROPERTY, groupIspCapability +*/ +#define GFISPGetProperty( handle, pIspProp ) \ + ((PGFISPTABLE)handle)->ISPGetProperty( handle, pIspProp ) + +/** Sets up the ISP API for use with a particular camera. + + @param handle Valid handle to GFISPAPI component. + @param pCameraResolution Pointer to a #GFCAMERARESOLUTIONTYPE structure + with valid BayerInfo. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + + You must call GFISPGetProperty before calling any other ISP API functions, + with the exception of GFISPGetProperty. This function initializes ISP + to work with a particular resolution of camera. + +*/ +#if defined(DVS_DEVELOPMENT) +#define GFISPSetup( handle, vxhandle, pCameraResolution, vxBlt ) \ + ((PGFISPTABLE)handle)->ISPSetup( handle, vxhandle, pCameraResolution, vxBlt ) +#else +#define GFISPSetup( handle, pCameraResolution ) \ + ((PGFISPTABLE)handle)->ISPSetup( handle, pCameraResolution ) +#endif + +/** Resizes/repositions all windows based on resolution data. + + @param handle Valid handle to GFISPAPI component. + @param pCameraResolution Pointer to a #GFCAMERARESOLUTIONTYPE structure + with valid BayerInfo. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + This function resizes and repositions the windows for several ISP parameters + based on the provided BayerInfo struct. Affected parameters are: + - Timing + - M1-M4 statistics windows + - Optical black regions + - Lens shading center point + +*/ +#define GFISPSetResolution( handle, pCameraResolution ) \ + ((PGFISPTABLE)handle)->ISPSetResolution( handle, pCameraResolution ) + +/** Get an attribute of the GFISPAPI. + + @param handle Valid handle to GFISPAPI component. + @param aid Attribute ID. One of #GFISPATTRIBUTES enumeration type. + @param pAttrData Pointer to an #NvU32 to be filled with the attribute value. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPATTRIBUTES +*/ +#define GFISPGetAttribute( handle, aid, pAttrData ) \ + ((PGFISPTABLE)handle)->ISPGetAttribute( handle, aid, pAttrData ) + +/** Set an attribute of the GFISPAPI. + + @param handle Valid handle to GFISPAPI component. + @param aid Attribute ID. A #GFISPATTRIBUTES enumeration type value. + @param attrData Pointer to an #NvU32 to be filled with the attribute value. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + Under the NVIDIA ISP implementation, certain ISP functions can be turned + on or off independent of parameter settings. In most cases, this function + simply switches certain ISP functions on or off. + + To set parameters for specific ISP functions, see GFISPSetParameter(). + + @see GFISPATTRIBUTES +*/ +#define GFISPSetAttribute( handle, aid, attrData ) \ + ((PGFISPTABLE)handle)->ISPSetAttribute( handle, aid, attrData ) + +/** Set an attribute of the GFISPAPI to its default value. + + @param handle Valid handle to GFISPAPI component. + @param aid Attribute ID. A #GFISPATTRIBUTES enumeration type value. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPATTRIBUTES +*/ +#define GFISPSetAttributeToDefault( handle, aid ) \ + ((PGFISPTABLE)handle)->ISPSetAttributeToDefault( handle, aid ) + +/** Get parameters for a given ISP functional block. + + @param handle Valid handle to GFISPAPI component. + @param pid Parameter ID. A #GFISPPARAMETERS enumeration type value. + @param pSize Pointer to an #NvU32 to be filled with the parameter size. Can be NULL. + @param pPara Pointer to a certain GFISPAPI data structure, depending on #pid. Can be NULL. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPPARAMETERS +*/ +#define GFISPGetParameter( handle, pid, pSize, pPara ) \ + ((PGFISPTABLE)handle)->ISPGetParameter( handle, pid, pSize, pPara ) + +/** Set parameters for a given ISP functional block. + + @param handle Valid handle to GFISPAPI component. + @param pid Parameter ID. A #GFISPPARAMETERS enumeration type value. + @param size #NvU32 with actual size of GFISPAPI structure pointed to by #pPara. + @param pPara Pointer to a certain GFISPAPI data structure, depending on #pid. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_SIZE_TOO_SMALL #size parameter is too small + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPPARAMETERS +*/ +#define GFISPSetParameter( handle, pid, size, pPara ) \ + ((PGFISPTABLE)handle)->ISPSetParameter( handle, pid, size, pPara ) + +/** Set parameters for a given ISP functional block to their default value. + + @param handle Valid handle to GFISPAPI component. + @param pid Parameter ID. A #GFISPPARAMETERS enumeration type value. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPPARAMETERS +*/ +#define GFISPSetParameterToDefault( handle, pid ) \ + ((PGFISPTABLE)handle)->ISPSetParameterToDefault( handle, pid ) + +/** Triggers MWindow statistics to be gathered on the next frame. + + @param handle Valid handle to GFISPAPI component. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + This function will trigger MWindow statistics to be gathered for + any of the M2, M3, M4 statistics that are turned on. M1 statistics + are constantly gathered. The statistics will become available at + the end of the next frame, and can be read by calling + GFISPReadMWindowValues(). + + Calling GFISPTriggerMWindowGather implicitly sets + #GFISP_ATTR_ENABLE_STATS_INT to 1. + + @see GFISPReadMWindowValues +*/ +#define GFISPTriggerMWindowGather( handle ) \ + ((PGFISPTABLE)handle)->ISPTriggerMWindowGather( handle ) + +/** Reads gathered MWindow statistics if they are ready. + + @param handle Valid handle to GFISPAPI component. + @param szM1Buffer Maximum size of M1Buffer provided by caller (in bytes). The + GFISPAPI fills the buffer as much as it can. If zero, the GFISPAPI + doesn't fill the M1Buffer. + @param pM1Buffer Array of 8 data. First four 32-bit values will be filled with average + RGGB pixel values. Next four values will be filled with peak pixel values. + Can be NULL, then the GFISPAPI doesn't fill M1Buffer. + @param szM2Buffer Maximum size of M2Buffer provided by caller (in bytes). The + GFISPAPI fills the buffer as much as it can. If zero, the GFISPAPI + doesn't fill the M2Buffer. + @param pM2Buffer Array of 16 data. Data is arranged in 32-bit words as follows: + {R1, Gr1, Gb1, B1, + R2, Gr2, Gb2, B2, ...} + Can be NULL, then the GFISPAPI doesn't fill M2Buffer. + @param szM3Buffer Maximum size of M3Buffer provided by caller (in bytes). The + GFISPAPI fills the buffer as much as it can. If zero, the GFISPAPI + doesn't fill the M3Buffer. + @param pM3Buffer Array to hold pixel samples. The size matches the M3 Window specification. + The data is arranged as follows: + {R1, R2, R3, R4}, + {Gr1, Gr2, Gr3, Gr4}, + {Gb1, Gb2, Gb3, Gb4}, + {B1, B2, B3, B4}, + {R5, R6, R7, R8}, + ... + Can be NULL, then the GFISPAPI doesn't fill M3Buffer. + @param szM4Buffer Maximum size of M4Buffer provided by caller (in bytes). The + GFISPAPI fills the buffer as much as it can. If zero, the GFISPAPI + doesn't fill the M4Buffer. + @param pM4Buffer Array of 2*M4WindowNumber data. Data is arranged as follows: + {HF1, Luma1, HF2, Luma2, ...} + Can be NULL, then the GFISPAPI doesn't fill M4Buffer. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_STATISTICS_NOT_READY M2/M3/M4 statistics not ready. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + Call this function to read the MWindow values gathered by the last call to + GFISPTriggerMWindowGather(). The user may either poll for statistics ready + by checking the return code, or use the interrupt mechanism to only call + GFISPReadMWindowValues once the statistics are ready. + + After the statistics are gathered, they will remain available for reading + until the next call to GFISPTriggerMWindowGather(). + + M1 statistics are gathered every frame regardless of whether + GFISPTriggerMWindowGather() has been called. The user can read + the last frame's M1 statistics without ever triggering a gather by + passing 0 and NULL for the M2-M4 parameters to GFISPReadMWindowValues(). + + @see GFISPTriggerMWindowGather +*/ +#define GFISPReadMWindowValues( handle, szM1Buffer, pM1Buffer, \ + szM2Buffer, pM2Buffer, szM3Buffer, pM3Buffer, szM4Buffer, pM4Buffer ) \ + ((PGFISPTABLE)handle)->ISPReadMWindowValues( handle, szM1Buffer, pM1Buffer, \ + szM2Buffer, pM2Buffer, szM3Buffer, pM3Buffer, szM4Buffer, pM4Buffer ) + +/** Call Oem function defined in ISP script. + + @param handle Valid handle to GFISPAPI component. + @param ScriptFuncTag Function tag used by the script. + @param size Number of entries in the buffer pointed to by #pBuffer. + @param pBuffer Point to a @param #NvU32 buffer that will be passed to script function. + Use it to send parameter to script function and get data back. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + Call this function to access script function OemScriptFunc(). +*/ +#define GFISPOEMScriptFunc( handle, ScriptFuncTag, size, pBuffer ) \ + ((PGFISPTABLE)handle)->ISPOEMScriptFunc( handle, ScriptFuncTag, size, pBuffer ) + +/** Trigger periodic software 3A function. + + @param handle Valid handle to GFISPAPI component. + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + Call this function at every vertical blank to trigger periodic software 3A function +*/ +#define GFISP3APeriodicTrigger( handle ) \ + ((PGFISPTABLE)handle)->ISP3APeriodicTrigger( handle ) + +/** Exposure Bracketing Function + @param handle Valid handle to GFISPAPI component + @param mode Range: 0 Exposure value output by AC Algo + -1 Less by one-third stop than AC Output + 1 More by one-third stop than AC Output + @param.pRetExpsoure Expsoure at current mode is returned through this pointer + @param pGain Gain at current mode is returned through this pointer + @retval GF_SUCCESS or GF_ERROR + + Call this function three times with different modes each time in order to record images with exposure bracketing +*/ +#define GFISPAeBracketingSetET(handle, mode, pRetExposure, pRetGain) \ + ((PGFISPTABLE)handle)->ISPAeBracketingSetET( mode, pRetExposure, pRetGain ) + +/** White Balance Bracketing Function + @param handle Valid handle to GFISPAPI component + @param mode Range: 0 Exposure value output by AC Algo + -1 Less by one Illuminant than AC Output + 1 More by one Illuminant than AC Output + @param pRetCCT Color Temprature at current mode is returned through this pointer + @retval GF_SUCCESS or GF_ERROR + + Call this function three times with different modes each time in order to record images with White Balance bracketing +*/ +#define GFISPAwbBracketingSetIllum(handle, mode, pRetCCT) \ + ((PGFISPTABLE)handle)->ISPAwbBracketingSetIllum( mode, pRetCCT ) + +/** Register callback function for the convergence of software Auto White balance + + @param handle Valid handle to GFISPAPI component. + @param algoType whether AWB, AE or AF + @param func Pointer to the callback function + @param pParameter pointer to the argument of function call + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR If invalid function pointer is passed + + Call this function when application wants to know whether the auto white balance algorithm is converged or not. + When algorithm converges it calls the function func which is registered as callback function. +*/ +#define GFISPRegister3ACallback(handle, algoType, func, pParameter) \ + ((PGFISPTABLE)handle)->ISPRegister3ACallback( handle, algoType, func, pParameter ) + +/*@}*/ // End function macros + +/*@}*/ // End ISP API Doxygen + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GF_ISP__ */ diff --git a/Start_WM/test6/inc/GFIspError.h b/Start_WM/test6/inc/GFIspError.h new file mode 100755 index 00000000..4f173424 --- /dev/null +++ b/Start_WM/test6/inc/GFIspError.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFIspError.h + * GFSDK Image Signal Processor API error code header file. + */ + +#ifndef __GFISPERROR_H__ +#define __GFISPERROR_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define GFISP_ERROR_ILLEGAL_PARAMETER (GFISP_ERROR | 0x00000001L) +#define GFISP_ERROR_BAD_HANDLE (GFISP_ERROR | 0x00000002L) +#define GFISP_ERROR_SIZE_TOO_SMALL (GFISP_ERROR | 0x00000003L) +#define GFISP_ERROR_STATISTICS_NOT_READY (GFISP_ERROR | 0x00000004L) +#define GFISP_ERROR_CALL_SETUP_FIRST (GFISP_ERROR | 0x00000005L) +#define GFISP_ERROR_OUT_OF_MEMORY (GFISP_ERROR | 0x00000006L) + +#ifdef __cplusplus +} +#endif + +#endif // __GFISPERROR_H__ + + + diff --git a/Start_WM/test6/inc/GFJxDec.h b/Start_WM/test6/inc/GFJxDec.h new file mode 100755 index 00000000..879f10ed --- /dev/null +++ b/Start_WM/test6/inc/GFJxDec.h @@ -0,0 +1,508 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFJxDec.h +GFSDK JPEG Decode API header file. +*/ +#ifndef _GF_JPEG_DEC__ +#define _GF_JPEG_DEC__ + +#include "nvtypes.h" +#include "GFVx.h" + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif + +/** @addtogroup groupJx JxDecAPI JPEG Decoder API +*/ + /*
        +
      • @ref pageGxAppNotes +
          +
        • @ref pageGxAppNotes1 +
        +
      + */ + +/*@{*/ + +// JXDECCapFlags + +/** JxDecAPI property flag: Support for Sequential encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_SEQUENTIAL_DCT 0x00000001 + +/** JxDecAPI property flag: Support for Progressive encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_PROGRESS_DCT 0x00000002 + +/** JxDecAPI property flag: Support for lossless encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_LOSSLESS 0x00000004 + +/** JxDecAPI property flag: Support for hierarchical encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_HIERARCHICAL 0x00000008 + +/** JxDecAPI property flag: Support for 8 bits encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_8_BIT 0x00000010 + +/** JxDecAPI property flag: "No" Support for 12 bits encoded JPEG Presently. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_12_BIT 0x00000020 + +/** JxDecAPI property flag: Support for Interleaved mode. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_INTERLEAVE 0x00000040 + +/** JxDecAPI property flag: "No" Support presently for Interleaved mode. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_NO_INTERLEAVE 0x00000080 + +/** JxDecAPI property flag: Support for Huffman Coding. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_HUFFMAN 0x00000100 + +/** JxDecAPI property flag: No Support for Arithematic Coding presently. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_ARITHMETIC 0x00000200 + +/** JxDecAPI property flag: No Support for Interchange format coding. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_INTERCHANGE 0x00000400 + +/** JxDecAPI property flag: Support for Pixel Based Cropping(MCU based Cropping). + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_CROPPING 0x00001000 + +/** JxDecAPI property flag: Support for YUV444 encoded JPEG images. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_YUV444 0x00002000 + +/** JxDecAPI property flag: Support for YUV422 encoded JPEG images. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_YUV422 0x00004000 + +/** JxDecAPI property flag: YUV422 Rotation Supported. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_ROTATED_YUV422 0x00008000 + +/** JxDecAPI property flag: Support for YUV420 encoded JPEG images. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_YUV420 0x00010000 + +/** JxDecAPI property flag: Support for Gray Scale encoded JPEG images. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_GRAY_SCALE 0x00020000 + +/** JxDecAPI property flag: Support for Extended RGB format 24/32 bpp. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_EXTEND_RGB 0x00040000 + +/** JxDecAPI property flag: Support for YUV420 output decoded format. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_420_OUTPUT 0x00080000 + +/** JxDecAPI property flag: Support for YUV422 output decoded format. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_422_OUTPUT 0x00100000 + +/** Image source dimensions and color format of the input JPEG to be decoded. + This structure is passed as parameter to GFJxDecGetImageInfo(). + + @see GFRMSURFACE::ColorFormat, GFJxDecGetImageInfo() +*/ +typedef struct _GFJXDECIMAGEINFO +{ + NvU32 IIFlag; /**< Deprecated, do not use. + This variable is set to the same error code as returned by GFJxDecGetImageInfo(). + @deprecated + */ + NvU32 Width; /**< Width of the input image */ + NvU32 Height; /**< Height of the input image */ + NvU32 ColorFormat; /**< Color Format of input image (YUV420, YUV422, ...) + @see GFRMSURFACE.ColorFormat */ +}GFJXDECIMAGEINFO, *PGFJXDECIMAGEINFO; + +/** GFJxDecStart parameter structure. + This structure specifies target surface, scaling, source + and destination cropping for the decode operation. + + @see GFJxDecStart() +*/ +typedef struct _GFJXDECSTART +{ + NvU32 SFlag; /**< Deprecated, do not use. @deprecated */ + PGFRMSURFACE pDestSurf; /**< Destination Surface to hold the decoded image. + The color format of the surface controls the output color format. + If no destination cropping rectangle is given, the decoded picture + is scaled to match the surface size. + */ + PGFRECT pCroppingRect; /**< Source cropping area to be decoded, or NULL for no cropping. + Top-left position of the cropping rectangle must be aligned + to an MCU boundary. + */ + PGFRECT pDestRect; /**< Destination cropping area, or NULL for no cropping. + If a destination cropping rectangle is given, the decoded picture + will be scaled to fit this rectangle. + */ + NvU32 Error; /**< Deprecated, do not use. + This variable will be set to the same value as returned by GFJxDecStart(). + @deprecated + */ +} GFJXDECSTART, *PGFJXDECSTART; + + +//SFlag: not used anymore. Cropping is decided on whether +//the pCroppingRect is NULL or not +#define GF_JXDEC_SFLAG_CROPPING 0 + +/** GF_DECODER_IDLE is returned if hardware decoder is idle by GFJxDecGetStatus(). + @see GFJxDecGetStatus() +*/ +#define GF_DECODER_IDLE 0x00000001 + +/** GF_DECODER_BUSY is returned if hardware decoder is busy by GFJxDecGetStatus(). + @see GFJxDecGetStatus() +*/ +#define GF_DECODER_BUSY 0x00000002 + + +/** JxDecAPI Pass JX_DEC_SET_READBITSTREAM to GFJxDecSet to register call back function +@see GFJxDecSet() +*/ +#define JX_DEC_SET_READBITSTREAM 1 + +/** Structure holding the callback function pointer. + Used in registering the callback function +*/ +typedef struct _GFJXDECCALLBACK +{ + void *pPara; /**< Not used anymore */ + NvU32 (*pCallBack)(void * pPara, NvU8 ** ppBuffer, NvS32 * BufferLength); + /**< + Application callback function pointer. + Register a callback function for fetching JPEG Image data. + + @param *pPara Not used anymore + @param ppBuffer Buffer Pointer + @param BufferLength Buffer Length in bytes, 0 if no bytes read. + + @retval The number of bytes read successfully, 0 if no bytes read. + */ + +}GFJXDECCALLBACK, *PGFJXDECCALLBACK; + +/** Structure holding the callback function pointer. + Used in registering the callback function +*/ +typedef struct _GFJXDECGETIMAGECALLBACK +{ + void *pPara; + /**< pPara is a parameter passed from application, + and application wants API to call back with this parameter + */ + NvU32 (*pCallBack)(void * pPara, PGFRMSURFACE pImageSurf, PGFRECT pImageRect, NvU32 uiImageFlag); + /**< + Application callback function pointer. + Register a callback function for fetching decoded JPEG Image data. + + @param *pPara Parameter to pass on to application callback function + @param pImageSurf Surface Pointer + @param pImageRect Source rectangle + @param uiImageFlag + + + +
      #JX_DEC_IF_LAST_PORTION_IMAGEThis is the last portion of decoded image
      + @retval 0 + */ +}GFJXDECGETIMAGECALLBACK, *PGFJXDECGETIMAGECALLBACK; + + +/** This is the last portion of the Image. + @see GFJXDECGETIMAGECALLBACK +*/ +#define JX_DEC_IF_LAST_PORTION_IMAGE 0x00000001 //this is the last portion of decoded image + +//Attribute uiFeature + +/** Set get decoded image call back(inorder to dump the decoded YUV from JPEG). + @see GFJXDECGETIMAGECALLBACK, GFJxDecGetImageInfo +*/ +#define JX_DEC_GETIMAGE 0x00000001 + +/** Pass JX_DEC_GETIMAGE_COLORFORMAT with GFJxDecGetAttribute to get JPEG image color format. */ +#define JX_DEC_GETIMAGE_COLORFORMAT 0x00000002 + + +/** Call this function get the JxDec Component's handle. + @param hRm (#GFRmHandle) Handle to the Resource Manager + @param phJxDec (#GFJxDECHandle) Pointer to the JxDecAPI Handle + @param state Set to Default state. + @param hCh (#GFRmChHandle) Channel Handle + @retval #GF_SUCCESS JxDec component registered successfully + @retval #GF_ERROR Some error occured +*/ +GF_RETTYPE GFJxDecOpen(GFRmHandle hRm, GFJxDecHandle *phJxDec, GF_STATE_TYPE state, GFRmChHandle hCh); + + +/** The function releases the JxDec's Component handle. + @param phJxDec (#GFJxDECHandle) Pointer to the JxDecAPI Handle +*/ +void GFJxDecClose(GFJxDecHandle *phJxDec); + +/** This function returns version and capabilities of JPEG decoder. + + @param hJxDec Handle to JxDecAPI + @param pJXProp Pointer to property structure to be filled in + + @retval #GF_SUCCESS \a pJXProp filled in successfully + @retval #GF_ERROR Some error occured + + @see GFPROPERTY +*/ +GF_RETTYPE GFJxDecGetProperty(GFJxDecHandle hJxDec, PGFPROPERTY pJXProp); + +/** This function returns the status of the JPEG Decoder + + @param hJxDec Handle to JxDecAPI + @param pStatus Returns status, GF_DECODER_BUSY or GF_DECODER_IDLE. +*/ +GF_RETTYPE GFJxDecGetStatus(GFJxDecHandle hJxDec, NvU32* pStatus); + +/** The funtion gets the information about the input image and fills it into the pInfo + + If the function fails, it will return an error code describing the failure cause. + + @param hJxDec Handle to JxDecAPI + @param pInfo Pointer to Image Information structure to be filled in + + @retval GF_SUCCESS \a pInfo filled in successfully + @retval GF_JXDEC_IFLAG_INVALID_MARKER Invalid Marker in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_HDR_LEN Invalid header (marker) length in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_SIG Invalid Image Signature(eg: JFIF, AVI, ..) in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_DQT Invalid Quantization Table in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_DHT Invalid Huffman Tables in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_VALUE Invalid image parameters (eg: width, height , ...) in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_FORMAT Invalid format in JPEG file + @retval GF_JXDEC_IFLAG_PROGRESSIVE_MARKER Invalid Marker in JPEG file + @see GFJXDECIMAGEINFO +*/ +GF_RETTYPE GFJxDecGetImageInfo(GFJxDecHandle hJxDec, PGFJXDECIMAGEINFO pInfo); + +/** This function sets up a callback function + @param hJxDec Handle to JxDecAPI + @param uiFeature Feature ID to set + @param pInfo Feature specific parameter + + + + + + + + +
      \a uiFeature\a pInfo interpretationMeaning
      JX_DEC_SET_READBITSTREAMGFJXDECCALLBACK*Set up Jpeg bitstream feed callback
      + + @retval #GF_SUCCESS If successful + @retval #GFJXD_ERROR_INVALID_PARAMETER Invalid parameter + + @see GFJXDECCALLBACK +*/ +GF_RETTYPE GFJxDecSet(GFJxDecHandle hJxDec, NvU32 uiFeature, void* pInfo); + +/** Set attributes for the decoder. + @param hJxDec Handle to JxDecAPI, + @param attrID Attribute ID to be set + @param pInfo Attruvyte specific parameter + + + + + + +
      #JX_DEC_GETIMAGE Get the YUV decoded JPEG image into a file, Sets the decoder image callback
      #JX_DEC_GETIMAGE_COLORFORMAT Set get decoded image color format.
      + + @retval #GF_SUCCESS +*/ +GF_RETTYPE GFJxDecSetAttribute(GFJxDecHandle hJxDec, NvU32 attrID, NvU32* pInfo); + +/** Gets attributes for the decoder + @param hJxDec Handle to JxDecAPI, + @param attrID Attribute ID to read + @param pInfo Pointer to block returning attribute specific data + + + + + +
      #JX_DEC_GETIMAGE Get the YUV decoded JPEG image into a file, Sets the decoder image callback
      #JX_DEC_GETIMAGE_COLORFORMAT Set get decoded image color format.
      +*/ +GF_RETTYPE GFJxDecGetAttribute(GFJxDecHandle hJxDec, NvU32 attrID, NvU32* pInfo); + +/** Setup JxDecAPI for JPEG decoding a frame. + + If GFJxDecStart() fails, it will return an error code describing the failure cause. + If GFJxDecStart() succeeded, GFJxDecEnd() must be called later. + + @param hJxDec Handle to JxDecAPI + @param pStart Pointer to #GFJXDECSTART parameter structure. + + @retval GF_SUCCESS Success + @retval GFRM_ERROR_OUT_MEMORY Not enough free GPU or system memory + @retval GF_JXDEC_NOT_SUPPORT_DESTSURFACE_FORMAT Destination Surface format not supported by the decoder + @retval GF_JXDEC_DECODER_WIDTH_TOO_BIG Image source width exceeds max decoder width + @retval GF_JXDEC_DECODER_HEIGHT_TOO_BIG Image source height exceeds max decoder height + + @see GFJXDECSTART, GFJxDecSetAttribute(),GFJxDecEnd() +*/ +GF_RETTYPE GFJxDecStart(GFJxDecHandle hJxDec, PGFJXDECSTART pStart); + +/** Decode the image + @param hJxDec Handle to JxDecAPI + @param uiFlag Reserved, must be 0. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see GFJxDecGetImageInfo(), GFJxDecStart(), GFJxDecSetAttribute(), GFJxDecEnd() + +*/ +GF_RETTYPE GFJxDecDecodeImage(GFJxDecHandle hJxDec, NvU32 uiFlag); + +/** End or cancel decoding a frame. + Must be called only, if GFJxDecStart() has been called before. + @param hJxDec Handle to JxDecAPI +*/ +GF_RETTYPE GFJxDecEnd(GFJxDecHandle hJxDec); + + +/** GFJxDecAPI Error Codes. */ +enum +{ + /** GFJxDecAPI API called with invalid parameters. */ + GFJXD_ERROR_INVALID_PARAMETER = GFJXD_ERROR, + + /** Operation not supported. */ + GFJXD_ERROR_NOT_SUPPORTED, + + /** Encountered incomplete bitstream during decoding. */ + GFJXD_ERROR_INCOMPLETE_BITSTREAM, + + /** GFJxDecStart() return code: Can't support this destination surface type. + @see GFJXDECSTART, GFJxDecStart() + */ + GF_JXDEC_NOT_SUPPORT_DESTSURFACE_FORMAT, + + /** GFJxDecStart() return code: Image width is too big for hardware decoder to handle + @see GFJXDECSTART, GFJxDecStart() + */ + GF_JXDEC_DECODER_WIDTH_TOO_BIG, + + /** GFJxDecStart() return code: Image height is too big for hardware decoder to handle + @see GFJXDECSTART, GFJxDecStart() + */ + GF_JXDEC_DECODER_HEIGHT_TOO_BIG, + + /** GFJxDecGetImageInfo() return code: If set then the input marker is Invalid, + if unset its a valid marker. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_MARKER, + + /** GFJxDecGetImageInfo() return code: If set then the Header Length is Invalid, + if unset its a valid header length. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_HDR_LEN, + + /** GFJxDecGetImageInfo() return code: If set then the Signature(eg: JFIF, AVI, ..) is Invalid, + if unset its a valid signature. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_SIG, + + /** GFJxDecGetImageInfo() return code: If set then the there occured an error in reading the Quantization Table, + if unset the Quantization Table was read clean. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_DQT, + + /** GFJxDecGetImageInfo() return code: If set then the Huffman Tables were not loaded properly + if unset Huffman Tables were loaded. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_DHT, + + /** GFJxDecGetImageInfo() return code: If set then there was an invalid value(eg : erroneous/incomplete bitstream) in the stream, + if unset its a valid Iflag. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_VALUE, + + /** GFJxDecGetImageInfo() return code: If set then the progressive marker not supported, + if unset its a valid marker. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + + GF_JXDEC_IFLAG_PROGRESSIVE_MARKER, + /** GFJxDecGetImageInfo() return code: If set then there was an invalid header format encountered in the stream, + if unset its a valid Iflag. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_FORMAT +}; + + +/** @page pageJxDecAppNotes JxDecAPI Application Notes + @section pageJxDecAppNotes Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start GFSDK usage. + -# Call GFJxDecOpen() to obtain JxDecHandle which will be passed to different functions of JxDecAPI. + -# Query the properties through GFJxDecGetProperty() to check whether the desired JxDec features can be supported. + -# Call GFRmSurfaceAlloc() to allocate one surface to hold the decoded image. + -# Register the call back function using GFJxDecSet() + -# Call GFJxDecGetImageInfo() to get the JPEG image information, such as width and height. + -# GFJxDecStart() is the next function to call. This function will setup the decoder. + -# Call GFJxDecDecodeImage() to do the real decoding. + -# After the whole bitstream has been fed, call GFJxDecEnd() to end the decoding process. + -# Release surface by calling GFRmSurfaceFree(). + -# Release JPEG decoder by calling GFJxDecClose(). +*/ + +/*@}*/ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/Start_WM/test6/inc/GFJxEnc.h b/Start_WM/test6/inc/GFJxEnc.h new file mode 100755 index 00000000..c5170b44 --- /dev/null +++ b/Start_WM/test6/inc/GFJxEnc.h @@ -0,0 +1,1306 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFJxEnc.h + GFSDK JPEG Encode API header file. +*/ + +#ifndef _GF_JPEG_ENC__ +#define _GF_JPEG_ENC__ + +#include "GF.h" +#include "GFRm.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupJxEnc JxEncAPI JPEG Encoder API +
        +
      • @ref pageJxEncAppNotes +
          +
        • @ref pageJxEncAppNotes1 +
        +
      +*/ +/*@{*/ + +/** JxEncAPI property flag: JPEG quantization table is programmable. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_QTABLE 0x00000001 + +/** JxEncAPI property flag: Interrupt data capture mode and polling mode + supported, if this flag is off then only polling mode is supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_INTERRUPT 0x00000004 + +/** JxEncAPI property flag: Digital zoom supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_DIGITAL_ZOOM 0x00000008 + +/** JxEncAPI property flag: Motion JPEG mode supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_MOTION_JPEG 0x00000010 + +/** JxEncAPI property flag: Rate control supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_RATE_CONTROL 0x00000020 + +/** JxEncAPI property flag: Planar YUV422 data supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_422_PLANAR 0x00000040 + +/** JxEncAPI property flag: Rotation supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_ROTATION 0x00000080 + + +/** Image source/target dimensions and data source for JPEG encoding. + + This structure is passed as parameter to GFJxEncStart() and describes + data source, source cropping rectangle and destination image size. + + The surface the application wants to encode is pSrcSurf. If the application + wants to encode an image from a camera or to re-encode a JPEG bitstream, + this field should be set to NULL. If the application wants to encode an + image from the display, this field should point to the primary surface. If + an application wants to encode an existing image, it must create a system + memory surface to hold the image and set this field to the system memory + surface. + + @see GFJxEncStart() +*/ +typedef struct _GFJXENCSTART +{ + PGFRMSURFACE pSrcSurf;/**< Surface to encode, + NULL for camera or re-encode JPEG + */ + PGFRECT pSrcRect; /**< Source image area need to encode */ + NvU32 DestWidth; /**< Final encoded image width */ + NvU32 DestHeight; /**< Final encode image height */ + NvU32 uiOptions; /**< Bitmask of flags to control encoding + + + + + + + +
      #GF_CAPT_BITSTREAM If set only bitstream is output, if + unset JFIF header will be added
      #GF_CAPT_PIECE_MEALPiecemeal encoding @todo clarify + meaning
      + */ + NvU32 Error; /**< Returns detailed error code on GFJxEncStart() failure + + + + + + + +
      #GF_CAPT_ERROR_VIDEO_MEMORY_NOT_BIG_ENOUGHNot enough free video memory, try to release + unnecessary video surfaces
      #GF_CAPT_ERROR_WRONG_CONFIGWrong input parameters, for example srcRect + size greater than pSrcSurf dimensions
      #GF_CAPT_ERROR_NO_CALLBACKNo callback function available
      + */ +} GFJXENCSTART, *PGFJXENCSTART; + +/** JxEncAPI GFJXENCSTART::uiOptions flagbit: If set only bitstream is output, + if unset JFIF header will be added. + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_BITSTREAM 1 + +/** JxEncAPI GFJXENCSTART::uiOptions flagbit: Piecemeal encoding + @todo clarify meaning + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_PIECE_MEAL 2 + +/** JxEncAPI GFJXENCSTART::Error return code: Not enough free video memory. + Try to release unnecessary video surfaces. + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_ERROR_VIDEO_MEMORY_NOT_BIG_ENOUGH 1 + +/** JxEncAPI GFJXENCSTART::Error return code: Wrong input parameters. + E.g. srcRect size greater than pSrcSurf dimensions. + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_ERROR_WRONG_CONFIG 2 + +/** JxEncAPI GFJXENCSTART::Error return code: No callback function available. + @todo clarify + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_ERROR_NO_CALLBACK 4 + +/** Descriptor for JPEG encode buffers. + This structure describes a buffer and its fill status for encoded + JPEG data or raw YUV transfered from the JPEG encoder to the + application. It is used with GFJxEncCapture() and GFJxEncFetchImage() + in either polling or callback data fetch mode. + + @see GFJxEncCapture(), GFJxEncFetchImage(), GFJxEncPRComplete() +*/ +typedef struct _GFJXENC_BUF { + NvU8 *pBuf; /**< Pointer to the buffer */ + NvU32 bufSize; /**< Size of the buffer in bytes */ + NvU32 nBytesCaptured; /**< Number of bytes captured, + app initializes to 0 + */ +} GFJXENC_BUF, *PGFJXENC_BUF; + +/** Fetch buffer descriptor for use with GFJxEncFetchImage(). + This data structure is used by GFJxEncInterruptHandler() to fetch encoded + image data when IntType is GFJX_ENC_STREAM_BUF_INTR or GFJX_ENC_DONE_INTR. +*/ +typedef struct _GFJXENC_FETCH_BUF{ + PGFJXENC_BUF pBuf; + NvU32 numOfBuf; + NvU32 status; +} GFJXENC_FETCH_BUF, *PGFJXENC_FETCH_BUF; + + +/** JxEncAPI data fetch status code: All data of the current frame was fetched. + @see GFJxEncFetchImage(), GFJxEncCapture() +*/ +#define JXENC_DATA_COMPLETE 0x1 + +/** JxEncAPI data fetch status code: Data was fetched only partially. + The application should make more calls to GFJxEncFetchImage() to fetch + the rest. + @see GFJxEncFetchImage(), GFJxEncCapture() +*/ +#define JXENC_MORE_FETCH 0x2 + +/** JxEncAPI data fetch status code: New frame was encoded and is ready to + fetch. + @see GFJxEncFetchImage(), GFJxEncCapture() +*/ +#define JXENC_NEW_FRAME 0x8 + +/** JxEncAPI data fetch status code: Time out error occured while encoded data is fetching. + fetch. + @see GFJxEncFetchImage(), GFJxEncCapture() +*/ +#define JXENC_TIME_OUT 0x10 + +// definition of uiFeature for GFJxEncSetAttribute +//the following definations are for set only + +/** JxEncAPI attribute: Choose preset QTable, coefficients in luma and chroma + Qtable are all 1. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_100QUALITY 0 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable A and B, + divided by 2. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_85QUALITY 1 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable A and B. + + Interpretation of associated data block: None. + + Attribute is set-only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_75QUALITY 2 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable C and D. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_50QUALITY 3 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable C and D, + multiplied by 2. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_25QUALITY 4 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable C and D, + multiplied by 4. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_12QUALITY 5 + +//the following definations can be used for set and get + +/** JxEncAPI attribute: Set custom luma QTable. + + Interpretation of associated data block: + A table of 64 16-bit (type NvU16) entries with quantization coefficients + to be used for luma MCU's. + + Attribute can be set and get. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_LQTABLE 6 + +/** JxEncAPI attribute: Set custom chroma QTable. + + Interpretation of associated data block: + A table of 64 16-bit (type NvU16) entries with quantization coefficients + to be used for chroma MCU's. + + Attribute can be set and get. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_CQTABLE 7 + +/** JxEncAPI attribute: Decimation filter enable/disable. + + Interpretation of associated data block: +
      +    NvU32 decimation enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_FILTER 8 + +/** JxEncAPI attribute: Huffman bit stuffing. + + Interpretation of associated data block: +
      +    NvU32 Huffman stuffing enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_HUFF_BSTUFF 13 + +/** JxEncAPI attribute: Motion JPEG capturing mode enable/disable. + + Interpretation of associated data block: +
      +    NvU32 Motion JPEG capturing mode enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_MOTION_JPEG 14 + +/** JxEncAPI attribute: Raw data capturing mode enable/disable. + + Interpretation of associated data block: +
      +    NvU32 Raw data capturing mode enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_RAW_DATA 15 + +/** JxEncAPI attribute: Re-encode a JPEG bitstream. + + Registration of callback function for JPEG re-encode application: +
      +    #PGFJXDECCALLBACK structure
      +    
      + + Attribute is set only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_BITSTREAM 16 + +/** JxEncAPI attribute: JPEG encoding colour format. + + Only YUV420 and YUV422 encoding is supported. The JPEG encoder converts + the incoming image to the configured colour format, and then encodes it + in the JPEG bitstream. + + Only YUV420 and YUV422 are + valid. + + Interpretation of associated data block: +
      +    NvU32 Colour format identifier, one of:
      +          #GF_SURFACE_PLANAR_YUV422
      +          #GF_SURFACE_YUV420
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute(), GFRMSURFACE::ColorFormat +*/ +#define JX_ENC_ENCODE_FORMAT 17 + +/** JxEncAPI attribute: Maximum JPEG byte size. + + The JPEG encoder will not generate a JPEG bitstream larger than this. + + Interpretation of associated data block: +
      +    NvU32 Maximum size in bytes
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_MAX_SIZE 18 + +/** JxEncAPI attribute: Camera focal point. + + Image area which is close to the focal point will be encoded with higher + quality. Takes effect only when #JX_ENC_MAX_SIZE is set. + + Interpretation of associated data block: +
      +    NvU32 Focal point X position
      +    NvU32 Focal point Y position
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute(), #JX_ENC_DEGRADATION, + #JX_ENC_MAX_SIZE +*/ +#define JX_ENC_FOCAL_POINT 19 + +/** JxEncAPI attribute: Image quality degradation from focal point. + + Image areas further from the focal point get encoded with fewer bits. + The number of bits is linearly degraded based on the percentage of + degradation in the X and Y directions. This attribute takes effect only + when JX_ENC_MAX_SIZE is set. + + Interpretation of associated data block: +
      +    NvU32 X direction degradation percentage
      +    NvU32 Y direction degradation percentage
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute(), #JX_ENC_FOCAL_POINT, + #JX_ENC_MAX_SIZE +*/ +#define JX_ENC_DEGRADATION 20 + +/** JxEncAPI attribute: JPEG encode rotation and flip control. + + Interpretation of associated data block: +
      +    NvU32 Rotation and flip control, one of the following constants
      +            #JX_ENC_ROTATE_0
      +            #JX_ENC_ROTATE_90
      +            #JX_ENC_ROTATE_180
      +            #JX_ENC_ROTATE_270
      +          optionally logically ORed with zero or more of the following flags
      +            #JX_ENC_H_FLIP
      +            #JX_ENC_V_FLIP
      +    
      + + Default is #JX_ENC_ROTATE_0. + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATION 21 + +/** JxEncAPI attribute: Rotation and flip control for rartial rotation API. + + Enables and configures the partial rotation engine for partially rotated + JPEG encoding. Partially rotated JPEG encoding allows for rotated encoding + of large image sizes with a small image capture buffer. + + Interpretation of associated data block: +
      +    NvU32 Rotation and flip control, one of the following constants
      +            #JX_PRENC_ROTATE_UNSET - reset and disable partial rotation engine
      +            #JX_ENC_ROTATE_0
      +            #JX_ENC_ROTATE_90
      +            #JX_ENC_ROTATE_180
      +            #JX_ENC_ROTATE_270
      +          if not #JX_PRENC_ROTATE_UNSET optionally logically ORed with zero or
      +          more of the following flags
      +            #JX_ENC_H_FLIP
      +            #JX_ENC_V_FLIP
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_PARTIAL_ROTATE 22 + +/** JxEncAPI attribute: Bypass FIFO. + + Interpretation of associated data block: +
      +    NvU32 Raw data capturing mode enable
      +          0 = Fetching encoded data through DMA FIFO
      +          1 = Fetching encoded data directly through output buffer not through
      +              DMA FIFO
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_BYPASS_FIFO 23 + +/** JxEncAPI attribute: Piece-Meal encoding. + + Interpretation of associated data block: +
      +    NvU32 Piece-Meal encoding enable
      +          0 = enable
      +          1 = disable
      +    
      + + Attribute is get only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_PIECE_MEAL 24 + +/** JxEncAPI attribute: Fetch Low bitstream. + + Registration of callback function for fetching raw data stream from JPEG encoder: +
      +    #PGFJXDECCALLBACK structure
      +    
      + + Attribute is set only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ + +#define JX_ENC_RAW_DATA_STREAM 25 + +/** JxEncAPI attribute: Fetch Low JPEG bitstream. + + Registration of callback function for fetching JPEG raw data stream from JPEG encoder: +
      +    #PGFJXDECCALLBACK structure
      +    
      + + Attribute is set only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ + +#define JX_ENC_RAW_JPEG_CAPTURE 26 + +/** JxEncAPI attribute: Set Timeout value + + + Interpretation of associated data block: +
      +    NvU32 timeout   timeout value
      +        0       = no timeout
      +        > 0     = timeout value
      +    
      + + Attribute is set only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ + +#define JX_ENC_TIMEOUT_CONF 27 + +/** JxEncAPI attribute: Stop preview enable/disable. + + Interpretation of associated data block: +
      +    NvU32 Stop preview mode enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ + +#define JX_ENC_STOP_PREVIEW 28 + + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + Non-rotated JPEG encode. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ + +#define JX_ENC_ROTATE_0 0x0 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode rotated 90 degrees. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATE_90 0x1 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode rotated 180 degrees. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATE_180 0x2 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode rotated 270 degrees. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATE_270 0x3 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode horizontally flipped. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_H_FLIP 0x10 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode vertically flipped. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_V_FLIP 0x20 + +/** Option for attribute #JX_ENC_PARTIAL_ROTATE: Reset and disable partial + rotation. + Pass this to GFJxEncSetAttribute() for attribute #JX_ENC_PARTIAL_ROTATE + to unset the Partial Rotation Flag and reset the PR Engine. + @see #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATE_UNSET 0xff + +typedef void (*GFJX_ENC_CALLBACK)(void *userData); + +/** JxEncAPI interrupt operation types. + Constants to specify operation for a call to GFJxEncInterruptControl(). + @see GFJX_ENC_INTERRUPT_TYPE, GFJxEncInterruptControl() +*/ +typedef enum +{ + /** Enable interrupt/status assertion for an interrupt type. */ + GFJX_ENC_INTERRUPT_ENABLE, + + /** Disable interrupt/status assertion for an interrupt type. */ + GFJX_ENC_INTERRUPT_DISABLE, + + /** Clear interrupt/status assertion for an interrupt type. */ + GFJX_ENC_INTERRUPT_CLEAR, + + /** Query for interrupt/status assertion for an interrupt type. */ + GFJX_ENC_INTERRUPT_QUERY_STATUS, + + /** Set DMA FIFO threshold. */ + GFJX_ENC_INTERRUPT_SET_DMA_FIFO_THRESHOLD, + + /** Get DMA FIFO threshold. */ + GFJX_ENC_INTERRUPT_GET_DMA_FIFO_THRESHOLD, + + /** Set strean buffer threshold. */ + GFJX_ENC_INTERRUPT_SET_BUF_THRESHOLD, + + /** Get strean buffer threshold. */ + GFJX_ENC_INTERRUPT_GET_BUF_THRESHOLD + +} GFJX_ENC_INTERRUPT_OPERATION_TYPE; + + +/** JxEncAPI interrupt types. + @see GFJX_ENC_INTERRUPT_OPERATION_TYPE, GFJxEncInterruptControl() +*/ +typedef enum +{ + /** JPEG read DMA FIFO low threshold. + Interrupt/status is asserted if the JPEG read DMA FIFO status is less + than the JPEG read DMA FIFO threshold value. + */ + GFJX_ENC_DMA_FIFO_LOW_INTR = 0, + + /** JPEG read DMA FIFO high threshold. + Interrupt/status is asserted if the JPEG read DMA FIFO status is + greater than or equal to the JPEG read DMA FIFO threshold value. + */ + GFJX_ENC_DMA_FIFO_HIGH_INTR = 0x1, + + /** Stream buffer threshold interrupt. */ + GFJX_ENC_STREAM_BUF_INTR = 0x2, + + /** Main buffer end hit interrupt. */ + GFJX_ENC_MAIN_BUF_HIT_INTR = 0x4, + + /** Encoding done interrupt. */ + GFJX_ENC_DONE_INTR = 0x8, + + /** Encoded stream transfer done interrupt. */ + GFJX_ENC_TRANSFER_DONE_INTR = 0x10, + + /** Maximum bit count hit interrupt. */ + GFJX_ENC_MAX_BIT_HIT_INTR = 0x20, + + /** Circular buffer overflow interrupt. */ + GFJX_ENC_CIR_BUF_OVERFLOW_INTR = 0x40 + +} GFJX_ENC_INTERRUPT_TYPE; + +/** JxEncAPI virtual function pointer table. */ +typedef struct _GFJXENCTABLE +{ + GF_RETTYPE (* JxEncGetProperty)(GFJxEncHandle hJxEnc, PGFPROPERTY pJXProp); + GF_RETTYPE (* JxEncSetAttribute)(GFJxEncHandle hJxEnc, + NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* JxEncGetAttribute)(GFJxEncHandle hJxEnc, + NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* JxEncStart)(GFJxEncHandle hJxEnc, PGFJXENCSTART pStart); + GF_RETTYPE (* JxEncFetchImage)(GFJxEncHandle hJxEnc, + PGFJXENC_BUF aBuf, NvU32 nBuf, NvU32 *pStatus); + GF_RETTYPE (* JxEncEnd)(GFJxEncHandle hJxEnc); + GF_RETTYPE (* JxEncSetupInterrupt)(GFJxEncHandle hJxEnc, + void (*Inter)(void *), void *IPara); + GF_RETTYPE (* JxEncCapture)(GFJxEncHandle hJxEnc, + PGFJXENC_BUF aBuf, NvU32 nBuf, NvU32 *pStatus); + GF_RETTYPE (* JxEncInterruptControl)(GFJxEncHandle hJxEnc, + GFJX_ENC_INTERRUPT_TYPE IntType, GFJX_ENC_INTERRUPT_OPERATION_TYPE op, + void * pData); + GF_RETTYPE (* JxEncInterruptHandler)(GFJxEncHandle hJxEnc, + GFJX_ENC_INTERRUPT_TYPE IntType, void * pData); // Reserved. + GF_RETTYPE (*JxEncPRComplete)(GFJxEncHandle hJxEnc, + PGFJXENC_BUF inBuf,NvU32 inBufNum,PGFJXENC_BUF outBuf, + NvU32 outBufNum,PGFJXENC_BUF dcacBuf,NvU32 dcacBufNum); + GF_RETTYPE (*JxEncBracket)(GFJxEncHandle hJxEnc, + GFJX_ENC_CALLBACK before, + GFJX_ENC_CALLBACK after, + void *userData); +} GFJXENCTABLE, *PGFJXENCTABLE; + +#ifdef PROJECT_SEC_G1 +// Attribute constant and data structure for EXIF +#define JX_ENC_SET_EXIF_INFO 30 + +typedef struct _GFJXENCEXIFINFO +{ + NvS8 CameraMaker[32]; + NvS8 CameraModel[40]; + NvS8 FirmwareVersion[5]; + NvU32 FNumberNum; + NvU32 FNumberDenom; + NvS32 ExpBiasNum; + NvS32 ExpBiasDenom; + NvU16 WhiteBalance; + NvU32 DigitalZoomNum; + NvU32 DigitalZoomDenom; +} GFJXENCEXIFINFO; +#endif + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFJxEncOpen(GFRmHandle hRm, GFJxEncHandle *phJxEnc, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFJxEncClose(GFJxEncHandle *phJxEnc); + +/* #### JxEnc Helper macros. Maybe useful for backward compatible API. #### */ + +/** @name Functions +@{*/ + +/** This function returns version and capabilities of API and hardware. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param pJXProp (PGFPROPERTY) Pointer to property structure to be filled in + + @retval #GF_SUCCESS \a pJXProp filled in successfully + @retval #GF_ERROR Some error occured + + The #GFPROPERTY structure passed with parameter \a pJXProp will be + filled in on successfull return. The GFPROPERTY::Capability field + will hold a combination of flagbits indicating capabilities specific + to the JxEncAPI: + + + + + + + + + + + + + + + + +
      #GF_JX_ENC_CAP_QTABLE JPEG quantization table is programmable.
      #GF_JX_ENC_CAP_INTERRUPT Interrupt data capture mode and polling mode supported, + if this flag is off then only polling mode is supported.
      #GF_JX_ENC_CAP_DIGITAL_ZOOMDigital zoom supported.
      #GF_JX_ENC_CAP_MOTION_JPEG Motion JPEG mode supported.
      #GF_JX_ENC_CAP_RATE_CONTROLRate control supported.
      #GF_JX_ENC_CAP_422_PLANAR Planar YUV422 data supported.
      #GF_JX_ENC_CAP_ROTATION Rotation supported.
      + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the JxEncAPI functions. + + @see GFPROPERTY +*/ +#define GFJxEncGetProperty(hJxEnc, pJXProp) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncGetProperty(hJxEnc, pJXProp) + +/** Set configuration of a feature of the JPEG encoder hardware. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param uiFeature (NvU32) Feature type identifier, see table. + @param pInfo (NvU32*) Pointer to feature specific input parameter block. + Pointer type will be reinterpreted according to + feature type. + + @retval #GF_SUCCESS Configuration changed successfully + @retval #GF_ERROR Some error occured + + The feature to be set is identified with parameter \a uiFeature, + specific input parameters are passed via a block in parameter \a pInfo. + The contents of this data block is interpreted depending on the + feature to be set. + + The following features are defined, for the data to be provided in + \a pInfo see the individual attribute's documentation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      \b Attribute \b Direction \b Synopsis
      #JX_ENC_SET_100QUALITYset Choose preset QTable, coefficients in luma + and chroma Qtable are all 1.
      #JX_ENC_SET_85QUALITY set Choose preset QTable, standard Qtable A and B, + divided by 2.
      #JX_ENC_SET_75QUALITY set Choose preset QTable, standard Qtable A and B.
      #JX_ENC_SET_50QUALITY set Choose preset QTable, standard Qtable C and D.
      #JX_ENC_SET_25QUALITY set Choose preset QTable, standard Qtable C and D, + multiplied by 2.
      #JX_ENC_SET_12QUALITY set Choose preset QTable, standard Qtable C and D, + multiplied by 4.
      #JX_ENC_LQTABLE set, getSet custom luma QTable.
      #JX_ENC_CQTABLE set, getSet custom chroma QTable.
      #JX_ENC_FILTER set, getDecimation filter enable/disable.
      #JX_ENC_HUFF_BSTUFF set, getHuffman bit stuffing.
      #JX_ENC_MOTION_JPEG set, getMotion JPEG capturing mode enable/disable.
      #JX_ENC_RAW_DATA set, getRaw data capturing mode enable/disable.
      #JX_ENC_BITSTREAM set Re-encode a JPEG bitstream.
      #JX_ENC_ENCODE_FORMAT set, getJPEG encoding colour format.
      #JX_ENC_MAX_SIZE set, getMaximum JPEG byte size.
      #JX_ENC_FOCAL_POINT set, getCamera focal point.
      #JX_ENC_DEGRADATION set, getImage quality degradation from focal point.
      #JX_ENC_ROTATION set, getJPEG encode rotation and flip control.
      #JX_ENC_PARTIAL_ROTATEset, getRotation and flip control for Partial Rotation API.
      #JX_ENC_BYPASS_FIFO set, getBypass FIFO.
      #JX_ENC_PIECE_MEAL get Piece-Meal encoding.
      #JX_ENC_STOP_PREVIEW set, getStop preview mode enable/disable.
      #JX_ENC_RAW_JPEG_CAPTURE set Fetch Low JPEG bitstream.
      #JX_ENC_RAW_DATA_STREAM set Fetch Low bitstream.
      #JX_ENC_TIMEOUT_CONF set, getSet Timeout value.
      + + Most of the time an application should only set a quantization table for + luminance or chrominance. These quantization tables are in the same format + as standard quantization tables (1 to 255). Other features are hardware + dependent. + + @see GFJxEncGetAttribute() +*/ +#define GFJxEncSetAttribute(hJxEnc, uiFeature, pInfo) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncSetAttribute(hJxEnc, uiFeature, pInfo) + +/** Get current configuration of a feature of the JPEG encoder hardware. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param uiFeature (NvU32) Feature type identifier, + see table in GFJxEncSetAttribute(). + @param pInfo (NvU32*) Pointer to feature specific input parameter block. + Pointer type will be reinterpreted according to + feature type. + + @retval #GF_SUCCESS \a pInfo filled in successfully + @retval #GF_ERROR Some error occured + + @see GFJxEncSetAttribute() +*/ +#define GFJxEncGetAttribute(hJxEnc, uiFeature, pInfo) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncGetAttribute(hJxEnc, uiFeature, pInfo) + +/** Setup JxEncAPI for JPEG encoding. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param pStart (#PGFJXENCSTART) Pointer to #GFJXENCSTART structure for + definition of encode source and destination + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured, check GFJXENCSTART::Error for + detailed error reason code. + + Before starting capture, the application should call this function to setup + the encoder. Once this function has been called, the application can use + GFJxEncCapture() to capture as many frames as desired. JxEncCapture() + starts and optionally fetches data for a frame. JxEncFetchImageData() + fetches the image data to host CPU side. An application should keep calling + it until all encoded data is processed. Finally GFJxEncEnd() has to be + called to release the encoder. + + Parameter \a pStart passes a #GFJXENCSTART structure describing image data + source, source cropping area, and destination size. + + Encoding is from one of the following sources: + - VI (Camera, cropping and scale up/down is done via VxVIPSet(), + Rotation/flip is done via JxEncSelectEPPRotation() ) + - Screen encoding (GC, source is primary surface) + - Bitstream encoding. This is used to re-encode a JPEG bit stream, and + invokes JxDecAPI internally to decode the existing bitstream. + The following options are available for bitstream re-encoding: + - Crop image size + - Scale up + - Change QTables + - Apply rate control + - Rotation (0, 90, 180, 270, H-Flip, V-Flip) + + On failure an error reason code is returned in field GFJXENCSTART::Error of + parameter \a pStart. + + @see GFJXENCSTART, GFJxEncSetAttribute(), GFJxEncCapture(), + GFJxEncFetchImage(), GFJxEncEnd() +*/ +#define GFJxEncStart(hJxEnc, pStart) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncStart(hJxEnc, pStart) + +/** Polls JxEncAPI for data fetch from JPEG encoder. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param aBuf (#PGFJXENC_BUF) Pointer to array of #GFJXENC_BUF structures + @param nBuf (NvU32) Number of pointers passed with \a aBuf. + @param pStatus (NvU32) Returns data fetch status, see table + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Captures the JPEG encoded bit stream in the given application owned + buffers. Capturing the encoded image can be done in polling or interrupt + mode. This function should be called after GFJxEncCapture(). It is usually + called from either the application's fetching poll loop, or the interrupt + callback routine set up with GFJxEncSetupInterrupt(). + + The application must fill all the fields in the referenced buffer + structures and must make sure each PGFJXENC_BUF::nBytesCaptured is set + to 0. The PGFJXENC_BUF::nBytesCaptured field is updated by the JXEncAPI + to show the actual number of bytes captured. JXEncAPI keeps filling the + buffers in the array until it exhausts all the buffers. If all the buffers + are exhausted and there is more data to be copied, the function returns + and sets \a pStatus to #JXENC_MORE_FETCH. The application should then keep + calling GFJxEncFetchImage() to fetch the remaining data. Each buffer in + the array should be a multiple of 64 bytes for best performance. + + The status of the data fetch is returned in \a pStatus as one of the + following reason codes: + + + + + + +
      #JXENC_DATA_COMPLETEAll data of the current frame was + fetched.
      #JXENC_MORE_FETCH Data was fetched only partially. + The application should make more calls to GFJxEncFetchImage() to + fetch the rest.
      #JXENC_NEW_FRAME A new frame was encoded and is ready + to fetch.
      #JXENC_TIME_OUT Timeout on GFJxEncFetchImage +
      + + @see GFJxEncCapture(), GFJxEncSetupInterrupt(), #GFJXENC_BUF +*/ +#define GFJxEncFetchImage(hJxEnc, aBuf, nBuf, pStatus) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncFetchImage(hJxEnc, aBuf, nBuf, pStatus) + +/** Polls JxEncAPI for data fetch from JPEG encoder. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function disables the encoder and releases internal resources related + to the current capture. + + @see GFJxEncStart() +*/ +#define GFJxEncEnd(hJxEnc) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncEnd(hJxEnc) + +/** Register a callback function for fetching encoded JPEG data. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param Inter (void(*)(void *)) Application callback function pointer + @param IPara (void*) Parameter to pass on to application callback function + + @retval #GF_SUCCESS Callback installed successfully + @retval #GF_ERROR Some error occured + + This function can be used to register a callback function for fetching + encoded JPEG data. This function must be called before GFJxEncCapture(). + The callback function must meet the following prototype: + +
      +    void InterruptCallback(void* lPara);
      +    
      + + Whenever encoding is triggered, JXEncAPI calls the registered interrupt + callback function, passing on the application defined parameter \a IPara. + + Inside the callback function, the application can call GFJxEncFetchImage() + to portionally fetch the encoded datastream. + + If no callback function shall be used, the application could alternatively + use a polling scheme. + + @see GFJxEncCapture() +*/ +#define GFJxEncSetupInterrupt(hJxEnc, Inter, IPara) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncSetupInterrupt(hJxEnc, Inter, IPara) + +/** Trigger JPEG encoder for one frame and optionally display capture preview. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param aBuf (#PGFJXENC_BUF) Pointer to array #GFJXENC_BUF structures + @param nBuf (NvU32) Number of pointers passed with \a aBuf, if + passing 0 then the function is non-blocking + @param pStatus (NvU32) Returns data fetch status, for reason codes + see table at GFJxEncFetchImage() + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Triggers the JPEG encoder for a frame and optionally displays the same + frame in a preview window in decimated form. + + Encoded data can be fetched via a polling scheme or via an interrupt + handler set up with GFJxEncSetupInterrupt(). In any case + GFJxEncFetchImage() is used to transfer encoded data to application + buffers. + + If application set up an interrupt handler to fetch encoded data, then + \a nBuf should be passed as 0. + + This function can optionally fetch data right after triggering encoding to + buffers provided via \a aBuf. This will block the CPU until all data is + returned or buffer space is exhausted. If \a nBuf is 0, the function + returns right away and \a pStatus is updated to #JXENC_NEW_FRAME to + indicate data is pending. The application should then call + GFJxEncFetchImage() either from an interrupt handler or from same thread to + fetch the encoded/raw data. + + If \a nBuf is not 0, it specifies the number of buffers in the array + \a aBuf. The function will block until it runs out of buffers. It + will return #JXENC_MORE_FETCH in parameter \a pStatus if more data is + available. The application must call GFJxEncFetchImage() to fetch the + remaining data. See GFJxEncFetchImage() for information on return + status codes and how the passed buffers are handled. + + JPEG Encoding from camera or raw data capture from camera happens in + realtime, so if the internal circular buffer in GPU memory is not big + enough then GFJxEncFetchImage() should be called more fequently to empty + the outputBuf and avoid buffer overflows. + + @see GFJxEncSetupInterrupt(), GFJxEncFetchImage(), #GFJXENC_BUF +*/ +#define GFJxEncCapture(hJxEnc, aBuf, nBuf, pStatus) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncCapture(hJxEnc, aBuf, nBuf, pStatus) + +/** JxEncAPI Component-level interrupt control. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param IntType (#GFJX_ENC_INTERRUPT_TYPE) JxEncAPI interrupt type + @param op (#GFJX_ENC_INTERRUPT_OPERATION_TYPE) GFJxEncAPI interrupt + operation + @param pData (void*) Pointer to input or output data block, see table + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GF_ERROR_BAD_PARAMETER Invalid parameters + + The following operations (parameter op) are defined for this call. + + Operation #GFJX_ENC_INTERRUPT_ENABLE + + Enable status/interrupt generation for interrupts of type specified by + \a IntType. + + Depending on the interrupt type additional action and the parameter + \a pData is interpreted as following: + + + + + + + + + + + + + + + + + +
      #GFJX_ENC_DMA_FIFO_LOW_INTR JPEG read DMA FIFO status/interrupt generation is put into low + threshold mode, i.e. interrupt/status is asserted if the JPEG + read DMA FIFO status is less than the threshold value. + + \a pData points to block containing:
      + NvU32 DMA FIFO low threshold value in range 0..15 + + \a pData can be NULL to leave the threshold value unchanged. +
      #GFJX_ENC_DMA_FIFO_HIGH_INTRJPEG read DMA FIFO status/interrupt generation is put into + high threshold mode, i.e. interrupt/status is asserted if the + JPEG read DMA FIFO status is greater than or equal toless than + the threshold value. + + \a pData points to block containing:
      + NvU32 DMA FIFO high threshold value in range 0..15 + + \a pData can be NULL to leave the threshold value unchanged. +
      #GFJX_ENC_STREAM_BUF_INTR \a pData points to block containing:
      + NvU32 JPEG stream buffer threshold value in bytes, must + be multiple of 8 + + \a pData can be NULL to leave the threshold value unchanged. +
      otherwise\a pData is ignored
      + + Operation #GFJX_ENC_INTERRUPT_DISABLE + + Disable status/interrupt generation for interrupts of type specified by + \a IntType. + + Operation #GFJX_ENC_INTERRUPT_CLEAR + + Clear status/interrupt assertion for interrupt of type specified by + \a IntType. + + Operation #GFJX_ENC_INTERRUPT_QUERY_STATUS + + Return current status/interrupt assertion for interrupt of type + specified by \a IntType. The state is returned in the block referenced + by \a pData. + + Interpretation of associated data block \a pData +
      +        NvU32 Interrupt/status assertion state, one of:
      +              GF_INTERRUPT_ON_STATUS_TRUE = asserted
      +              GF_INTERRUPT_ON_STATUS_FALSE = not asserted
      +        
      + + Operation #GFJX_ENC_INTERRUPT_SET_DMA_FIFO_THRESHOLD + + Set DMA FIFO threshold value that controls interrupt/status assertion + for interrupt types #GFJX_ENC_DMA_FIFO_LOW_INTR and + #GFJX_ENC_DMA_FIFO_HIGH_INTR. + + Interpretation of associated data block \a pData +
      +        NvU32 DMA FIFO threshold value in range 0..15
      +        
      + + Operation #GFJX_ENC_INTERRUPT_GET_DMA_FIFO_THRESHOLD + + Return DMA FIFO threshold value that controls interrupt/status + assertion for interrupt types #GFJX_ENC_DMA_FIFO_LOW_INTR and + #GFJX_ENC_DMA_FIFO_HIGH_INTR. + + Interpretation of associated data block \a pData +
      +        NvU32 DMA FIFO threshold value in range 0..15
      +        
      + + Operation #GFJX_ENC_INTERRUPT_SET_BUF_THRESHOLD + + Set JPEG stream buffer threshold value that controls interrupt/status + assertion for interrupt type #GFJX_ENC_STREAM_BUF_INTR. + + Interpretation of associated data block \a pData +
      +        NvU32 DMA read buffer threshold value in bytes, must be multiple of 8
      +        
      + + Operation #GFJX_ENC_INTERRUPT_GET_BUF_THRESHOLD + + Return JPEG stream buffer threshold value that controls + interrupt/status assertion for interrupt type + #GFJX_ENC_STREAM_BUF_INTR. + + Interpretation of associated data block \a pData +
      +        NvU32 DMA read buffer threshold value in bytes, must be multiple of 8
      +        
      + + @see GFJX_ENC_INTERRUPT_TYPE, GFJX_ENC_INTERRUPT_OPERATION_TYPE +*/ +#define GFJxEncInterruptControl(hJxEnc, IntType, op, pData)\ + ((PGFJXENCTABLE)hJxEnc)->JxEncInterruptControl(hJxEnc, IntType, op, pData) + +/** Standard interrupt handler for fetching encoded JPEG data. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param IntType (#GFJX_ENC_INTERRUPT_TYPE) JxEncAPI interrupt type + @param pData (void*) Pointer to input or output data block, + depending on \a IntType. See table. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + + + +
      \a IntType Interpretation of \a pData
      #GFJX_ENC_STREAM_BUF_INTR, GFJX_ENC_DONE_INTR#PGFJXENC_FETCH_BUF
      + + Usually this callback is not used, because the interrupt service thread + at the application level can call GFJxEncFetchImage() directly to + complete the task of fetching encoded data. + + @todo clarify + @see GFJxEncFetchImage() +*/ +#define GFJxEncInterruptHandler(hJxEnc, IntType, pData)\ + ((PGFJXENCTABLE)hJxEnc)->JxEncInterruptHandler(hJxEnc, IntType, pData) + +/** Generate final JPEG bitstream from a partially rotated bitstream. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param inBuf (#PGFJXENC_BUF) Pointer to array of #GFJXENC_BUF structs + holding fragmented input bitstream + @param inBufNum (NvU32) Size of array \a inBuf + @param outBuf (#PGFJXENC_BUF) Pointer to array of #GFJXENC_BUF structs + to output fragmented JPEG bitstream + @param outBufNum (NvU32) Size of array \a outBuf + @param dcacBuf (#PGFJXENC_BUF) ? + @param dcacBufNum (NvU32) Size of array \a dcacBuf + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @todo clarify +*/ +#define GFJxEncPRComplete(hJxEnc,inBuf,inBufNum,outBuf,outBufNum,dcacBuf,dcacBufNum)\ + ((PGFJXENCTABLE)hJxEnc)->JxEncPRComplete(hJxEnc,inBuf,inBufNum,outBuf,outBufNum,dcacBuf,dcacBufNum) + +/** Provide callbacks for immediately before and after any encode events. + These will be called by JxEncode() when it is invoked. + Calling this routine a second time will overwrite previously set + values. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param before (#GFJX_ENC_CALLBACK) proc to call before capture + @param after (#GFJX_ENC_CALLBACK) proc to call after capture + @param userData (void *) data to be supplied to before() and + after() when they are invoked. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +#define GFJxEncBracket(hJxEnc, before, after, userData) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncBracket(hJxEnc, before, after, userData) + +/*@}*/ +/*@}*/ + /** @page pageJxEncAppNotes JxEncAPI Application Notes + + @section pageJxEncAppNotes1 Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start GFSDK usage. + The description is for a typical case where encoding of a still image being captured + from a camera is done and preview shown on the display. + + 1. In case of camera encoding, setup the camera & initialize VIP.
      + + 2. Obtain the handle specific to JPEG encoder by calling GFJxEncOpen().
      + + 3. Call GFRmSurfaceAlloc() to allocate one referance surface for encoding purposes.
      + + 4. Call GFJxEncSetAttribute() if specific features need to be set, + such as encoding width, encoding height, rotation, quality factor, etc.
      + + 5. Start the encoding by calling GFJxEncStart().
      + + 6. If the current source image is from the CPU, the application should call GFJxEncFeedImage() + to feed the image to the GFJxEncAPI via GFJxEncCapture().
      + + 7. The application should fetch the encoded stream by calling GFJxEncFetchImage(). + Application should keep it calling till whole encoded data is out.
      + + 8. For exiting, free all relevent resources and call GFJxEncEnd() to free the JPEG encoder component.
      + + */ +#ifdef __cplusplus +} // only need to export C interface if + // used by C++ source code +#endif + +#endif //_GF_JPEG_ENC__ diff --git a/Start_WM/test6/inc/GFMinimalIsp.h b/Start_WM/test6/inc/GFMinimalIsp.h new file mode 100755 index 00000000..5f5546d3 --- /dev/null +++ b/Start_WM/test6/inc/GFMinimalIsp.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2007 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef __GFMINIMALISP_H_ +#define __GFMINIMALISP_H_ + +#include "GF.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +GF_RETTYPE GFMinimalIspOpen(GFRmHandle hRm, GFMinimalIspHandle *phIsp, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMinimalIspClose(GFMinimalIspHandle *phIsp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Start_WM/test6/inc/GFMmProc.h b/Start_WM/test6/inc/GFMmProc.h new file mode 100755 index 00000000..1489db73 --- /dev/null +++ b/Start_WM/test6/inc/GFMmProc.h @@ -0,0 +1,1766 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFMmProc.h + GFSDK Multimedia Processor API header file. +*/ + +#ifndef __GFMmProc_H__ +#define __GFMmProc_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupMmProc MmProcAPI Multimedia Processor API +*/ +/*@{*/ + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFMmProcOpen(GFRmHandle hRm, GFMmProcHandle *phMmProc, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMmProcClose(GFRmHandle hRm, GFMmProcHandle *phMmProc); + +//***************************************************************************** +//***************************************************************************** +// +// Packages +// +//***************************************************************************** +//***************************************************************************** + +// +// These defines are used to import or remove functionality within the audio +// engine. +// +//#define GFMMPROC_BASIC_AUDIO + +// +// Adds audio controls to the package beyond basic playback. +// +//#define GFMMPROC_BASIC_AUDIO + +// +// Adds advanced multimedia processing and functionality. +// +// NOTE: Currently the advanced feature set requires the basic level of audio +// support. This requirement may not be present in future revisions. +// +//#define GFMMPROC_BASIC_AUDIO +//#define GFMMPROC_ADVANCED + +// +// Adds 3D audio controls (requires GFMMPROC_ADVANCED). +// +//#define GFMMPROC_BASIC_AUDIO +//#define GFMMPROC_ADVANCED +//#define GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS + +// +// Adds advanced controls (requires GFMMPROC_ADVANCED). +// +//#define GFMMPROC_BASIC_AUDIO +//#define GFMMPROC_ADVANCED +//#define GFMMPROC_ADVANCED_CONTROLS + +// +// Adds global effect audio controls (requires GFMMPROC_ADVANCED_CONTROLS). +// +//#define GFMMPROC_BASIC_AUDIO +//#define GFMMPROC_ADVANCED +//#define GFMMPROC_ADVANCED_CONTROLS +//#define GFMMPROC_ADVANCED_AUDIO_EFFECT_CONTROLS + + +//***************************************************************************** +//***************************************************************************** +// +// Defines +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_BASIC_AUDIO || defined GFMMPROC_ADVANCED +#define GFMMPROC_TIME_UNITS_PER_SECOND 1000000 +#endif + +typedef GF_HANDLE GFMMPROC_OBJECT; + + +//***************************************************************************** +// Object +//***************************************************************************** +// +typedef struct _GFMMPROC_OBJECT_TABLE +{ + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + +} GFMMPROC_OBJECT_TABLE; + +#define GFMMPROC_OBJECT_DEFAULT_STR "Object" +#define GFMMPROC_OBJECT_MANAGER_STR "Manager" +#define GFMMPROC_OBJECT_GLOBAL_MANAGER_STR "GlobalManager" +#define GFMMPROC_OBJECT_PLAYER_STR "Player" +#define GFMMPROC_OBJECT_SOUND_SOURCE_3D_STR "SoundSource3D" +#define GFMMPROC_OBJECT_SPECTATOR_STR "Spectator" +#define GFMMPROC_OBJECT_MODULE_STR "Module" +#define GFMMPROC_OBJECT_MEDIA_PROCESSOR_STR "MediaProcessor" +#define GFMMPROC_OBJECT_CODEC_STR "Codec" + +#define GFMMPROC_CONTROL_DEFAULT_STR "Control" +#define GFMMPROC_CONTROL_MIDI_STR "MIDI" +#define GFMMPROC_CONTROL_PITCH_STR "Pitch" +#define GFMMPROC_CONTROL_RATE_STR "Rate" +#define GFMMPROC_CONTROL_RECORD_STR "Record" +#define GFMMPROC_CONTROL_STOP_TIME_STR "StopTime" +#define GFMMPROC_CONTROL_TEMPO_STR "Tempo" +#define GFMMPROC_CONTROL_TONE_STR "Tone" +#define GFMMPROC_CONTROL_VOLUME_STR "Volume" + +#define GFMMPROC_CONTROL_AUDIO_FORMAT_STR "AudioFormat" +#define GFMMPROC_CONTROL_EFFECT_STR "Effect" +#define GFMMPROC_CONTROL_EFFECT_ORDER_STR "EffectOrder" +#define GFMMPROC_CONTROL_FORMAT_STR "Format" +#define GFMMPROC_CONTROL_MIDI_CHANNEL_STR "MIDIChannel" +#define GFMMPROC_CONTROL_PAN_STR "Pan" +#define GFMMPROC_CONTROL_PRIORITY_STR "Priority" + +#define GFMMPROC_CONTROL_COMMIT_STR "Commit" +#define GFMMPROC_CONTROL_ORIENTATION_STR "Orientation" +#define GFMMPROC_CONTROL_DIRECTIVITY_STR "Directivity" +#define GFMMPROC_CONTROL_DISTANCE_ATTENUATION_STR "DistanceAttenuation" +#define GFMMPROC_CONTROL_DOPPLER_STR "Doppler" +#define GFMMPROC_CONTROL_LOCATION_STR "Location" +#define GFMMPROC_CONTROL_MACROSCOPIC_STR "Macroscopic" +#define GFMMPROC_CONTROL_OBSTRUCTION_STR "Obstruction" +#define GFMMPROC_CONTROL_3DCOEFFICIENTS_STR "3DCoefficients" + +#define GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_STR "AudioVirtualizer" +#define GFMMPROC_CONTROL_EFFECT_ACOUSTIC_ECHO_CANCELLATION_STR "AcousticEchoCancellation" +#define GFMMPROC_CONTROL_EFFECT_SBC_STR "SBC" +#define GFMMPROC_CONTROL_EFFECT_SBR_STR "SBR" +#define GFMMPROC_CONTROL_EFFECT_DRC_STR "DRC" +#define GFMMPROC_CONTROL_EFFECT_CHORUS_STR "Chorus" +#define GFMMPROC_CONTROL_EFFECT_EQUALIZER_STR "Equalizer" +#define GFMMPROC_CONTROL_EFFECT_REVERB_STR "Reverb" +#define GFMMPROC_CONTROL_REVERB_SOURCE_STR "ReverbSource" + + +#define GFMmProcObjectIsInstance(handle, objectType) \ + ((GFMMPROC_OBJECT_TABLE*)handle)->MmProcObjectIsInstance(handle, objectType) + +GF_HANDLE GFMmProcObjectAlloc(GFMmProcHandle component, const char* objectType); +void GFMmProcObjectFree(GF_HANDLE handle); + +#if defined GFMMPROC_BASIC_AUDIO || defined GFMMPROC_ADVANCED + +typedef GF_HANDLE GFMMPROC_STREAM; + +//***************************************************************************** +// Stream +//***************************************************************************** +// +typedef struct _GFMMPROC_STREAM_TABLE +{ + void (*MmProcStreamClose)(GFMMPROC_STREAM handle); + NvS32 (*MmProcStreamGetBuffer)(GFMMPROC_STREAM handle, NvU32 tag, void** descriptor, void** buffer); + void (*MmProcStreamReleaseBuffer)(GFMMPROC_STREAM handle, NvU32 tag, NvU32 status, NvU32 size); + void (*MmProcStreamReset)(GFMMPROC_STREAM handle); + +} GFMMPROC_STREAM_TABLE; + +#define GFMMPROC_STREAM_END_OF_MEDIA 0x00000001 + +#define GFMmProcStreamClose(handle) \ + ((GFMMPROC_STREAM_TABLE*)handle)->MmProcStreamClose(handle) +#define GFMmProcStreamGetBuffer(handle, tag, descriptor, buffer) \ + ((GFMMPROC_STREAM_TABLE*)handle)->MmProcStreamGetBuffer(handle, tag, descriptor, buffer) +#define GFMmProcStreamReleaseBuffer(handle, tag, status, size) \ + ((GFMMPROC_STREAM_TABLE*)handle)->MmProcStreamReleaseBuffer(handle, tag, status, size) +#define GFMmProcStreamReset(handle) \ + ((GFMMPROC_STREAM_TABLE*)handle)->MmProcStreamReset(handle) + +#endif // #if defined GFMMPROC_BASIC_AUDIO || defined GFMMPROC_ADVANCED + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_BASIC_AUDIO +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_BASIC_AUDIO + +typedef GFMMPROC_OBJECT GFMMPROC_CONTROL; +typedef GF_HANDLE GFMMPROC_CONTROLLABLE; +typedef GFMMPROC_OBJECT GFMMPROC_MANAGER; +typedef GFMMPROC_CONTROLLABLE GFMMPROC_PLAYER; +typedef GF_HANDLE GFMMPROC_PLAYER_LISTENER; +typedef GF_HANDLE GFMMPROC_TIME_BASE; +typedef enum { + GFMMPROC_CODEC_TYPE_UNSPECIFIED = 0, + GFMMPROC_CODEC_TYPE_I2S, + GFMMPROC_CODEC_TYPE_AC97 +} GFMMPROC_CODEC_TYPE; + +//***************************************************************************** +// Control +//***************************************************************************** +// +typedef GFMMPROC_OBJECT_TABLE GFMMPROC_CONTROL_TABLE; + + +//***************************************************************************** +// Controllable +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROLLABLE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + GFMMPROC_CONTROL (*MmProcControllableGetControl)(GFMMPROC_CONTROLLABLE handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcControllableGetControls)(GFMMPROC_CONTROLLABLE handle); + +} GFMMPROC_CONTROLLABLE_TABLE; + +#define GFMmProcControllableGetControl(handle, controlType) \ + ((GFMMPROC_CONTROLLABLE_TABLE*)handle)->MmProcControllableGetControl(handle, controlType) +#define GFMmProcControllableGetControls(handle) \ + ((GFMMPROC_CONTROLLABLE_TABLE*)handle)->MmProcControllableGetControls(handle) + + +//***************************************************************************** +// Manager +//***************************************************************************** +// +typedef struct _GFMMPROC_MANAGER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + GFMMPROC_PLAYER (*MmProcManagerCreatePlayer)(GFMMPROC_MANAGER handle, char* locator); +// GFMMPROC_PLAYER (*MmProcManagerCreatePlayerForDataSource)(GFMMPROC_MANAGER handle, DataSource source); + GFMMPROC_PLAYER (*MmProcManagerCreatePlayerForStream)(GFMMPROC_MANAGER handle, GFMMPROC_STREAM stream, char* contentType); + char* (*MmProcManagerGetSupportedContentTypes)(GFMMPROC_MANAGER handle, char* protocol); + char* (*MmProcManagerGetSupportedProtocols)(GFMMPROC_MANAGER handle, char* contentType); + GFMMPROC_TIME_BASE (*MmProcManagerGetSystemTimeBase)(GFMMPROC_MANAGER handle); + void (*MmProcManagerPlayTone)(GFMMPROC_MANAGER handle, NvU32 note, NvU32 duration, NvU32 volume); + void (*MmProcManagerProcess)(GFMMPROC_MANAGER handle); + GFMMPROC_CODEC_TYPE (*MmProcManagerGetCodecType)(GFMMPROC_MANAGER handle); + void (*MmProcManagerCodecWrite)(GFMMPROC_MANAGER handle, NvU32 offset, NvU32 value); + NvU32 (*MmProcManagerCodecRead)(GFMMPROC_MANAGER handle, NvU32 offset); + +} GFMMPROC_MANAGER_TABLE; + +#define GFMMPROC_MANAGER_MIDI_DEVICE_LOCATOR "device://midi" +#define GFMMPROC_MANAGER_TONE_DEVICE_LOCATOR "device://tone" + +#define GFMmProcManagerCreatePlayer(handle, locator) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCreatePlayer(handle, locator) +//#define GFMmProcManagerCreatePlayerForDataSource(handle, source) Add multiline delineator here +// ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCreatePlayerForDataSource(handle, source) +#define GFMmProcManagerCreatePlayerForStream(handle, stream, contentType) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCreatePlayerForStream(handle, stream, contentType) +#define GFMmProcManagerGetSupportedContentTypes(handle, protocol) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerGetSupportedContentTypes(handle, protocol) +#define GFMmProcManagerGetSupportedProtocols(handle, contentType) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerGetSupportedProtocols(handle, contentType) +#define GFMmProcManagerGetSystemTimeBase(handle) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerGetSystemTimeBase(handle) +#define GFMmProcManagerPlayTone(handle, note, duration, volume) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerPlayTone(handle, note, duration, volume) +#define GFMmProcManagerProcess(handle) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerProcess(handle) +#define MmProcManagerGetCodecType(handle) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerGetCodecType(handle) +#define MmProcManagerCodecWrite(handle, offset, value) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCodecWrite(handle, offset, value) +#define MmProcManagerCodecRead(handle, offset) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCodecRead(handle, offset) + + +//***************************************************************************** +// Player +//***************************************************************************** +// +typedef struct _GFMMPROC_PLAYER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Controllable Methods + // + GFMMPROC_CONTROL (*MmProcControllableGetControl)(GFMMPROC_CONTROLLABLE handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcControllableGetControls)(GFMMPROC_CONTROLLABLE handle); + + void (*MmProcPlayerAddPlayerListener)(GFMMPROC_PLAYER handle, GFMMPROC_PLAYER_LISTENER playerListener); + void (*MmProcPlayerClose)(GFMMPROC_PLAYER handle); + void (*MmProcPlayerDeallocate)(GFMMPROC_PLAYER handle); + char* (*MmProcPlayerGetContentType)(GFMMPROC_PLAYER handle); + NvS64 (*MmProcPlayerGetDuration)(GFMMPROC_PLAYER handle); + NvS64 (*MmProcPlayerGetMediaTime)(GFMMPROC_PLAYER handle); + NvU32 (*MmProcPlayerGetState)(GFMMPROC_PLAYER handle); + GFMMPROC_TIME_BASE (*MmProcPlayerGetTimeBase)(GFMMPROC_PLAYER handle); + NvU32 (*MmProcPlayerPrefetch)(GFMMPROC_PLAYER handle); + void (*MmProcPlayerPull)(GFMMPROC_PLAYER handle, NvS32 allow); + void (*MmProcPlayerRealize)(GFMMPROC_PLAYER handle); + void (*MmProcPlayerRemovePlayerListener)(GFMMPROC_PLAYER handle, GFMMPROC_PLAYER_LISTENER playerListener); + void (*MmProcPlayerSetLoopCount)(GFMMPROC_PLAYER handle, NvS32 count); + NvS64 (*MmProcPlayerSetMediaTime)(GFMMPROC_PLAYER handle, NvS64 now); + void (*MmProcPlayerSetTimeBase)(GFMMPROC_PLAYER handle, GFMMPROC_TIME_BASE master); + void (*MmProcPlayerStart)(GFMMPROC_PLAYER handle); + void (*MmProcPlayerStop)(GFMMPROC_PLAYER handle); + +} GFMMPROC_PLAYER_TABLE; + +#define GFMMPROC_PLAYER_UNREALIZED 100 +#define GFMMPROC_PLAYER_REALIZED 200 +#define GFMMPROC_PLAYER_PREFETCHED 300 +#define GFMMPROC_PLAYER_STARTED 400 +#define GFMMPROC_PLAYER_CLOSED 0 +#define GFMMPROC_PLAYER_TIME_UNKNOWN -1 + +#define GFMmProcPlayerAddPlayerListener(handle, playerListener) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerAddPlayerListener(handle, playerListener) +#define GFMmProcPlayerClose(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerClose(handle) +#define GFMmProcPlayerDeallocate(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerDeallocate(handle) +#define GFMmProcPlayerGetContentType(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetContentType(handle) +#define GFMmProcPlayerGetDuration(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetDuration(handle) +#define GFMmProcPlayerGetMediaTime(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetMediaTime(handle) +#define GFMmProcPlayerGetState(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetState(handle) +#define GFMmProcPlayerGetTimeBase(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetTimeBase(handle) +#define GFMmProcPlayerPrefetch(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerPrefetch(handle) +#define GFMmProcPlayerPull(handle, allow) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerPull(handle, allow) +#define GFMmProcPlayerRealize(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerRealize(handle) +#define GFMmProcPlayerRemovePlayerListener(handle, playerListener) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerRemovePlayerListener(handle, playerListener) +#define GFMmProcPlayerSetLoopCount(handle, count) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerSetLoopCount(handle, count) +#define GFMmProcPlayerSetMediaTime(handle, now) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerSetMediaTime(handle, now) +#define GFMmProcPlayerSetTimeBase(handle, master) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerSetMediaTime(handle, master) +#define GFMmProcPlayerStart(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerStart(handle) +#define GFMmProcPlayerStop(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerStop(handle) + + +//***************************************************************************** +// PlayerListener +//***************************************************************************** +// +typedef struct _GFMMPROC_PLAYER_LISTENER_TABLE +{ + void (*MmProcPlayerListenerPlayerUpdate)(GFMMPROC_PLAYER_LISTENER handle, GFMMPROC_PLAYER player, const char* event, void* eventData); + +} GFMMPROC_PLAYER_LISTENER_TABLE; + +#define GFMMPROC_PLAYER_LISTENER_BUFFERING_STARTED "bufferingStarted" +#define GFMMPROC_PLAYER_LISTENER_BUFFERING_STOPPED "bufferingStopped" +#define GFMMPROC_PLAYER_LISTENER_CLOSED "closed" +#define GFMMPROC_PLAYER_LISTENER_END_OF_MEDIA "endOfMedia" +#define GFMMPROC_PLAYER_LISTENER_DEVICE_AVAILABLE "deviceAvailable" +#define GFMMPROC_PLAYER_LISTENER_DEVICE_UNAVAILABLE "deviceUnavailable" +#define GFMMPROC_PLAYER_LISTENER_DURATION_UPDATED "durationUpdated" +#define GFMMPROC_PLAYER_LISTENER_ERROR "error" +#define GFMMPROC_PLAYER_LISTENER_FORMAT_CHANGED "formatChanged" +#define GFMMPROC_PLAYER_LISTENER_RECORD_ERROR "recordError" +#define GFMMPROC_PLAYER_LISTENER_RECORD_STARTED "recordStarted" +#define GFMMPROC_PLAYER_LISTENER_RECORD_STOPPED "recordStopped" +#define GFMMPROC_PLAYER_LISTENER_STARTED "started" +#define GFMMPROC_PLAYER_LISTENER_STOPPED "stopped" +#define GFMMPROC_PLAYER_LISTENER_STOPPED_AT_TIME "stoppedAtTime" +#define GFMMPROC_PLAYER_LISTENER_VOLUME_CHANGED "volumeChanged" + +#define GFMmProcPlayerListenerPlayerUpdate(handle, player, event, eventData) \ + ((GFMMPROC_PLAYER_LISTENER_TABLE*)handle)->MmProcPlayerListenerPlayerUpdate(handle, player, event, eventData) + + +//***************************************************************************** +// TimeBase +//***************************************************************************** +// +typedef struct _GFMMPROC_TIME_BASE_TABLE +{ + NvU32 (*MmProcTimeBaseGetTime)(GFMMPROC_TIME_BASE handle); + +} GFMMPROC_TIME_BASE_TABLE; + +#define GFMmProcTimeBaseGetTime(handle) \ + ((GFMMPROC_TIME_BASE_TABLE*)handle)->MmProcTimeBaseGetTime(handle) + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_BASIC_AUDIO_CONTROLS +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_BASIC_AUDIO_CONTROLS + +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_MIDI; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_PITCH; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_RATE; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_RECORD; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_STOP_TIME; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_TEMPO; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_TONE; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_VOLUME; + + + +//***************************************************************************** +// MIDIControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_MIDI_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32* (*MmProcControlMidiGetBankList)(GFMMPROC_CONTROL_MIDI hande, NvS32 custom); + NvS8 (*MmProcControlMidiGetChannelVolume)(GFMMPROC_CONTROL_MIDI hande, NvU8 channel); + char* (*MmProcControlMidiGetKeyName)(GFMMPROC_CONTROL_MIDI hande, NvS32 bank, NvS32 program, NvS32 key); + NvS32* (*MmProcControlMidiGetProgram)(GFMMPROC_CONTROL_MIDI hande, NvU8 channel); + NvS32* (*MmProcControlMidiGetProgramList)(GFMMPROC_CONTROL_MIDI hande, NvS32 bank); + char* (*MmProcControlMidiGetProgramName)(GFMMPROC_CONTROL_MIDI hande, NvS32 bank, NvS32 program); + NvS32 (*MmProcControlMidiIsBankQuerySupported)(GFMMPROC_CONTROL_MIDI hande); + NvS32 (*MmProcControlMidiLongMidiEvent)(GFMMPROC_CONTROL_MIDI hande, NvS8* data, NvS32 offset, NvS32 length); + void (*MmProcControlMidiShortMidiEvent)(GFMMPROC_CONTROL_MIDI hande, NvS32 type, NvS32 data1, NvS32 data2); + +} GFMMPROC_CONTROL_MIDI_TABLE; + +#define GFMMPROC_CONTROL_MIDI_CONTROL_CHANGE 176 +#define GFMMPROC_CONTROL_MIDI_NOTE_ON 144 + +#define GFMmProcControlMidiGetBankList(handle, custom) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetBankList(handle, custom) +#define GFMmProcControlMidiGetChannelVolume(handle, channel) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetChannelVolume(handle, channel) +#define GFMmProcControlMidiGetKeyName(handle, bank, program, key) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetKeyName(handle, bank, program, key) +#define GFMmProcControlMidiGetProgram(handle, channel) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetProgram(handle, channel) +#define GFMmProcControlMidiGetProgramList(handle, bank) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetProgramList(handle, bank) +#define GFMmProcControlMidiGetProgramName(handle, bank, program) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetProgramName(handle, bank, program) +#define GFMmProcControlMidiIsBankQuerySupported(handle) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiIsBankQuerySupported(handle) +#define GFMmProcControlMidiLongMidiEvent(handle) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiLongMidiEvent(handle, data, offset, length) +#define GFMmProcControlMidiShortMidiEvent(handle, type, data1, data2) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->(handle, type, data1, data2) + + +//***************************************************************************** +// PitchControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_PITCH_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlPitchGetMaxPitch)(GFMMPROC_CONTROL_PITCH handle); + NvS32 (*MmProcControlPitchGetMinPitch)(GFMMPROC_CONTROL_PITCH handle); + NvS32 (*MmProcControlPitchGetPitch)(GFMMPROC_CONTROL_PITCH handle); + NvS32 (*MmProcControlPitchSetPitch)(GFMMPROC_CONTROL_PITCH handle, NvS32 millisemitones); + +} GFMMPROC_CONTROL_PITCH_TABLE; + +#define GFMmProcControlPitchGetMaxPitch(handle) \ + ((GFMMPROC_CONTROL_PITCH_TABLE*)handle)->MmProcControlPitchGetMaxPitch(handle) +#define GFMmProcControlPitchGetMinPitch(handle) \ + ((GFMMPROC_CONTROL_PITCH_TABLE*)handle)->MmProcControlPitchGetMinPitch(handle) +#define GFMmProcControlPitchGetPitch(handle) \ + ((GFMMPROC_CONTROL_PITCH_TABLE*)handle)->MmProcControlPitchGetPitch(handle) +#define GFMmProcControlPitchSetPitch(handle, millisemitones) \ + ((GFMMPROC_CONTROL_PITCH_TABLE*)handle)->MmProcControlPitchSetPitch(handle, millisemitones) + + +//***************************************************************************** +// RateControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_RATE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlRateGetMaxRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateGetMinRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateGetRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateSetRate)(GFMMPROC_CONTROL_RATE handle, NvS32 millirate); + +} GFMMPROC_CONTROL_RATE_TABLE; + +#define GFMmProcControlRateGetMaxRate(handle) \ + ((GFMMPROC_CONTROL_RATE_TABLE*)handle)->MmProcControlRateGetMaxRate(handle) +#define GFMmProcControlRateGetMinRate(handle) \ + ((GFMMPROC_CONTROL_RATE_TABLE*)handle)->MmProcControlRateGetMinRate(handle) +#define GFMmProcControlRateGetRate(handle) \ + ((GFMMPROC_CONTROL_RATE_TABLE*)handle)->MmProcControlRateGetRate(handle) +#define GFMmProcControlRateSetRate(handle, millirate) \ + ((GFMMPROC_CONTROL_RATE_TABLE*)handle)->MmProcControlRateSetRate(handle, millirate) + + +//***************************************************************************** +// RecordControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_RECORD_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlRecordCommit)(GFMMPROC_CONTROL_RECORD handle); + char* (*MmProcControlRecordGetContentType)(GFMMPROC_CONTROL_RECORD handle); + void (*MmProcControlRecordSetRecordLocation)(GFMMPROC_CONTROL_RECORD handle, char* locator); + void (*MmProcControlRecordSetRecordStream)(GFMMPROC_CONTROL_RECORD handle, GFMMPROC_STREAM stream, char* contentType); + NvS32 (*MmProcControlRecordSetRecordSizeLimit)(GFMMPROC_CONTROL_RECORD handle, NvS32 size); + void (*MmProcControlRecordStartRecord)(GFMMPROC_CONTROL_RECORD handle); + void (*MmProcControlRecordStopRecord)(GFMMPROC_CONTROL_RECORD handle); + void (*MmProcControlRecordReset)(GFMMPROC_CONTROL_RECORD handle); + +} GFMMPROC_CONTROL_RECORD_TABLE; + +#define GFMmProcControlRecordCommit(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordCommit(handle) +#define GFMmProcControlRecordGetContentType(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordGetContentType(handle) +#define GFMmProcControlRecordSetRecordLocation(handle, locator) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordSetRecordLocation(handle, locator) +#define GFMmProcControlRecordSetRecordStream(handle, stream, contentType) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordSetRecordStream(handle, stream, contentType) +#define GFMmProcControlRecordSetRecordSizeLimit(handle, size) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordSetRecordSizeLimit(handle, size) +#define GFMmProcControlRecordStartRecord(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordStartRecord(handle) +#define GFMmProcControlRecordStopRecord(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordStopRecord(handle) +#define GFMmProcControlRecordReset(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordReset(handle) + + +//***************************************************************************** +// StopTimeControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_STOP_TIME_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS64 (*MmProcControlStopTimeGetStopTime)(GFMMPROC_CONTROL_STOP_TIME handle); + void (*MmProcControlStopTimeSetStopTime)(GFMMPROC_CONTROL_STOP_TIME handle, NvS64 stopTime); + +} GFMMPROC_CONTROL_STOP_TIME_TABLE; + +#define GFMMPROC_CONTROL_STOP_TIME_RESET -1 + +#define GFMmProcControlStopTimeGetStopTime(handle) \ + (GFMMPROC_CONTROL_STOP_TIME_TABLE*)handle)->MmProcControlStopTimeGetStopTime(handle) +#define GFMmProcControlStopTimeSetStopTime(handle, stopTime) \ + ((GFMMPROC_CONTROL_STOP_TIME_TABLE*)handle)->MmProcControlStopTimeSetStopTime(handle, stopTime) + + +//***************************************************************************** +// TempoControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_TEMPO_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Rate Methods + // + NvS32 (*MmProcControlRateGetMaxRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateGetMinRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateGetRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateSetRate)(GFMMPROC_CONTROL_RATE handle, NvS32 millirate); + + NvS32 (*MmProcControlTempoGetTempo)(GFMMPROC_CONTROL_TEMPO handle); + NvS32 (*MmProcControlTempoSetTempo)(GFMMPROC_CONTROL_TEMPO handle, NvS32 millitempo); + +} GFMMPROC_CONTROL_TEMPO_TABLE; + +#define GFMmProcControlTempoGetTempo(handle) \ + ((GFMMPROC_CONTROL_TEMPO_TABLE*)handle)->MmProcControlTempoGetTempo(handle) +#define GFMmProcControlTempoSetTempo(handle) \ + ((GFMMPROC_CONTROL_TEMPO_TABLE*)handle)->MmProcControlTempoSetTempo(handle, millitempo) + + +//***************************************************************************** +// ToneControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_TONE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlToneSetSequence)(GFMMPROC_CONTROL_TONE handle, NvS8* sequence); + +} GFMMPROC_CONTROL_TONE_TABLE; + +#define GFMMPROC_CONTROL_TONE_VERSION -2 +#define GFMMPROC_CONTROL_TONE_TEMPO -3 +#define GFMMPROC_CONTROL_TONE_RESOLUTION -4 +#define GFMMPROC_CONTROL_TONE_BLOCK_START -5 +#define GFMMPROC_CONTROL_TONE_BLOCK_END -6 +#define GFMMPROC_CONTROL_TONE_PLAY_BLOCK -7 +#define GFMMPROC_CONTROL_TONE_SET_VOLUME -8 +#define GFMMPROC_CONTROL_TONE_REPEAT -9 +#define GFMMPROC_CONTROL_TONE_C4 60 +#define GFMMPROC_CONTROL_TONE_SILENCE -1 + +#define GFMmProcControlToneSetSequence(handle, sequence) \ + ((GFMMPROC_CONTROL_TONE_TABLE*)handle)->MmProcControlToneSetSequence(handle, sequence) + + +//***************************************************************************** +// VolumeControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_VOLUME_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlVolumeGetLevel)(GFMMPROC_CONTROL_VOLUME handle); + NvS32 (*MmProcControlVolumeIsMuted)(GFMMPROC_CONTROL_VOLUME handle); + NvS32 (*MmProcControlVolumeSetLevel)(GFMMPROC_CONTROL_VOLUME handle, NvS32 level); + void (*MmProcControlVolumeSetMute)(GFMMPROC_CONTROL_VOLUME handle, NvS32 mute); + +} GFMMPROC_CONTROL_VOLUME_TABLE; + +#define GFMmProcControlVolumeGetLevel(handle) \ + ((GFMMPROC_CONTROL_VOLUME_TABLE*)handle)->MmProcControlVolumeGetLevel(handle) +#define GFMmProcControlVolumeIsMuted(handle) \ + ((GFMMPROC_CONTROL_VOLUME_TABLE*)handle)->MmProcControlVolumeIsMuted(handle) +#define GFMmProcControlVolumeSetLevel(handle, level) \ + ((GFMMPROC_CONTROL_VOLUME_TABLE*)handle)->MmProcControlVolumeSetLevel(handle, level) +#define GFMmProcControlVolumeSetMute(handle, mute) \ + ((GFMMPROC_CONTROL_VOLUME_TABLE*)handle)->MmProcControlVolumeSetMute(handle, mute) + + +#endif // GFMMPROC_BASIC_AUDIO_CONTROLS + +#endif // GFMMPROC_BASIC_AUDIO + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_ADVANCED +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_ADVANCED + +typedef GF_HANDLE GFMMPROC_MODULE; +typedef GFMMPROC_MODULE GFMMPROC_EFFECT_MODULE; +typedef GFMMPROC_MANAGER GFMMPROC_GLOBAL_MANAGER; +typedef GFMMPROC_CONTROLLABLE GFMMPROC_MEDIA_PROCESSOR; +typedef GF_HANDLE GFMMPROC_MEDIA_PROCESSOR_LISTENER; +typedef GFMMPROC_CONTROLLABLE GFMMPROC_SPECTATOR; +typedef GFMMPROC_MODULE GFMMPROC_SOUND_SOURCE_3D; + + +//***************************************************************************** +// Module +//***************************************************************************** +// +typedef struct _GFMMPROC_MODULE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Controllable Methods + // + GFMMPROC_CONTROL (*MmProcControllableGetControl)(GFMMPROC_CONTROLLABLE handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcControllableGetControls)(GFMMPROC_CONTROLLABLE handle); + + void (*MmProcModuleAddMIDIChannel)(GFMMPROC_MODULE handle, GFMMPROC_PLAYER player, NvS32 channel); + void (*MmProcModuleAddPlayer)(GFMMPROC_MODULE handle, GFMMPROC_PLAYER player); + void (*MmProcModuleRemoveMIDIChannel)(GFMMPROC_MODULE handle, GFMMPROC_PLAYER player, NvS32 channel); + void (*MmProcModuleRemovePlayer)(GFMMPROC_MODULE handle, GFMMPROC_PLAYER player); + +} GFMMPROC_MODULE_TABLE; + +#define GFMmProcModuleAddMIDIChannel(handle, player, channel) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleAddMIDIChannel(handle, player, channel) +#define GFMmProcModuleAddPlayer(handle, player) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleAddPlayer(handle, player) +#define GFMmProcModuleGetControl(handle, controlType) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleGetControl(handle, controlType) +#define GFMmProcModuleGetControls(handle) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleGetControls(handle) +#define GFMmProcModuleRemoveMIDIChannel(handle, player, channel) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleRemoveMIDIChannel(handle, player, channel) +#define GFMmProcModuleRemovePlayer(handle, player) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleRemovePlayer(handle, player) + + +//***************************************************************************** +// EffectModule +//***************************************************************************** +// +typedef GFMMPROC_MODULE_TABLE GFMMPROC_EFFECT_MODULE_TABLE; + + +//***************************************************************************** +// GlobalManager +//***************************************************************************** +// +typedef struct _GFMMPROC_GLOBAL_MANAGER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Manager Methods + // + GFMMPROC_PLAYER (*MmProcManagerCreatePlayer)(GFMMPROC_MANAGER handle, char* locator); +// GFMMPROC_PLAYER (*MmProcManagerCreatePlayerForDataSource)(GFMMPROC_MANAGER handle, DataSource source); + GFMMPROC_PLAYER (*MmProcManagerCreatePlayerForStream)(GFMMPROC_MANAGER handle, GFMMPROC_STREAM stream, char* type); + char* (*MmProcManagerGetSupportedContentTypes)(GFMMPROC_MANAGER handle, char* protocol); + char* (*MmProcManagerGetSupportedProtocols)(GFMMPROC_MANAGER handle, char* contentType); + GFMMPROC_TIME_BASE (*MmProcManagerGetSystemTimeBase)(GFMMPROC_MANAGER handle); + void (*MmProcManagerPlayTone)(GFMMPROC_MANAGER handle, NvU32 note, NvU32 duration, NvU32 volume); + void (*MmProcManagerProcess)(GFMMPROC_MANAGER handle); + GFMMPROC_CODEC_TYPE (*MmProcManagerGetCodecType)(GFMMPROC_MANAGER handle); + void (*MmProcManagerCodecWrite)(GFMMPROC_MANAGER handle, NvU32 offset, NvU32 value); + NvU32 (*MmProcManagerCodecRead)(GFMMPROC_MANAGER handle, NvU32 offset); + + GFMMPROC_EFFECT_MODULE (*MmProcGlobalManagerCreateEffectModule)(GFMMPROC_GLOBAL_MANAGER handle); + GFMMPROC_MEDIA_PROCESSOR (*MmProcGlobalManagerCreateMediaProcessor)(GFMMPROC_GLOBAL_MANAGER handle); + GFMMPROC_SOUND_SOURCE_3D (*MmProcGlobalManagerCreateSoundSource3D)(GFMMPROC_GLOBAL_MANAGER handle); + GFMMPROC_CONTROL (*MmProcGlobalManagerGetControl)(GFMMPROC_GLOBAL_MANAGER handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcGlobalManagerGetControls)(GFMMPROC_GLOBAL_MANAGER handle); + GFMMPROC_SPECTATOR (*MmProcGlobalManagerGetSpectator)(GFMMPROC_GLOBAL_MANAGER handle); + char* (*MmProcGlobalManagerGetSupportedMediaProcessorInputTypes)(GFMMPROC_GLOBAL_MANAGER handle); + NvS32 (*MmProcGlobalManagerGetUnitsPerMeter)(GFMMPROC_GLOBAL_MANAGER handle); + void (*MmProcGlobalManagerSetUnitsPerMeter)(GFMMPROC_GLOBAL_MANAGER handle, NvS32 newScalingFactor); + +} GFMMPROC_GLOBAL_MANAGER_TABLE; + +#define GFMmProcGlobalManagerCreateEffectModule(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerCreateEffectModule(handle) +#define GFMmProcGlobalManagerCreateMediaProcessor(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerCreateMediaProcessor(handle) +#define GFMmProcGlobalManagerCreateSoundSource3D(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerCreateSoundSource3D(handle) +#define GFMmProcGlobalManagerGetControl(handle, controlType) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetControl(handle, controlType) +#define GFMmProcGlobalManagerGetControls(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetControls(handle) +#define GFMmProcGlobalManagerGetSpectator(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetSpectator(handle) +#define GFMmProcGlobalManagerGetSupportedMediaProcessorInputTypes(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetSupportedMediaProcessorInputTypes(handle) +#define GFMmProcGlobalManagerGetUnitsPerMeter(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetUnitsPerMeter(handle) +#define GFMmProcGlobalManagerSetUnitsPerMeter(handle, newScalingFactor) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerSetUnitsPerMeter(handle, newScalingFactor) + + +//***************************************************************************** +// MediaProcessor +//***************************************************************************** +// +typedef struct _GFMMPROC_MEDIA_PROCESSOR_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Controllable Methods + // + GFMMPROC_CONTROL (*MmProcControllableGetControl)(GFMMPROC_CONTROLLABLE handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcControllableGetControls)(GFMMPROC_CONTROLLABLE handle); + + void (*MmProcMediaProcessorAbort)(GFMMPROC_MEDIA_PROCESSOR handle); + void (*MmProcMediaProcessorAddMediaProcessorListener)(GFMMPROC_MEDIA_PROCESSOR handle, + GFMMPROC_MEDIA_PROCESSOR_LISTENER mediaProcessorListener); + void (*MmProcMediaProcessorComplete)(GFMMPROC_MEDIA_PROCESSOR handle); + NvS32 (*MmProcMediaProcessorGetProgress)(GFMMPROC_MEDIA_PROCESSOR handle); + void (*MmProcMediaProcessorRemoveMediaProcessorListener)(GFMMPROC_MEDIA_PROCESSOR handle, + GFMMPROC_MEDIA_PROCESSOR_LISTENER mediaProcessorListener); + void (*MmProcMediaProcessorStart)(GFMMPROC_MEDIA_PROCESSOR handle); + void (*MmProcMediaProcessorStop)(GFMMPROC_MEDIA_PROCESSOR handle); + GFMMPROC_PLAYER (*MmProcMediaProcessorSetInput)(GFMMPROC_MEDIA_PROCESSOR handle, GFMMPROC_STREAM input, char* contentType, NvS32 length); + GFMMPROC_PLAYER (*MmProcMediaProcessorSetOutput)(GFMMPROC_MEDIA_PROCESSOR handle, GFMMPROC_STREAM output, char* contentType); + +} GFMMPROC_MEDIA_PROCESSOR_TABLE; + +#define GFMMPROC_MEDIA_PROCESSOR_UNKNOWN -1 + +#define GFMmProcMediaProcessorAbort(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorAbort(handle) +#define GFMmProcMediaProcessorAddMediaProcessorListener(handle, mediaProcessorListener) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorAddMediaProcessorListener(handle, mediaProcessorListener) +#define GFMmProcMediaProcessorComplete(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorComplete(handle) +#define GFMmProcMediaProcessorGetProgress(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorGetProgress(handle) +#define GFMmProcMediaProcessorRemoveMediaProcessorListener(handle, mediaProcessorListener) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorRemoveMediaProcessorListener(handle, mediaProcessorListener) +#define GFMmProcMediaProcessorStart(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorStart(handle) +#define GFMmProcMediaProcessorStop(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorStop(handle) +#define GFMmProcMediaProcessorSetInput(handle, input, contentType, length) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorSetInput(handle, input, contentType, length) +#define GFMmProcMediaProcessorSetOutput(handle, output, contentType) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorSetOutput(handle, output, contentType) + + +//***************************************************************************** +// MediaProcessorListener +//***************************************************************************** +// +typedef struct _GFMMPROC_MEDIA_PROCESSOR_LISTENER_TABLE +{ + void (*MmProcMediaProcessorListenerMediaProcessorUpdate)(GFMMPROC_MEDIA_PROCESSOR_LISTENER handle, + GFMMPROC_MEDIA_PROCESSOR processor, char* event, + void* eventData); + +} GFMMPROC_MEDIA_PROCESSOR_LISTENER_TABLE; + +#define GFMMPROC_MEDIA_PROCESSOR_LISTENER_PROCESSING_COMPLETED "processingCompleted" +#define GFMMPROC_MEDIA_PROCESSOR_LISTENER_PROCESSING_ERROR "processingError" + +#define GFMmProcMediaProcessorListenerMediaProcessorUpdate(handle, processor, event, eventData) \ + ((GFMMPROC_MEDIA_PROCESSOR_LISTENER_TABLE*)handle)->MmProcMediaProcessorListenerMediaProcessorUpdate(handle, processor, event, eventData) + + +//***************************************************************************** +// Spectator +//***************************************************************************** +// +typedef GFMMPROC_CONTROLLABLE_TABLE GFMMPROC_SPECTATOR_TABLE; + + +//***************************************************************************** +// SoundSource3D +//***************************************************************************** +// +typedef GFMMPROC_MODULE_TABLE GFMMPROC_SOUND_SOURCE_3D_TABLE; + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS + +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_COMMIT; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_ORIENTATION; +typedef GFMMPROC_CONTROL_ORIENTATION GFMMPROC_CONTROL_DIRECTIVITY; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_DISTANCE_ATTENUATION; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_DOPPLER; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_LOCATION; +typedef GFMMPROC_CONTROL_ORIENTATION GFMMPROC_CONTROL_MACROSCOPIC; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_OBSTRUCTION; + +#include "GFAudio.h" + +//***************************************************************************** +// CommitControl +//***************************************************************************** +typedef struct _GFMMPROC_CONTROL_COMMIT_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlCommitCommit)(GFMMPROC_CONTROL_COMMIT handle); + NvS32 (*MmProcControlCommitIsDeferred)(GFMMPROC_CONTROL_COMMIT handle); + void (*MmProcControlCommitSetDeferred)(GFMMPROC_CONTROL_COMMIT handle, NvS32 deferred); + +} GFMMPROC_CONTROL_COMMIT_TABLE; + +#define GFMmProcControlCommitCommit(handle) \ + ((GFMMPROC_CONTROL_COMMIT_TABLE*)handle)->MmProcControlCommitCommit(handle) +#define GFMmProcControlCommitIsDeferred(handle) \ + ((GFMMPROC_CONTROL_COMMIT_TABLE*)handle)->MmProcControlCommitIsDeferred(handle) +#define GFMmProcControlCommitSetDeferred(handle, deferred) \ + ((GFMMPROC_CONTROL_COMMIT_TABLE*)handle)->MmProcControlCommitSetDeferred(handle, deferred) + + + +//***************************************************************************** +// OrientationControl +//***************************************************************************** +typedef struct _GFMMPROC_CONTROL_ORIENTATION_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlOrientationGetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32* frontVector, NvVectorS32* aboveVector); + void (*MmProcControlOrientationSetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32 frontVector, NvVectorS32 aboveVector); + +} GFMMPROC_CONTROL_ORIENTATION_TABLE; + +#define GFMmProcControlOrientationGetOrientation(handle, frontVector, aboveVector) \ + ((GFMMPROC_CONTROL_ORIENTATION_TABLE*)handle)->MmProcControlOrientationGetOrientation(handle, frontVector, aboveVector) +#define GFMmProcControlOrientationSetOrientation(handle, frontVector, aboveVector) \ + ((GFMMPROC_CONTROL_ORIENTATION_TABLE*)handle)->MmProcControlOrientationSetOrientation(handle, frontVector, aboveVector) + + +//***************************************************************************** +// DirectivityControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_DIRECTIVITY_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Orientation Methods + // + void (*MmProcControlOrientationGetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32* frontVector, NvVectorS32* aboveVector); + void (*MmProcControlOrientationSetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32 frontVector, NvVectorS32 aboveVector); + + void (*MmProcControlDirectivityGetParameters)(GFMMPROC_CONTROL_DIRECTIVITY handle, NvVectorS32* vector); + void (*MmProcControlDirectivitySetParameters)(GFMMPROC_CONTROL_DIRECTIVITY handle, + NvS32 minAngle, NvS32 maxAngle, NvS32 rearLevel); + +} GFMMPROC_CONTROL_DIRECTIVITY_TABLE; + +#define GFMmProcControlDirectivityGetParameters(handle, vector) \ + ((GFMMPROC_CONTROL_DIRECTIVITY_TABLE*)handle)->MmProcControlDirectivityGetParameters(handle, vector) +#define GFMmProcControlDirectivitySetParameters(handle, minAngle, maxAngle, rearLevel) \ + ((GFMMPROC_CONTROL_DIRECTIVITY_TABLE*)handle)->MmProcControlDirectivitySetParameters(handle, minAngle, maxAngle, rearLevel) + + +//***************************************************************************** +// DistanceAttenuationControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlDistanceAttenuationGetMaxDistance)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle); + NvS32 (*MmProcControlDistanceAttenuationGetMinDistance)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle); + NvS32 (*MmProcControlDistanceAttenuationGetMuteAfterMax)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle); + NvS32 (*MmProcControlDistanceAttenuationGetRolloffFactor)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle); + void (*MmProcControlDistanceAttenuationSetParameters)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle, + NvS32 minDistance, NvS32 maxDistance, + NvS32 muteAfterMax, NvS32 rolloffFactor); + +} GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE; + +#define GFMmProcControlDistanceAttenuationGetMaxDistance(handle) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationGetMaxDistance(handle) +#define GFMmProcControlDistanceAttenuationGetMinDistance(handle) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationGetMinDistance(handle) +#define GFMmProcControlDistanceAttenuationGetMuteAfterMax(handle) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationGetMuteAfterMax(handle) +#define GFMmProcControlDistanceAttenuationGetRolloffFactor(handle) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationGetRolloffFactor(handle) +#define GFMmProcControlDistanceAttenuationSetParameters(handle, minDistance, maxDistance, muteAfterMax, rolloffFactor) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationSetParameters(handle, minDistance, maxDistance, muteAfterMax, rolloffFactor) + + +//***************************************************************************** +// DopplerControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_DOPPLER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlDopplerGetVelocityCartesian)(GFMMPROC_CONTROL_DOPPLER handle, NvVectorS32* vector); + NvS32 (*MmProcControlDopplerIsEnabled)(GFMMPROC_CONTROL_DOPPLER handle); + void (*MmProcControlDopplerSetEnabled)(GFMMPROC_CONTROL_DOPPLER handle, NvS32 dopplerEnabled); + void (*MmProcControlDopplerSetVelocityCartesian)(GFMMPROC_CONTROL_DOPPLER handle, NvVectorS32 vector); + void (*MmProcControlDopplerSetVelocitySpherical)(GFMMPROC_CONTROL_DOPPLER handle, + NvS32 azimuth, NvS32 elevation, NvS32 radius); + +} GFMMPROC_CONTROL_DOPPLER_TABLE; + +#define GFMmProcControlDopplerGetVelocityCartesian(handle, vector) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerGetVelocityCartesian(handle, vector) +#define GFMmProcControlDopplerIsEnabled(handle) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerIsEnabled(handle) +#define GFMmProcControlDopplerSetEnabled(handle, dopplerEnabled) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerSetEnabled(handle, dopplerEnabled) +#define GFMmProcControlDopplerSetVelocityCartesian(handle, vector) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerSetVelocityCartesian(handle, vector) +#define GFMmProcControlDopplerSetVelocitySpherical(handle, azimuth, elevation, radius) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerSetVelocitySpherical(handle, azimuth, elevation, radius) + + +//***************************************************************************** +// LocationControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_LOCATION_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlLocationGetCartesian)(GFMMPROC_CONTROL_LOCATION handle, NvVectorS32* vector); + void (*MmProcControlLocationSetCartesian)(GFMMPROC_CONTROL_LOCATION handle, NvVectorS32 vector); + void (*MmProcControlLocationSetSpherical)(GFMMPROC_CONTROL_LOCATION handle, NvS32 azimuth, NvS32 elevation, NvS32 radius); + void (*MmProcControlLocationSetCoefficients)(GFMMPROC_CONTROL_LOCATION handle,GFMMPROC_SOUND_SOURCE_3D SS3D,GFMMPROC_SPECTATOR spec, NvS32 CurrVec[],NvS32 TargVec[]); + void (*MmProcControlLocationGetCoefficients)(GFMMPROC_CONTROL_LOCATION handle, void* Coeff); + +} GFMMPROC_CONTROL_LOCATION_TABLE; + +#define GFMmProcControlLocationGetCartesian(handle, vector) \ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationGetCartesian(handle, vector) +#define GFMmProcControlLocationSetCartesian(handle, vector) \ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationSetCartesian(handle, vector) +#define GFMmProcControlLocationSetSpherical(handle, azimuth, elevation, radius) \ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationSetSpherical(handle, azimuth, elevation, radius) +#define GFMmProcControlLocationSetCoefficients(handle, SS3D,spec, CurrVec,TargVec) \ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationSetCoefficients(handle, SS3D,spec, CurrVec,TargVec) +#define GFMmProcControlLocationGetCoefficients(handle,pCoeff)\ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationGetCoefficients(handle,pCoeff) + +//***************************************************************************** +// MacroscopicControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_MACROSCOPIC_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Orientation Methods + // + void (*MmProcControlOrientationGetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32* frontVector, NvVectorS32* aboveVector); + void (*MmProcControlOrientationSetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32 frontVector, NvVectorS32 aboveVector); + + void (*MmProcControlMacroscopicGetSize)(GFMMPROC_CONTROL_MACROSCOPIC handle, NvVectorS32* vector); + void (*MmProcControlMacroscopicSetSize)(GFMMPROC_CONTROL_MACROSCOPIC handle, NvVectorS32 vector); + +} GFMMPROC_CONTROL_MACROSCOPIC_TABLE; + +#define GFMmProcControlMacroscopicGetSize(handle, vector) \ + ((GFMMPROC_CONTROL_MACROSCOPIC_TABLE*)handle)->MmProcControlMacroscopicGetSize(handle, vector) +#define GFMmProcControlMacroscopicSetSize(handle, vector) \ + ((GFMMPROC_CONTROL_MACROSCOPIC_TABLE*)handle)->MmProcControlMacroscopicSetSize(handle, vector) + + +//***************************************************************************** +// ObstructionControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_OBSTRUCTION_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlObstructionGetHFLevel)(GFMMPROC_CONTROL_OBSTRUCTION handle); + NvS32 (*MmProcControlObstructionGetLevel)(GFMMPROC_CONTROL_OBSTRUCTION handle); + void (*MmProcControlObstructionSetHFLevel)(GFMMPROC_CONTROL_OBSTRUCTION handle, NvS32 HFLevel); + void (*MmProcControlObstructionSetLevel)(GFMMPROC_CONTROL_OBSTRUCTION handle, NvS32 level); + +} GFMMPROC_CONTROL_OBSTRUCTION_TABLE; + +#define GFMmProcControlObstructionGetHFLevel(handle) \ + ((GFMMPROC_CONTROL_OBSTRUCTION_TABLE*)handle)->MmProcControlObstructionGetHFLevel(handle) +#define GFMmProcControlObstructionGetLevel(handle) \ + ((GFMMPROC_CONTROL_OBSTRUCTION_TABLE*)handle)->MmProcControlObstructionGetLevel(handle) +#define GFMmProcControlObstructionSetHFLevel(handle, HFLevel) \ + ((GFMMPROC_CONTROL_OBSTRUCTION_TABLE*)handle)->MmProcControlObstructionSetHFLevel(handle, HFLevel) +#define GFMmProcControlObstructionSetLevel(handle, level) \ + ((GFMMPROC_CONTROL_OBSTRUCTION_TABLE*)handle)->MmProcControlObstructionSetLevel(handle, level) + + +#endif // GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS + + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_ADVANCED_CONTROLS +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_ADVANCED_CONTROLS + +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_AUDIO_FORMAT; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_EFFECT; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_EFFECT_ORDER; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_FORMAT; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_MIDI_CHANNEL; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_PAN; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_PRIORITY; + + + +//***************************************************************************** +// FormatControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_FORMAT_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlFormatGetEstimatedBitRate)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetFormat)(GFMMPROC_CONTROL_FORMAT handle); + NvS32 (*MmProcControlFormatGetIntParameterValue)(GFMMPROC_CONTROL_FORMAT handle, char* parameter); + NvS32 (*MmProcControlFormatGetMetadataOverride)(GFMMPROC_CONTROL_FORMAT handle); + NvS32 (*MmProcControlFormatGetMetadataSupportMode)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetStrParameterValue)(GFMMPROC_CONTROL_FORMAT handle, char* parameter); + char* (*MmProcControlFormatGetSupportedFormats)(GFMMPROC_CONTROL_FORMAT handle); + NvS32* (*MmProcControlFormatGetSupportedIntParameterRange)(GFMMPROC_CONTROL_FORMAT handle, char* parameter); + char* (*MmProcControlFormatGetSupportedIntParameters)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetSupportedMetadataKeys)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetSupportedStrParameters)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetSupportedStrParameterValues)(GFMMPROC_CONTROL_FORMAT handle, char* parameter); + void (*MmProcControlFormatSetFormat)(GFMMPROC_CONTROL_FORMAT handle, char* format); + void (*MmProcControlFormatSetMetadata)(GFMMPROC_CONTROL_FORMAT handle, char* key, char* value); + void (*MmProcControlFormatSetMetadataOverride)(GFMMPROC_CONTROL_FORMAT handle, NvS32 override); + void (*MmProcControlFormatSetParameterStr)(GFMMPROC_CONTROL_FORMAT handle, char* parameter, char* value); + NvS32 (*MmProcControlFormatSetParameterInt)(GFMMPROC_CONTROL_FORMAT handle, char* parameter, NvS32 value); + +} GFMMPROC_CONTROL_FORMAT_TABLE; + +#define GFMMPROC_CONTROL_FORMAT_METADATA_NOT_SUPPORTED 0 +#define GFMMPROC_CONTROL_FORMAT_METADATA_SUPPORTED_FIXED_KEYS 1 +#define GFMMPROC_CONTROL_FORMAT_METADATA_SUPPORTED_FREE_KEYS 2 + +#define GFMMPROC_CONTROL_FORMAT_PARAM_BITRATE "bitrate" +#define GFMMPROC_CONTROL_FORMAT_PARAM_BITRATE_TYPE "bitrate type" +#define GFMMPROC_CONTROL_FORMAT_PARAM_BITS_PER_SAMPLE "bits per sample" +#define GFMMPROC_CONTROL_FORMAT_PARAM_CHANNELS "channels" +#define GFMMPROC_CONTROL_FORMAT_PARAM_FRAMERATE "frame rate" +#define GFMMPROC_CONTROL_FORMAT_PARAM_QUALITY "quality" +#define GFMMPROC_CONTROL_FORMAT_PARAM_SAMPLERATE "sample rate" +#define GFMMPROC_CONTROL_FORMAT_PARAM_TRACK "track" +#define GFMMPROC_CONTROL_FORMAT_PARAM_TRACKS_AVAILABLE "tracks available" +#define GFMMPROC_CONTROL_FORMAT_PARAM_VERSION_TYPE "version type" + +#define GFMMPROC_CONTROL_FORMAT_TRACK_ALL -1 +#define GFMMPROC_CONTROL_FORMAT_TRACK_DEFAULT 0 +#define GFMMPROC_CONTROL_FORMAT_TRACK_ONE 1 + + +#define GFMmProcControlFormatGetEstimatedBitRate(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetEstimatedBitRate(handle) +#define GFMmProcControlFormatGetFormat(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetFormat(handle) +#define GFMmProcControlFormatGetIntParameterValue(handle, parameter) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetIntParameterValue(handle, parameter) +#define GFMmProcControlFormatGetMetadataOverride(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetMetadataOverride(handle) +#define GFMmProcControlFormatGetMetadataSupportMode(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetMetadataSupportMode(handle) +#define GFMmProcControlFormatGetStrParameterValue(handle, parameter) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetStrParameterValue(handle, parameter) +#define GFMmProcControlFormatGetSupportedFormats(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedFormats(handle) +#define GFMmProcControlFormatGetSupportedIntParameterRange(handle, parameter) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedIntParameterRange(handle, parameter) +#define GFMmProcControlFormatGetSupportedIntParameters(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedIntParameters(handle) +#define GFMmProcControlFormatGetSupportedMetadataKeys(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedMetadataKeys(handle) +#define GFMmProcControlFormatGetSupportedStrParameters(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedStrParameters(handle) +#define GFMmProcControlFormatGetSupportedStrParameterValues(handle, parameter) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedStrParameterValues(handle, parameter) +#define GFMmProcControlFormatSetFormat(handle, format) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetFormat(handle, format) +#define GFMmProcControlFormatSetMetadata(handle, key, value) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetMetadata(handle, key, value) +#define GFMmProcControlFormatSetMetadataOverride(handle, override) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetMetadataOverride(handle, override) +#define GFMmProcControlFormatSetParameterStr(handle, parameter, value) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetParameterStr(handle, parameter, value) +#define GFMmProcControlFormatSetParameterInt(handle, parameter, value) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetParameterInt(handle, parameter, value) + + + +//***************************************************************************** +// AudioFormatControl +//***************************************************************************** +// +typedef GFMMPROC_CONTROL_FORMAT_TABLE GFMMPROC_CONTROL_AUDIO_FORMAT_TABLE; + + +//***************************************************************************** +// EffectControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + +} GFMMPROC_CONTROL_EFFECT_TABLE; + +#define GFMMPROC_CONTROL_EFFECT_SCOPE_LIVE_ONLY 1 +#define GFMMPROC_CONTROL_EFFECT_SCOPE_RECORD_ONLY 2 +#define GFMMPROC_CONTROL_EFFECT_SCOPE_LIVE_AND_RECORD 3 + +#define GFMmProcControlEffectGetPreset(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectGetPreset(handle) +#define GFMmProcControlEffectGetPresetNames(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectGetPresetNames(handle) +#define GFMmProcControlEffectGetScope(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectGetScope(handle) +#define GFMmProcControlEffectIsEnabled(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectIsEnabled(handle) +#define GFMmProcControlEffectIsEnforced(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectIsEnforced(handle) +#define GFMmProcControlEffectSetEnabled(handle, enable) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectSetEnabled(handle, enable) +#define GFMmProcControlEffectSetEnforced(handle, enforced) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectSetEnforced(handle, enforced) +#define GFMmProcControlEffectSetPreset(handle, preset) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectSetPreset(handle, preset) +#define GFMmProcControlEffectSetScope(handle, scope) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectSetScope(handle, scope) + + +//***************************************************************************** +// EffectOrderControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_ORDER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlEffectOrderGetEffectOrder)(GFMMPROC_CONTROL_EFFECT_ORDER handle, GFMMPROC_CONTROL_EFFECT effect); + GFMMPROC_CONTROL_EFFECT (*MmProcControlEffectOrderGetEffectOrders)(GFMMPROC_CONTROL_EFFECT_ORDER handle); + NvS32 (*MmProcControlEffectOrderSetEffectOrder)(GFMMPROC_CONTROL_EFFECT_ORDER handle, GFMMPROC_CONTROL_EFFECT effect, NvS32 order); + +} GFMMPROC_CONTROL_EFFECT_ORDER_TABLE; + +#define GFMmProcControlEffectOrderGetEffectOrder(handle, effect) \ + ((GFMMPROC_CONTROL_EFFECT_ORDER_TABLE*)handle)->(handle, effect) +#define GFMmProcControlEffectOrderGetEffectOrders(handle) \ + ((GFMMPROC_CONTROL_EFFECT_ORDER_TABLE*)handle)->MmProcControlEffectOrderGetEffectOrders(handle) +#define GFMmProcControlEffectOrderSetEffectOrder(handle, effect, order) \ + ((GFMMPROC_CONTROL_EFFECT_ORDER_TABLE*)handle)->MmProcControlEffectOrderSetEffectOrder(handle, effect, order) + + +//***************************************************************************** +// MIDIChannelControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_MIDI_CHANNEL_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + GFMMPROC_CONTROL (*MmProcControlMidiChannelGetChannelControl)(GFMMPROC_CONTROL_MIDI_CHANNEL handle, char* controlType, NvS32 channel); + GFMMPROC_CONTROL* (*MmProcControlMidiChannelGetChannelControls)(GFMMPROC_CONTROL_MIDI_CHANNEL handle, NvS32 channel); + +} GFMMPROC_CONTROL_MIDI_CHANNEL_TABLE; + +#define GFMmProcControlMidiChannelGetChannelControl(handle, controlType, channel) \ + ((GFMMPROC_CONTROL_MIDI_CHANNEL_TABLE*)handle)->MmProcControlMidiChannelGetChannelControl(handle, controlType, channel) +#define GFMmProcControlMidiChannelGetChannelControls(handle, channel) \ + ((GFMMPROC_CONTROL_MIDI_CHANNEL_TABLE*)handle)->MmProcControlMidiChannelGetChannelControls(handle, channel) + + +//***************************************************************************** +// PanControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_PAN_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlPanGetPan)(GFMMPROC_CONTROL_PAN handle); + NvS32 (*MmProcControlPanSetPan)(GFMMPROC_CONTROL_PAN handle, NvS32 pan); + +} GFMMPROC_CONTROL_PAN_TABLE; + +#define GFMmProcControlPanGetPan(handle) \ + ((GFMMPROC_CONTROL_PAN_TABLE*)handle)->MmProcControlPanGetPan(handle) +#define GFMmProcControlPanSetPan(handle, pan) \ + ((GFMMPROC_CONTROL_PAN_TABLE*)handle)->MmProcControlPanSetPan(handle, pan) + + +//***************************************************************************** +// PriorityControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_PRIORITY_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlPriorityGetPriority)(GFMMPROC_CONTROL_PRIORITY handle); + void (*MmProcControlPrioritySetPriority)(GFMMPROC_CONTROL_PRIORITY handle, NvS32 level); + +} GFMMPROC_CONTROL_PRIORITY_TABLE; + +#define GFMmProcControlPriorityGetPriority(handle) \ + ((GFMMPROC_CONTROL_PRIORITY_TABLE*)handle)->MmProcControlPriorityGetPriority(handle) +#define GFMmProcControlPrioritySetPriority(handle, level) \ + ((GFMMPROC_CONTROL_PRIORITY_TABLE*)handle)->MmProcControlPrioritySetPriority(handle, level) + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_ADVANCED_AUDIO_EFFECT_CONTROLS +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_ADVANCED_AUDIO_EFFECT_CONTROLS + +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_ACOUSTIC_ECHO_CANCELLATION; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_CHORUS; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_EQUALIZER; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_REVERB; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_DRC; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_REVERB_SOURCE; + +//***************************************************************************** +// AudioVirtualizerControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectAudioVirtualizerGetSpread)(GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER handle); + void (*MmProcControlEffectAudioVirtualizerSetSpread)(GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER handle, NvS32 width); + +} GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_TABLE; + +#define GFMmProcControlEffectAudioVirtualizerGetSpread(handle) \ + ((GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_TABLE*)handle)->MmProcControlEffectAudioVirtualizerGetSpread(handle) +#define GFMmProcControlEffectAudioVirtualizerSetSpread(handle, width) \ + ((GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_TABLE*)handle)->MmProcControlEffectAudioVirtualizerSetSpread(handle, width) + + +//***************************************************************************** +// AcousticEchoCancellationControl +//***************************************************************************** +// +typedef GFMMPROC_CONTROL_EFFECT_TABLE GFMMPROC_CONTROL_EFFECT_ACOUSTIC_ECHO_CANCELLATION_TABLE; + +//***************************************************************************** +// SBCControl +//***************************************************************************** +// +typedef GFMMPROC_CONTROL_EFFECT_TABLE GFMMPROC_CONTROL_EFFECT_SBC_TABLE; + +//***************************************************************************** +// SBRControl +//***************************************************************************** +// +typedef GFMMPROC_CONTROL_EFFECT_TABLE GFMMPROC_CONTROL_EFFECT_SBR_TABLE; + + +//***************************************************************************** +// ChorusControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectChorusGetAverageDelay)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetMaxAverageDelay)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetMaxModulationDepth)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetMaxModulationRate)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetMinModulationRate)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetModulationDepth)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetModulationRate)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetWetLevel)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + void (*MmProcControlEffectChorusSetAverageDelay)(GFMMPROC_CONTROL_EFFECT_CHORUS handle, NvS32 delay); + void (*MmProcControlEffectChorusSetModulationDepth)(GFMMPROC_CONTROL_EFFECT_CHORUS handle, NvS32 depth); + void (*MmProcControlEffectChorusSetModulationRate)(GFMMPROC_CONTROL_EFFECT_CHORUS handle, NvS32 rate); + NvS32 (*MmProcControlEffectChorusSetWetLevel)(GFMMPROC_CONTROL_EFFECT_CHORUS handle, NvS32 level); + +} GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE; + +#define GFMmProcControlEffectChorusGetAverageDelay(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetAverageDelay(handle) +#define GFMmProcControlEffectChorusGetMaxAverageDelay(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetMaxAverageDelay(handle) +#define GFMmProcControlEffectChorusGetMaxModulationDepth(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetMaxModulationDepth(handle) +#define GFMmProcControlEffectChorusGetMaxModulationRate(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetMaxModulationRate(handle) +#define GFMmProcControlEffectChorusGetMinModulationRate(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetMinModulationRate(handle) +#define GFMmProcControlEffectChorusGetModulationDepth(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetModulationDepth(handle) +#define GFMmProcControlEffectChorusGetModulationRate(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetModulationRate(handle) +#define GFMmProcControlEffectChorusGetWetLevel(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetWetLevel(handle) +#define GFMmProcControlEffectChorusSetAverageDelay(handle, delay) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusSetAverageDelay(handle, delay) +#define GFMmProcControlEffectChorusSetModulationDepth(handle, depth) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusSetModulationDepth(handle, depth) +#define GFMmProcControlEffectChorusSetModulationRate(handle, rate) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusSetModulationRate(handle, rate) +#define GFMmProcControlEffectChorusSetWetLevel(handle, level) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusSetWetLevel(handle, level) + + +//***************************************************************************** +// EqualizerControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectEqualizerGetBand)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 frequency); + NvS32 (*MmProcControlEffectEqualizerGetBandLevel)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 band); + NvS32 (*MmProcControlEffectEqualizerGetBass)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + NvS32 (*MmProcControlEffectEqualizerGetCenterFreq)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 band); + NvS32 (*MmProcControlEffectEqualizerGetMaxBandLevel)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + NvS32 (*MmProcControlEffectEqualizerGetMinBandLevel)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + NvS32 (*MmProcControlEffectEqualizerGetNumberOfBands)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + NvS32 (*MmProcControlEffectEqualizerGetTreble)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + void (*MmProcControlEffectEqualizerSetBandLevel)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 level, NvS32 band); + NvS32 (*MmProcControlEffectEqualizerSetBass)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 level); + NvS32 (*MmProcControlEffectEqualizerSetTreble)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 level); + NvS32 (*MmProcControlEffectEqualizerSetBandX)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 *levelptr); + +} GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE; + +#define GFMMPROC_CONTROL_EFFECT_EQUALIZER_UNDEFINED -1004 + +#define GFMmProcControlEffectEqualizerGetBand(handle, frequency) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->(handle, frequency) +#define GFMmProcControlEffectEqualizerGetBandLevel(handle, band) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetBandLevel(handle, band) +#define GFMmProcControlEffectEqualizerGetBass(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetBass(handle) +#define GFMmProcControlEffectEqualizerGetCenterFreq(handle, band) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetCenterFreq(handle, band) +#define GFMmProcControlEffectEqualizerGetMaxBandLevel(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetMaxBandLevel(handle) +#define GFMmProcControlEffectEqualizerGetMinBandLevel(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetMinBandLevel(handle) +#define GFMmProcControlEffectEqualizerGetNumberOfBands(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetNumberOfBands(handle) +#define GFMmProcControlEffectEqualizerGetTreble(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetTreble(handle) +#define GFMmProcControlEffectEqualizerSetBandLevel(handle, level, band) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerSetBandLevel(handle, level, band) +#define GFMmProcControlEffectEqualizerSetBass(handle, level) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerSetBass(handle, level) +#define GFMmProcControlEffectEqualizerSetTreble(handle, level) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerSetTreble(handle, level) +#define GFMmProcControlEffectEqualizerSetBandX(handle, levelptr) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerSetBandX(handle, levelptr) + + +//***************************************************************************** +// Dynamic Range Control (DRC) +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_DRC_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectDRCGetDRCEnable)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetDRCEnable)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); + NvS32 (*MmProcControlEffectDRCGetNoiseGateTh)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetNoiseGateTh)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); + NvS32 (*MmProcControlEffectDRCGetLowerCompTh)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetLowerCompTh)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); + NvS32 (*MmProcControlEffectDRCGetUpperCompTh)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetUpperCompTh)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); + NvS32 (*MmProcControlEffectDRCGetClipTh)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetClipTh)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); +} GFMMPROC_CONTROL_EFFECT_DRC_TABLE; + +#define GFMmProcControlEffectDRCGetDRCEnable(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetDRCEnable(handle) +#define GFMmProcControlEffectDRCSetDRCEnable(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetDRCEnable(handle, Param) +#define GFMmProcControlEffectDRCGetNoiseGateTh(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetNoiseGateTh(handle) +#define GFMmProcControlEffectDRCSetNoiseGateTh(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetNoiseGateTh(handle, Param) +#define GFMmProcControlEffectDRCGetLowerCompTh(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetLowerCompTh(handle) +#define GFMmProcControlEffectDRCSetLowerCompTh(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetLowerCompTh(handle, Param) +#define GFMmProcControlEffectDRCGetUpperCompTh(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetUpperCompTh(handle) +#define GFMmProcControlEffectDRCSetUpperCompTh(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetUpperCompTh(handle, Param) +#define GFMmProcControlEffectDRCGetClipTh(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetClipTh(handle) +#define GFMmProcControlEffectDRCSetClipTh(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetClipTh(handle, Param) + + + + +//***************************************************************************** +// ReverbControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_REVERB_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectReverbGetReverbLevel)(GFMMPROC_CONTROL_EFFECT_REVERB handle); + NvS32 (*MmProcControlEffectReverbGetReverbTime)(GFMMPROC_CONTROL_EFFECT_REVERB handle); + NvS32 (*MmProcControlEffectReverbSetReverbLevel)(GFMMPROC_CONTROL_EFFECT_REVERB handle, NvS32 level); + void (*MmProcControlEffectReverbSetReverbTime)(GFMMPROC_CONTROL_EFFECT_REVERB handle, NvS32 time); + +} GFMMPROC_CONTROL_EFFECT_REVERB_TABLE; + +#define GFMmProcControlEffectReverbGetReverbLevel(handle) \ + ((GFMMPROC_CONTROL_EFFECT_REVERB_TABLE*)handle)->MmProcControlEffectReverbGetReverbLevel(handle) +#define GFMmProcControlEffectReverbGetReverbTime(handle) \ + ((GFMMPROC_CONTROL_EFFECT_REVERB_TABLE*)handle)->MmProcControlEffectReverbGetReverbTime(handle) +#define GFMmProcControlEffectReverbSetReverbLevel(handle, level) \ + ((GFMMPROC_CONTROL_EFFECT_REVERB_TABLE*)handle)->MmProcControlEffectReverbSetReverbLevel(handle, level) +#define GFMmProcControlEffectReverbSetReverbTime(handle, time) \ + ((GFMMPROC_CONTROL_EFFECT_REVERB_TABLE*)handle)->MmProcControlEffectReverbSetReverbTime(handle, time) + + +//***************************************************************************** +// ReverbSourceControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_REVERB_SOURCE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlReverbSourceGetRoomLevel)(GFMMPROC_CONTROL_REVERB_SOURCE handle); + void (*MmProcControlReverbSourceSetRoomLevel)(GFMMPROC_CONTROL_REVERB_SOURCE handle, NvS32 level); + +} GFMMPROC_CONTROL_REVERB_SOURCE_TABLE; + +#define GFMMPROC_CONTROL_REVERB_SOURCE_DISCONNECT -2147483648 + +#define GFMmProcControlReverbSourceGetRoomLevel(handle) \ + ((GFMMPROC_CONTROL_REVERB_SOURCE_TABLE*)handle)->MmProcControlReverbSourceGetRoomLevel(handle) +#define GFMmProcControlReverbSourceSetRoomLevel(handle, level) \ + ((GFMMPROC_CONTROL_REVERB_SOURCE_TABLE*)handle)->MmProcControlReverbSourceSetRoomLevel(handle, level) + + + +#endif // GFMMPROC_ADVANCED_AUDIO_EFFECT_CONTROLS + +#endif // GFMMPROC_ADVANCED_CONTROLS + +#endif // GFMMPROC_ADVANCED + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Start_WM/test6/inc/GFMxDec.h b/Start_WM/test6/inc/GFMxDec.h new file mode 100755 index 00000000..78cc7c5c --- /dev/null +++ b/Start_WM/test6/inc/GFMxDec.h @@ -0,0 +1,727 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an +* express license agreement from NVIDIA Corporation is strictly prohibited. +*/ + +/** @file GFMxDec.h +GFSDK MPEG Decode API header file. +*/ + +#ifndef _GF_MPEG_DEC__ +#define _GF_MPEG_DEC__ + +#include "nvtypes.h" +#include "GFVx.h" +#include "GFDef.h" + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif + + /** @addtogroup groupMxDec MxDecAPI MPEG Decode API +
        +
      • @ref pageMxDecAppNotes +
          +
        • @ref pageMxDecAppNotes1 +
        +
      + */ + /*@{*/ + + /****************************************************************************************************/ + // MXDECCapFlags + /** MxDecAPI property flag: Support for Simple Profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_SIMPLE 0x00000001 + /** MxDecAPI property flag: Support for simple profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ + +#define GF_MXDEC_CAP_SCALE 0x00000002 + /** MxDecAPI property flag: Support for simple scale profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ + +#define GF_MXDEC_CAP_CORE 0x00000004 + /** MxDecAPI property flag: Support for CORE profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ + +#define GF_MXDEC_CAP_MAIN 0x00000008 + /** MxDecAPI property flag: Support for MAIN profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ + + /** MxDecAPI property flag: Support for N_bit profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_N_BIT 0x00000010 + + /** MxDecAPI property flag: Support for LEVEL 1. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_LEVEL1 0x00000100 + + /** MxDecAPI property flag: Support for LEVEL 2. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_LEVEL2 0x00000200 + + /** MxDecAPI property flag: Support for LEVEL 3. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_LEVEL3 0x00000400 + + /** MxDecAPI property flag: Support for LEVEL 4. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_LEVEL4 0x00000800 + + /** MxDecAPI property flag: Support for Post Processing's de-blocking. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_DB 0x00001000 + + /** MxDecAPI property flag: Support for Post Processing's de-ringing. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_DR 0x00002000 + + /****************************************************************************************************/ + /** This structure holds the video object plane (VOP) information. */ + typedef struct _GFMXDECVOP + { + NvU32 uiVOPinfo; /**< Set new VOP information */ + NvU32 uiFFORWARD; /**< FCODE_FORWARD, ignore this value if it is I frame */ + PGFRMSURFACE pRef; /**< Reference VOP, ignore this item, if current VOP is an I */ + PGFRMSURFACE pCur; /**< Current VOP */ + PGFRECT pRefRect; /**< Specifies a rectangular area within the pRef surface for the + GFMxDecAPI to use with the reference image. This field only takes + effect when MXDEC_VOP_SPECIFY_REFSURF_RECT is set. The rectangle’s + top and left should be aligned by the application, which should call + GFMxDecGetAttribute() with MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT + and MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT to get the required + alignment. The rectangle's width and height should exactly match the + image width and height that is encoded in the bit stream. */ + + PGFRECT pCurRect; /**< Specifies a rectangular area of the pCur surface within which the + GFMxDecAPI should place the decoded image output. This field only takes + effect if MXDEC_VOP_SPECIFY_CURSURF_RECT is set. The rectangle’s top and + left should be aligned by the application, which should call GFMxDecGetAttribute() + with MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT and + MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT to get the required alignment. + The rectangle's width and height should exactly match the image width and + height that is encoded in the bit stream. */ + }GFMXDECVOP, *PGFMXDECVOP; + + /****************************************************************************************************/ + //uiVOPinfo values + /** GFMXDECVOP::uiVOPinfo : If set, this is P VOP. If unset, it is I VOP. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_P_VOP 0x1 + + /** GFMXDECVOP::uiVOPinfo : This parameter comes as a part of the bitstream. + This indicates that rounding should be performed while doing Motion Compensation. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_ROUNDING_ONE 0x2 + + /** GFMXDECVOP::uiVOPinfo : If set, this bitstream is short video header format. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_SHORT_HEADER 0x4 + + /** GFMXDECVOP::uiVOPinfo : If set, If this flag is set, pRefSurfRect must be set. + GFMxDec will reference image in pRefSurfRect area of pRef surface. Otherwise, GFMxDec will reference the whole pRef surface area. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_SPECIFY_REFSURF_RECT 0x8 + + /** GFMXDECVOP::uiVOPinfo : If this flag is set, pCurSurfRect must be set. GFMxDec will output decoded image to + pCurSurfRect area of pCur surface. Otherwise, GFMxDec will output to pCur surface starting from top left corner , the width and + height are equal to pCur surface width and height. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_SPECIFY_CURSURF_RECT 0x10 + + /****************************************************************************************************/ + /** This structure holds the postprocessing information. */ + typedef struct _GFMXDECPP + { + PGFRMSURFACE* pDestSurf; /**< Pointer to an array of surfaces that will hold the result from Post Processing + pointer to an array of surfaces to accommodate auto post processing. */ + PGFRMSURFACE* pSrcSurf; /**< Pointer to an array of surfaces to be post processed pointer to an array of surfaces + to accommodate auto post processing. */ + PGFRECT pRect; /**< Rectangular area to be processed for both source and destination surfaces. + @see GFRECT */ + NvU32 numofDestSurf; /**< Number of Destination Surfaces. If MXDEC_PP_AUTO flag is set, this parameter must be filled. */ + NvU32 numofSrcSurf; /**< Number of Source Surfaces. If MXDEC_PP_AUTO flag is set, this parameter must be filled. */ + NvU8 * lpQuantiser; /**< Pointer to array of quantization steps (QPs) for macroblocks in + the source VOP. The GFMxDecAPI automatically saved the last + two decoded VOP’s QP tables. The application may not need to + reload the table if it can make sure the source VOP is one of the + last decoded VOPs. This field must be filled if + MXDEC_PP_RELOAD_QUANTIZER is set. */ + NvU32 PPOption; /**< Post-processing option. */ + /**< + + + + + + + + + + +
      #MXDEC_PP_DB_ONTurn on DeBlocking filter for this frame
      #MXDEC_PP_DR_ONTurn on DeRinging filter for this frame
      #MXDEC_PP_AUTOAuto trigger Post Processing by Hardware
      #MXDEC_PP_RELOAD_QUANTIZERReload the source VOP's qunantizers
      #MXDEC_PP_OP_ASYNCEnables ASYNC mode
      + */ + } GFMXDECPP, *PGFMXDECPP; + + /****************************************************************************************************/ + // PPOption + /** GFMXDECPP::PPOption : Turn on DeBlocking filter for this frame. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_DB_ON 0x1 + + /** GFMXDECPP::PPOption : Turn on DeRinging filter for this frame. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_DR_ON 0x2 + + /** GFMXDECPP::PPOption : Auto trigger Post Processing by Hardware. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_AUTO 0x4 + + /** GFMXDECPP::PPOption : Reload the source VOP's qunantizers. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_RELOAD_QUANTIZER 0x8 + + /** GFMXDECPP::PPOption : enables ASYN mode. GFMxDecPostProcessing() + will return after pushing the commands but without waiting for them to + complete. This option is useful to achieve some paralellism because + post-processed frame is usually not used right away for rendering. So + there is enough time for hardware to complete the decoding before this + frame will be used by app. It is ok to call PostProcessing even when + decoding of this frame is not complete. Inside GPU, hardware synchronizes + with the decoder. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_OP_ASYNC 0x00000010 + + /****************************************************************************************************/ + //pStatus + /** Argument pStatus in GFMxDecGetStatus() : GFMxDecGetStatus() can be called by the application to indicate whether 1 frame + has been decoded or not. + @see GFMXDECTABLE::MxDecGetStatus */ +#define GF_DECODER_FRAME_DONE 0x00000010 + + /** Argument pStatus in GFMxDecGetStatus() : GFMxDecGetStatus() can be called by the application to indicate whether post-processing + engine is done with the frame or not. + @see GFMXDECTABLE::MxDecGetStatus */ +#define GF_DECODER_PP_FRAME_DONE 0x00000020 + + /****************************************************************************************************/ + /** GFMxDecSet::uiFeature : Application sets this attribute to register a callback function and + its correpnding parameter to read bitstream data */ +#define MXDEC_SET_READBITSTREAM 1 + + /** GFMxDecSet::uiFeature Application needs to set this flag in order to send MPEG4 bitstream data in Prefill Mode; + When this is set: + - application does not need to register any bitstream-read callback function as data will be fed upfront. + - application needs to set an attribute MXDEC_ATTR_PRE_DETERMINED_BOUNDARY to indicate that data will be fed on frame boundary. + @see GFMXDECTABLE::MxDecSet */ +#define GFMXDEC_OPTION_PREFILLBUFFER 0x00000002 + + /****************************************************************************************************/ + /** Structure holding the callback function pointer. + Used in registering the callback function + The callback function is a function which the API calls to request a portion of the bit stream from the application. + @see GFMXDECTABLE::MxDecSet + */ + typedef struct _GFMXDECCALLBACK + { + void *pPara; /**< pPara is a parameter passed from application and the application + wants the API to callback with this parameter. */ + NvU32 (*pCallBack)(void * pPara, NvU8 ** ppBuffer, NvS32 * BufferLength, NvU32 uFlag); + /**< + Application callback function pointer. + Register a callback function for fetching MPEG stream data. + + If application set MXDEC_ATTR_PRE_DETERMINED_BOUNDARY, application should + return MXDEC_BOUNDARY_REACHED when the boundary is detected. + If APP does not set MXDEC_ATTR_PRE_DETERMINED_BOUNDARY, 0 should be returned. + + @param *pPara Parameter to pass on to application callback function + @param ppBuffer Buffer Pointer + @param BufferLength Parameter to pass on to application callback function + @param uFlag Flag for reading bitstream backward/forward. + + + + + +
      #MXDEC_READ_BITSTREAM_FORWARDRead bitstream in forward direction
      #MXDEC_READ_BITSTREAM_BACKWARDRead bitstream in backward direction
      + + @retval The number of bytes read successfully, 0 if no bytes read. + */ + }GFMXDECCALLBACK, *PGFMXDECCALLBACK; + + /****************************************************************************************************/ + /** Returned by application when MXDEC_ATTR_PRE_DETERMINED_BOUNDARY is set and boundary is detected. */ +#define MXDEC_BOUNDARY_REACHED 0x00000001 + + // for backward/forward reading bitstream flags + /** Read bitstream in forward direction. + @see GFMXDECCALLBACK + */ +#define MXDEC_READ_BITSTREAM_FORWARD 0x00000002 + + /** Read bitstream in backward direction. + @see GFMXDECCALLBACK + */ +#define MXDEC_READ_BITSTREAM_BACKWARD 0x00000003 + + /****************************************************************************************************/ + //uiVOLinfo + /** GFMXDECMP4SETVOL::uiVOLinfo : If set indicates that VOL is in short header format. + @see GFMXDECMP4SETVOL*/ +#define MXDEC_MP4_SET_SHORT_HEADER 0x00000001 + + /****************************************************************************************************/ + /** This structure hold information of the PreFill buffer. + */ + typedef struct _GFMXDECPREFILLBUFFER + { + NvU8* pPreFillBuffer; /**< Input, Prefill buffer pointer filled by application. */ + NvU32 PreFillBufferLength; /**< Input, Length of pref-fill buffer. */ + NvU32 PreFillBufferBytesConsumed; /**< Output, Amount of bytes consumed by the component. */ + NvU32 prefill_enabled; /**< Flag to identify if prefill buffer is supplied by application. */ + } GFMXDECPREFILLBUFFER; + + /****************************************************************************************************/ + /** This structure hold the information needed for decoding a Video Object Layer (VOL). + @see GFMXDECTABLE::MxDecMP4DecVOL */ + typedef struct _GFMXDECMP4DECVOL + { + NvU32 uiVOLinfo; /**< Indicates format of the VOL. Set by API. */ + /**< + + + + + + + + + + + + + + + + + + +
      #MXDEC_MP4_SHORT_HEADERShort header format detected
      #MXDEC_MP4_DATA_PARTITIONData Partitioning mode detected
      #MXDEC_MP4_PROFILE_LEVELProfile and level field is valid
      #MXDEC_MP4_PRIORITYPriority field is valid
      #MXDEC_MP4_VSOTYPEVisual object type field is valid
      #MXDEC_MP4_VIDEO_SIGNALVideoFormat and VideoRange fields are valid
      #MXDEC_MP4_COLOR_DESCRIPTIONColor, Transfer and Matrix fields are valid
      #MXDEC_MP4_VOIDVObjectID field is valid
      #MXDEC_MP4_VOLIDVOLID field is valid
      + */ + NvU32 uiWidth; /**< Display width, set by API */ + NvU32 uiHeight; /**< Display height, set by API */ + unsigned int Profile; /**< Mpeg4 Profile. Set by API.*/ + /**< + + +
      #MXDEC_MP4_SIMPLE_PROFILEProfile is simple profile
      #MXDEC_MP4_ADVANCE_SIMPLE_PROFILEProfile is advance simple profile
      + */ + unsigned int Level; /**< Mpeg4 Level. Set by API. */ + unsigned int VObjectID; /**< Video Object ID. Set by API. */ + unsigned int VOLID; /**< Video Object Layer ID. Set by API. */ + unsigned int Priority; /**< Priority(of what (???)). Set by API. */ + unsigned int VSOType; /**< VSO(full form(???)) Type. Set by API. */ + unsigned int VideoFormat; /**< Video Format (what are the possible values (???)). Set by API. */ + unsigned int VideoRange; /**< Video Range. Set by API. */ + unsigned int Color; /**< Color primaries. */ + unsigned int Transfer; /**< Transfer charateristics. */ + unsigned int Matrix; /**< Matrix coefficients(???). */ + GFMXDECPREFILLBUFFER prefill; + }GFMXDECMP4DECVOL, *PGFMXDECMP4DECVOL; + + /****************************************************************************************************/ + //uiVOLinfo + /** GFMXDECMP4DECVOL::uiVOLinfo : Short header format detected. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_SHORT_HEADER 0x00000001 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Data Partitioning mode detected. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_DATA_PARTITION 0x00000002 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Profile and level field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_PROFILE_LEVEL 0x00000004 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Priority field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_PRIORITY 0x00000008 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Visual object type field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_VSOTYPE 0x00000010 + + /** GFMXDECMP4DECVOL::uiVOLinfo : VideoFormat and VideoRange fields are valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_VIDEO_SIGNAL 0x00000020 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Color, Transfer and Matrix fields are valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_COLOR_DESCRIPTION 0x00000040 + + /** GFMXDECMP4DECVOL::uiVOLinfo : VObjectID field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_VOID 0x00000080 + + /** GFMXDECMP4DECVOL::uiVOLinfo : VOLID field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_VOLID 0x00000100 + + /****************************************************************************************************/ + //Profile + /** GFMXDECMP4DECVOL::Profile : Profile is simple profile. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_SIMPLE_PROFILE 0x00000000 + + /** GFMXDECMP4DECVOL::Profile : Profile is advance simple profile. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_ADVANCE_SIMPLE_PROFILE 0x00000009 + + /****************************************************************************************************/ + //resync options + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next nearest VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEAREST_VOL 0x1 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next nearest VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEAREST_VOP 0x2 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next nearest I-VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEAREST_I_VOP 0x4 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEXT_VOL 0x8 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEXT_VOP 0x10 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next I-VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEXT_I_VOP 0x20 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous nearest VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_NEAREST_VOL 0x40 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous nearest VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_NEAREST_VOP 0x80 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous nearest I-VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_NEAREST_I_VOP 0x100 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_PREVIOUS_VOL 0x200 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_PREVIOUS_VOP 0x400 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous I-VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_PREVIOUS_I_VOP 0x800 + + /****************************************************************************************************/ + /** This structure hold the information needed for decoding a Video Object Plane (VOP). + @see GFMXDECTABLE::MxDecMP4DecVOP */ + typedef struct _GFMXDECMP4DECVOP + { + PGFRMSURFACE pRef; /**< Reference VOP, ignore this item, if current VOP is an I. Set by application. */ + PGFRMSURFACE pCur; /**< Current VOP. Set by application. */ + PGFRECT pRefRect; /**< Reference rectangle. Set by application. + pRefRect specifies a rectangle area for GFMxDec to reference the reference image. + This rectangle area should be within the pRef surface. The rectangle top, left should + be aligned by application. Application should call GFMxDecGetAttribute() with + MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT and MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT + attributions to get the required alignment. This rectangle's width and height should + exactly match with the image width and height which has been coded in bit stream. If + pRefRect is NULL, GFMxDec will use pRef surface width and height as reference image dimension. + */ + PGFRECT pCurRect; /**< Current rectangle. Set by application. + pCurRect specifies a rectangle area for GFMxDec to output the decoded image. + This field only take effect when MXDEC_MP4_DEC_VOP_SPECIFY_REFSURF_RECT flag is set. + This rectangle area should be within the pCur surface. The rectangle top, left should be + aligned by application. Application should call GFMxDecGetAttribute() with + MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT and MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT + attributions to get the required alignment. This rectangle's width and height should exactly + match with the image width and height which has been coded in bit stream. If pCurRect is NULL, + GFMxDec will use pCur surface dimension as decoded image dimension. + */ + NvU32 uiVOPinfo; /**< Get current VOP information. Set by API. + + +
      #MXDEC_MP4_VOP_PVOP is coded as P-VOP
      #MXDEC_MP4_NOT_CODEDVOP is not coded
      (???)What about I-VOP?(???)
      + */ + NvU32 uiTimeStamp; /**< Time to display this VOP, in milliseconds. Set by API. */ + NvU8 *pMBInfo; /**< Pointer to array where information of whether the MB is decoded or not is stored. + Each element will tell if this corresponding MB is wrong. Set by API. */ + NvU32 uiVOPOption; /**< Must be used to set ASYNC option */ + + GFMXDECPREFILLBUFFER prefill; + }GFMXDECMP4DECVOP, *PGFMXDECMP4DECVOP; + + /** GFMXDECMP4DECVOP::uiVOPOption: enables ASYNC mode. GFMxDecMP4DecVOP() + will return after pushing the commands but without waiting for them to + complete. This option is useful to achieve some paralellism because + decoded frame is usually not used right away for rendering. So + there is enough time for hardware to complete the decoding before this + frame will be used by app. It is ok to call PostProcessing even when + decoding of this frame is not complete. Inside GPU, hardware synchronizes + with the decoder. */ +#define MXDEC_MP4DECVOP_OP_ASYNC 0x00000001 + + + /****************************************************************************************************/ + //uiVOPinfo + /** GFMXDECMP4DECVOP::uiVOPinfo : VOP is coded as P-VOP. + @see GFMXDECMP4DECVOP */ +#define MXDEC_MP4_VOP_P 0x00000001 + + /** GFMXDECMP4DECVOP::uiVOPinfo : VOP is not coded. + @see GFMXDECMP4DECVOP */ +#define MXDEC_MP4_NOT_CODED 0x00000002 //Not coded VOP + + /****************************************************************************************************/ + //when GF_ERROR is return check the following flag + /** This flag is set when atleast one MB is wrong. If application has setup pMBinfo, it can check which MB is wrong. */ +#define MXDEC_MP4_BAD_MB 0x00010000 + + /****************************************************************************************************/ + +#define MXDEC_ATTR_PRE_DETERMINED_BOUNDARY 0x00000001 + /**< MxDecAPI Attribute : Application will determine the decoding boundary, for MPEG4, this boundary means VOL + and VOP boundary. For certain file formats, those boundary information are stored in the video file, application + can easily use those information to determine the boundary. If APP wants API to detect the boundary, application + should not disable this attribute. This is mainly for streaming case, where application does not have those handy + boundary information. API will automatically detect those boundaries. Application does not need to parse the + bitstream to detect those boundaries.\n + Value to be passed to GFMxDecSetAttribute for setting this attribute: + +
      *pInfo == 1Application will determine the decoding boudary
      *pInfo == 0Application will not determine the decoding boudary
      + @see GFMXDECTABLE::MxDecSetAttribute + */ + +#define MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT 0x00000002 + /**< MxDecAPI Attribute : This attribute only can be used for GFMxDecGetAttribute. If application wants to set pDestRect + in GFMXDECVOP or GFMXDECMP4DECVOP, application must use this attribute to get alignment information and align the rectangle + top & left corner accordingly. Value returned by GFMxDecGetAttribute:\n + *pInfo: Top field alignment in term of lines + @see GFMXDECTABLE::MxDecGetAttribute + */ + +#define MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT 0x00000003 + /**< MxDecAPI Attribute : This attribute only can be used for GFMxDecGetAttribute. If application wants to set pDestRect + in GFMXDECVOP or GFMXDECMP4DECVOP, application must use those attributes to get alignment information and align the rectangle + top & left corner accordinately. Value returned by GFMxDecGetAttrubute:\n + *pInfo: left field alignment in term of pixels + @see GFMXDECTABLE::MxDecGetAttribute + */ + +#define GF_MXDEC_ATTR_DEC_ENABLE_RAISE_WAIT 0x00000004 + /**< MxDecAPI Attribute : This attribute only can be used for GFMxDecSetAttribute. + Value passed to GFMxDecSetAttribute:\n + + + + + +
      *pInfo == 1Raisevectors are allocated per Surface.\n + There will be 2 (3 if PostProcessing is ON) sets of raise-wait happening\n + 1) Decoder raises On_Frame_Decoded, and VxBlt waits.\n + 2) (If enabled in APP) PostProcessing API raises On_PP_Frame_Done, and VxBlt waits.\n + 3) VxBlt raises On_Bltted, and Decoder waits.
      *pInfo == 0 (Default)We do not allocate surface raise vectors but a single raise vector.\n + 1) In Decoder, we poll Frame_done, and return only after its done.\n + 2) In PostProcessing we poll PP_Frame_done, and return only after its done.\n + 3) It is observed that Frame_done & PP_Frame_done bits are affected only if raise is done on those.\n + Thats why single raise vector is still needed. This raise vector is not in any suface but in MxDecHandle.
      + @see GFMXDECTABLE::MxDecSetAttribute + */ + +#define MXDEC_ATTR_DISABLE_EC 0x00000005 + /**< MxDecAPI Attribute : Application can disable Error Concealment (EC) by setting this attribute. By default, EC is enabled. + Decoder has The Error Robustness (ER) and Concealment (EC) for mpeg4 decoding. + + Error Robustness (Always ON) : + The ER means the code will detect any error in the bitstream at proper places and will still proceed ahead for decoding the + remaining stream, for posible non-errored data. + + Error Concealment (Default ON): Can be disabled by this very attribute MXDEC_ATTR_DISABLE_EC. + EC means, the decoder will try to use previously decoded information to simulate the lost data. The below steps of EC: + + Lost Motion Vector recovery and concealment: + 1. Rational interpolation: Predict the lost MV from the current frame + 2. Use MV from prev frame + 3. Use MV from step 3 and 4, to reconstruct 2 sets of the texture data for lost MB. + + @see GFMXDECTABLE::MxDecSetAttribute */ + +#define MXDEC_ATTR_MP4_DEC_GET_MBERR_MAP_MATRIX 0x00000006 + /**< MxDecAPI Attribute : This attribute only can be used for GFMxDecGetAttribute. If application wants to get MB error map for + till recently decoded frame. Input parameter is a character array pMBErrMapMatrix of size "number of MBs in a frame". On returning + this call fills this char array with 1s & 0s. 1: MB correctly decoded & 0: MB corrupted. This is cumulative err map till this call + is made. In this API call after copying the err map to the char array, internal map is resit to all clean MBs. \n + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU8 * pMBErrMapMatrix
      +    
      + @see GFMXDECTABLE::MxDecGetAttribute + */ + + /****************************************************************************************************/ + + /** Typesafe function for opening this component. + + @param hRm (GFRmHandle) Handle specific to Resource Manager API + @param phMxDec (GFMxDecHandle *) Pointer to handle specific to MxDecAPI + @param state (GF_STATE_TYPE) The state is used to decide if a new ChHandle is to be allocated for MxDec component or not. + The values that state can take are: + + + +
      #GF_STATE_DEFAULT
      #GF_STATE_NEW_OR_SHARE
      #GF_STATE_NEW_ONLY
      #GF_STATE_SHARE_ONLY
      + + @param hCh (GFRmChHandle) Resource Manager Channel Handle + + @retval GF_SUCCESS : If successful + @retval GF_ERROR : If error occured + */ + /**< Typesafe functions for opening and closing this component. + This API also checks for hardware resources needed through GFRmHwResourceConstraint(). + Trying to open a second video instance will fail due to existing open context. + */ + +GF_RETTYPE GFMxDecOpen(GFRmHandle hRm, GFMxDecHandle *phMxDec, + GF_STATE_TYPE state, GFRmChHandle hCh); + + /** Typesafe function for opening this component. + + @param phMxDec (GFMxDecHandle *) Pointer to handle specific to MxDecAPI + + Close the video instance. + */ +void GFMxDecClose(GFMxDecHandle *phMxDec); + +GF_RETTYPE GFMxDecGetProperty (GFMxDecHandle MxHandle, PGFPROPERTY pMXProp); +GF_RETTYPE GFMxDecPostProcessing (GFMxDecHandle pdec, PGFMXDECPP pP); +GF_RETTYPE GFMxDecSetAttribute (GFMxDecHandle pdec, NvU32 uiFeature, NvU32 *pInfo); +GF_RETTYPE GFMxDecGetAttribute (GFMxDecHandle pdec, NvU32 uiFeature, NvU32 *pInfo); +GF_RETTYPE GFMxDecSet (GFMxDecHandle pdec, NvU32 uiFeature, void *pInfo); +GF_RETTYPE GFMxDecMP4DecVOL (GFMxDecHandle pdec, PGFMXDECMP4DECVOL pVOL); +GF_RETTYPE GFMxDecMP4DecVOP (GFMxDecHandle pdec, PGFMXDECMP4DECVOP pVOP); +GF_RETTYPE GFMxDecMP4DecResync (GFMxDecHandle pdec, NvU32 ResyncOption); + + //return value +#define GFMXDEC_ERROR_NOT_SUPPORT_FORMAT (GFMXD_ERROR | 0x00000001) + /**< This error is returned when the input file format is not supported by the decoder. */ +#define GFMXDEC_ERROR_HEADER_DAMAGED (GFMXD_ERROR | 0x00000002) + /**< This error is returned when the header of the mpeg4 stream is damaged. */ +#define GFMXDEC_ERROR_NO_VOL_HEADER (GFMXD_ERROR | 0x00000003) + /**< This error is returned when no Video Object Layer (VOL) header is detected. */ +#define GFMXDEC_ERROR_NOT_ENOUGH_SYSTEM_MEM (GFMXD_ERROR | 0x00000004) + /**< This error is returned when system is out of memory. */ + + //return value +#define GFMXDEC_ERROR_DETECTED_VOL (GFMXD_ERROR | 0x00000005) + /**< This error is returned when VOL was detected while decoding VOP. */ +#define GFMXDEC_ERROR_END_OF_FILE (GFMXD_ERROR | 0x00000006) + /**< This error is returned when end of file is reached. */ +#define GFMXDEC_ERROR_CORRUPTED_VOP (GFMXD_ERROR | 0x00000007) + /**< This error is returned when the VOP is corrupted and cannot be recovered. */ + + //return value +#define GFMXDEC_ERROR_RESYNC_END_OF_FILE (GFMXD_ERROR | 0x00000008) + /**< This error is returned when end of file is reached while looking for resync marker. */ +#define GFMXDEC_ERROR_RESYNC_DETECTED_VOL (GFMXD_ERROR | 0x00000009) + /**< This error is returned when a VOL start is detected while searching for VOP resync marker. */ +#define GFMXDECMP4_DSP_TIMEOUT (GFMXD_ERROR | 0x00000010) + /**< This error is returned when DSP does not return anything for a predetermined timeout period. This error indicates possibility of DSP hang. */ +#define GFMXDEC_ERROR_START_CODE (GFMXD_ERROR | 0x00000011) + /**< This error is returned when no start code is found in a chunk of data. */ + + /*@}*/ + + /** @page pageMxDecAppNotes MxDecAPI Application Notes + @section pageMxDecAppNotes1 Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start + GFSDK usage. + + + 1. Initialize the display panel by using GFRmIxInit().\n + + 2. Open the display component by calling GFDxOpen() to get the GFMxDecAPI Dxhandle.\n + + 3. Initialize the display start address, stride and bits per pixel using GFDxSetDisplay().\n + + 4. Get the various attributes of the display panel (width, height, etc) using GFDxGetAttribute().\n + + 5. For clearing the screen, open the graphics component using GFGxOpen() and use GFGxFillRect() for filling the screen with + some color (say, black).\n + + 6. Open the FDev component for performing file I/O using GFFDevOpen() and mount it using GFFDevMount().\n + + 7. Open the Vx component using GFVxOpen() and get the GFVxAPI VxHandle. \n + + 8. Query the properties with GFVxGetProperty() to see whether this GFVxAPI version supports MPEG decoding.\n + + 9. If it supports MPEG decoding, call GFMxDecOpen() to get the GFMxDecAPI MxHandle.\n + + 10. Call GFMxDecGetProperty() to query properties. Check whether this GFMxDAPI version can support the desired + MPEG profile and level.\n + + 11. If the properties check out, call GFRmSurfaceAlloc() to allocate at least one reference surface and one + current surface for decoding purposes.\n + + 12. If the postprocessing engine is needed, allocate one surface to hold the postprocessing results.\n + + 13. For display purposes, the decoder application could call GFVxBlt() for the following two scenarios. \n + (a) Performing color space conversion and then a stretch blit to the primary surface directly. \n + (b) Blitting to the overlay surface.\n + Please refer to the latest GFVxAPI document for additional information. \n + + 14. The decoder application should decode VOP-by-VOP. Call GFMxDecSetVOP() to set up the VOP’s characteristics.\n + + 15. After the decoder application has decoded enough macroblocks, call GFMxDecSetMBs() to trigger the hardware + to decode those macroblocks until all macroblocks in the current VOP are finished. GFMxDecSetMBs() may initiate + the postprocessing engine or video engine automatically.\n + + 16. Before exiting the application, the decoder application should call GFRmSurfaceFree() to free the surfaces + that have been allocated. \n + + 17. Call GFMxClose() with the MxHandle to release the resources of the decoder module.\n + + 18. Similarly, call the close functions of the other components which have been opened.\n + + */ + +#ifdef __cplusplus +} // only need to export C interface if +// used by C++ source code +#endif + +#endif + diff --git a/Start_WM/test6/inc/GFMxDecH264.h b/Start_WM/test6/inc/GFMxDecH264.h new file mode 100755 index 00000000..351ca7ca --- /dev/null +++ b/Start_WM/test6/inc/GFMxDecH264.h @@ -0,0 +1,1536 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an +* express license agreement from NVIDIA Corporation is strictly prohibited. +*/ + +/** @file GFMxDecH264.h +GFSDK H264 Decode API header file. +*/ + +#ifndef _GF_MPEG_DEC_H264__ +#define _GF_MPEG_DEC_H264__ + +#include "nvtypes.h" +#include "GFVx.h" +#include "GFDef.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /** @addtogroup groupMxDecH264 MxDecH264API H264 Decode API + + The H.264/AVC decoder API handles H.264/AVC baseline-compliant bit + streams for this version, but has been defined to handle all of the three + profiles for future expansion. + + The H.264/AVC decoder API has two sets of API—a high level API and a low + level API. + + Using the High Level API + + The high level API has a built-in entropy decoder. It decodes the bit stream + and performs error concealment if the bit stream has an error. This high level + API calls the low level API internally. When using the high level API, the + application can ignore the low level API. + + The MxDecH264API high level functions include the following: + - GFMxDecH264DecSequence() + - GFMxDecH264DecPicture() + - GFMxDecH264Set() + - GFMxDecH264DecSEI() + - GFMxDecH264DecNewFrameNum() + + Using the Low Level API + + The low level API is essentially a macroblock decoder engine. It decodes + macroblock by macroblock. When using the low level API, the application + needs to handle the entropy decoding and error concealment. The low level + API assumes that the information passed from caller is correct, and does not + have any error concealment functionality build in. The application which + called the low level API must make sure that no macroblocks are missing for + any picture. + + The MxDecH264API low level functions include the following: + - GFMxDecH264SetSequence() + - GFMxDecH264SetPicture() + - GFMxDecH264SetSlice() + - GFMxDecH264SetMBs() + + Application Notes + +
        +
      • @ref pageMxDecH264AppNotes +
          +
        • @ref pageMxDecH264AppNotes1 +
        • @ref pageMxDecH264AppNotes2 +
        +
      + */ + /*@{*/ + + /** MxDecH264API property flag: Baseline profile supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_BASELINE 0x00000001UL + + /** MxDecH264API property flag: Main profile supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_MAIN 0x00000002UL + + /** MxDecH264API property flag: Extended profile supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_EXTENDED 0x00000004UL + + /** MxDecH264API property flag: LEVEL 1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL10 0x00000100UL + + /** MxDecH264API property flag: LEVEL 1.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL11 0x00000200UL + + /** MxDecH264API property flag: LEVEL 1.2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL12 0x00000400UL + + /** MxDecH264API property flag: LEVEL 1.3 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL13 0x00000800UL + + /** MxDecH264API property flag: LEVEL 2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL20 0x00001000UL + + /** MxDecH264API property flag: LEVEL 2.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL21 0x00002000UL + + /** MxDecH264API property flag: LEVEL 2.2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL22 0x00004000UL + + /** MxDecH264API property flag: LEVEL 3 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL30 0x00008000UL + + /** MxDecH264API property flag: LEVEL 3.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL31 0x00010000UL + + /** MxDecH264API property flag: LEVEL 3.2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL32 0x00020000UL + + /** MxDecH264API property flag: LEVEL 4 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL40 0x00040000UL + + /** MxDecH264API property flag: LEVEL 4.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL41 0x00080000UL + + /** MxDecH264API property flag: LEVEL 4.2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL42 0x00100000UL + + /** MxDecH264API property flag: LEVEL 5 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL50 0x00200000UL + + /** MxDecH264API property flag: LEVEL 5.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL51 0x00400000UL + + /** MxDecH264API property flag: Post Processing de-blocking supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_DB 0x01000000UL + + /** MxDecH264API property flag: Post Processing de-ringing supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_DR 0x02000000UL + + /** VUI Parameters for GFMXDECH264DECSEQUENCE + */ + typedef struct _GFMXDECH264DECVUI + { + NvU32 num_units_in_tick; + NvU32 time_scale; + NvU32 fixed_frame_rate_flag; + }GFMXDECH264DECVUI, *PGFMXDECH264DECVUI; + + /** Parameter structure for MxDecH264DecSequence(). + Both input and output parameters are passed via this structure to MxDecH264DecSequence(). + @see MxDecH264DecSequence() + */ + typedef struct _GFMXDECH264DECSEQUENCE + { + NvU32 uiSequenceOption; /**< Input flags, see GFMXDECH264_DECSEQUENCEOPTION_* */ + NvU32 SequenceInfo; /**< Output flags, see GF_MXDEC_H264_DEC_SEQUENCE_* */ + NvU16 profile_idc; /**< Output, H264 profile ID */ + NvU16 level_idc; /**< Output, H264 level ID */ + NvU16 seq_parameter_set_id;/** PicOrderCnt(CurrPic) + Greater than 1 specifies that the pan-scan rectangle information persists until + - A new coded video sequence begins + - A picture in an access unit containing a pan-scan rectangle SEI message with the + same value of pan_scan_rect_id is output having + (PicOrderCnt() > PicOrderCnt(CurrPic)) && (PicOrderCnt()<= PicOrderCnt(CurrPic) + pan_scan_rect_repetition_period ) + */ + } GFMXDECH264DECSEIPANSCAN, *PGFMXDECH264DECSEIPANSCAN; + + typedef struct _GFMXDECH264DECSEISUBSEQLAYER + { + NvU32 num_sub_seq_layers_minus1; /**< Output, Specifies the number of sub-sequence layers in the sequence */ + NvU32 accurate_statistics_flag; /**< Output, This flag when equal to 1 indicates that the values of average_bit_rate and + average_frame_rate are rounded from statistically correct values. + When equal to 0 indicates that the average_bit_rate and the average_frame_rate are estimates + and may deviate somewhat from the correct values. + */ + NvU32 average_bit_rate; /**< Output, Indicates the average bit rate in units of 1000 bits per second. */ + NvU32 average_frame_rate; /**< Output, Indicates the average frame rate in units of frames/(256 seconds). */ + } GFMXDECH264DECSEISUBSEQLAYER, *PGFMXDECH264DECSEISUBSEQLAYER; + + typedef struct _GFMXDECH264DECSEISUBSEQ + { + NvU32 sub_seq_layer_num; /**< Output, Identifies the sub-sequence layer number of the target sub-sequence */ + NvU32 sub_seq_id; /**< Output, Identifies the target sub-sequence. */ + NvU32 duration_flag; /**< Output, Equal to 0 indicates that the duration of the target sub-sequence is not specified. */ + NvU32 sub_seq_duration; /**< Output, Specifies the duration of the target sub-sequence in clock ticks of a 90-kHz clock. */ + NvU32 average_rate_flag; /**< Output, equal to 0 indicates that the average bit rate and the average frame rate of the target + sub-sequence are unspecified + */ + NvU32 accurate_statistics_flag; /**< Output, Same as accurate_statistics_flag in _GFMXDECH264DECSEISUBSEQLAYER*/ + NvU32 average_bit_rate; /**< Output, Indicates the average bit rate in (1000 bits)/second of the target sub-sequence.*/ + NvU32 average_frame_rate; /**< Output, Indicates the average frame rate in units of frames/(256 seconds) of the target sub-sequence.*/ + NvU32 num_referenced_subseqs; /**< Output, Specifies the number of sub-sequences that contain pictures that are used as reference pictures + for inter prediction in the pictures of the target sub-sequence. + */ + NvU32 ref_sub_seq_layer_num; + NvU32 ref_sub_seq_id; + NvU32 ref_sub_seq_direction; /**< Output, ref_sub_seq_layer_num, ref_sub_seq_id, and ref_sub_seq_direction identify the sub-sequence + that contains pictures that are used as reference pictures for inter prediction in the pictures + of the target sub-sequence. + */ + } GFMXDECH264DECSEISUBSEQ, *PGFMXDECH264DECSEISUBSEQ; + + + + /** ulBitMask, ulBitpayloadType: Application will set the corresponding bit of ulBitMask depending upon its requirement of the + particular payload type of SEI Message. + H264 Decoder API will set the corresponding bit of ulBitpayloadType depending upon the availability of the + particular payload type indicated by ulBitMask flag in the SEI NAL unit. + + @see ulBitpayloadType, ulBitMask in _GFMXDECH264DECSEI + */ + + /** Bit 0: SEI message for buffering period. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_BUFFERING_PERIOD 0x00000001UL + + /** Bit 1: SEI message for picture timing. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_PICTURE_TIMING 0x00000002UL + + /** Bit 2: SEI message for Pan Scan Rect. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_PAN_SCAN 0x00000004UL + + /** Bit 11: SEI message for Sequence Layer Characterization. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_SEQ_LAYER_CHARECTERIZATION 0x00000800UL + + /** Bit 12: SEI message for Sequence Characterization. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_SEQ_CHARECTERIZATION 0x00001000UL + + /** Parameter structure for MxDecH264DecSEI(). + Both input and output parameters are passed via this structure to MxDecH264DecSEI(). + @see MxDecH264DecSEI() + */ + typedef struct _GFMXDECH264DECSEI + { + NvU32 payloadType; /**< Output, Specifies the type of SEI payload */ + NvU32 payloadSize; /**< Output, Specifies the number of bytes in SEI payload */ + GFMXDECH264DECSEIBUFFERINGPERIOD buffperiod; /**< Output, Complete information after parsing the buffering period message of SEI NAL unit + GFMXDECH264DECSEIBUFFERINGPERIOD structure + */ + GFMXDECH264DECSEIPICTIMING pictiming; /**< Output, Complete information after parsing the pic_timing message of SEI NAL unit + GFMXDECH264DECSEIPICTIMING structure + */ + GFMXDECH264DECSEIPANSCAN panscan; /**< Output, Complete information after parsing the Pan Scan message of SEI NAL unit + GFMXDECH264DECSEIPANSCAN structure + */ + GFMXDECH264DECSEISUBSEQLAYER subseqlayer; /**< Output, Complete information after parsing the sub-Seqlayer message of SEI NAL unit + GFMXDECH264DECSEISUBSEQLAYER structure + */ + GFMXDECH264DECSEISUBSEQ subseq; /**< Output, Complete information after parsing the sub-Seqlayer message of SEI NAL unit + GFMXDECH264DECSEISUBSEQ structure + */ + NvU8 *pPreFillBuffer; /**< Input, Pointer bitstream for sequence header to decode */ + NvU32 PreFillBufferLength;/**< Input, Length of bitstream in bytes, must cover the entire sequence header */ + NvU32 ulBitpayloadType; /**< Output, Each Bit Informs a particular SEI message required by the application + so that the H264 decoder only parses that message related data stream + */ + NvU32 ulBitMask; /**< Input, Each Masking Bit indicated which information is required by the application */ + } GFMXDECH264DECSEI, *PGFMXDECH264DECSEI; + + /** GFMXDECH264DECSEQUENCE::SequenceInfo ouput flagbit: constraint_set0_flag is on in the bitstream. + */ +#define GF_MXDEC_H264_DEC_SEQUENCE_CONSTRAINT_SET0_FLAG 0x00000001 + + /** GFMXDECH264DECSEQUENCE::SequenceInfo ouput flagbit: constraint_set1_flag is on in the bitstream. + */ +#define GF_MXDEC_H264_DEC_SEQUENCE_CONSTRAINT_SET1_FLAG 0x00000002 + + /** GFMXDECH264DECSEQUENCE::SequenceInfo ouput flagbit: constraint_set2_flag is on in the bitstream. + */ +#define GF_MXDEC_H264_DEC_SEQUENCE_CONSTRAINT_SET2_FLAG 0x00000004 + + /** GFMXDECH264DECSEQUENCE::SequenceInfo output flagbit: Frame cropping. + If this flag is set GFMXDECH264DECSEQUENCE::CroppingRect contains a valid + frame cropping rectangle. + */ +#define GF_MXDEC_H264_DEC_SEQUENCE_FRAME_CROPPING_FLAG 0x00000008 + + /** GFMXDECH264DECSEQUENCE::uiSequenceOption input flagbit: Bitstream is passed with GFMxDecH264DecSequence(). + If this flag is set bitstream data is passed with the call to GFMxDecH264DecSequence() + instead via the read bitstrem callback. This can be used only with boundary detection + on application level. The bitstream data is passed via GFMXDECH264DECSEQUENCE::pPreFillBuffer and + GFMXDECH264DECSEQUENCE::PreFillBufferLength. + */ +#define GFMXDECH264_DECSEQUENCEOPTION_PREFILLBUFFER 0x00000001 + +#define GFMXDECH264_MAX_NUM_REF_FRAMES 17 + typedef struct + { + NvU32 POC; + NvU8 isNotDisplayed; + NvU8 RetainDuringDPBFlush; + NvU8 status; + }GFMXDECH264_DPB_DATA; + + + /** Parameter structure for MxDecH264DecPicture(). + Both input and output parameters are passed via this structure to MxDecH264DecPicture(). + @see MxDecH264DecPicture() + */ + typedef struct _GFMXDECH264DECPICTURE + { + NvU32 uiPictureOption; /**< Input flagbits, see GF_MXDEC_H264_DEC_PICTURE_SPECIFY_*. */ + PGFRECT pPictureRect; /**< Input, Target rectangle. + GFMXDECH264DECPICTURE::pPictureRect specifies a rectangle on the + output surface for GFMxDec to output the decoded image. + + This field only take effect when MXDEC_H264_DEC_PICTURE_SPECIFY_SURF_RECT + flag is set. + + The rectangle must be within the surface. The rectangle's top and + left position must be aligned by application. Call GFMxDecGetAttribute() + with #MXDEC_ATTR_H264_DEC_PICTURE_RECT_TOP_ALIGNMENT and + #MXDEC_ATTR_H264_DEC_PICTURE_RECT_LEFT_ALIGNMENT to read the alignment + requirements. The rectangle's width and height must match the video frame + width and height as returned from MxDecH264DecSequence() in + GFMXDECH264DECSEQUENCE::pic_width and GFMXDECH264DECSEQUENCE::pic_height. + + Note: Feature not yet implemented. + */ + NvU32 uiPictureInfo; /**< Output flags, see GF_MXDEC_H264_DEC_PICTURE_*. */ + PGFRMSURFACE reconstructedSurf; /**< Output, Surface holding the decoded picture. + If frame is not decoded then reconstructedSurf will not get initialsed i.e. NULL + So VXBLT is called if the reconstructedSurf is not NULL. + */ + NvU32 uiPictureOrderCount; /**< Output */ + NvU32 uiTimeStamp; /**< Output, frame timestamp in miliseconds, valid only if GF_MXDEC_H264_DEC_PICTURE_TIME_STAMP set. */ + NvU8 * pMBInfo; /**< Output, each element tells the particular MB is wrong or not. */ + NvU32 UsedAsReference; /**< Output */ + NvU8* pPreFillBuffer; /**< Input, Pointer bitstream for frame to decode + The bitstream pointer needs to be 4-bytes aligned. + */ + NvU32 PreFillBufferLength; /**< Input, Length of bitstream in bytes, must cover the entire frame */ + NvU32 PreFillBufferBytesConsumed; /**< Output, Amount of bytes consumed by the component */ + NvU16 flushDPB; /**< Output, set to !=0 by the decoder when it encounters a memory_management_control_operation = 5 + indication in the bitstream. The application should display (if the + NoOutputofPriorPics flag is not set) and flush the entire DPB, i.e remove + all previously stored frames from DPB. + Current frame should not be displayed/flushed. + + See \a NoOutputofPriorPics for more info. + */ + NvU16 NoOutputofPriorPics; /**< Output, set by the decoder when it encounters a no_output_of_prior_pics_flag in + the bitstream. If this set, then flushDPB will also be set. The application + should flush the entire DPB, i.e remove all previously stored frames from DPB. + Current frame should not be displayed/flushed. + + Summary: + + + + + +
      NoOutputofPriorPicsflushDPBApplications response
      1 1 Remove all previously stored frames. No display.
      0 1 Display all previously stored frames and then remove from DPB.
      0 0 Normal operation of decoder.
      + */ + NvU32 ReconSurfaceNumber; /**< Index of reconstructed surface, this is an index into GFMXDECH264SURFLIST::surfList[]. + valid only if GFMXDECH264DECPICTURE::reconstructedSurf is not NULL. + Invalid for streams with picture reordering. + */ + GFMXDECH264_DPB_DATA dpb_data[GFMXDECH264_MAX_NUM_REF_FRAMES]; + } GFMXDECH264DECPICTURE, *PGFMXDECH264DECPICTURE; + + //uiPictureOption + + /** GFMXDECH264DECPICTURE::uiPictureOption input flagbit: Use target rectangle. + If this flag is set, the GFMXDECH264DECPICTURE::pPictureRect will point to + a rectangle on the output surface, where the reconstructed frame is placed. + */ +#define GF_MXDEC_H264_DEC_PICTURE_SPECIFY_SURF_RECT 0x00000001 + + /** GFMXDECH264DECPICTURE::uiPictureOption input flagbit: Bitstream is passed with MxDecH264DecPicture(). + If this flag is set bitstream data is passed with the call to MxDecH264DecPicture() + instead via the read bitstrem callback. This can be used only with frame boundary detection + on application level. The bitstream data is passed via GFMXDECH264DECPICTURE::pPreFillBuffer and + GFMXDECH264DECPICTURE::PreFillBufferLength. + */ +#define GF_MXDEC_H264_DEC_PICTURE_SPECIFY_PREFILLBUFFER 0x00000002 + + //PictureInfo: + + /** GFMXDECH264DECSEQUENCE::PictureInfo output flagbit: Current picture is IDR. + */ +#define GF_MXDEC_H264_DEC_PICTURE_IDR 0x00000001 + + /** GFMXDECH264DECSEQUENCE::PictureInfo output flagbit: GFMXDECH264DECSEQUENCE::uiTimeStamp field is valid. + */ +#define GF_MXDEC_H264_DEC_PICTURE_TIME_STAMP 0x00000002 + + /** GFMXDECH264DECSEQUENCE::PictureInfo output flagbit: Decoded picture has at least one corrupted macroblock. + */ +#define GF_MXDEC_H264_DEC_PICTURE_BAD_MB 0x00000004 + + /** GFMXDECH264DECSEQUENCE::PictureInfo output flagbit: + Required by the application to decide whether post processing should be applied for a particular frame + DeblockingFlag is set, when Deblocking Filtering is disabled for all the slices + DeblockingFlag is reset even if deblocking filtering is enabled for atleast one slice + */ +#define GF_MXDEC_H264_DEC_PICTURE_DEBLOCKING_FILTER 0x00000008 + + typedef struct _GFMXDECH264SEQUENCE + { + NvU32 SequenceInfo; + NvU16 pic_width_in_mbs_minus1; + NvU16 pic_height_in_map_units_minus1; + } GFMXDECH264SEQUENCE, *PGFMXDECH264SEQUENCE; + //PictureInfo: +#define GF_MXDEC_H264_SEQUENCE_FRAME_MB_ONLY_FLAG 0x00000001 + //if frame_mb_only_flag is on, this flag must be on +#define GF_MXDEC_H264_SEQUENCE_MB_ADAPTIVE_FRAME_FIELD_FLAG 0x00000002 + //if mb_adaptive_frame_filed_flag is on, this flag must be on +#define GF_MXDEC_H264_SEQUENCE_DIRECT_8X8_INFERENCE_FLAG 0x00000004 + //if direct_8x8_inference_flag is on, this flag must be on + + + typedef struct _GFMXDECH264PICTURE + { + NvU32 PictureInfo; + PGFRMSURFACE reconstructedSurf; //surface to hold the decoded picture + PGFRECT pRect; + NvU8 weighted_bidpred_idc; + NvS8 chroma_qp_index_offset; + } GFMXDECH264PICTURE, *PGFMXDECH264PICTURE; + //PictureInfo: +#define GF_MXDEC_H264_PICTURE_WEIGHTED_PRED_FLAG 0x00000001 + //if weighted_pred_flag is on, this flag must be on +#define GF_MXDEC_H264_PICTURE_DEBLOCKING_FILTER_CONTROL_PRESENT_FLAG 0x00000002 + //if deblocing_filter_control_present_flag is on, this flag must be on +#define GF_MXDEC_H264_PICTURE_CONSTRAINED_INTRA_PRED_FLAG 0x00000004 + //if constrained_intra_pred_flag is on, this flag must be on +#define GF_MXDEC_H264_PICTURE_IDR 0x00000008 +#define GF_MXDEC_H264_PICTURE_SPECIFY_SURFACE_RECT 0x00000010 + // If this flag is set, pRect must be set. GFMxDec will reference image + // in pRect area of reference surface and output the decoded image in + // the pRect area of reconstructedSurf. Otherwise, GFMxDec will use + // the whole surface area. + + + typedef struct _GFMXDECH264WEIGHT + { + NvS8 luma_weight; + NvS8 luma_offset; + NvS8 Cb_weight; + NvS8 Cb_offset; + NvS8 Cr_weight; + NvS8 Cr_offset; + } GFMXDECH264WEIGHT, *PGFMXDECH264WEIGHT; + + + + typedef struct _GFMXDECH264SLICE + { + NvU32 SliceInfo; + NvU16 first_mb_in_slice; + NvU16 reserved; + NvU8 slice_type; + NvU8 num_ref_idx_l0_active_minues1; + NvU8 num_ref_idx_l1_active_minues1; + NvU8 disable_deblocking_filter_idc ; + NvU8 slice_alpha_c0_offset_div2; + NvU8 slice_beta_offset_div2; + PGFRMSURFACE ref_l0_surfaces[16]; + PGFRMSURFACE ref_l1_surfaces[16]; + GFMXDECH264WEIGHT weighttableL0[16]; + GFMXDECH264WEIGHT weighttableL1[16]; + } GFMXDECH264SLICE, *PGFMXDECH264SLICE; + //SliceInfo: +#define GF_MXDEC_H264_SLICE_FILED_PIC_FLAG 0x01 + //when filed_pic_flag is on, this flag must be set +#define GF_MXDEC_H264_SLICE_BOTTOM_FILED_FLAG 0x02 + //when bottom_field_flag is on, this flag must be set +#define GF_MXDEC_H264_SLICE_DIRECT_SPATIAL_MV_PRED_FLAG 0x04 + //when DIRECT_SPATIAL_MV_PRED_FLAG is on, this flag must be set + + + typedef struct _GFMXDECH264I4X4LPREDMODE + { + NvU32 uiPredMode0to7; //Luma4X4 Blk 0 to 7's prediction modes. + NvU32 uiPredMode8to15; //Luma4X4 Blk 8 to 15's prediction modes. + } GFMXDECH264I4X4LPREDMODE, *PGFMXDECH264I4X4LPREDMODE; + + typedef struct _GFMXDECH264MV + { + NvS16 Horizontal; + //Horizonal motion vector component. + NvS16 Vertical; + //Vertical motion vector component + } GFMXDECH264MV, *PGFMXDECH264MV; + + + typedef struct _GFMXDECH264REFIDX + { + NvU8 Ref_idx_l0[4]; //PartIdx's reference index + NvU8 Ref_idx_l1[4]; //PartIdx's reference index + } GFMXDECH264REFIDX, *PGFMXDECH264REFIDX; + + + typedef struct _GFMXDECH264SUBMBTYPE + { + NvU8 sub_mb_type[4]; //PartIdx's sub_mb_type + } GFMXDECH264SUBMBTYPE, *PGFMXDECH264SUBMBTYPE; + + + typedef struct _GFMXDECH264MB + { + NvU16 uiTotalSize; + //Total size in bytes for current macroblock, including this structure + //itself and necessary following structure behind of this structure. + //Reference the data following GFMXDECH264MB. + NvU16 uiTotalCOEFs;// total Coefs for this macroblock + NvU32 curMBAddress; // current macroblock address + NvU8 MBInfo; + // this is the mb_type in bit stream and mb_field_decoding_flag + NvU8 uiQP; //this is QPy + NvU8 coded_block_pattern; + //This field is only valid when current macroblock is not Intra_16x16 + NvU8 Intra_chroma_pred_mode; + //This field is valid only when current macroblock is Intra + GFMXDECH264SUBMBTYPE sub_mb_type; + union + { + GFMXDECH264I4X4LPREDMODE I4X4LPredMode; //Intra_4X4 only + GFMXDECH264REFIDX RefIdx; //Inter only + } mode; // TODO: Name this better + NvS32 numCoefsPerSubMB[32]; + NvS16 index; + } GFMXDECH264MB, *PGFMXDECH264MB; + + //MBInfo: +#define GF_MXDEC_H264_MB_FILED_DECODING_ENABLE 0x80 + //when mb_field_decoding_flag is on, this flag must be set +#define GF_MXDEC_H264_MB_SKIP_MB 0x40 + //skip MB + + //The data following GFMXDECH264MB: + //If current macroblock is skipped macroblock, no further data is needed. + + //If current macroblock is IPCM, there are 384 bytes following GFMXDECH264MB. + + //If current macroblock is Inter macroblock, and is using picture list 0 only, + //necessary number of GFMXDECH264MV are following. If current macroblock is + //using picture list 1 only, necessary number of GFMXDECH264MV are following. + //If current macroblock is using both picture list 0 and list 1, necessary + //number of GFMXDECH264MV for list 0, and necessary number of GFMXDECH264MV + //for list 1 are following GFMXDECH264MB. + + //For both Intra and Inter macroblock, the last portion of data which follows + //GFMXDECH264MB is GFMXDECH264MB.uiTotalCOEFs of GFMXDECH264COEF. + + + + // definition for attribute + + /** GFMxDecH264 Attribute: Application will determine the decoding boundaries. + For H.264/AVC, this boundary means sequence and picture boundary. For certain file formats, + those boundary information are stored in a meta data file. Alternatively the application + could parse NAL unit boundaries from the H264 stream and determine decoding units. + If application wants GFMxDecH264 to detect the boundary, it should not enable this + attribute. + + If prefill mode (see #GFMXDECH264_DECSEQUENCEOPTION_PREFILLBUFFER) is used, + this attribute must be enabled. Disabled by default. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 1: APP will determine the decoding boudary
      +    0: APP will not determine the decoding boundary
      +    
      + + @see GFMxDecH264GetAttribute(), GFMxDecH264SetAttribute() + */ +#define GF_MXDEC_H264_ATTR_PRE_DETERMINED_BOUNDARY 0x00000001 + + /** GFMxDecH264 Attribute: Enforce display ordering for sequences containing out of order frames. + + Disabled by default. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 !=0: Enable reordering
      +    0: Disable reordering
      +    
      + + @see GFMxDecH264GetAttribute(), GFMxDecH264SetAttribute() + */ +#define GF_MXDEC_H264_ATTR_DISPLAY_REORDERING 0x00000002 + +#define GF_MXDEC_H264_ATTR_DSP_STREAM_BUFFERING 0x00000003 + //This Attribute only can be used for GFMxDecH264SetAttribute + //If the Application wants to set the mode DSP_STREAM_BUFFERING in H264Decoder, enable the #define DSP_STREAM_BUFFERING in App, + //then APP will enable the attribute by calling the GFMxDecH264SetAttribute. + //this attribute is used to pass the buffer details, from Application to the host side of GFSDK H264 component. + + /** GFMxDecH264 Attribute: Enable decode surface locking in MxDecH264DecPicture(). + + MxDecH264DecPicture() returns the decoded surface number in GFMXDECH264DECPICTURE::ReconSurfaceNumber, + which is an index into the decode surface list GFMXDECH264SURFLIST::surfList[] set via + #GF_MXDEC_H264_SET_SURFACE_LIST. If surface locking is enabled, MxDecH264DecPicture() will + automatically 'lock' the returned surface and exclude it from its list of + surfaces used for further decoding. GFMxDecH264 can still read from a locked surface + (for reference frames), but it will not overwrite it. The application must not + write into a locked surface, since it still may be used as reference frame. + + This locking mechanism is intended for usecases, where the application directly displays + the decode surface as video overlay. See also @ref pageMxDecH264AppNotes2 + + With surface locking enable, each successfully decoded surface has to be unlocked by the + application with GFMxDecH264Set / #GF_MXDEC_H264_SET_UNLOCK_SURFACE. + + Since locked surfaces cannot be used for decoding, the number of decoding surfaces + set with #GF_MXDEC_H264_SET_SURFACE_LIST must be R+1+N, where R is the maximum number of + reference frames and N the maximum number of simultaneously locked surfaces. + Otherwise MxDecH264DecPicture() may fail. + + Disabled by default. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 !=0: Enable surface locking
      +    0: Disable surface locking
      +    
      + + @see GFMxDecH264GetAttribute(), GFMxDecH264SetAttribute(), GF_MXDEC_H264_SET_UNLOCK_SURFACE, @ref pageMxDecH264AppNotes2 + */ +#define GF_MXDEC_H264_ATTR_SURFACE_LOCKING 0x00000004 + + /** GFMxDecH264 Attribute: Get H264 decoder's DSP handle. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 DSP handle
      +    
      + + GFMxDecH264GetAttribute() returns error GFMXDECH264_ERROR_INVALID_STATE, if DSP side not initialized. + Can be get only. + + @internal + @see GFMxDecH264GetAttribute() + */ +#define GF_MXDEC_H264_ATTR_GETDSPHANDLE 0x00000005 + +#define GF_MXDEC_H264_ATTR_DEC_PICTURE_RECT_TOP_ALIGNMENT 0x00000007 + //This attribute only can be used for GFMxDecGetAttribute + //If application wants to set pDestRect in GFMXDECPICTURE or GFMXDECH264DECPICTURE, + //application must use this attributes to get allignment information and + //align the rectangle top & left corner accordinately. + //*pInfo: top fieled alignment in term of lines + +#define GF_MXDEC_H264_ATTR_DEC_PICTURE_RECT_LEFT_ALIGNMENT 0x00000008 + //This attribute only can be used for GFMxDecGetAttribute + //If application wants to set pDestRect in GFMXDECH264PICTURE or GFMXDECH264DECPICTURE, + //application must use those attributes to get allignment information and + //align the rectangle top & left corner accordinately. + //*pInfo: left fieled alignment in term of pixels + +#define GF_MXDEC_H264_ATTR_DEC_ENABLE_RAISE_WAIT 0x00000009 + /* + * This attribute only can be used for GFMxDecSetAttribute + * if (*pInfo == 1) + * { + * Raisevectors are allocated per Surface. + * There will be 2 (3 if PostProcessing is ON) sets of raise-wait happening + * 1) Decoder raises On_Frame_Decoded, and VxBlt waits. + * 2) (If enabled in APP) PostProcessing API raises On_PP_Frame_Done, and VxBlt waits. + * 3) VxBlt raises On_Bltted, and Decoder waits. + * } + * else // DEFAULT + * { + * We do not allocate surface raise vectors but a single raise vector + * - In Decoder, we poll Frame_done, and return only after its done + * - In PostProcessing we poll PP_Frame_done, and return only after its done + * - I observed that Frame_done & PP_Frame_done bits are affected only if raise is done on those. Thats why single raise vector is still needed. + * This raise vector is not in any suface but in pdec. + * } + */ + +#define GF_MXDEC_H264_ATTR_LEN_OF_NALSIZE 0x0000000a + /*To support the decoding of .264 stream where NAL size appears instead of StartCode + This is to get the length of the NAL size value*/ +#define GF_MXDEC_H264_ATTR_NALSIZE_DECODING 0x0000000b + /* To support runtime decision making between the start code decoding and NAL size decoding*/ + + + /** GFMxDecH264 Attribute: Indicate to the H264 decoder that surfaces have + already been allocated by the Application before the sps is decoded. + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 (Height << 16)| (Width)
      +    
      + + Can be set only. + */ +#define GF_MXDEC_H264_ATTR_SURFACE_ALLOCATED 0x0000000c + + /** GFMxDecH264 Attribute: Set number of maximum supported reference frames. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 Number of reference frames 
      +    
      + + This can be called before or after GFMxDecH264Set(GF_MXDEC_H264_SET_SURFACE_LIST). + The number of reference frames must be smaller than the number of surfaces + set via GFMxDecH264Set(GF_MXDEC_H264_SET_SURFACE_LIST). + + If this attribute is not set, the number of supported reference frames will be + equal to one less the number of surfaces set in GFMxDecH264Set(GF_MXDEC_H264_SET_SURFACE_LIST). + + Can be set only. + + @see GF_MXDEC_H264_SET_SURFACE_LIST + */ +#define GF_MXDEC_H264_ATTR_MAXREFFRAMES 0x0000000d + + /** GFMxDecH264 Attribute: Get Error Map Matrix for MBs in last decoded frame. + + This attribute only can be used for GFMxDecGetAttribute. If application wants to get MB error map for + till recently decoded frame. Input parameter is a character array pMBErrMapMatrix of size "number of MBs in a frame". On returning + this call fills this char array with 1s & 0s. 1: MB correctly decoded & 0: MB corrupted. This is cumulative err map till this call + is made. In this API call after copying the err map to the char array, internal map is reset to all clean MBs. + Internal map is reset to all clean MBs also when I or SI slice is found. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU8 * pMBErrMapMatrix
      +    
      + + @internal + @see GFMxDecH264GetAttribute() + */ +#define GF_MXDEC_H264_ATTR_GET_MBERR_MAP_MATRIX 0x0000000e + +/** GFMxDecH264 Attribute: Set Error Concealment (EC) Mode ON or OFF. + + EC is Dynamically ON by default. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 !=0: Enable EC
      +            0: Disable EC
      +    
      + + @see GFMxDecH264SetAttribute() +*/ +#define GF_MXDEC_H264_ATTR_SWITCH_EC_MODE 0x0000000f + +/** GFMxDecH264 Attribute: Set Single Slice Per Frame Mode ON or OFF. + + By default multiple slices per frame is assumed. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 !=0: Single slice per frame
      +            0: Multiple slices per frame
      +    
      + + @see GFMxDecH264SetAttribute() +*/ +#define GF_MXDEC_H264_ATTR_SINGLE_SLICE_PER_FRAME 0x00000010 + + + +/** GFMxDecH264 Attribute: Put the h264 decoder in the TSPlayer + mode. This has to be done first, and sets up the h264 decoder to cooperate + with the TS Demux task on the AVP. Does nothing when decode is on the + host +*/ +#define GF_MXDEC_H264_ATTR_SET_TSPLAYER_MODE 0x00000011 + + +/** Parameter structure for MxDecH264PostProcessing(). + Both input and output parameters are passed via this structure to MxDecH264PostProcessing(). + @see MxDecH264PostProcessing() +*/ + + typedef struct _GFMXDECHH264PP + { + PGFRMSURFACE* pDestSurf;/**< input, + pointer to an array of surfaces that will + hold the result from Post Processing + pointer to an array of surfaces to + accommodate auto post processing + */ + PGFRMSURFACE* pSrcSurf; /**< input, + pointer to an array of surfaces to be //post processed + pointer to an array of surfaces to + accommodate auto post processing + */ + PGFRECT pRect; /**< input, + Rectangle area to be processed for both + src and dest surface + */ + + NvU32 numofDestSurf; /**< input, + If MXDEC_PP_AUTO flag is set, this + parameter must be filled + */ + NvU32 numofSrcSurf; /**< input, + If MXDEC_PP_AUTO flag is set, this + parameter must be filled + */ + NvU8 * lpQuantiser; /**< input, + point to array of QPs for Macro Blocks in + the source VOP. GFMX automatically saved + the last two decoded VOP's QP tables, + Decoder application may not need to reload + the table if it can make sure the source + VOP is the one within the last decoded + VOPs. If MXDEC_PP_RELOAD_QUANTIZER is set, + this field must be filled. + */ + NvU32 PPOption; /** + NvS32 >0 Surface index which was returned in GFMXDECH264DECPICTURE::ReconSurfaceNumber. + NvS32 -1 Reset all locked surfaces to unlocked + NvS32 -2 Reserved for internal use + + + @see GF_MXDEC_H264_ATTR_SURFACE_LOCKING + */ +#define GF_MXDEC_H264_SET_UNLOCK_SURFACE 3 + + /** GFMxDecH264Set() feature ID: Sync host side H264 state from DSP side. + @internal + */ +#define GF_MXDEC_H264_SET_SYNC_WITH_DSP 4 + + /** GFMxDecH264Set() feature ID: Set or reset DSP idle callback. + Can be called on DSP side only. + \a pInfo is a pointer to a #GFMXDECH264CALLBACK structure. + @internal + */ +#define GF_MXDEC_H264_SET_DSPIDLEHANDLER 5 + +/** GFMxDecH264Set() feature ID: Allow the DSP message poll thread to wake up and terminate. + Can be called on Host side only. + \a pInfo is ignored. + @internal +*/ +#define GF_MXDEC_H264_SET_EXITDSPMSGTHREAD 6 + + /** Parameter structure for GFMxDecH264Set() feature #GF_MXDEC_H264_SET_DSPIDLEHANDLER. + @internal + */ + typedef struct _GFMXDECH264DSPIDLECALLBACK + { + /** Application defined parameter to forward to GFMXDECH264DSPIDLECALLBACK::pCallBack. */ + void *pPara; + + /** Callback function, which is called from AVP idle loop. + @param pPara Application defined parameter, forwarded from GFMXDECH264DSPIDLECALLBACK::pPara + */ + void (*pCallBack)(void* pPara); + + } GFMXDECH264DSPIDLECALLBACK; + + + /** Parameter structure for GFMxDecH264Set() feature #GF_MXDEC_H264_SET_READBITSTREAM. */ + typedef struct _GFMXDECH264CALLBACK + { + /** Application defined parameter to forward to GFMXDECH264CALLBACK::pCallBack. */ + void *pPara; + + /** Callback function, which is called by MxDecH264 to fetch a portion of bitstream data. + @param pPara Application defined parameter, forwarded from GFMXDECH264CALLBACK::pPara + @param ppBuffer Callback returns address of the next portion of stream data in \a *ppBuffer + @param pBufferLength Callback returns number of bytes in \a ppBuffer in \a *pBufferLength + @param uFlag Specifies scan stream direction + + + +
      GF_MXDEC_H264_READ_BITSTREAM_FORWARD Forward scan
      GF_MXDEC_H264_READ_BITSTREAM_BACKWARDBackward scan
      + + @return If the #MXDEC_ATTR_PRE_DETERMINED_BOUNDARY attribute is set, the callback + should return #GF_MXDEC_H264_BOUNDARY_REACHED when a frame boundary is + detected, or 0 if no boundary is detected. + If the #MXDEC_ATTR_PRE_DETERMINED_BOUNDARY attribute is not set, the callback + should return 0. + */ + NvU32 (*pCallBack)(void* pPara, NvU8** ppBuffer, NvS32* pBufferLength, NvU32 uFlag); + + }GFMXDECH264CALLBACK, *PGFMXDECH264CALLBACK; + + + + /** GFMXDECH264CALLBACK::pCallBack return code */ +#define GF_MXDEC_H264_BOUNDARY_REACHED 0x00000001 + /** GFMXDECH264CALLBACK::pCallBack uFlag value: Stream forward scan. */ +#define GF_MXDEC_H264_READ_BITSTREAM_FORWARD 0x00000002 + /** GFMXDECH264CALLBACK::pCallBack uFlag value: Stream backward scan. */ +#define GF_MXDEC_H264_READ_BITSTREAM_BACKWARD 0x00000003 + + /** Maximum number of surface pointers GFMXDECH264SURFLIST::surfList[]. */ +#define MXDEC_H264_NUM_SURFACES 17 + + /** Parameter structure for GFMxDecH264Set() feature #GF_MXDEC_H264_SET_READBITSTREAM. */ + typedef struct _GFMXDECH264SURFLIST + { + /** Number of valid surfaces in GFMXDECH264SURFLIST::surfList[]. + The number of valid surfaces includes reference, decode surfaces and optional buffer frames. + Must be within range 1 and 17. + */ + NvU32 numSurfs; + + /** Surface pointer list. + + Assuming N is the number of reference frames, the first N+1 surfaces + in this list will be used as reference and decode surfaces. The currently + decoded surface can refer to the N remaining surfaces in this set as + reference frames. + + If surface locking mode (#GF_MXDEC_H264_ATTR_SURFACE_LOCKING) is enabled, + The remaining M = numSurfs - (N+1) surfaces are used as extra surfaces, + to fascilate pre-buffered decoding. + */ + PGFRMSURFACE surfList[MXDEC_H264_NUM_SURFACES]; + + }GFMXDECH264SURFLIST, *PGFMXDECH264SURFLIST; + + + typedef enum + { + GFMX_DEC_H264_INTERRUPT_ENABLE, + GFMX_DEC_H264_INTERRUPT_DISABLE, + GFMX_DEC_H264_INTERRUPT_CLEAR + } GFMX_DEC_H264_INTERRUPT_OPERATION_TYPE; // Interrupt operation. + + typedef enum + { + GFMX_DEC_H264_DSP_COMMAND_INTR, + GFMX_DEC_H264_POST_PROCESSING_DONE_INTR, + GFMX_DEC_H264_DECODE_DONE_INTR + } GFMX_DEC_H264_INTERRUPT_TYPE; + + typedef struct _GFMXDECH264TABLE + { + GF_RETTYPE (* MxDecH264GetProperty)(GFMxDecH264Handle hMxDecH264, PGFPROPERTY pMXProp ); + GF_RETTYPE (* MxDecH264GetStatus)(GFMxDecH264Handle hMxDecH264, NvU32 * pStatus); + GF_RETTYPE (* MxDecH264DecSequence)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264DECSEQUENCE pSequence); + GF_RETTYPE (* MxDecH264DecPicture)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264DECPICTURE pPicture); + GF_RETTYPE (* MxDecH264SetSequence)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264SEQUENCE pSequence); + GF_RETTYPE (* MxDecH264SetPicture)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264PICTURE pPicture); + GF_RETTYPE (* MxDecH264SetSlice)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264SLICE pSlice); + GF_RETTYPE (* MxDecH264SetMBs)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264MB pMBs); + GF_RETTYPE (* MxDecH264PostProcessing)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264PP pP); + GF_RETTYPE (* MxDecH264SetAttribute)(GFMxDecH264Handle hMxDecH264, NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* MxDecH264GetAttribute)(GFMxDecH264Handle hMxDecH264, NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* MxDecH264Set)(GFMxDecH264Handle hMxDecH264, NvU32 uiFeature, void * pInfo); + GF_RETTYPE (* MxDecH264InterruptControl)(GFMxDecH264Handle hMxDecH264, + GFMX_DEC_H264_INTERRUPT_TYPE IntType, GFMX_DEC_H264_INTERRUPT_OPERATION_TYPE op, + void * pData); + GF_RETTYPE (* MxDecH264InterruptHandler)(GFMxDecH264Handle hMxDecH264, + GFMX_DEC_H264_INTERRUPT_TYPE IntType, void * pData); // Reserved. + GF_RETTYPE (* MxDecH264DSPPoll)(GFMxDecH264Handle hMxDecH264, NvU32 timeout); + GF_RETTYPE (* MxDecH264DecSEI)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264DECSEI pSEI); + GF_RETTYPE (* MxDecH264DecNewFrameNum)(GFMxDecH264Handle hMxDecH264,NvU8* VideoBuffPtr,NvU32 VideoBufferLength); + } GFMXDECH264TABLE, *PGFMXDECH264TABLE; + + /**< Typesafe functions for opening and closing this component. + This API also checks for hardware resources needed through GFRmHwResourceConstraint(). + Trying to open a second video instance will fail due to existing open context. + */ +GF_RETTYPE GFMxDecH264Open(GFRmHandle hRm, GFMxDecH264Handle *phMxDecH264, + GF_STATE_TYPE state, GFRmChHandle hCh); + + /**< Close the video instance. + */ +void GFMxDecH264Close(GFMxDecH264Handle *phMxDecH264); + +#if NVCPU_IS_XTENSA +#define MXDH264OFFSET sizeof(GFMXDECH264TABLE) +#else +#define MXDH264OFFSET 0 +#endif + + + /** GFMxDecH264 error code: GFMxDecH264DecSequence() encountered end of bitstream. + @see GFMxDecH264DecSequence() + */ +#define GFMXDECH264_ERROR_SEQUENCE_END_OF_FILE (GFMXDH264_ERROR | 0x00000001) + + /** GFMxDecH264 error code: GFMxDecH264DecSequence() bitstream format not supported. + The sequence header specifies a bitstream format, that is not supported. Most likely + reason for this error is that the H.264 profile is not supported. + @see GFMxDecH264DecSequence() + */ +#define GFMXDECH264_ERROR_SEQUENCE_NOT_SUPPORTED (GFMXDH264_ERROR | 0x00000002) + + /** GFMxDecH264 error code: GFMxDecH264DecSequence() encountered out of GPU memory error. + The application can try to free GPU memory and call GFMxDecH264DecSequence() again. + @see GFMxDecH264DecSequence() + */ +#define GFMXDECH264_ERROR_SEQUENCE_NOT_ENOUGH_MEM (GFMXDH264_ERROR | 0x00000003) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() encountered sequence header. + The application should call GFMxDecH264DecSequence() in response to this return code, + to decode the sequence header. + @see GFMxDecH264DecPicture(), GFMxDecH264DecSequence() + */ +#define GFMXDECH264_ERROR_PICTURE_DETECTED_SEQUENCE (GFMXDH264_ERROR | 0x00000004) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() encountered end of bitstream. + @see GFMxDecH264DecPicture() + */ +#define GFMXDECH264_ERROR_PICTURE_END_OF_FILE (GFMXDH264_ERROR | 0x00000005) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() encountered an unrecoverable bitstream error. + The application should call GFMxDecH264DecPicture() again, MxDecH264 will then + scan for the next frame boundary and try to decode this frame. + @see GFMxDecH264DecPicture() + */ +#define GFMXDECH264_ERROR_PICTURE_CORRUPTED_PICTURE (GFMXDH264_ERROR | 0x00000006) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() encountered out of GPU memory error. + The application can try to free GPU memory and call GFMxDecH264DecPicture() again. + @see GFMxDecH264DecPicture() + */ +#define GFMXDECH264_ERROR_PICTURE_NOT_ENOUGH_MEM (GFMXDH264_ERROR | 0x00000007) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() returns status to inform application + whether picture parameter set is not initialized, which may happen either when picture + parameter set is absent or corrupted. pic_parameter_set_id is checked for negative value. + */ +#define GFMXDECH264_ERROR_PICTURE_PARAMETER_SET_NOT_INITIALIZED (GFMXDH264_ERROR | 0x00000008) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() returns error status to inform application + that picture parameter set is corrupted. + */ +#define GFMXDECH264_ERROR_PICTURE_PARAMETER_SET_CORRUPTED (GFMXDH264_ERROR | 0x00000009) + + /** GFMxDecH264 error code: GFMxDecH264 API was used in invalid state of the decoder. + */ +#define GFMXDECH264_ERROR_INVALID_STATE (GFMXDH264_ERROR | 0x0000000A) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() returns status to inform application that + all the surfaces where it could decode are locked. + */ +#define GFMXDECH264_ERROR_PICTURE_ALL_SURFACES_LOCKED (GFMXDH264_ERROR | 0x0000000B) + + /*For DecPic timeout on DSP side.*/ +#define GFMXDECH264_ERROR_MXDEC_PIC_TIMEOUT (GFMXDH264_ERROR + 0x0000000C) + + + /** GFMxDecH264 error code: GFMxDecH264DecSEI() is not supported in bitstream callback mode. + @see GFMxDecH264DecSEI() + */ +#define GFMXDECH264_ERROR_SEI_NOT_SUPPORTED_FOR_BITSTREAM_CALLBACK_MODE (GFMXDH264_ERROR | 0x0000000D) + + /** GFMxDecH264 error code: GFMxDecH264DecSEI() encountered end of bitstream. + @see GFMxDecH264DecSEI() + */ +#define GFMXDECH264_ERROR_SEI_END_OF_FILE (GFMXDH264_ERROR | 0x0000000E) + + /** GFMxDecH264 error code: GFMxDecH264DecSEI() cannot decode this NAL Unit as its not SEI. + @see GFMxDecH264DecSEI() + */ +#define GFMXDECH264_ERROR_SEI_NOT_SEI_RBSP (GFMXDH264_ERROR | 0x0000000F) + + /** GFMxDecH264 error code: GFMxDecH264DecSEI() Timed out on DSP side. + @see GFMxDecH264DecSEI() + */ +#define GFMXDECH264_ERROR_SEI_TIMEOUT (GFMXDH264_ERROR | 0x00000010) + + /** GFMxDecH264 error code: GFMxDecH264DecNewFrameNum() cannot decode this NAL Unit as + it does not contain frame number information. + @see GFMxDecH264DecNewFrameNum() + */ +#define GFMXDECH264_ERROR_DECFRAMENUM_NOTSUPPORTED (GFMXDH264_ERROR | 0x00000011) + + /* #### MxDecH264 Helper macros. Maybe useful for backward compatible API. #### */ + + /** This function returns version and capabilities of API and hardware. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pMXProp (PGFPROPERTY) Pointer to property structure to be filled in + + @retval #GF_SUCCESS \a pJXProp filled in successfully + @retval #GF_ERROR Some error occured + + The #GFPROPERTY structure passed with parameter \a pMXProp will be + filled in on successfull return. The GFPROPERTY::Capability field + will hold a combination of flagbits indicating capabilities specific + to the MxDecH264API: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GF_MXDEC_H264_CAP_BASELINEBaseline profile supported
      #GF_MXDEC_H264_CAP_MAINMain profile supported
      #GF_MXDEC_H264_CAP_EXTENDEDExtended profile supported
      #GF_MXDEC_H264_CAP_LEVEL10LEVEL 1.0 supported
      #GF_MXDEC_H264_CAP_LEVEL11LEVEL 1.1 supported
      #GF_MXDEC_H264_CAP_LEVEL12LEVEL 1.2 supported
      #GF_MXDEC_H264_CAP_LEVEL13LEVEL 1.3 supported
      #GF_MXDEC_H264_CAP_LEVEL20LEVEL 2.0 supported
      #GF_MXDEC_H264_CAP_LEVEL21LEVEL 2.1 supported
      #GF_MXDEC_H264_CAP_LEVEL22LEVEL 2.2 supported
      #GF_MXDEC_H264_CAP_LEVEL30LEVEL 3.0 supported
      #GF_MXDEC_H264_CAP_LEVEL31LEVEL 3.1 supported
      #GF_MXDEC_H264_CAP_LEVEL32LEVEL 3.2 supported
      #GF_MXDEC_H264_CAP_LEVEL40LEVEL 4.0 supported
      #GF_MXDEC_H264_CAP_LEVEL41LEVEL 4.1 supported
      #GF_MXDEC_H264_CAP_LEVEL42LEVEL 4.2 supported
      #GF_MXDEC_H264_CAP_LEVEL50LEVEL 5.0 supported
      #GF_MXDEC_H264_CAP_LEVEL51LEVEL 5.1 supported
      #GF_MXDEC_H264_CAP_DBPost Processing de-blocking supported
      #GF_MXDEC_H264_CAP_DRPost Processing de-ringing supported
      + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxDecH264API functions. + + @see GFPROPERTY + */ +#define GFMxDecH264GetProperty(hMxDecH264, pMXProp) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264GetProperty(hMxDecH264, pMXProp) + +#define GFMxDecH264GetStatus(hMxDecH264, pStatus) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264GetStatus(hMxDecH264, pStatus) + + /** Decode sequence header. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pSequence (PGFMXDECH264DECSEQUENCE) Pointer to #GFMXDECH264DECSEQUENCE parameter structure + + @retval GF_SUCCESS Sequence header was decoded successfully + + NAL units with nal_unit_type = 7 should be passed to GFMxDecH264DecSequence(). Such NAL units + contain Sequence Parameter Set (SPS). The nal_ref_idc should be a non-zero value. + + This function will be called whenever a sequence header is found in the bitstream, decode + it and return its characteristics. + + @see GFMXDECH264DECSEQUENCE + */ +#define GFMxDecH264DecSequence(hMxDecH264, pSequence)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264DecSequence(hMxDecH264, pSequence) + + /** Decode a picture. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pPicture (PGFMXDECH264DECPICTURE) Pointer to #GFMXDECH264DECPICTURE parameter structure + + @retval GF_SUCCESS Frame was decoded successfully + @retval GFMXDECH264_ERROR_PICTURE_DETECTED_SEQUENCE Sequence header detected + @retval GFMXDECH264_ERROR_PICTURE_END_OF_FILE End of stream encountered + @retval GFMXDECH264_ERROR_PICTURE_CORRUPTED_PICTURE Unrecoverable bitstream error during frame decode + @retval GFMXDECH264_ERROR_PICTURE_NOT_ENOUGH_MEM Out of GPU memory + + All NAL units with nal_unit_type other than 7, should be passed to GFMxDecH264DecPicture(). + In specific, for nal_unit_type value as 8, the NAL Unit contains a Picture Parameter Set (PPS) and + for nal_unit_type ranging between 1 and 5, the NAL units contain coded slices. + + GFMxDecH264DecPicture decodes one picture from the bit stream. If GFMxDecH264DecPicture detects an + error, it will perform error concealment. If the error is not concealable, GFMxDecH264DecPicture returns + the error back to the application. + If the current stream position is not on the start of a frame, the function scans forward until a frame + start or sequence header is detected. + + For actions to take on the particular return codes, refer to the return code documentation. + + @see GFMXDECH264DECPICTURE + */ +#define GFMxDecH264DecPicture(hMxDecH264, pPicture)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264DecPicture(hMxDecH264, pPicture) + + + /** Decode a SEI rbsp. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pSEI (PGFMXDECH264DECSEI) Pointer to #GFMXDECH264DECSEI parameter structure + + @retval GF_SUCCESS SEI rbsp was decoded successfully + @retval GFMXDECH264_ERROR_SEI_NOT_SUPPORTED_FOR_BITSTREAM_CALLBACK_MODE This API is not supported in bitstream callback mode + @retval GFMXDECH264_ERROR_PICTURE_END_OF_FILE End of stream encountered + @retval GFMXDECH264_ERROR_SEI_NOT_SEI_RBSP cannot decode this NAL Unit as its not SEI + + All NAL units with nal_unit_type 6 can be passed to GFMxDecH264DecSEI() for decoding in prefill mode. + + GFMxDecH264DecSEI decodes SEI rbsp. + + For actions to take on the particular return codes, refer to the return code documentation. + + @see GFMXDECH264DECSEI + */ +#define GFMxDecH264DecSEI(hMxDecH264, pSEI)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264DecSEI(hMxDecH264, pSEI) + + + /** Decode slice header and extract framenumber. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param VideoBuffPtr Pointer to bitstream + @param VideoBufferLength Length of bitstream data available in the buffer + + @retval framenum Framenumber of current nal unit data + @retval GFMXDECH264_ERROR_DECFRAMENUM_NOTSUPPORTED Nal unit type not supported + + NAL units with nal_unit_type 1 and 5 can be passed to parse slice header and extract + framenumber. + This function can be used in prefill buffer mode to find all nal units which + belongs to same frame before calling GFMxDecH264DecPicture. + + */ + + +#define GFMxDecH264DecNewFrameNum(hMxDecH264,VideoBuffPtr,VideoBufferLength) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264DecNewFrameNum(hMxDecH264,VideoBuffPtr,VideoBufferLength) + + +#define GFMxDecH264SetSequence(hMxDecH264, pSequence)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetSequence(hMxDecH264, pSequence) + +#define GFMxDecH264SetPicture(hMxDecH264, pPicture)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetPicture(hMxDecH264, pPicture) + +#define GFMxDecH264SetSlice(hMxDecH264, pSlice)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetSlice(hMxDecH264, pSlice) + +#define GFMxDecH264SetMBs(hMxDecH264, pMBs) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetMBs(hMxDecH264, pMBs) + +/** Post Processing on a decoded YUV surface. + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pP (PGFMXDECH264PP) Pointer to #GFMXDECH264PP parameter structure + + @retval GF_SUCCESS Applied post processing on decoded surface successfully + + GFMxDecH264PostProcessing() function can perform DeRinging and DeBlocking or DeBlocking only on a decoded YUV surface data. + + GFMXDECH264DECSEQUENCE::PictureInfo output flagbit (GF_MXDEC_H264_DEC_PICTURE_DEBLOCKING_FILTER) + is set by the API if H264 bit stream does not have in-the-loop DeBlocking. + This means app can perform out-of-the-loop DeBlocking by calling GFMxDecH264PostProcessing(). + If H264 bit stream has in-the-loop processing then hardware H264 decoder will perform in-the-loop DeBlokcing + and API resets this flag to zero to indicate that app should not perform DeBlocking. + + GFMxDecH264PostProcessing can be called any time. we need decoded YUV surface data and Qp values for each MB. + If video is decoded by our hardware decoder then Qp values are saved in the internal SRAM for the last frame. + + + @see GFMXDECH264PP + +*/ + + + +#define GFMxDecH264PostProcessing(hMxDecH264, pP) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264PostProcessing(hMxDecH264, pP) + +#define GFMxDecH264SetAttribute(hMxDecH264, uiFeature, pInfo) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetAttribute(hMxDecH264, uiFeature, pInfo) + +#define GFMxDecH264GetAttribute(hMxDecH264, uiFeature, pInfo) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264GetAttribute(hMxDecH264, uiFeature, pInfo) + + /** Set various runtime parameters. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param uiFeature (NvU32) ID of feature to set + @param pInfo (void*) Feature specific data + + @retval GF_SUCCESS Success + @retval GF_FAILURE Failure + + The following features identified by parameter \a uiFeature can be set, see documentation + for the individual \a uiFeature IDs for interpretation of data in parameter \a pInfo: + + + + + + + + + + + +
      uiFeatureMeaningpInfo interpretation
      #GF_MXDEC_H264_SET_READBITSTREAMSet up a stream callback function.GFMxDec calls + that callback function to request a portion of the bit stream from the application.#GFMXDECH264CALLBACK *
      #GF_MXDEC_H264_SET_SURFACE_LISTSet a list of surfaces for to be used to store reference and decode frames.#GFMXDECH264SURFLIST *
      #GF_MXDEC_H264_SET_UNLOCK_SURFACEUnlock one or all locked surface.NvS32
      + */ +#define GFMxDecH264Set(hMxDecH264, uiFeature, pInfo) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264Set(hMxDecH264, uiFeature, pInfo) + +#define GFMxDecH264InterruptControl(hMxDecH264, IntType, op, pData)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264InterruptControl(hMxDecH264, IntType, op, pData) + +#define GFMxDecH264InterruptHandler(hMxDecH264, IntType, pData)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264InterruptHandler(hMxDecH264, IntType, pData) + +#define GFMxDecH264DSPPoll(MxHandle, timeout)\ + ((PGFMXDECH264TABLE)((NvU32)MxHandle+MXDH264OFFSET))->MxDecH264DSPPoll(MxHandle, timeout) + + //Use the following flags in the setattribute function for the picture boundary mode. + //If you wish to send the sequence header separately from the first frame use the first flag(SEPARATE_SEQUENCE_HEADER) + //else use the second flag. +#define GFMXDECH264_SEPARATE_SEQUENCE_HEADER 0x1 +#define GFMXDECH264_COMBINED_SEQUENCE_HEADER 0x2 + + + /*@}*/ + + /** @page pageMxDecH264AppNotes MxDecH264API Application Notes + + @section pageMxDecH264AppNotes1 Programming Sequence + + Todo + + @section pageMxDecH264AppNotes2 Decode Surface Locking + + The H264 decoder can operate in a surface locking mode, which is activated by + attribute #GF_MXDEC_H264_ATTR_SURFACE_LOCKING. In this mode, GFMxDecH264DecPicture() + will automatically 'lock' the current surface with the decoded frame, and exclude it + from its surface pool available for decoding new frames. + + Surface locking is intended for usecases, were the decode surface is directly used as overlay. + For the duration it is displayed as overlay, the locked state ensures, that it won't be + overwritten. With this mechanism H264 decode and screen update can run in independent thread + contexts. + + If a surface from the pool is locked, it can still be used as a reference frame. + However it will never be reused and overwritten during a succeeding call to + GFMxDecH264DecPicture(). + + The application can re-add the locked surface to the set of writable surfaces by + calling GFMxDecH264Set / GF_MXDEC_H264_SET_UNLOCK_SURFACE. + + A locked surface is identified on return from GFMxDecH264DecPicture() via + GFMXDECH264DECPICTURE::ReconSurfaceNumber. This ID needs to be passed later to + GF_MXDEC_H264_SET_UNLOCK_SURFACE to perform the unlocking. + + The application has to ensure that at least + 1 surfaces + in the pool stay unlocked. If GFMxDecH264DecPicture() is called with unsufficient + free surfaces, error GFMXDECH264_ERROR_PICTURE_ALL_SURFACES_LOCKED will be returned. + + The number of surfaces set via GFMxDecH264Set / GF_MXDEC_H264_SET_SURFACE_LIST / + GFMXDECH264SURFLIST::surfList must be at least N+1+M, where N is the number of reference + frames and M the maximum allowed number of simulteneously locked surfaces. + + The lock-state of all surfaces can be reset via GFMxDecH264Set / GF_MXDEC_H264_SET_UNLOCK_SURFACE + passing -1 as surface ID. + */ + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Start_WM/test6/inc/GFMxDecRV9.h b/Start_WM/test6/inc/GFMxDecRV9.h new file mode 100755 index 00000000..a341d500 --- /dev/null +++ b/Start_WM/test6/inc/GFMxDecRV9.h @@ -0,0 +1,853 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFMxDecRV9.h + GFSDK RV9 Decode API header file. +*/ + +#ifndef _GF_MPEG_DEC_RV9__ +#define _GF_MPEG_DEC_RV9__ + +#include "nvtypes.h" +#include "GFVx.h" + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif +/** @addtogroup group MxDecRV9API +*/ +/*@{*/ + + +// MXDECRV9 CapabilityEx Flag +#define GF_MXDEC_RV9_CAPEx_USE_DSP 0x00000001 +// Whenever DSP is used for decoding +// Surace type should be = GF_SURFACE_VIDEO_MEMORY +// Surface hint type = GF_MEMORY_HINT_BOTTOM_UP +// In case of Host Used for decoding +// Surace type = GF_SURFACE_SYSTEM_MEMORY +// Surface hint type = 0 +// MXDECRV9CapFlags +/************************************************************************************************************/ + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_SIMPLE 0x00000001 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_MEDIUM 0x00000002 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_COMPLEX 0x00000004 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_LEVEL1 0x00000100 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_LEVEL2 0x00000200 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_LEVEL3 0x00000400 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_LEVEL4 0x00000800 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_DB 0x00001000 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_DR 0x00002000 +/*********************************************************************************************************************/ + + + + /** This structure holds various informations each of the frame to be decoded . +This structure is passed as parameter to GFMXDECRV9TABLE::MxDecRV9DecodeFrame. +*/ + +typedef struct _GFMXDECRV9FRAME +{ + + + NvU32 uiFrameOption; /**< uiFrameOption values + + + +
      #GF_MXDEC_RV9_DEC_FRAME_SPECIFY_SURF_RECTspecify rect area to hold the reconstructed image.
      + */ + PGFRECT pFrameRect; /**< not in use */ + NvU32 uiFrameType; /**< set new frame type information +
      + + + + + + +
      #GF_MXDEC_RV9_DISPLAY_FRAME
      #GF_MXDEC_RV9_KEY_FRAME
      #GF_MXDEC_RV9_P_FRAME
      #GF_MXDEC_RV9_B_FRAME
      #GF_MXDEC_RV9_DONT_DISPLAY_FRAME
      #GF_MXDEC_RV9_ERRONEOUS_FRAME
      + */ + PGFRMSURFACE pReconstructedSurf;/**< This is the surface to hold the decoded picture */ + NvU32 uiFrameSequenceCount; /**< set by GFMxDecRV9API */ + NvU32 uiTimeStamp; /**< in terms of millisecond */ + NvU8* pPreFillBuffer; /**< Input, Pointer bitstream for frame to decode */ + NvU32 PreFillBufferLength; /**< Input, Length of bitstream in bytes, must cover the entire frame */ + +}GFMXDECRV9FRAME, *PGFMXDECRV9FRAME; + +//uiFrameOption +/******************************************************************************************/ +/** uiFrameOption for GFMXDECRV9FRAME passed as an argument in MxDecRV9DecodeFrame(). \n +specify rect area to hold the reconstructed image.\n +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame. +*/ +#define GF_MXDEC_RV9_DEC_FRAME_SPECIFY_SURF_RECT 0x00000001 + +//uiFrameType values + +/******************************************************************************************/ +/** uiFrameType values for GFMXDECRV9FRAME set by MxDecRV9DecodeFrame(). \n + +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_DISPLAY_FRAME 0x0 + +/** uiFrameType values for GFMXDECRV9FRAME set by MxDecRV9DecodeFrame(). \n + The decoded Frame is I-frame. +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_KEY_FRAME 0x1 + +/** uiFrameType values for GFMXDECRV9FRAME set by MxDecRV9DecodeFrame(). \n +The Decoded Frame is P-frame. +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_P_FRAME 0x2 + +/** uiFrameType values for GFMXDECRV9FRAME set by MxDecRV9DecodeFrame(). \n + The decoded Frame is B-frame. +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_B_FRAME 0x4 + +/** uiFrameType values for GFMXDECRV9FRAME passed as an argument in MxDecRV9DecodeFrame(). \n + +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_DONT_DISPLAY_FRAME 0x8 + +/** uiFrameType values for GFMXDECRV9FRAME passed as an argument in MxDecRV9DecodeFrame(). \n + Decode frame is Erroneous +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_ERRONEOUS_FRAME 0x16 +/***********************************************************************************************************************/ + +/** This structure holds various informations needed for Post Processing of decoded frame . +This structure is passed as parameter to MxDecRV9PostProcessing(). +*/ +typedef struct _GFMXDECRV9PP +{ + PGFRMSURFACE pPPSurf; + /**< pointer to surface that will + hold the result from Post Processing + */ + PGFRECT pPPRect; + /**< Rectangle area to be processed for both + source and destination surface + */ + + PGFRMSURFACE pSrcSurf; + /**< pointer to surface that will + hold the result from Post Processing + */ + PGFRECT pSrcRect; + /**< Rectangle area to be processed for both + source and destination surface + */ +} GFMXDECRV9PP, *PGFMXDECRV9PP; + +// PPOption +#define GF_MXDEC_RV9_PP_SM_OFF 0x0 //Turn OFF Smoothing filter for this frame +#define GF_MXDEC_RV9_PP_SM_ON 0x1 //Turn ON Smoothing filter for this frame +#define GF_MXDEC_RV9_PP_DR_ON 0x2 //Turn ON DeRinging filter for this frame + + +// Hardware Status +/************************************************************************************************************/ + +#define GF_DECODER_FRAME_DONE 0x00000010 + + + +#define GF_DECODER_PP_FRAME_DONE 0x00000020 + +/*********************************************************************************************************/ +#define GF_DECODER_PP_FRAME_RV9 0x00000040// + + +/** Attribute MxDecRV9Set::uiFeature.\n + Application sets this attribute to register a callback function and + its correpnding parameter to read bitstream data . +@see GFMXDECRV9TABLE::MxDecRV9Set, pInfo should be a pointer to PGFMXDECRV9CALLBACK \n +*/ +#define GF_MXDEC_RV9_SET_READBITSTREAM 0x1 + + + +/** Attribute MxDecRV9Set::uiFeature \n + This will setup the surface list, including all of the ref surface and one reconstructed one. \n +@see GFMXDECRV9TABLE::MxDecRV9Set, pInfo should a pointer PGFMXDECRV9SURFLIST +*/ +#define GF_MXDEC_RV9_SET_SURFACE_LIST 0x2 + + + +/** Attribute MxDecRV9Set::uiFeature \n + This will Set the GFMxDecRV9API to decode the RV8 stream + By default GFMxDecRV9API will assume the stream to be RV9 stream\n +@see GFMXDECRV9TABLE::MxDecRV9Set +*/ +#define GF_MXDEC_RV9_BITSTREAM_RV8 0x4 + + +/** Attribute GFMxDecRV9SetAttribute::uiFeature and GFMxDecRV9GetAttribute::uiFeature \n + Application will determine the decoding boundary, for RV9, this boundary means VOL + and VOP boundary. For certain file formats, those boundary information are + stored in the video file, APP can easily use those information to determine + the boundary. + If APP wants API to detect the boundary,App should not disable this attribute. This is mainly for streaming case, APP does + not have those handy boundary information. API will automatically detects those + boundaries. APP does not need to parse the bitstream to detect those boundaries.\n + *pInfo: 1: APP will determine the decoding boudary\n + *pInfo: 0: APP will not determine the decoding boundary \n +@see GFMXDECRV9TABLE::MxDecRV9SetAttribute +*/ +#define GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY 0x00000001 + + + +/** Attribute GFMxDecRV9GetAttribute::uiFeature \n + This attribute only can be used for GFMxDecGetAttribute + If application wants to set pDestRect in GFMXDECVOP or GFMXDECMP4DECVOP, + application must use this attributes to get allignment information and + align the rectangle top & left corner accordinately.\n + *pInfo: top fieled alignment in term of lines \n +@see GFMXDECRV9TABLE::MxDecRV9GetAttribute +*/ +#define GF_MXDEC_ATTR_RV9_DEC_FRAME_RECT_TOP_ALIGNMENT 0x00000002 + + + +/** Attribute GFMxDecRV9GetAttribute::uiFeature \n + This attribute only can be used for GFMxDecGetAttribute + If application wants to set pDestRect in GFMXDECVOP or GFMXDECMP4DECVOP, + application must use those attributes to get allignment information and + align the rectangle top & left corner accordinately.\n + *pInfo: left fieled alignment in term of pixels\n + +@see GFMXDECRV9TABLE::MxDecRV9GetAttribute +*/ +#define GF_MXDEC_ATTR_RV9_DEC_FRAME_RECT_LEFT_ALIGNMENT 0x00000003 + + +/** Attribute GFMxDecRV9SetAttribute::uiFeature and GFMxDecRV9GetAttribute::uiFeature \n + Application will fill the buffer and push the data to the decoder. +*/ +#define GF_MXDEC_RV9_ATTR_PREFILLBUFFER 0x00000008 + +/********************************************************************************************************/ + +/** Structure holding the callback function pointer. +Used in registering the callback function +The callback function is a function which the API calls to request a portion of the bit stream from the application. +@see GFMXDECRV9TABLE::MxDecRV9Set +*/ + + + +typedef struct _GFMXDECRV9CALLBACK +{ + void *pPara;/**< pPara is a parameter passed from APP, + and APP wants API to call back with this parameter + */ + NvU32 (*pCallBack)(void * pPara, NvU8 ** ppBuffer, NvU32 * BufferLength,NvU32 uFlag); + /**< Application callback function pointer. + Register a callback function for fetching RV9 data. + + @param *pPara Parameter to pass on to application callback function + @param ppBuffer Buffer Pointer + @param BufferLength Parameter to pass on to application callback function + + If APP set GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY, + APP should return GF_MXDEC_RV9HD_BOUNDARY_REACHED when the boundary is + detected. + If APP does not set GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY, + 0 should be returned. + */ + +}GFMXDECRV9CALLBACK, *PGFMXDECRV9CALLBACK; + +#define GF_MXDEC_RV9HD_ENDOFFILE 0x00000200 +#define GF_MXDEC_RV9HD_APP_DETECT_BOUNDARY 0x00001000 +#define GF_MXDEC_RV9HD_BOUNDARY_REACHED 0x00002000 +#define GF_MXDEC_RV9HD_ENDOFFILE_REACHED 0x00004000 +#define GF_MXDEC_RV9HD_APP_PREFILLBUFFER 0x00008000 +#define GF_MXDEC_RV9HD_BEGININGOFFILE_REACHED 0x00010000 + + + +/** MxDecRV9API GFMXDECRV9CALLBACK::(*pCallBack)(, , ,uFlag)\n + for reading bitstream in forward direction +@see GFMXDECRV9CALLBACK +*/ +#define GF_MXDEC_RV9_READ_BITSTREAM_FORWARD 0x00000002 + +/** MxDecRV9API GFMXDECRV9CALLBACK::(*pCallBack)(, , ,uFlag) \n + for reading bitstream in reverse direction. +@see GFMXDECRV9CALLBACK +*/ +#define GF_MXDEC_RV9_READ_BITSTREAM_BACKWARD 0x00000003 + +//Resync options : + +/** MxDecRV9API GFMxDecRV9Resync( ,ResyncOption)\n + Resynchronize forward to the nearest I frame. If the GFMxDecRV9API is right + before an I frame, GFMxDecRV9Resync() returns immediately. Otherwise, + GFMxDecRV9Resync() moves forward, parsing bits until it reaches the first bit of the next I frame. +@see ResyncOption, GFMXDECRV9TABLE::MxDecRV9Resync +*/ + +#define GF_MXDEC_RV9_RESYNC_FORWARD_NEAREST_I_FRAME 0x00000001 + +/** MxDecRV9API GFMxDecRV9Resync(,ResyncOption)\n + Resynchronize backward to the nearest I frame. + GFMxDecRV9Resync() moves backward, parsing bits until it reaches the first bit of the previous I frame. +@see ResyncOption, GFMXDECRV9TABLE::MxDecRV9Resync +*/ +#define GF_MXDEC_RV9_RESYNC_BACKWARD_NEAREST_I_FRAME 0x00000002 + +/** MxDecRV9API GFMxDecRV9Resync(,ResyncOption)\n + Resynchronize backward to the nearest P frame. + GFMxDecRV9Resync() moves backward, parsing bits until it reaches the first bit of the previous P frame. +@see ResyncOption, GFMXDECRV9TABLE::MxDecRV9Resync +*/ +#define GF_MXDEC_RV9_RESYNC_BACKWARD_NEAREST_P_FRAME 0x00000004 + + + +/** this macro is used in GFMXDECRV9SURFLIST structure \n + Reference surfaces for RV9 decoder. */ +#define GF_MXDEC_RV9_NUM_SURFACES 3 + +/** This structure is used to Set up a list of surfaces for RV9 + decoder . +*/ + +typedef struct _GFMXDECRV9SURFLIST +{ + + PGFRMSURFACE SurfList[GF_MXDEC_RV9_NUM_SURFACES]; + /**< an array of PGFRMSURFACE + @see #GF_MXDEC_RV9_NUM_SURFACES + */ + + +}GFMXDECRV9SURFLIST, *PGFMXDECRV9SURFLIST; + +/** This structure is passed to MxDecRV9DecodePictureHeader() function, which sets + different fields of this structure. +*/ +typedef struct _GFMXDECRV9PICHDR +{ + NvU32 uiRV8StreamInfo; + /**< set by GFMxDecRV9API. Valid only if it is RV8 stream + + + + + + + + + + + +
      #GF_MXDEC_RV8_UMVUnrestricted Motion Vector
      #GF_MXDEC_RV8_DFIn loop Deblocking filter
      #GF_MXDEC_RV8_SSSlice Structured
      #GF_MXDEC_RV8_RPRReference Picture Resampling
      #GF_MXDEC_RV8_ROUNDRound off for half pixel motion compensation
      + */ + NvU32 uiRV9StreamInfo; + /**< set by GFMxDecRV9API. Valid only if it is RV9 stream + + + + + +
      #GF_MXDEC_RV9_INTERLACEInterlaced mode used
      #GF_MXDEC_RV9_DF_PASS_THRUIn loop Deblocking filter is disabled
      + */ + NvU32 uiWidth; /**< Video width */ + NvU32 uiHeight; /**< Video height */ + NvU32 uiTR; /**< Temporal reference in milliseconds */ + +}GFMXDECRV9PICHDR, *PGFMXDECRV9PICHDR; + +//uiRV8StreamInfo + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo \n + Unrestricted Motion Vector. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_UMV 0x00000001 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo \n + In loop Deblocking filter. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_DF 0x00000002 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo\n + Slice Structured. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_SS 0x00000004 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo \n + Reference Picture Resampling. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_RPR 0x00000008 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo \n + Round off for half pixel motion compensation. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_ROUND 0x00000010 + +//uiRV9StreamInfo + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV9StreamInfo \n + Interlaced mode used. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV9_INTERLACE 0x00000001 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV9StreamInfo \n + In loop Deblocking filter is disabled. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV9_DF_PASS_THRU 0x00000002 + +//resync options +//TBD + +//when GF_ERROR is return check the following flag +#define GF_MXDEC_RV9_BAD_MB 0x00010000 //there is at least one MB is wrong + //if APP set up pMBInfo, APP can check which MB is wrong + +/** MxDecRV9API interrupt operation types. +Constants to specify operation for a call to MxDecRV9InterruptControl(). +@see GF_MXDEC_RV9_INTERRUPT_OPERATION_TYPE, GFMXDECRV9TABLE::MxDecRV9InterruptControl +*/ +typedef enum +{ + /** Enable interrupt/status assertion for an interrupt type. */ + GF_MXDEC_RV9_INTERRUPT_ENABLE, + + /** Disable interrupt/status assertion for an interrupt type. */ + GF_MXDEC_RV9_INTERRUPT_DISABLE, + + /** Clear interrupt/status assertion for an interrupt type. */ + GF_MXDEC_RV9_INTERRUPT_CLEAR +} GF_MXDEC_RV9_INTERRUPT_OPERATION_TYPE; // Interrupt operation. + + + +/** MxDecRV9API interrupt types. +@see GF_MXDEC_RV9_INTERRUPT_TYPE, GFMXDECRV9TABLE::MxDecRV9InterruptControl and GFMXDECRV9TABLE::MxDecRV9InterruptHandler +*/ +typedef enum +{ + /** Interrupt type is DSP Command Interrupt */ + GF_MXDEC_RV9_DSP_COMMAND_INTR, + + /** Interrupt type Post Processing done */ + GF_MXDEC_RV9_POST_PROCESSING_DONE_INTR, + + /** Interrupt type is Decoding done Interrupt */ + GF_MXDEC_RV9_DECODE_DONE_INTR +} GF_MXDEC_RV9_INTERRUPT_TYPE; + +/** MxDecRV9API virtual function pointer table. */ +typedef struct _GFMXDECRV9TABLE +{ + + /** This function returns version and capabilities of API and hardware. + + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param pMXProp (PGFPROPERTY) Pointer to GFPROPERTY structure to be filled in + + @retval GF_SUCCESS \a pMXProp filled in successfully + @retval GF_ERROR Some error occured + + The GFPROPERTY structure passed with parameter \a pMXProp will be + filled in on successfull return. The GFPROPERTY::Capability field + will hold a combination of flagbits indicating capabilities specific + to the MxDecRV9API: + + + + + + + + + + + + + + + + + + + + +
      #GF_MXDEC_RV9_CAP_SIMPLE support simple profile.
      #GF_MXDEC_RV9_CAP_MEDIUM support medium profile.
      #GF_MXDEC_RV9_CAP_COMPLEX support complex profile
      #GF_MXDEC_RV9_CAP_LEVEL1support LEVEL 1.
      #GF_MXDEC_RV9_CAP_LEVEL2 support LEVEL 2.
      #GF_MXDEC_RV9_CAP_LEVEL3 support LEVEL 3.
      #GF_MXDEC_RV9_CAP_LEVEL4 support LEVEL 4.
      #GF_MXDEC_RV9_CAP_DB support Post Processing's smoothing filter for RV8 streams.
      #GF_MXDEC_RV9_CAP_DR support Post Processing's de-ringing.
      + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxDecRV9API functions. + + @see GFPROPERTY +*/ + GF_RETTYPE (* MxDecRV9GetProperty)(GFMxDecRV9Handle hMxDecRV9, PGFPROPERTY pMXProp ); + + + + GF_RETTYPE (* MxDecRV9GetStatus)(GFMxDecRV9Handle hMxDecRV9, NvU32 * pStatus); + + + /** This function applies the postprocessing filters to the source surface and outputs + the new image to the destitation surface. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param pP (#PGFMXDECRV9PP) Pointer to the PGFMXDECRV9PP. + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + GF_ERROR Return values for the above function + + @see PGFMXDECRV9PP +*/ + GF_RETTYPE (* MxDecRV9PostProcessing)(GFMxDecRV9Handle hMxDecRV9, PGFMXDECRV9PP pP); + + + /** This function sets the MxDecRV9API options. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param uiFeature : + + + + + +
      #GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY will determine the VOL and VOP boundary, for RV9.
      #GF_MXDEC_RV9_ATTR_PREFILLBUFFERApp will fill the buffer and push the data to the decoder.
      + @param pInfo Pointer to the information buffer. + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + +*/ + GF_RETTYPE (* MxDecRV9SetAttribute)(GFMxDecRV9Handle hMxDecRV9, NvU32 uiFeature, NvU32* pInfo); + + + /** This function gets the MxDecRV9API options. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param uiFeature : + + + + + +
      #GF_MXDEC_ATTR_RV9_DEC_FRAME_RECT_TOP_ALIGNMENT
      #GF_MXDEC_ATTR_RV9_DEC_FRAME_RECT_LEFT_ALIGNMENT
      #GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY
      #GF_MXDEC_RV9_ATTR_PREFILLBUFFER
      + @param pInfo Pointer to the information buffer. + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + +*/ + GF_RETTYPE (* MxDecRV9GetAttribute)(GFMxDecRV9Handle hMxDecRV9, NvU32 uiFeature, NvU32* pInfo); + + + /** This function sets the MxDecRV9API options. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param uiFeature : + + + + + + + +
      #GF_MXDEC_RV9_SET_READBITSTREAM will Set up readbitstream call back function.
      #GF_MXDEC_RV9_SET_SURFACE_LISTwill setup the surface list, including all of the ref surface and one reconstructed one.
      #GF_MXDEC_RV9_BITSTREAM_RV8 will Set the GFMxDecRV9API to decode the RV8 stream.
      + @param pInfo Pointer to the information buffer. + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + +*/ + GF_RETTYPE (* MxDecRV9Set)(GFMxDecRV9Handle hMxDecRV9, NvU32 uiFeature, void * pInfo); + + + + +/** This function Decodes the picture header and gives the related information in + PictureHeader. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param pPictureHeader Pointer to the #GFMXDECRV9PICHDR. + @retval GF_SUCCESS \a if it successfully decodes the Header + @retval GF_ERROR Some error occured + GF_ERROR Return values for the above function + + + + + + + + + +
      #GF_ERROR_RV9DECPICTUREHDR_DETECTED There is a sequence header in the bit stream. + Application need to decide this sequence is an error or this + is intended to be in the bit stream.
      #GF_ERROR_RV9DECPICTUREHDR_END_OF_FILE No more bit stream from application.
      #GF_ERROR_RV9DECPICTUREHDR_CORRUPTED GFMxDecRV9DecPicture encounters an un-recoverable error + in the bit stream. Application should call GFMxDecRV9Resync + API to skip this picture.
      #GF_ERROR_RV9DECPICTUREHDR_NOT_ENOUGH_MEM There is not enough memory.
      + + @see GFMXDECRV9PICHDR +*/ + GF_RETTYPE (* MxDecRV9DecodePictureHeader)(GFMxDecRV9Handle hMxDecRV9, PGFMXDECRV9PICHDR pPictureHeader); + + + /** This function decodes one frame from the bitstream. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param pFrame pointer to #PGFMXDECRV9FRAME + @retval GF_SUCCESS \a if successful + @retval #GF_MXDEC_RV9_FRAMEDEC_EOF_REACHED \a No more bit streams from the application. + +*/ + GF_RETTYPE (* MxDecRV9DecodeFrame)(GFMxDecRV9Handle hMxDecRV9, PGFMXDECRV9FRAME pFrame); + + + +/** GFMxDecRV9Resync re-synchronizes to a specific position of a bit stream.. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param ResyncOption : + + + + + + + +
      #GF_MXDEC_RV9_RESYNC_FORWARD_NEAREST_I_FRAME.Resynchronize forward to the nearest I frame.
      #GF_MXDEC_RV9_RESYNC_BACKWARD_NEAREST_I_FRAME.Resynchronize backward to the nearest I frame.
      #GF_MXDEC_RV9_RESYNC_BACKWARD_NEAREST_P_FRAME.Resynchronize backward to the nearest P frame.
      + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + +*/ + GF_RETTYPE (* MxDecRV9Resync)(GFMxDecRV9Handle hMxDecRV9, NvU32 ResyncOption); + + + + + GF_RETTYPE (* MxDecRV9InterruptControl)(GFMxDecRV9Handle hMxDecRV9, + GF_MXDEC_RV9_INTERRUPT_TYPE IntType, GF_MXDEC_RV9_INTERRUPT_OPERATION_TYPE op, + void * pData); + + + + /** This function provides component-level interrupt control for the + MxDecRV9API. It is optional because an interrupt service thread (IST) at the + application level can call the MxDecRV9API to complete the task. + @param hMxDecRV9(GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param IntType MxDecRV9API interrupt type as defined in + “#GF_MXDEC_RV9_INTERRUPT_TYPE” + @param pData Pointer to data being passed in or out. + @retval GF_SUCCESS \a if successful. + @retval GF_ERROR Some error occured. + +*/ + GF_RETTYPE (* MxDecRV9InterruptHandler)(GFMxDecRV9Handle hMxDecRV9, + GF_MXDEC_RV9_INTERRUPT_TYPE IntType, void * pData); // Reserved. + +} GFMXDECRV9TABLE, *PGFMXDECRV9TABLE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFMxDecRV9Open(GFRmHandle hRm, GFMxDecRV9Handle *phMxDecRV9, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMxDecRV9Close(GFMxDecRV9Handle *phMxDecRV9); + +#if NVCPU_IS_XTENSA +#define MXDRV9OFFSET sizeof(GFMXDECRV9TABLE) +#else +#define MXDRV9OFFSET 0 +#endif + + +//ERROR return values for the GFMxDecRV9DecodePictureHeader() + +/** ERROR return values for the GFMxDecRV9DecodePictureHeader() \n + There is a sequence header in the bit stream. + Application need to decide this sequence is an error or this + is intended to be in the bit stream. + @see GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_ERROR_RV9DECPICTUREHDR_DETECTED 0x00000001 + + +/**ERROR return values for the GFMxDecRV9DecodePictureHeader() \n + No more bit stream from application. + @see GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_ERROR_RV9DECPICTUREHDR_END_OF_FILE 0x00000002 + + +/** ERROR return values for the GFMxDecRV9DecodePictureHeader() \n + GFMxDecRV9DecPicture encounters an un-recoverable error + in the bit stream. Application should call GFMxDecRV9Resync + API to skip this picture. + @see GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_ERROR_RV9DECPICTUREHDR_CORRUPTED 0x00000003 + +/**ERROR return values for the GFMxDecRV9DecodePictureHeader() \n + There is not enough memory. +*/ +#define GF_ERROR_RV9DECPICTUREHDR_NOT_ENOUGH_MEM 0x00000004 + +//ERROR return values for MxDecRV9DecodeFrame() +/** ERROR return values for MxDecRV9DecodeFrame()\n + API returns this error when End of file is reached,i.e No more bit stream from application. + once this ERROR is returned, the application should provide more media files to decode or + exit gracefully.*/ +#define GF_MXDEC_RV9_FRAMEDEC_EOF_REACHED 0x00000001 + +/* #### MxDecRV9API Helper macros. Maybe useful for backward compatible API. #### */ + + +/* #### MxDecRV9 Helper macros. Maybe useful for backward compatible API. #### */ +#define GFMxDecRV9GetProperty(hMxDecRV9, pMXProp) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9GetProperty(hMxDecRV9, pMXProp) + +#define GFMxDecRV9GetStatus(hMxDecRV9, pStatus) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9GetStatus(hMxDecRV9, pStatus) + +#define GFMxDecRV9DecodePictureHeader(hMxDecRV9, pPictureHeader)\ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9DecodePictureHeader(hMxDecRV9, pPictureHeader) + +#define GFMxDecRV9PostProcessing(hMxDecRV9, pP) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9PostProcessing(hMxDecRV9, pP); + +#define GFMxDecRV9SetAttribute(hMxDecRV9, uiFeature, pInfo) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9SetAttribute(hMxDecRV9, uiFeature, pInfo) + +#define GFMxDecRV9GetAttribute(hMxDecRV9, uiFeature, pInfo) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9GetAttribute(hMxDecRV9, uiFeature, pInfo) + +#define GFMxDecRV9Set(hMxDecRV9, uiFeature, pInfo) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9Set(hMxDecRV9, uiFeature, pInfo) + +#define GFMxDecRV9DecodeFrame(hMxDecRV9, pFrame) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9DecodeFrame(hMxDecRV9, pFrame) + +#define GFMxDecRV9Resync(hMxDecRV9, ResyncOption) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9Resync(hMxDecRV9, ResyncOption) + +#define GFMxDecRV9InterruptControl(hMxDecRV9, IntType, op, pData)\ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9InterruptControl(hMxDecRV9, IntType, op, pData) + +#define GFMxDecRV9InterruptHandler(hMxDecRV9, IntType, pData)\ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9InterruptHandler(hMxDecRV9, IntType, pData) + + + +/*@}*/ +/*@}*/ + + +/** @page pageMxDecRV9AppNotes MxDecRV9API Application Notes + @section pageMxDecRV9AppNotes1 Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start + GFSDK usage. + + + + 1. Call GFMxDecRV9Open() to obtain RV9Handle. This handle will be passed to different functions of MxDecRV9API. + + 2. Call GFMxDecRV9GetProperty()to querry the properties.Check whether this + MxDecRV9API version can support the desired RV9 profile and level. + + 3. Set different attributes of RV9 decoder using GFMxDecRV9SetAttribute(), + #GFMXDECRV9TABLE::MxDecRV9SetAttribute. + + 4. Decode the picture header using GFMxDecRV9DecodePictureHeader(), + #GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader. + + 5. call GFRmSurfaceAlloc() to allocate at least one reference surface and one + current surface for decoding purposes. + + 6. If the postprocessing engine is needed, allocate one surface to hold the + postprocessing results. + + 7. For display purposes, the decoder application could call GFVxBlt() for + the following two scenarios. Please refer to the latest GFVxAPI document + for additional information. + + + + 8. The decoder application should decode on frame by frame basis. Call GFMxDecRV9DecodeFrame() to decode each frame. + once GF_MXDEC_RV9_FRAMEDEC_EOF_REACHED is returnd by API, application should exit gracefully. + #GFMXDECRV9TABLE::MxDecRV9DecodeFrame + + 9. If Post processing is enabled , call GFMxDecRV9PostProcessing(). + #GFMXDECRV9TABLE::MxDecRV9PostProcessing + + 10. Before exiting the application, the decoder application should call + GFRmSurfaceFree() to free the surfaces that have been allocated. + + 11. Call GFMxDecRV9Close() with RV9Handle to release the resources of the decoder module. + +*/ + + +#ifdef __cplusplus +} // only need to export C interface if + // used by C++ source code +#endif + +#endif diff --git a/Start_WM/test6/inc/GFMxDecVC1.h b/Start_WM/test6/inc/GFMxDecVC1.h new file mode 100755 index 00000000..da28a6ec --- /dev/null +++ b/Start_WM/test6/inc/GFMxDecVC1.h @@ -0,0 +1,732 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFMxDecVC1.h +GFSDK VC1 Decode API header file. +*/ + +#ifndef _GF_MPEG_DEC_VC1__ +#define _GF_MPEG_DEC_VC1__ + +#include "nvtypes.h" +#include "GFVx.h" +#include "GFDef.h" + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif + + /** @addtogroup groupMxDecVC1 MxDecVC1API VC1 Decode API + The VC1 decoder API handles WMV simple profile-compliant bit + streams for this version, but has been defined to handle all of the three + profiles for future expansion. + + The VC1 decoder API has two sets of API—a high level API and a low + level API. + + Using the High Level API + + The high level API has a built-in entropy decoder. It decodes the bit stream. + This high level API calls the low level API internally. When using the high level API, the + application can ignore the low level API. + + The MxDecVC1API high level functions include the following: + - GFMxDecVC1DecSequenceLayer() + - GFMxDecVC1DecPicture() + - GFMxDecVC1Set() + + Using the Low Level API + + The low level API is essentially a macroblock decoder engine. It decodes + macroblock by macroblock. When using the low level API, the application + needs to handle the entropy decoding. The low level + API assumes that the information passed from caller is correct, and does not + have any error concealment functionality build in. The application which + called the low level API must make sure that no macroblocks are missing for + any picture. + + The MxDecVC1API low level functions include the following: + - GFMxDecVC1SetPicture() + - GFMxDecVC1SetMBs() + - GFMxDecVC1SetPicture() + +
        +
      • @ref pageMxDecVC1AppNotes +
          +
        • @ref pageMxDecVC1AppNotes1 +
        +
      + */ + /*@{*/ + + // MXDECVC1CapFlags + + /** MxDecVC1API property flag: Simple profile supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_SIMPLE 0x00000001 + + /** MxDecVC1API property flag: Main profile supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_MAIN 0x00000002 + + /** MxDecVC1API property flag: Extended profile supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_ADVANCE 0x00000004 + + /** MxDecVC1API property flag: Low LEVEL supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LOWLEVEL 0x00000008 + + /** MxDecVC1API property flag: Medium LEVEL supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_MEDIUMLEVEL 0x00000010 + + /** MxDecVC1API property flag: High LEVEL supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_HIGHLEVEL 0x00000100 + + /** MxDecVC1API property flag: LEVEL 0 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL0 0x00000200 + + /** MxDecVC1API property flag: LEVEL 1 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL1 0x00000400 + + /** MxDecVC1API property flag: LEVEL 2 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL2 0x00000800 + + /** MxDecVC1API property flag: LEVEL 3 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL3 0x00001000 + + /** MxDecVC1API property flag: LEVEL 4 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL4 0x00002000 + + + /**Enable the DSP side profiling */ +//#define GF_ENABLE_PROFILER 1 + +// to divert the code for checking the non-working of hw modules as of now +#define USE_HW_MODULES + + /** Parameter structure for MxDecVC1DecSequenceLayer(). + Both input and output parameters are passed via this structure to MxDecVC1DecSequenceLayer(). + @see MxDecVC1DecSequenceLayer() + */ + + + typedef struct _GFMXDECVC1DECSEQUENCELAYER + { + + NvU32 uiSequenceOption; /**< Input flags, see GFMXDECVC1_DECSEQUENCEOPTION_* */ + NvU8 ucSequenceLayerInfo; /**< SequenceLayerInfo Definition */ + NvU16 usWidth; /**< Horizontal size of the coded picture in pixels */ + NvU16 usHeight; /**< Vertical size of the coded picture in pixels */ + NvU8 ucProfile; /**< Profile of the sequence */ + NvU8 ucLevel; /**< Level of the sequence */ + NvU32 uiHRDRate; /**< Peak transmission rate R in bits per second */ + NvU32 uiHRDBufferSize; /**< Buffer size B in milliseconds. */ + NvU32 uiFrameRate; /**< Rounding frame rate of the encoded clips */ + NvU8* pPreFillBuffer; /**< Input, Pointer bitstream for sequence header to decode */ + NvU32 PreFillBufferLength; /**< Input, Length of bitstream in bytes, must cover the entire sequence header */ + NvU32 PreFillBufferBytesConsumed;/**< Output, Amount of bytes consumed by the component */ + + } GFMXDECVC1DECSEQUENCELAYER, *PGFMXDECVC1DECSEQUENCELAYER; + + //SequenceLayerInfo: +#define MXDEC_VC1_CONSTANT_BITRATE 0x00000001 /**< Flag is set when the sequence is encoded at constant bitrate */ +#define MXDEC_VC1_MULTIRESOLUTION 0x00000002 /**< Flag indicating that the frames can be coded at smaller */ + //resolution. Resolution change is allowed only on I pictures. + //Information of the picture + + /** GFMXDECVC1DECSEQUENCELAYER::uiSequenceOption input flagbit: Bitstream is passed with GFMxDecVC1DecSequenceLayer(). + If this flag is set bitstream data is passed with the call to GFMxDecVC1DecSequenceLayer() + instead via the read bitstrem callback. This can be used only with boundary detection + on application level. The bitstream data is passed via GFMXDECVC1DECSEQUENCELAYER::pPreFillBuffer and + GFMXDECVC1DECSEQUENCELAYER::PreFillBufferLength. + */ +#define GFMXDECVC1_DECSEQUENCEOPTION_PREFILLBUFFER 0x00000001 + + + /** Parameter structure for MxDecVC1DecPicture(). + Both input and output parameters are passed via this structure to MxDecVC1DecPicture(). + @see MxDecVC1DecPicture() + */ + typedef struct _GFMXDECVC1DECPICTURE + { + /**< the following fields are set by app */ + NvU32 uiPictureOption; /**< Set by application. Set to 0 for this version.*/ + PGFRMSURFACE pRef; /**< Reference Picture Surface */ + PGFRMSURFACE pCur; /**< Current Picture Surface */ + PGFRECT pRefRect; /**< pRefSurfRect specified a rectangular area within + the pRef surface, and GFMxDecVC1 references the + image in the pRefSurfRect area of the pRef surface. + If pRefSurfRect is NULL, entire pRef surface is referred.*/ + + PGFRECT pCurRect; /**pCurSurfRect specified a rectangular area within + the pCur surface, and GFMxDecVC1 references the + image in the pCurSurfRect area of the pCur surface. + If CurSurfRect is NULL, entire pCur surface is referred. + */ + + /**< the following fields are set by MxDecVC1DecPicture API */ + NvU32 uiPictureInfo; /**< Current Picture Information. */ + + NvU8* pPreFillBuffer; /**< Input, Pointer bitstream for frame to decode */ + NvU32 PreFillBufferLength; /**< Input, Length of bitstream in bytes, must cover the entire frame */ + NvU32 PreFillBufferBytesConsumed; /**< Output, Amount of bytes consumed by the component */ + + NvU32 uiTimeStamp; /**< Value Specified in Picture Layer Header.*/ + NvU8 * pMBInfo; /**< each element tells the particular MB is wrong or not.*/ + +#ifdef GF_ENABLE_PROFILER + + NvU32 DSPTimers[10]; +#endif + + } GFMXDECVC1DECPICTURE, *PGFMXDECVC1DECPICTURE; + + //PictureInfo: +#define MXDEC_VC1_DEC_PICTURE_P 0x00000001 //Flag is set when current Picture is P type +#define MXDEC_VC1_DEC_NOT_CODED 0x00000010 //Flag is set when current picture is not coded. + +//uiPictureOption + +/** GFMXDECVC1DECPICTURE::uiPictureOption input flagbit: Use target rectangle. + If this flag is set, the GFMXDECVC1DECPICTURE::pPictureRect will point to + a rectangle on the output surface, where the reconstructed frame is placed. +*/ +#define GF_MXDEC_VC1_DEC_PICTURE_SPECIFY_SURF_RECT 0x00000001 + +/** GFMXDECVC1DECPICTURE::uiPictureOption input flagbit: Bitstream is passed with MxDecVC1DecPicture(). + If this flag is set bitstream data is passed with the call to MxDecVC1DecPicture() + instead via the read bitstrem callback. This can be used only with frame boundary detection + on application level. The bitstream data is passed via GFMXDECVC1DECPICTURE::pPreFillBuffer and + GFMXDECVC1DECPICTURE::PreFillBufferLength. +*/ +#define GF_MXDEC_VC1_DEC_PICTURE_SPECIFY_PREFILLBUFFER 0x00000002 + +/** GFMXDECVC1DECPICTURE::uiPictureOption input flagbit: If This Flag is Set Reading of + .rcv wrapper will be skipped for each picture. +*/ +#define GF_MXDEC_VC1_DEC_PICTURE_SPECIFY_SKIP_RCV_WRAPPER 0x00000004 + + /**Low level API Picture structure + */ + typedef struct _GFMXDECVC1PICTURE + { + NvU32 PictureInfo; /**< Current Picture Information defined in + //GFMXDECVC1PICTURE Definitions */ + PGFRMSURFACE pRef; /**< Reference Picture Surface */ + PGFRMSURFACE pCur; /**< Current Picture Surface */ + PGFRECT pRefRect; /**< pRefSurfRect specified a rectangular area + within the pRef surface, and GFMxDecVC1 + references the image in the pRefSurfRect + area of the pRef surface. If pRefSurfRect is NULL, + entire pRef surface is referred. */ + PGFRECT pCurRect; /**< pCurSurfRect specified a rectangular area + within the pCur surface, and GFMxDecVC1 + references the image in the pCurSurfRect + area of the pRef surface. If pCurSurfRect is NULL, + entire pCur surface is referred. */ + + } GFMXDECVC1PICTURE, *PGFMXDECVC1PICTURE; + //PictureInfo: +#define MXDEC_VC1_PICTURE_P_PICTURE 0x00000001 + //Indicates a P Picture when set otherwise a I Picture +#define MXDEC_VC1_PICTURE_SPECIFY_REFSURF_RECT 0x00000002 + //If this Flag is set, pRefSurfRect must be set, and GFMxDecVC1 + //references the image in the pRefSurfRect area of the pRef surface. + //Otherwise entire pRef surface is referred. +#define MXDEC_VC1_PICTURE_SPECIFY_CURSURF_RECT 0x00000004 + //If this Flag is set, pCurSurfRect must be set, and GFMxDecVC1 outputs + //the decoded image in the pCurSurfRect area of the pCur surface. + //Otherwise entire pCur surface is referred. +#define MXDEC_VC1_PICTURE_ROUNDING_ONE 0x00000008 + //PICTURE_ROUNDING_TYPE is one + + + /**motion vector information for current macroblock*/ + + typedef struct _GFMXDECVC1VECTOR + { + NvS16 sH_MV_DATA; /**< Horizonal motion vector data. */ + NvS16 sV_MV_DATA; /**< Vertical motion vector data. */ + } GFMXDECVC1VECTOR, *PGFMXDECVC1VECTOR; + + /**coefficient information for macroblock*/ + + typedef struct _GFMXDECVC1COEF + { + NvU8 uiLAST; /**< This last non-zero coefficient in current block */ + NvU8 uiRUN; /**< How many zeroes precede this coefficient */ + NvS16 iLEVEL; /**< This coefficient's level value */ + } GFMXDECVC1COEF, *PGFMXDECVC1COEF; + + /**macroblock information*/ + + typedef struct _GFMXDECVC1MB + { + NvU16 uiX; /**< MB's x position in the picture*/ + NvU16 uiY; /**< MB's y position in the picture*/ + NvU32 uiMBInfo; /**< MacroBlock characteristics*/ + NvU32 uiBlkType[6]; /**< Block characteristics*/ + NvU8 uiBlkCoded[6]; /**< Block characteristics*/ + NvU8 uiBlkNZC[6]; /**< Block characteristics*/ + NvU8 ucFirstCodedBlk; /**< First Coded Block in Macroblock*/ + NvU16 uiQuantiser; /**< current MB's quantiser*/ + GFMXDECVC1VECTOR Vector[4]; /**< motion vector zero ~ three*/ + NvU32 uiNumofCoef; /**< number of GFMXDECVC1COEF //structures for current MB*/ + + } GFMXDECVC1MB, *PGFMXDECVC1MB; + + //MBInfo: +#define MXDEC_VC1_MB_TYPE_INTER 0x1 //inter mb + + /*Quantiser Type of MacroBlock */ +#define MXDEC_VC1_MB_NON_UNIFORM_QUANTISER 0x2 //Non Uniform Quantiser + + +#define MXDEC_VC1_MB_AC_PRED_ON 0x80 //AC prediction is on +#define MXDEC_VC1_MB_FIELDTX 0x100 +#define MXDEC_VC1_MB_MV_1_MVS 0x200 //1 motion vector coded +#define MXDEC_VC1_MB_MV_4_MVS 0x400 //4 motion vector coded +#define MXDEC_VC1_MB_SKIPPED 0x800 //Macro Block not coded + + /* Motion vector direction bits [15:14] */ +#define MXDEC_VC1_MB_DIRECT 0x1000 +#define MXDEC_VC1_MB_FORWARD 0x2000 +#define MXDEC_VC1_MB_BACKWARD 0x4000 + +#define MXDEC_VC1_MB_AUTO_DISPLAY 0x8000 +#define MXDEC_VC1_MB_OVERLAP 0x10000 + + +#define MXDEC_VC1_MB_MV_MODE1MV_HALF_PEL_BILINEAR 0x20000 +#define MXDEC_VC1_MB_MV_MODE1MV_HALF_PEL 0x40000 +#define MXDEC_VC1_MB_MV_MODE_MIXED_MV 0x100000 +#define MXDEC_VC1_MB_MV_MODE_INTENSITY_COMP 0x200000 + +#define MXDEC_VC1_MB_MV_RANGE_64_32 0x400000 +#define MXDEC_VC1_MB_MV_RANGE_128_64 0x800000 +#define MXDEC_VC1_MB_MV_RANGE_512_128 0x1000000 +#define MXDEC_VC1_MB_MV_RANGE_1024_256 0x2000000 + + + //uiBlkInfo +#define MXDEC_VC1_BLK_CODED 0x1 + + +#define MXDEC_VC1_BLK_INTER 0x2 +#define MXDEC_VC1_BLK_INTER8X8 0x4 +#define MXDEC_VC1_BLK_INTER8X4 0x8 +#define MXDEC_VC1_BLK_INTER4X8 0x10 +#define MXDEC_VC1_BLK_INTER4X4 0x20 +#define MXDEC_VC1_BLK_INTER_ANY 0x40 + +#define MXDEC_VC1_BLK_INTRA 0x80 +#define MXDEC_VC1_BLK_INTRA_TOP 0x100 +#define MXDEC_VC1_BLK_INTRA_LEFT 0x200 + + +#define MXDEC_VC1_SUBBLK_0 0x1 +#define MXDEC_VC1_SUBBLK_1 0x2 +#define MXDEC_VC1_SUBBLK_2 0x4 +#define MXDEC_VC1_SUBBLK_3 0x8 + + + + //After GFMX decodes this Macro Block, it will auto trigger video engine to display + //this VOP if decoder application set auto blt on through GFVxBlt. + //If MXDEC_MB_AUTO_PP and MXDEC_MA_AUTO_DISPLAY both on, //GFMX will trigger Post Processing first, then trigger display engine. + + + // definition for attribute + + /** GFMxDecVC1 Attribute: Application will determine the decoding boundary, this boundary + means sequence and picture layer boundary. + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 1: APP will determine the decoding boudary
      +    0: APP will not determine the decoding boundary
      +    
      + + @see GFMxDecVC1GetAttribute(), GFMxDecVC1SetAttribute() + */ +#define GF_MXDEC_VC1_ATTR_PRE_DETERMINED_BOUNDARY 0x00000001 + + /** GFMxDecVC1 Attribute: This attribute only can be used for GFMxDecGetAttribute + If application wants to set pDestRect in GFMXDECPICTURE or GFMXDECVC1DECPICTURE, + application must use this attributes to get allignment information and + align the rectangle top & left corner accordinately. + *pInfo: top fieled alignment in term of lines + */ +#define GF_MXDEC_VC1_ATTR_DEC_PICTURE_RECT_TOP_ALIGNMENT 0x00000010 + + /** GFMxDecVC1 Attribute: This attribute only can be used for GFMxDecVC1GetAttribute + If application wants to set pDestRect in GFMXDECVC1PICTURE or GFMXDECVC1DECPICTURE, + application must use those attributes to get allignment information and + align the rectangle top & left corner accordinately. + *pInfo: left fieled alignment in term of pixels + */ +#define GF_MXDEC_VC1_ATTR_DEC_PICTURE_RECT_LEFT_ALIGNMENT 0x00000011 + + /** GFMxDecVC1 Attribute: Save decoder internal state information. This attribute only can be used for GFMxDecVC1GetAttribute + *pInfo: state handle + */ +#define GF_MXDEC_VC1_ATTR_DEC_SAVE_STATE 0x00000012 + + /** GFMxDecVC1 Attribute: Restore decoder internal state information. This attribute only can be used for GFMxDecVC1SetAttribute + *pInfo: state handle + */ +#define GF_MXDEC_VC1_ATTR_DEC_RESTORE_STATE 0x00000013 + + /** GFMxDecVC1 Attribute: Delete particular state handle. This attribute only can be used for GFMxDecVC1SetAttribute + *pInfo: state handle + */ +#define GF_MXDEC_VC1_ATTR_DEC_DELETE_STATE 0x00000014 + +#define GF_MXDEC_VC1_ATTR_DEC_ENABLE_RAISE_WAIT 0x00000015 + //Use this attribute to enable RaiseWait mechanish. This is required for OpenMax application. + //Decoder works in FRAME_DONE polling mode by default.This attribute only can be used for GFMxDecVC1SetAttribute + //*pInfo: state handle. + + typedef struct _GFMXDECVC1PP + { + PGFRMSURFACE* pDestSurf;/**< pointer to an array of surfaces that will + hold the result from Post Processing + pointer to an array of surfaces to + accommodate auto post processing + */ + PGFRMSURFACE* pSrcSurf; /**< pointer to an array of surfaces to be //post processed + pointer to an array of surfaces to + accommodate auto post processing + */ + PGFRECT pRect; /**< Rectangle area to be processed for both + src and dest surface + */ + NvU32 numofDestSurf; /**< If MXDEC_PP_AUTO flag is set, this + parameter must be filled + */ + NvU32 numofSrcSurf; /**< If MXDEC_PP_AUTO flag is set, this + parameter must be filled + */ + NvU8 * lpQuantiser; /**< point to array of QPs for Macro Blocks in + the source VOP. GFMX automatically saved + the last two decoded VOP's QP tables, + Decoder application may not need to reload + the table if it can make sure the source + VOP is the one within the last decoded + VOPs. If MXDEC_PP_RELOAD_QUANTIZER is set, + this field must be filled. + */ + NvU32 PPOption; /** + + +
      Performing color space conversion and then a stretch blit to the primary surface directly.Blitting to the overlay surface.
      GF_MXDEC_VC1_READ_BITSTREAM_FORWARD Forward scan
      GF_MXDEC_VC1_READ_BITSTREAM_BACKWARDBackward scan
      + + @return If the #MXDEC_ATTR_PRE_DETERMINED_BOUNDARY attribute is set, the callback + should return #GF_MXDEC_VC1_BOUNDARY_REACHED when a frame boundary is + detected, or 0 if no boundary is detected. + If the #MXDEC_ATTR_PRE_DETERMINED_BOUNDARY attribute is not set, the callback + should return 0. + */ + + /**pPara is a parameter passed from APP, + and APP wants API to call back with this parameter */ + + NvU32 (*pCallBack)(void * pPara, NvU8 ** ppBuffer, NvS32 * BufferLength, NvU32 uFlag); + /** If APP set GF_MXDEC_ATTR_PRE_DETERMINED_BOUNDARY, + APP should return GF_MXDEC_VC1_BOUNDARY_REACHED when the boundary is + detected. + If APP does not set GF_MXDEC_ATTR_PRE_DETERMINED_BOUNDARY, + 0 should be returned. */ + + }GFMXDECVC1CALLBACK, *PGFMXDECVC1CALLBACK; + + /** GFMXDECVC1CALLBACK::pCallBack return code */ +#define GF_MXDEC_VC1_BOUNDARY_REACHED 0x00000001 + /** GFMXDECVC1CALLBACK::pCallBack uFlag value: Stream forward scan. */ +#define GF_MXDEC_VC1_READ_BITSTREAM_FORWARD 0x00000002 + /** GFMXDECVC1CALLBACK::pCallBack uFlag value: Stream backward scan. */ +#define GF_MXDEC_VC1_READ_BITSTREAM_BACKWARD 0x00000003 + + + + typedef enum + { + GFMX_DEC_VC1_INTERRUPT_ENABLE, + GFMX_DEC_VC1_INTERRUPT_DISABLE, + GFMX_DEC_VC1_INTERRUPT_CLEAR + } GFMX_DEC_VC1_INTERRUPT_OPERATION_TYPE; // Interrupt operation. + + typedef enum + { + GFMX_DEC_VC1_DECODE_DONE_INTR, + GFMX_DEC_VC1_POST_PROCESSING_DONE_INTR, + GFMX_DEC_VC1_DSP_COMMAND_INTR, + } GFMX_DEC_VC1_INTERRUPT_TYPE; + + typedef struct _GFMXDECVC1TABLE + { + GF_RETTYPE (* MxDecVC1GetProperty)(GFMxDecVC1Handle hMxDecVC1, PGFPROPERTY pMXProp ); + GF_RETTYPE (* MxDecVC1GetStatus)(GFMxDecVC1Handle hMxDecVC1, NvU32 * pStatus); + GF_RETTYPE (* MxDecVC1DecSequenceLayer)(GFMxDecVC1Handle hMxDecVC1, PGFMXDECVC1DECSEQUENCELAYER pSequenceLayer); + GF_RETTYPE (* MxDecVC1DecPicture)(GFMxDecVC1Handle hMxDecVC1, PGFMXDECVC1DECPICTURE pPicture); + GF_RETTYPE (* MxDecVC1SetPicture)(GFMxDecVC1Handle hMxDecVC1, PGFMXDECVC1PICTURE pPicture); + GF_RETTYPE (* MxDecVC1SetMBs)(GFMxDecVC1Handle hMxDecVC1, PGFMXDECVC1MB pMBs); + GF_RETTYPE (* MxDecVC1SetAttribute)(GFMxDecVC1Handle hMxDecVC1, NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* MxDecVC1GetAttribute)(GFMxDecVC1Handle hMxDecVC1, NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* MxDecVC1Set)(GFMxDecVC1Handle hMxDecVC1, NvU32 uiFeature, void * pInfo); + GF_RETTYPE (* MxDecVC1InterruptControl)(GFMxDecVC1Handle hMxDecVC1, + GFMX_DEC_VC1_INTERRUPT_TYPE IntType, GFMX_DEC_VC1_INTERRUPT_OPERATION_TYPE op, + void * pData); + GF_RETTYPE (* MxDecVC1InterruptHandler)(GFMxDecVC1Handle hMxDecVC1, + GFMX_DEC_VC1_INTERRUPT_TYPE IntType, void * pData); // Reserved. + GF_RETTYPE (* MxDecVC1DecResync)(GFMxDecVC1Handle hMxDecVC1, NvU32 ResyncOption); + } GFMXDECVC1TABLE, *PGFMXDECVC1TABLE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFMxDecVC1Open(GFRmHandle hRm, GFMxDecVC1Handle *phMxDecVC1, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMxDecVC1Close(GFMxDecVC1Handle *phMxDecVC1); + +#if NVCPU_IS_XTENSA +#define MXDVC1OFFSET sizeof(GFMXDECVC1TABLE) +#else +#define MXDVC1OFFSET 0 +#endif + + /** #### MxDecVC1 Helper macros. Maybe useful for backward compatible API. #### + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxDecVC1API functions. + + @see GFPROPERTY + */ + +#define GFMxDecVC1GetProperty(hMxDecVC1, pMXProp) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1GetProperty(hMxDecVC1, pMXProp) + +#define GFMxDecVC1GetStatus(hMxDecVC1, pStatus) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1GetStatus(hMxDecVC1, pStatus) + + /** Decode sequence header. + + @param hMxDecVC1 (GFMxDecVC1Handle) Handle to MxDecVC1 component + @param pSequence (PGFMXDECVC1DECSEQUENCELAYER) Pointer to #GFMXDECVC1DECSEQUENCELAYER parameter structure + + @retval GF_SUCCESS Sequence header was decoded successfully + + This function will be called whenever a sequence header is found in the bitstream, decode + it and return its characteristics. + + @see GFMXDECVC1DECSEQUENCELAYER + */ +#define GFMxDecVC1DecSequenceLayer(hMxDecVC1, pSequenceLayer)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1DecSequenceLayer(hMxDecVC1, pSequenceLayer) + + + //return value + /** GFMxDecVC1 error code: GFMxDecVC1DecSequenceLayer() encountered end of bitstream. + @see GFMxDecVC1DecSequenceLayer() + */ +#define GFMXDECVC1_SEQUENCELAYER_ERROR_END_OF_FILE (GFMXDVC1_ERROR | 0x00000001) + + /** GFMxDecVC1 error code: GFMxDecVC1DecSequenceLayer() bitstream format not supported. + The sequence header specifies a bitstream format, that is not supported. Most likely + reason for this error is that the VC1 profile is not supported. + @see GFMxDecVC1DecSequenceLayer() + */ +#define GFMXDECVC1_SEQUENCELAYER_ERROR_NOT_SUPPORT_FORMAT (GFMXDVC1_ERROR | 0x00000002) + + /** GFMxDecVC1 error code: GFMxDecVC1DecSequenceLayer() bitstream format is damaged due to + erroroneous stream. + @see GFMxDecVC1DecSequenceLayer() + */ +#define GFMXDECVC1_SEQUENCELAYER_ERROR_HEADER_DAMAGED (GFMXDVC1_ERROR | 0x00000003) + + /** GFMxDecVC1 error code: GFMxDecVC1DecSequenceLayer() encountered out of GPU memory error. + The application can try to free GPU memory and call GFMxDecVC1DecSequenceLayer() again. + @see GFMxDecVC1DecSequenceLayer() + */ +#define GFMXDECVC1_SEQUENCELAYER_ERROR_NOT_ENOUGH_SYSTEM_MEM (GFMXDVC1_ERROR | 0x00000004) + + + /** Decode a picture. + + @param GFMxDecVC1 (GFMxDecVC1Handle) Handle to MxDecVC1 component + @param pPicture (PGFMXDECVC1DECPICTURE) Pointer to #GFMXDECVC1DECPICTURE parameter structure + + @retval GF_SUCCESS Frame was decoded successfully + @retval GFMXDECVC1_PICTURE_ERROR_END_OF_FILE End of stream encountered + @retval GFMXDECVC1_PICTURE_ERROR_CORRUPTED_PICTURE Unrecoverable bitstream error during frame decode + @retval GFMXDECVC1_PICTURE_ERROR_NOT_ENOUGH_SYSTEM_MEM Out of GPU memory + @retval GFMXDECVC1_ERROR_RESYNC_END_OF_FILE Resync was found at end of bitstream. + @retval GFMXDECVC1_ERROR_P_PICTURE_FOUND_AT_START instead of Inter frame, intra was found in beginning. + @retval GFMXDECVC1_ERROR_DSP_TIMEOUT AVP times out + + GFMxDecVC1DecPicture decodes one picture from the bit stream. If GFMxDecVC1DecPicture detects an + error, GFMxDecVC1DecPicture returns the error back to the application. + If the current stream position is not on the start of a frame, the function scans forward until a frame + start or sequence header is detected. + + @see GFMXDECVC1DECPICTURE + */ +#define GFMxDecVC1DecPicture(hMxDecVC1, pPicture)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1DecPicture(hMxDecVC1, pPicture) + + //return value + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() encountered end of bitstream. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_PICTURE_ERROR_END_OF_FILE (GFMXDVC1_ERROR | 0x00000005) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() encountered an unrecoverable bitstream error. + The application should call GFMxDecVC1DecResync() again, MxDecVC1 will then + scan for the next frame boundary and try to decode this frame. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_PICTURE_ERROR_CORRUPTED_PICTURE (GFMXDVC1_ERROR | 0x00000006) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() encountered out of GPU memory error. + System memory is not enough to decode Picture. The application can try to free GPU memory and call + GFMxDecVC1DecPicture() again. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_PICTURE_ERROR_NOT_ENOUGH_SYSTEM_MEM (GFMXDVC1_ERROR | 0x00000007) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() upon calling GFMxDecVC1DecResync() + encountered end of bitstream. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_ERROR_RESYNC_END_OF_FILE (GFMXDVC1_ERROR | 0x00000008) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() got a + "P" frame without it's prior reference frame + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_ERROR_P_PICTURE_FOUND_AT_START (GFMXDVC1_ERROR | 0x00000009) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() DSP times out while decoding. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_ERROR_DSP_TIMEOUT (GFMXDVC1_ERROR | 0x0000000a) // dsp hang workaround :( + +#define GFMxDecVC1SetPicture(hMxDecVC1, pPicture)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1SetPicture(hMxDecVC1, pPicture) + +#define GFMxDecVC1SetMBs(hMxDecVC1, pMBs) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1SetMBs(hMxDecVC1, pMBs); + +#define GFMxDecVC1SetAttribute(hMxDecVC1, uiFeature, pInfo) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1SetAttribute(hMxDecVC1, uiFeature, pInfo) + +#define GFMxDecVC1GetAttribute(hMxDecVC1, uiFeature, pInfo) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1GetAttribute(hMxDecVC1, uiFeature, pInfo) + +#define GFMxDecVC1Set(hMxDecVC1, uiFeature, pInfo) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1Set(hMxDecVC1, uiFeature, pInfo) + +#define GFMxDecVC1DecResync(hMxDecVC1, ResyncOption) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1DecResync(hMxDecVC1, ResyncOption) + +#define GFMxDecVC1InterruptControl(hMxDecVC1, IntType, op, pData)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1InterruptControl(hMxDecVC1, IntType, op, pData) + +#define GFMxDecVC1InterruptHandler(hMxDecVC1, IntType, pData)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1InterruptHandler(hMxDecVC1, IntType, pData) + + + //resynch value +#define MXDEC_VC1_RESYNC_FORWARD_NEXT_PICTURE 0x00000001 + // resync to next picture +#define MXDEC_VC1_RESYNC_FORWARD_NEXT_I_PICTURE 0x00000002 + // resync to next I Picture +#define MXDEC_VC1_RESYNC_BACKWARD_PREVIOUS_PICTURE 0x00000004 + // resync to next picture +#define MXDEC_VC1_RESYNC_BACKWARD_PREVIOUS_I_PICTURE 0x00000008 + // resync to next I Picture + + //return value +#define VC1DECRESYNC_END_OF_FILE 0x00000002 // end of file whie resync + + /*@}*/ + + /** @page pageMxDecVC1AppNotes MxDecVC1API Application Notes + + @section pageMxDecVC1AppNotes1 Programming Sequence + + Todo + */ + + +#ifdef __cplusplus +} // only need to export C interface if +// used by C++ source code +#endif + +#endif + + diff --git a/Start_WM/test6/inc/GFMxDemTS.h b/Start_WM/test6/inc/GFMxDemTS.h new file mode 100755 index 00000000..3dbca68e --- /dev/null +++ b/Start_WM/test6/inc/GFMxDemTS.h @@ -0,0 +1,725 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFMxDemTS.h + GFSDK MPEG2 Transport Stream API (host) header file. +*/ + +#ifndef _GF_MPEG_TS__ +#define _GF_MPEG_TS__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup groupMxDemTS MxDemTSAPI MPEG2 Transport Stream Demux API + + This GFSDK component allows to create MPEG TS demux parsers either running + on the host or DSP side. TS data can be pushed from the application, + or be streamed from VIP. + + The are multiple types of parser objects, see also GFMXDEMTSPARSERTYPE: +
      +    GFMXDEMTSPARSERTYPE_HOST      - demux running on host
      +    GFMXDEMTSPARSERTYPE_DSP       - demux running on DSP  
      +    GFMXDEMTSPARSERTYPE_DSPAVSYNC - demux running on DSP with additional AVSync functionality
      +    
      + + Programming Sequence for Parsers running on Host, TS data from host + + - Call GFMxDemTSParserCreate(), in parameter structure GFMXDEMTSPARSERREQUEST pass + parameters #GFMXDEMTSPARSERTYPE_HOST and #GFMXDEMTSPARSERDATASOURCE_PUSH, + pass callback functions to handle demuxed substreams + - Poll GFMxDemTSParserPushData() to pass the incoming TS stream + - Call GFMxDemTSParserDestroy() to destroy parser object + + Programming Sequence for Parsers running on DSP, TS data from host + + - Call GFMxDemTSParserCreate(), in parameter structure GFMXDEMTSPARSERREQUEST pass + parameters #GFMXDEMTSPARSERTYPE_DSP and #GFMXDEMTSPARSERDATASOURCE_PUSH, + pass callback functions to handle demuxed substreams + - Poll GFMxDemTSParserPushData() to pass the incoming TS stream + - Call GFMxDemTSParserDestroy() to destroy parser object + - Destroy the DSP message handling thread + + Programming Sequence for Parser running on DSP, TS data from VIP + + Only one parser at a time can be created to capture data from VIP. + For this mode the parser must run on DSP. +*/ +/*@{*/ + +/** GFMxDemTSParser Maximum number of supported Services. + For ISDB-T 1seg, the max is 8 according to ARIB TR-B14, p7-28 +*/ +#define GFMXDEMTS_MAX_SERVICE_NO 8 + +/** GFMxDemTSParser Maximum number of supported Audio PES. + For ISDB-T 1seg, the max is 2. +*/ +#define GFMXDEMTS_MAX_AUDIO_PID_NO 2 + +/** Get TS Audio PID. + For detail see #GFMXDEMTSPARSERAUDIOPIDLIST. + @param audio (NvU32) Combined type and ID value + */ +#define GFMXDEMTS_GET_AUDIO_PID(audio) (audio & 0x1FFFU) // Get the lower 13 bits + +/** Get TS Service Type. + For detail see #GFMXDEMTSPARSERAUDIOPIDLIST. + @param service (NvU32) Combined type and ID value +*/ +#define GFMXDEMTS_GET_AUDIO_TYPE(audio) (audio >> 16) + +/** TS Audio Pid List. */ +typedef struct _GFMXDEMTSPARSERAUDIOPIDLIST +{ + NvU32 uAudioPidList[GFMXDEMTS_MAX_AUDIO_PID_NO]; //!< low 16 bits Audio PID, high 16 bits Audio Type + NvU32 uNoOfAudioPids; //!< Number valid entries in uAudioPidList[] + +} GFMXDEMTSPARSERAUDIOPIDLIST; + +/** Get TS Service ID. + For detail see #GFMXDEMTSPARSERPMTPIDLIST. + @param service (NvU32) Combined type and ID value +*/ +#define GFMXDEMTS_GET_PMT_PID(service) ((((NvU32)(service) & 0xffff00) >> 8) | 0x1FC8) + +/** Get TS Service Type. + For detail see #GFMXDEMTSPARSERPMTPIDLIST. + @param service (NvU32) Combined type and ID value +*/ +#define GFMXDEMTS_GET_PMT_PID_TYPE(service) ((NvU32)(service) & 0x0000ff) + +/** TS Service List. + */ +typedef struct _GFMXDEMTSPARSERPMTPIDLIST +{ + /** Array of services: + Array entries format: +
      +        32      24 23                           8 7               0
      +        +---------+------------------------------+----------------+
      +        | Invalid |             Service ID       |Service Type    |
      +        +---------+------------------------------+----------------+
      +        
      + */ + NvU32 uPmtPidList[GFMXDEMTS_MAX_SERVICE_NO]; + + /** Number of valid entries in GFMXDEMTSPARSERPMTPIDLIST::uPmtPidList[]. */ + NvU32 uNoOfServices; + +} GFMXDEMTSPARSERPMTPIDLIST; + + +/** TS parser types, parameter values for GFMXDEMTSPARSEREQUEST. */ +typedef enum +{ + /** Parser running on host system. + + Parser objects of this type run the TS demux on the host system. + In contrast to GFMXDEMTSPARSERTYPE_DSP no hardware resources are involved, + and any number of parser objects of this type can be created. + + TS data source is always of type GFMXDEMTSPARSERDATASOURCE_PUSH, i.e. + it is provided by the application via GFMxDemTSParserProcessData(). + */ + GFMXDEMTSPARSERTYPE_HOST = 0, + + /** Parser running on DSP. + + Parser objects of this type will instanciate a task on the DSP + to perform the demux processing. Demuxed data is returned to the host. + Demuxed audio data can optionally be processed entirely on DSP side + via GFMXDEMTSPARSERREQUEST::pAudioBufDesc. + + This parser type is intended for verifying demux functionality. + + TS data can be provided either from the host (GFMXDEMTSPARSERDATASOURCE_PUSH), + or acquired automatically from VIP (GFMXDEMTSPARSERDATASOURCE_VIP2DSP). + */ + GFMXDEMTSPARSERTYPE_DSP, + + /** Parser running on DSP with attached AVSync object. + + Parser objects of this type will instanciate 2 tasks on the DSP, + one to perform the demux processing, and one to decode AV-synced H264 video. + Audio is processed on DSP side via GFMXDEMTSPARSERREQUEST::pAudioBufDesc. + + TS data can be provided either from the host (GFMXDEMTSPARSERDATASOURCE_PUSH), + or acquired automatically from VIP (GFMXDEMTSPARSERDATASOURCE_VIP2DSP). + */ + GFMXDEMTSPARSERTYPE_DSPAVSYNC + +} GFMXDEMTSPARSERTYPE; + +/** TS data sources, parameter values for GFMXDEMTSPARSEREQUEST. */ +typedef enum +{ + /** TS data is pushed by the application. + + TS data is fed from the application via function calls to + GFMxDemTSParserProcessData(). + */ + GFMXDEMTSPARSERDATASOURCE_PUSH = 0, + + /** TS data is intercepted by the DSP task directly from VIP. + + The TS parser task running on the DSP will open the VIP in Type-A + interface mode to receive TS data via an interrupt handler. + + This setting can be used only for parsers running on the DSP + (#GFMXDEMTSPARSERTYPE is GFMXDEMTSPARSERTYPE_DSP). + */ + GFMXDEMTSPARSERDATASOURCE_VIP2DSP + +} GFMXDEMTSPARSERDATASOURCE; + +/** TS Parser object states. */ +typedef enum +{ + GFMXDEMTSDSPPARSERSTATE_INSTANTIATED=0, //!< Parser object instanciated, but not initialized + GFMXDEMTSDSPPARSERSTATE_READY, //!< Parser object initialized, ready to parse + GFMXDEMTSDSPPARSERSTATE_ERROR, //!< Parser object dead due to unrecoverable error (out of mem, etc) + GFMXDEMTSDSPPARSERSTATE_SHUTDOWN, //!< Parser object initialized, ready to parse, but shutdown initiated + GFMXDEMTSDSPPARSERSTATE_PAUSE //!< Parser object paused + +} GFMXDEMTSPARSERSTATE; + +/** TS Parser demux status bits. */ +typedef enum +{ + GFMXDEMTSPARSERSTATUS_PMT_READY = 0x01, + GFMXDEMTSPARSERSTATUS_NIT_READY = 0x02, + GFMXDEMTSPARSERSTATUS_VIDEO_FOUND = 0x04, + GFMXDEMTSPARSERSTATUS_AUDIO_FOUND = 0x08, + // if the number of status goes beyond 8, please change m_uStatus to 16 bits or 32 bits in #CNvTransportParser + +} GFMXDEMTSPARSERSTATUS; + +/** Parameter structure for GFMxDemTSParserGetStatus(). */ +typedef struct +{ + GFMXDEMTSPARSERSTATE state; //!< Parser object state + NvU32 status; //!< Parser status bitmask, see #GFMXDEMTSPARSERSTATUS + NvU32 frameDropCount; //!< Counts dropped frames in AVSync + +} GFMxDemTSParserStatus; + +/** TS parser notify reasoncodes for GFMXDEMTSPARSERREQUEST::OnNotify callback. */ +typedef enum +{ + /** Incoming TS starved. */ + GFMXDEMTSPARSERNOTIFY_TSSTARVED = 0, + + /** Overflow of TS data coming from VIP. */ + GFMXDEMTSPARSERNOTIFY_TSOVERFLOW, + + /** Underflow in audio buffer at demux output side. */ + GFMXDEMTSPARSERNOTIFY_AUDIOUNDERFLOW, + + /** Overflow in audio buffer at demux output side. */ + GFMXDEMTSPARSERNOTIFY_AUDIOOVERFLOW, + + /** Underflow in video buffer at demux output side. */ + GFMXDEMTSPARSERNOTIFY_VIDEOUNDERFLOW, + + /** Overflow in video buffer at demux output side. */ + GFMXDEMTSPARSERNOTIFY_VIDEOOVERFLOW, + + /** Parser detected PMT change. + Associated data: +
      +        NvU32 new PMT PID
      +        
      = 2*max ADTS frame size. + */ + NvU32 AudioBufferSize; + + /** Size of video demux buffer to claim in GPU memory. + This field is used only for parsers of type GFMXDEMTSPARSERTYPE_DSP and GFMXDEMTSPARSERTYPE_DSPAVSYNC. + Size must be power of 2 and <=2^24 bytes. + Optimum size depends on H264 bitrate, and should big enough to hold multiple NAL units. + */ + NvU32 VideoBufferSize; + + /** DSP-side handle (address to GFMXDECH264TABLE) of initialized GFMxDecH264 instance. + This address is in DSP address space. + + This field is used only for parsers of type GFMXDEMTSPARSERTYPE_DSPAVSYNC. + + @internal + */ + NvU32 MxDecH264DSPHandle; + + /** Video section callback. + Ignored for parser type GFMXDEMTSPARSERTYPE_DSPAVSYNC. + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param pllPTS Pointer to PTS, or NULL if not existent + @param pllDTS Pointer to DTS, or NULL if not existent + */ + GF_RETTYPE (*OnVideoData)(void* user, NvU8* pBytes, NvU32 cbBytes, NvU32 StreamID, NvS64* pllPTS, NvS64* pllDTS, int bPesStart); + + /** Audio section callback, or NULL to use shared DSP buffer. + + Can be NULL for parser type GFMXDEMTSPARSERTYPE_DSP. + Ignored for parser type GFMXDEMTSPARSERTYPE_DSPAVSYNC. + + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param pllPTS Pointer to PTS, or NULL if not existent + @param pllDTS Pointer to DTS, or NULL if not existent + */ + GF_RETTYPE (*OnAudioData)(void* user, NvU8* pBytes, NvU32 cbBytes, NvU32 StreamID, NvS64* pllPTS, NvS64* pllDTS, int bPesStart); + + /** PCR (Program Clock Reference) callback. + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param llPCRBase Clock + @param llPCRExt Clock + @param uDiscontinuity discontinuity flag + */ + void (*OnPCR)(void* user, NvS64 llPCRBase, NvU32 llPCRExt, NvU32 uDiscontinuity); + + /** Parser object error and status notify callback. + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param notifycode Notify reasoncode, see GFMXDEMTSPARSERNOTIFY + @param data Data specific to a notifycode + */ + void (*OnNotify)(void* user, NvU32 notifycode, void* data); + + /** Frame Decoded Callback + Will be called in sync with PTS of the frame. The passed surface will be locked, and the + application must unlock it later via GFMxDecH264Set() with feature ID GF_MXDEC_H264_SET_UNLOCK_SURFACE. + @param user Application defined parameter, forwarded from INvTransportParserCallback::user + @param surfaceID surface id + @param resolution high 16 bit for xres, low 16 bit for yres + @param pPTS Pointer to PTS of this frame + @param flags Flag bitmask, bit 0 set validity of PAN Scan Info + @param PanTopLeft Top-Left Offset for PAN Scan Rect, low 16 bit signed X, top 16 bit signed Y + @param PanBottomRight Bottom-Right Offset for PAN Scan Rect , low 16 bit signed X, top 16 bit signed Y + @param FrameType I/P Frame Type + */ + void (*OnFrameDecoded)(void* user, NvU32 sufaceID, NvU32 resolution, NvS64* pPTS, NvU32 flags, NvU32 PanTopLeft, NvU32 PanBottomRight, NvU32 FrameType); + + /** TS data callback + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param data TS data + @param size TS data size + */ + void (*OnTS)(void* user, NvU8* data, NvU32 size); + + /** Application private data, will be forwarded to callbacks */ + void* user; + + /** Returns address of circular buffer descriptor shared with audio decoder. + This address is in DSP address space. + This member is valid only, if GFMXDEMTSPARSERREQUEST::OnAudioData is NULL, + and if the parser is of type GFMXDEMTSPARSERTYPE_DSP. + */ + GF_RM_DSP_CIRCBUFFER* pAudioBufDesc; + +} GFMXDEMTSPARSERREQUEST; + +/** H264 Frame Type, the value is equal to Nal Type*/ +typedef enum +{ + MXDEMTS_H264_FRAME_IDR = 5, + MXDEMTS_H264_FRAME_P = 1, + MXDEMTS_H264_FRAME_INVALID = 0, +} MXDEMTS_H264_FRAME_TYPE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFMxDemTSOpen(GFRmHandle hRm, GFMxDemTSHandle *phMxDemTS, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMxDemTSClose(GFMxDemTSHandle *phMxDemTS); + +/** Create a TS parser. + + This function creates a TS parser running on the host. + + @param TsHandle Handle to TS component + @param pParserReq Parameter structure + @param pParserHandle Returns handle on success, unchanged on failure + + @retval GF_SUCCESS Success + @retval GF_ERROR_OUT_MEMORY Out of memory + @retval GFMXDEMTS_ERROR_CREATEDSPPARSER Failed to create parse object on DSP side + @retval GFMXDEMTS_ERROR_NODSPSUPPORT No DSP support in GFSDK +*/ +GF_RETTYPE GFMxDemTSParserCreate(GFMxDemTSHandle TsHandle, GFMXDEMTSPARSERREQUEST* pParserReq, GFMxDemTSParserHandle* pParserHandle); + +/** Destroy TS parser. + + Destroy an TS parser object previously created with GFMxDemTSParserCreate(). + Save to call on NULL handle. + + @param TsHandle Handle to TS component + @param pParserHandle Pointer to parser handle, will be reset to NULL on exit +*/ +void GFMxDemTSParserDestroy(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle* pParserHandle); + +/** Process a section of the TS stream. + + The input Transport Stream is parsed and the section type handlers passed + with GFMXDEMTSPARSERREQUEST are called as their sections are encountered in + the stream. + + A call of this function is usually triggered by an interrupt to feed the next + portion of an incoming Transport Stream. + + On each call of this function at least 188 byte (TS packet size) must be passed. + The Transport Stream is parsed in entities of 188 byte packets. If the passed buffer + contains an incomplete packet at the end, it will be copied to an internal buffer + and automatically combined with the second part on the next function call. + + Thus it is not required to pass in buffers aligned to TS packet starts, and the + buffer must not be a multiple of 188 bytes (TS packet size). However + doing so will guarant maximum demux performance since copying around incomplete packets + can be avoided. + + This function may only be called for parses created with #GFMXDEMTSPARSERDATASOURCE_PUSH. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pData Pointer to buffer containing TS, the buffer must contain + at least 188 bytes of stream data. Buffer start does not + need to be aligned with the start of an TS package. + @param pSize Pointer to buffer size, must be 188 or larger, will be updated + on exit with the number of bytes in the buffer, which where consumed. + If the parser was created on the DSP, this size must + not exceed the buffersize passed in GFMXDEMTSPARSERREQUEST::TSBufferSize. + On success GFMxDemTSParserPushData() will always consume all data, + on failure *pSize returns the number of bytes that were successfully + consumed before the failure occured. + @param timeout Time in ms to wait until DSP parser object gets ready to accept new data, + or 0 to block forever, (NvU32)-1 to return immediately if busy. + Ignored for DSP objects created with #GFMXDEMTSPARSERTYPE_HOST. + + @retval GF_SUCCESS Success + @retval GF_WAIT_TIME_OUT Timeout before data could be sent to DSP + @retval GF_ERROR_BUSY DSP was busy and data was not sent, call again, + returned only if \a timeout was (NvU32)-1 +*/ +GF_RETTYPE GFMxDemTSParserPushData(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU8* pData, NvU32* pSize, NvU32 timeout); + +/** (Re-)Start VIP TS data capture and demux on DSP. + + This function can be used only for parsers created as #GFMXDEMTSPARSERDATASOURCE_VIP2DSP. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success +*/ +GF_RETTYPE GFMxDemTSParserDSPStart(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Pause VIP TS data capture and demux on DSP. + + This function can be used only for parsers created as #GFMXDEMTSPARSERDATASOURCE_VIP2DSP. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param onOff Indicate Pause on or off + + @retval GF_SUCCESS Success +*/ +GF_RETTYPE GFMxDemTSParserDSPPause(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32 onOff); + +/** Step to the next Frame. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success +*/ +GF_RETTYPE GFMxDemTSParserDSPNextFrame(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Step to the next I Frame. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success +*/ +GF_RETTYPE GFMxDemTSParserDSPNextIFrame(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Get TS PmtPid List + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pPmtPidList Returns PMT PID List in current TS, with Service ID and Service Type combined + + @retval GF_SUCCESS Success + @retval GFMXDEMTS_ERROR_SERVICESLISTUNAVAILABLE NIT/PAT has not been parsed yet. + + @see GFMxDemTSSetPmtPid() +*/ +GF_RETTYPE GFMxDemTSParserGetPmtPidList(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, GFMXDEMTSPARSERPMTPIDLIST *pPmtPidList); + +/** Set TS Service + + PMT PID is set without any check. if the new PMT PID is successfully set, a + #GFMXDEMTSPARSERNOTIFY_TSPMTCHANGED notify will be sent to the caller application. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param uPmtPid uPmtPid to be set + + @retval GF_SUCCESS Success * + @see GFMxDemTSGetPmtPidList() + */ +GF_RETTYPE GFMxDemTSParserSetPmtPid(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32 uPmtPid); + +/** Get Active PmtPid + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pServiceID pointer to Active PmtPid. + + @retval GF_SUCCESS Success * + */ +GF_RETTYPE GFMxDemTSParserGetActivePmtPid(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32* pPmtPid); + +/** Get TS AudioPid List + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pAudioPidList Returns AUDIO PID List in current TS, with PID and Type combined + + @retval GF_SUCCESS Success + @retval GFMXDEMTS_ERROR_AUDIOPIDLISTUNAVAILABLE NIT/PAT has not been parsed yet. + + @see GFMxDemTSSetAudioPid() +*/ +GF_RETTYPE GFMxDemTSParserGetAudioPidList(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, GFMXDEMTSPARSERAUDIOPIDLIST *pAudioPidList); + +/** Set TS Audio Pid + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param uAudioPid uAudioPid to be set + + @retval GF_SUCCESS Success + @retval GFMXDEMTS_ERROR_AUDIOPIDUNAVAILABLE + @see GFMxDemTSGetAudioPidList() + */ +GF_RETTYPE GFMxDemTSParserSetAudioPid(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32 uAudioPid); + +/** Get Active AudioPid + + Audio PID is set if this AUDIO PID exists in current streams. Otherwise return an error + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pAudioPid pointer to Active AudioPid. + + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserGetActiveAudioPid(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32* pAudioPid); + +/** Reset All Table Version + + Reset all Table Versions, including PAT, NIT, and PMT. + For reset only PMT table version, see GFMxDemTSParserResetPmtTableVersion + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserResetAllTableVersions(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Reset PMT Table Version + + To reset all table version, see GFMxDemTSParserResetAllTableVersion + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserResetPmtTableVersion(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Set Play Speed + + Just used for normal play, for trick play, see xxx. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param PlaySpeed Play speed to set in 1.0 * 10^6. + A value of 100000 plays at 100% of the current sample rate. 100100 plays at 1.1%, + 100010 plays at 100.01%, the smallest increment 100001 plays at 100.001%. + Number less than 100000 will slow down the stream in the same way. + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserSetPlaySpeed(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32 PlaySpeed); + +/** Set VIP Capture + + @deprecated Do not use, will be removed from public API + + @param TsHandle Handle to TS component + @param VxHandle the Vx handle for setting VIP + @retval GF_SUCCESS Success * + */ +GF_RETTYPE GFMxDemTSSetVIP(GFMxDemTSHandle TsHandle, GFVxHandle VxHandle); + +/** VIP Capture on Host Side + + @deprecated Do not use, will be removed from public API + + it captures VIP data from host side, instead of DSP side. + For VIP Capture from DSP side, see #GFMXDEMTSPARSERREQUEST (GFMXDEMTSPARSERDATASOURCE_VIP2DSP) + + @param TsHandle Handle to TS component + @param pBuf Buffer to host VIP data + @param pBufSize Maximum buf size for input, and Number bytes captured for output + @retval GF_SUCCESS Success * + */ +GF_RETTYPE GFMxDemTSPollVIP(GFMxDemTSHandle TsHandle, NvU8* pBuf, NvU32 *pBufSize); + +/** Close VIP Capture + + @deprecated Do not use, will be removed from public API + + @param TsHandle Handle to TS component + @param VxHandle the Vx handle for setting VIP + @retval GF_SUCCESS Success * + */ +void GFMxDemTSCloseVIP(GFMxDemTSHandle TsHandle, GFVxHandle VxHandle); + +/** Get demux object state and status. + + Check Parser Status, can be called any time on the parser. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pStatus Returns parser object state and status. + + + + +
      Bits 0-7 Parser status bitmask, see #GFMXDEMTSPARSERSTATUS
      Bits 8-24 reserved for extension
      Bits 23-31Parser state, see #GFMXDEMTSPARSERSTATE
      + @retval GF_SUCCESS Success + @retval GFRM_ERROR_BAD_PARAMETER Invalid parser handle passed + */ +GF_RETTYPE GFMxDemTSParserGetStatus(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, GFMxDemTSParserStatus* pStatus); + +/** Clear Demux Buffers. + + This will clear demux input TS buffers. For parsers of type + GFMXDEMTSPARSERTYPE_DSPAVSYNC it will also clear ES (video and audio) output buffers. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserClearBuffers(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Enable or disable TS data to be returned from DSP to host. + + If disabled the GFMXDEMTSPARSERREQUEST::OnTS callback won't be called anymore. + This function has effect for parsers with datasource GFMXDEMTSPARSERDATASOURCE_VIP2DSP only. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param enable 0 to disable, !=0 to enable + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserDSPEnableOnTS(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, int enable); + +/** GFMxDemTSAPI Error code: Create Parser object on DSP failed. + @see GFMxDemTSParserCreate() +*/ +#define GFMXDEMTS_ERROR_CREATEDSPPARSER (GFMXDEMTS_ERROR + 0) + +/** GFMxDemTSAPI Error code: GFSDK not setup for DSP support. + @see GFMxDemTSParserCreate() +*/ +#define GFMXDEMTS_ERROR_NODSPSUPPORT (GFMXDEMTS_ERROR + 1) + +/** GFMxDemTSAPI Error code: GFMxDemTSGetPmtPidList() called when NIT/PAT not parsed yet. + @see GFMxDemTSGetPmtPidList() +*/ +#define GFMXDEMTS_ERROR_SERVICESLISTUNAVAILABLE (GFMXDEMTS_ERROR + 2) + +/** GFMxDemTSAPI Error code: GFMxDemTSSetPmtPid() when a wrong PMT PID is passed. + @see GFMxDemTSSetPmtPid() +*/ +#define GFMXDEMTS_ERROR_SERVICEUNAVAILABLE (GFMXDEMTS_ERROR + 3) + +/** GFMxDemTSAPI Error code: GFMxDemTSGetAudioPidList() called when PMT does not parsed yet, or + there is no Audio in current service. + @see GFMxDemTSGetAudioPidList() +*/ +#define GFMXDEMTS_ERROR_AUDIOPIDLISTUNAVAILABLE (GFMXDEMTS_ERROR + 4) + +/** GFMxDemTSAPI Error code: GFMxDemTSSetAudioPid() when a wrong Audio PID is passed. + @see GFMxDemTSSetAudioPid() +*/ +#define GFMXDEMTS_ERROR_AUDIOPIDUNAVAILABLE (GFMXDEMTS_ERROR + 5) + +/** GFMxDemTSAPI Error code: Signal frame decoded. + @internal +*/ +#define GFMXDEMTS_ERROR_AVSYNCFRAMEDECODED (GFMXDEMTS_ERROR + 6) + +/** GFMxDemTSAPI Error code: Cannot claim VIP. + @see GFMxDemTSParserCreate() +*/ +#define GFMXDEMTS_ERROR_VIPUNAVAILABLE (GFMXDEMTS_ERROR + 7) + +/** GFMxDemTSAPI Error code: GFMxDemTSParserGetActivePmtPid() called when there is pending PMT PID to be set. + @see GFMxDemTSParserGetActivePmtPid() +*/ +#define GFMXDEMTS_ERROR_GETSERVICEPMTPID (GFMXDEMTS_ERROR + 8) + +/** GFMxDemTSAPI Semaphore IDs. + These IDs can be used in the RmCreateSemaphore implementation of the + OS porting layer to identify GFMxDemTSAPI semaphores. +*/ +typedef enum +{ + GFMXDEMTS_SEMAPHORE_TSBUF = GF_MXDEMTSAPI<<24 + +} GFMXDEMTS_SEMAPHORE; + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _GF_MPEG_TS__ */ diff --git a/Start_WM/test6/inc/GFMxEnc.h b/Start_WM/test6/inc/GFMxEnc.h new file mode 100755 index 00000000..74d4bee7 --- /dev/null +++ b/Start_WM/test6/inc/GFMxEnc.h @@ -0,0 +1,795 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an +* express license agreement from NVIDIA Corporation is strictly prohibited. +*/ + +/** @file GFMxEnc.h +GFSDK MPEG Encode API header file. +*/ + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the GFMXENC_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// GFMXENC_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +#ifndef _GF_MPEG_ENC__ +#define _GF_MPEG_ENC__ + +#include "GFVx.h" +#include "GFDef.h" + +/** @addtogroup groupMxEnc GFMxEncAPI MPEG4 Encode API +
        +
      • @ref pageMxEncAppNotes +
          +
        • @ref pageMxEncAppNotes1 +
        +
      +*/ +/*@{*/ + +/** MxEncAPI property flag: Support Simple Profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_SIMPLE 0x00000001 //Support Simple Profile +/** MxEncAPI property flag: Support Simple Scale Profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_SCALE 0x00000002 //Support Simple Scale Profile +/** MxEncAPI property flag: Support CORE Profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_CORE 0x00000004 //Support CORE Profile +/** MxEncAPI property flag: Support MAIN Profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_MAIN 0x00000008 //Support MAIN Profile +/** MxEncAPI property flag: Support N_bit profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_N_BIT 0x00000010 //Support N_bit Profile +/** MxEncAPI property flag: Support LEVEL 1. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_LEVEL1 0x00000100 //Support LEVEL 1 +/** MxEncAPI property flag: Support LEVEL 2. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_LEVEL2 0x00000200 //Support LEVEL 2 +/** MxEncAPI property flag: Support LEVEL 3. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_LEVEL3 0x00000400 //Support LEVEL 3 +/** MxEncAPI property flag: Support LEVEL 4. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_LEVEL4 0x00000800 //Support LEVEL 4 +/** MxEncAPI property flag: Support Data Partitioning Mode. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_DATA_PARTITIONING 0x00001000 //Support Data Partitioning Mode +/** MxEncAPI property flag: Support RVLC Mode. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_RVLC 0x00002000 //Support RVLC Mode +/** MxEncAPI property flag: Support Rate Control. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_RATE_CONTROL 0x00004000 +//support rate control +/** MxEncAPI property flag: Support Intra MacroBlock Refreshing. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_IMRF 0x000008000 //Support Intra Macroblock Refreshing +/** MxEncAPI property flag: Support Rotation. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_ROTATION 0x000010000 //Support Rotation + +/** GFMxEncSetVOL parameter struct. */ +typedef struct _GFMXENCVOL +{ + NvU32 uiVOLInfo; /**< VOL characteristics */ + /**< + + + + + + + + + + + +
      #GF_MXENC_VOL_SHORT_VIDEO_HEADER
      #GF_MXENC_VOL_BYPASS_VLC
      #GF_MXENC_VOL_RESYNC_MARK_ENABLE
      #GF_MXENC_VOL_DATA_PARTITION_ENABLE
      #GF_MXENC_VOL_REVERSIBLE_VLC_ENABLE
      #GF_MXENC_VOL_RATE_CONTROL_ENABLE
      #GF_MXENC_VOL_STUFFING_ENABLE
      #GF_MXENC_VOL_AUTO_IMRF_ENABLE
      #GF_MXENC_VOL_MC_IMRF_ENABLE
      #GF_MXENC_VOL_THUMBNAIL_ENABLE
      + */ + PGFRMSURFACE pSrcSurf;/**< Surface to encode*/ + PGFRECT pSrcRect; /** + #GF_MXENC_VOP_4MV_ENABLE + #GF_MXENC_VOP_HALF_PEL_ENABLE + #GF_MXENC_VOP_PACKET_BASED_ON_MB_NUM + #GF_MXENC_VOP_AC_PRE_ALWAYS_ON + #GF_MXENC_VOP_AC_PRE_DYNAMICALLY_ON + #GF_MXENC_VOP_CHANGE_EXPECTED_SIZE + #GF_MXENC_VOP_CHANGE_INITQP + #GF_MXENC_VOP_CHANGE_MIN_MAX_QP + #GF_MXENC_VOP_4MV_ENABLE + #GF_MXENC_VOP_REDUCE_FRAME_RATE + #GF_MXENC_VOP_ENCODE_I_ASAP + #GF_MXENC_VOP_IMRF_CONTROL_IP_RATIO + #GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE + #GF_MXENC_VOP_LOAD_IMRF_MATRIX + #GF_MXENC_VOP_TIMESTAMP_CPU + #GF_MXENC_VOP_TIMESTAMP_VI + #GF_MXENC_VOP_CHANGE_MAX_QP_RELIEF + + */ + + NvU16 uiPacketSize; /**< If GF_MXENC_VOP_PACKET_BASED_ON_MB_NUM flag is on, this field tells the number of macroblocks in a packet. Otherwise, this field tells number of bytes in a packet.*/ + NvU16 uiIntra_DC_VLC_Thr; /**< Intra DC VLC Threshold*/ + NvU16 uiHECNum; /**< Frequency to inset HEC marker. 0 means no HEC marker at all. 1~7 means to insert HEC after 1~7 resync marker(s).*/ + NvU16 uiExpectedISize; /**< If next encoded VOP is I, this field tells GFMxEncAPI the size of bit stream which application expects in number of DWORD.*/ + NvU16 uiExpectedPSize; /**< If next encoded VOP is P, this field tells GFMxEnc the size of bit stream which application expects in number of DWORD.*/ + NvU16 uiInitialIQP; /**< Initial QP value for I VOP*/ + NvU16 uiInitialPQP; /**< Initial QP value for P VOP */ + + NvU16 uiMaxIQP; /**< Max QP value for I VOP*/ + NvU16 uiMinIQP; /**< Min QP value for I VOP */ + + NvU16 uiMaxPQP; /**< Max QP value for P VOP*/ + NvU16 uiMinPQP; /**< Min QP value for P VOP */ + NvU16 uiMaxQPRelief; /**< Max qp Relief*/ + + NvU16 uiNumofP; /**< Number of consecutive P VOPs between two I VOPs.*/ + NvU16 uiRNumerator; /**< Desired Framerate value. This field must be filled if flag GF_MXENC_VOP_REDUCE_FRAME_RATE is on.*/ + NvU16 uiRDenominator; /**< Camera Framerate. This field must be filled if flag GF_MXENC_VOP_REDUCE_FRAME_RATE is on.*/ + + NvU8 uiIMRFIMinValue; /**< Those values will take effect only when GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever an I VOP is encoded, MxEnc will generate a random number in this range for each macroblock.*/ + NvU8 uiIMRFIMaxValue; /**< Those values will take effect only when GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever an I VOP is encoded, MxEnc will generate a random number in this range for each macroblock.*/ + NvU8 uiIMRFPMinValue; /**< Those values will take effect only when GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever a Macro Block counter is reduced to 0, an Intra Macro Block will be generated by MxEnc. MxEnc will generate a random number in this range for this macroblock.*/ + NvU8 uiIMRFPMaxValue; /**< Those values will take effect only when GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever a Macro Block counter is reduced to 0, an Intra Macro Block will be generated by MxEnc. MxEnc will generate a random number in this range for this macroblock.*/ + NvU8 uiIMRFDefaultCounter; /**< This value will be used as the new counter when the refresh counter in the matrix is decreased to 0.*/ + NvU8* pMIRFMatrix; /**< Pointer to an array that holds counter for each Macro Block. When this counter is decreased to 0, one Intra Macro Block will be inserted.*/ + + NvU32 uiTimeStampModel; /**< Time Stamp Model (VI or CPU). + + + +
      #GF_MXENC_VOP_TIMESTAMP_CPU
      #GF_MXENC_VOP_TIMESTAMP_VI
      + */ + +}GFMXENCVOP, *PGFMXENCVOP; + +//uiVOPInfo: +/**GFMXENCVOP::uiVOPInfo: Enable 4 motion vectors, GFMxEnc will pick 1 MV or 4 MV, depends on which mode is more efficient.*/ +#define GF_MXENC_VOP_4MV_ENABLE 0x00000001 + +/**GFMXENCVOP::uiVOPInfo : Enable Half Pel Motion Estimation search*/ +#define GF_MXENC_VOP_HALF_PEL_ENABLE 0x00000002 + +/**GFMXENCVOP::uiVOPInfo:New packet based on the number of MBs. Not the length of the bit stream*/ +#define GF_MXENC_VOP_PACKET_BASED_ON_MB_NUM 0x00000004 + +/**GFMXENCVOP::uiVOPInfo:AC prediction always on*/ +#define GF_MXENC_VOP_AC_PRE_ALWAYS_ON 0x00000008 + +/**GFMXENCVOP::uiVOPInfo:AC prediction dynamically on*/ +#define GF_MXENC_VOP_AC_PRE_DYNAMICALLY_ON 0x00000010 + +/**GFMXENCVOP::uiVOPInfo : Change the expected size for I and P encoded frames. uiExpectedISize, uiExpectedPSize must be filled*/ +#define GF_MXENC_VOP_CHANGE_EXPECTED_SIZE 0x00000020 + +/**GFMXENCVOP::uiVOPInfo : Change the initial QP for I and P. uiInitialIQP, uiInitialPQP must be filled*/ +#define GF_MXENC_VOP_CHANGE_INITQP 0x00000040 + +/**GFMXENCVOP::uiVOPInfo : Change the Min and Max QP for I and P frames. uiMaxIQP, uiMinIQP, uiMaxPQP, uiMinPQP must be filled*/ +#define GF_MXENC_VOP_CHANGE_MIN_MAX_QP 0x00000080 + +/**GFMXENCVOP::uiVOPInfo : Reduce the frame rate by skipping certain frames. uiRNumerator and uiRDenominator must be set.*/ +#define GF_MXENC_VOP_REDUCE_FRAME_RATE 0x00000100 + +/**GFMXENCVOP::uiVOPInfo : Encode I VOP as soon as possible*/ +#define GF_MXENC_VOP_ENCODE_I_ASAP 0x00000200 + +/**GFMXENCVOP::uiVOPInfo : Number of P VOPs between two I VOPs controlled by intra macro block refreshing. If this flag is off, it is controlled by uiNumofP*/ +#define GF_MXENC_VOP_IMRF_CONTROL_IP_RATIO 0x00000400 + +/**GFMXENCVOP::uiVOPInfo : Application can change the counter range by setting this flag and give the range in uiIMRFIMinValue, uiIMRFIMaxValue, uiIMRFPMinValue and uiIMRFPMaxValue. Application only can turn on this flag when GF_MXENC_VOL_AUTO_IMRF_ENABLE is on.*/ +#define GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE 0x00000800 + +/**GFMXENCVOP::uiVOPInfo : Application must fill in uiIMRFDefaultCounter and pIMRFMatrix when this flag is on. Application only can turn on this flag when GF_MXENC_VOL_MC_IMRF_ENABLE flag is on.*/ +#define GF_MXENC_VOP_LOAD_IMRF_MATRIX 0x00001000 + +/**GFMXENCVOP::uiVOPInfo : Timestamp is provided by CPU*/ +#define GF_MXENC_VOP_TIMESTAMP_CPU 0x00010000 + +/**GFMXENCVOP::uiVOPInfo: Timestamp is generated by VI*/ +#define GF_MXENC_VOP_TIMESTAMP_VI 0x00020000 + +/**GFMXENCVOP::uiVOPInfo : Change MAX QP RELIEF value for Rate Control Algorithm*/ +#define GF_MXENC_VOP_CHANGE_MAX_QP_RELIEF 0x00100000 + +/**typedef struct _GFMXENCRCC*/ + +typedef struct _GFMXENCRCC +{ + NvU16 uiIQP; /** + #MXENC_VOP_P_VOP + #MXENC_VOP_MORE_FETCH + #MXENC_VOP_PORTION_PACKET + #MXENC_VOP_MORE_VOP + #MXENC_VOP_BEGIN_VOP + #MXENC_VOP_END_VOP + #MXENC_VOP_BUFFER_OVERFLOW + + */ + NvU32 uiAverageQP; /** + #GF_MXENC_CAP_SIMPLE + #GF_MXENC_CAP_SCALE + #GF_MXENC_CAP_CORE + #GF_MXENC_CAP_MAIN + #GF_MXENC_CAP_N_BIT + #GF_MXENC_CAP_LEVEL1 + #GF_MXENC_CAP_LEVEL2 + #GF_MXENC_CAP_LEVEL3 + #GF_MXENC_CAP_LEVEL4 + #GF_MXENC_CAP_DATA_PARTITIONING + #GF_MXENC_CAP_RVLC + #GF_MXENC_CAP_RATE_CONTROL + #GF_MXENC_CAP_IMRF + #GF_MXENC_CAP_ROTATION + + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxEncAPI functions. +*/ + +GF_RETTYPE GFMxEncGetStatus(GFMxEncHandle hMxEnc, NvU32 * pStatus); +/**< This function returns the hardware encoder’s status. + + @param MXhandle (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (NvU32 * ) @see GFMxEncGetStatus Definitions. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ +//pStatus +/**GFMxEncGetStatus Definitions : If hardware encoder is busy encoding VOPs*/ +#define GF_ENCODER_BUSY 0x00000001 + +/**GFMxEncGetStatus Definitions : At least one VOP is ready for fetching */ +#define GF_ENCODER_VOP_READY 0x00000002 + + +GF_RETTYPE GFMxEncSetVOL(GFMxEncHandle hMxEnc, PGFMXENCVOL pVOL); +/**< This function sets the characteristics of a new video object layer (VOL) and +tells the GFMxEncAPI the VOL information. The GFMxEncAPI does not +generate a VOL bit stream. The application needs to prepare a VOL by itself. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCVOL ) Set new VOL information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + + +GF_RETTYPE GFMxEncSetVOP(GFMxEncHandle hMxEnc, PGFMXENCVOP pVOP); +/**< This function sets the characteristics of a new video object plane (VOP). This +function should be called after GFMxEncSetVOL() and before +GFMxEncStart(). If the application decides to change any VOP information +during the encoding time (after GFMxEncStart()), the application can call +this function to pass the new VOP information to the GFMxEncAPI. +Otherwise, the application should not call this function, allowing the +GFMxEncAPI to reduce overhead. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCVOP ) Set new VOP information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + + +GF_RETTYPE GFMxEncRateControlConfig(GFMxEncHandle hMxEnc, PGFMXENCRCC pRCC); +/**< This function initializes the GFMxEncAPI rate control block. This function is +optional for application because the GFMxEncAPI automatically initializes +the rate control block. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCRCC ) Set rate control information.. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + +GF_RETTYPE GFMxEncFeedImage(GFMxEncHandle hMxEnc, + PGFMXENCFEEDIMAGE pFeedImage); +/**< The application can call this function if the application has the source image to feed to the encoder. +This function should not be called if the image comes directly from the video +input port (VIP), for example, from a camera. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCFEEDIMAGE ) New image information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + + +GF_RETTYPE GFMxEncFetchImage(GFMxEncHandle hMxEnc,PGFMXENCFETCHVOP pFetchVOP); +/**< An application should call this function to fetch the encoded VOP bit stream +or encoded raw data. If the source image is from the host, the application +should call this function after GFMxEncFeedImage(). If the source image is +from a video camera connected to the VIP and the application is using a +polling scheme, the application should call this function at least at the +camera’s frame rate. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCFETCHVOP ) Structure to hold encoded VOP information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + +GF_RETTYPE GFMxEncStart(GFMxEncHandle hMxEnc); +/**< This function starts the GFMxEncAPI module for encoding the bit stream. +The GFMxEncAPI assumes the first VOP it outputs is the first VOP in the +current VOL. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + +GF_RETTYPE GFMxEncPause(GFMxEncHandle hMxEnc); +/**< This function pauses the encoding process until GFMxEncPause() is called +again to Resume encoding, or GFMxEncStop() is called to totally stop encoding. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + +GF_RETTYPE GFMxEncStop(GFMxEncHandle hMxEnc); +/**< This function stops the encoding process. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + +GF_RETTYPE GFMxEncSetupInterrupt(GFMxEncHandle hMxEnc,void (*Inter)(void *), void * IPara); +/**< An application can use this function to set up the interrupt callback function. +This function must be called before GFMxEncStart(). +If this function returns GF_SUCCESS, whenever a VOP is ready the +GFMxEncAPI calls the interrupt callback function. Inside of the callback +function, the application can call GFMxEncSetVOP() if it is needed, and call +GFMxEncFetchImage() to fetch the encoded VOP. +If GF_ERROR is returned, the application should use a polling scheme. + + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param (*Inter)(void *) (void) Pointer to encoder application’s interrupt callback function. + @param IPara (void *) Pointer to parameter of encoder application’s interrupt callback function. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + +GF_RETTYPE GFMxEncSetAttribute(GFMxEncHandle hMxEnc, NvU32 uiFeature, NvU32* pInfo); +/**< This function sets a feature of the MPEG encoder hardware. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param uiFeature (NvU32) @see GFMxEncSetAttribute Definitions + @param pInfo (NvU32*) Pointer to the information buffer. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes + + GFMxEncSetAttribute_Definitions: + + + + + +
      #MXENC_ATTR_KEEP_PREV_ENCODING_INTERNAL_RESOURCE
      #MXENC_PREVIEW_ROTATE_BUFFER
      #MXENC_GET_PREVIEW_BUFFER
      #MXENC_ENABLE_INTERRUPT_MODE
      + + MXENC_ENABLE_INTERRUPT_MODE MXENC_GET_PREVIEW_BUFFER MXENC_PREVIEW_ROTATE_BUFFER MXENC_ATTR_KEEP_PREV_ENCODING_INTERNAL_RESOURCE +*/ + + +GF_RETTYPE GFMxEncGetAttribute(GFMxEncHandle hMxEnc, NvU32 uiFeature, NvU32* pInfo); +/**< This function gets a feature of the MPEG encoder hardware.. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param uiFeature (NvU32) see GFMxEncGetAttribute_Definitions below. + @param pInfo (NvU32*) Pointer to the information buffer. + + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes + + + +GFMxEncGetAttribute_Definitions: +GF4800 and subsequent generation of GPUs have rotator block which can rotate +video frame before encoding. In a normal mode a Encoder doesn't need to +capture whole video frame before encoding but in rotation mode, it needs to +capture full video frame (YUV4:2:0) before encoding. This means rotation +mode requires more memory. +This option can be used to enable rotation with 4 basic modes which can be +ORed with two h-flip and v-flip options. +Total of 8 unique combination of rotation modes are available. +*pInfo rotation degree used with MXENC_ATTR_ROTATION + + + + + + + + + +
      #MXENC_ATTR_ROTATION
      #MXENC_ATTR_ROTATE_0
      #MXENC_ATTR_ROTATE_90
      #MXENC_ATTR_ROTATE_180
      #MXENC_ATTR_ROTATE_270
      #MXENC_ATTR_H_FLIP
      #MXENC_ATTR_V_FLIP
      + + + + +*/ + +/** @name GFMxEncGetAttribute_Definitions +*/ +//@{ + +/**GFMxEncGetAttribute_Definitions: +*/ + +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATION*/ +#define MXENC_ATTR_ROTATION 1 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATE_0*/ +#define MXENC_ATTR_ROTATE_0 0x0 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATE_90*/ +#define MXENC_ATTR_ROTATE_90 0x1 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATE_180*/ +#define MXENC_ATTR_ROTATE_180 0x2 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATE_270*/ +#define MXENC_ATTR_ROTATE_270 0x3 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_H_FLIP*/ +#define MXENC_ATTR_H_FLIP 0x10 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_V_FLIP*/ +#define MXENC_ATTR_V_FLIP 0x20 +//@} + + + +GF_RETTYPE GFMxEncInterruptControl(GFMxEncHandle MxHandle); +/**< This function enables the MxEnc interrupt. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + +/** @name GFMxEncAPI_Error_Codes +*/ +//@{ + +/** GFMXE_SUCCESS*/ +#define GFMXE_SUCCESS GF_SUCCESS +/** GFMXE_ERROR_NOT_SUPPORT_FORMAT */ +#define GFMXE_ERROR_NOT_SUPPORT_FORMAT (GFMXE_ERROR | 0x00000001) +/** GFMXE_ERROR_INVALID_PARAMETER */ +#define GFMXE_ERROR_INVALID_PARAMETER (GFMXE_ERROR | 0x00000002) +/** GFMXE_ERROR_NOT_ENOUGH_EMBEDDED_MEM */ +#define GFMXE_ERROR_NOT_ENOUGH_EMBEDDED_MEM (GFMXE_ERROR | 0x00000003) +/** GFMXE_ERROR_SET_ATTRIBUTE_FAILED */ +#define GFMXE_ERROR_SET_ATTRIBUTE_FAILED (GFMXE_ERROR | 0x00000004) + +//@} + + + /*@}*/ + + /** @page pageMxEncAppNotes MxEncAPI Application Notes + + @section pageMxEncAppNotes1 Programming Sequence + + Todo + */ + +#ifdef __cplusplus +} // only need to export C interface if +// used by C++ source code +#endif + +#endif //#ifndef _GF_MPEG_ENC__ diff --git a/Start_WM/test6/inc/GFMxEncH264.h b/Start_WM/test6/inc/GFMxEncH264.h new file mode 100755 index 00000000..f4f81228 --- /dev/null +++ b/Start_WM/test6/inc/GFMxEncH264.h @@ -0,0 +1,788 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an +* express license agreement from NVIDIA Corporation is strictly prohibited. +*/ + +/** @file GFMxEncH264.h +GFSDK H264 Encode API header file. +*/ + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the GFMXENC_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// GFMXENC_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +#ifndef _GF_MPEG_ENC_H264__ +#define _GF_MPEG_ENC_H264__ + +#include "GFVx.h" + +#include "GFDef.h" + +/** @addtogroup groupMxEncH264 MxEncH264API H264 Encode API +
        +
      • @ref pageMxEncH264AppNotes +
          +
        • @ref pageMxEncH264AppNotes1 +
        +
      +*/ +/*@{*/ + +/** @name GFMxEncH264 API Property Caps */ +//@{ +/** MxEncH264API property flag: Support baseline Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_BASELINE 0x00000001 //support baseline profile +/** MxEncH264API property flag: Support Main Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_MAIN 0x00000002 //support main profile +/** MxEncH264API property flag: Support extended Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_EXTENDED 0x00000004 //support extended profile +/** MxEncH264API property flag: Support high 10 Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_HIGH10 0x00000008 //support high 10 profile +/** MxEncH264API property flag: Support high 422 Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_HIGH422 0x00000010 //support high 422 profile +/** MxEncH264API property flag: Support high 444 Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_HIGH444 0x00000020 //support high 444 profile +/** MxEncH264API property flag: Level_IDC following H.264 spec definition. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_LEVEL_IDC(Capability) \ + ((Capability >> 12) & 0xfff)//Level_IDC following H.264 spec definition +/** MxEncH264API property flag: Support data partitioning mode. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_DATA_PARTITIONING 0x10000000 //support data partitioning mode +/** MxEncH264API property flag: Support rate control. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_RATE_CONTROL 0x20000000 //support rate control +/** MxEncH264API property flag: Support intra macro block refreshing. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_IMRF 0x40000000 //support intra macro block refreshing +/** MxEncH264API property flag: Support rotation. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_ROTATION 0x80000000 //support rotation + +//@} + + + + +/**typedef struct GFMXENCH264SETSEQUENCE_TAG*/ +typedef struct GFMXENCH264SETSEQUENCE_TAG +{ + NvU32 SequenceInfo; /**< Sequence characteristics */ + /**< + + + + + + + + + + + +
      #GF_MXENC_H264_SEQUENCE_CONSTRAINT_SET0_FLAG
      #GF_MXENC_H264_SEQUENCE_CONSTRAINT_SET1_FLAG
      #GF_MXENC_H264_SEQUENCE_CONSTRAINT_SET2_FLAG
      #GF_MXENC_H264_SEQUENCE_DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG
      #GF_MXENC_H264_SEQUENCE_FRAME_MBS_ONLY_FLAG
      #GF_MXENC_H264_SEQUENCE_RATE_CONTROL_ENABLE
      #GF_MXENC_H264_SEQUENCE_AUTO_IMRF_ENABLE
      #GF_MXENC_H264_SEQUENCE_MC_IMRF_ENABLE
      #GF_MXENC_H264_SEQUENCE_REALTIME_ENCODE
      #GF_MXENC_H264_SEQUENCE_DEBLK_I_SLICE
      + */ + NvU32 profile_idc; /** + #GF_MXENC_H264_PICTURE_CHANGE_INIT_QP + #GF_MXENC_H264_PICTURE_REDUCE_FRAME_RATE + #GF_MXENC_H264_PICTURE_ENCODE_IDR_ASAP + #GF_MXENC_H264_PICTURE_CHANGE_MIN_MAX_QP + #GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE + #GF_MXENC_H264_PICTURE_LOAD_IMRF_MATRIX + #GF_MXENC_H264_PICTURE_4MV_ENABLE + #GF_MXENC_H264_PICTURE_HALF_PEL_ENABLE + #GF_MXENC_H264_PICTURE_DEBLK_FILTER_ENABLE + #GF_MXENC_H264_PICTURE_MULTI_SLICE_ENABLE + + */ + NvU32 numofSlicesGroup; /**< Number of slice groups, default value = 0 */ + NvU32 sliceGroupMapType; /**< default value is 0 , interleaved slice groups */ + NvU32 num_of_ref_idx_10_active; /**< Specifies the maximum reference index for reference picture list 0 ,default value is 0 */ + NvU32 num_of_ref_idx_11_active; /**< Default value is 0 */ + NvS32 pic_init_qp; /**< Initial value of the slice QP*/ + NvS32 pic_init_qs; /**< Initial value of the slice QS */ + NvS32 chroma_qp_index_offset; /**< Specifies the offset that shall be added to QPY and QSY for addressing the table of QPC values. The value of chroma_qp_index_offset shall be in the range of -12 to +12, inclusive. */ + NvU32 uiMaxIDRQP; /**< Max QP value for IDR */ + NvU32 uiMinIDRQP; /**< Min QP value for IDR */ + + NvU32 uiMaxNONIDRQP; /**< Max QP value for non-IDR picture */ + NvU32 uiMinNONIDRQP; /**< Min QP value for non-IDR picture */ + + NvU32 SliceAlpha; /**< Aplha value for Deblocking */ + NvU32 SliceBeta; /**< Beta value for Deblocking */ + + /**< Packetisation for H264*/ + NvU32 uiPacketCtrlDisable; /**< Disables the packet mode control */ + NvU32 uiPacketMode; /**< If 1 ,then in macroblock mode else in bytes mode, bytes mode not supported */ + NvU32 uiPacketSize; /**< Packet size in MBs or bytes, packet size in bytes is not supported, Value can range from zero to the number of MBs in a frame */ + + NvU32 uiNumofPicBetween2IDRs; /**< Number of P frames in between consecutive I Frames */ + NvU32 uiRNumerator; /**< Desired Framerate value. This field must be filled if flag GF_MXENC_H264_PICTURE_REDUCE_FRAME_RATE is on. */ + NvU32 uiRDenominator; /**< Camera Framerate. This field must be filled if flag F_MXENC_H264_PICTURE_REDUCE_FRAME_RATE is on. */ + NvU32 uiIMRFIMinValue; /**< Those values will take effect only when GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever an I frame is encoded, MxEncH264 will generate a random number in this range for each macroblock */ + NvU32 uiIMRFIMaxValue; /**< Those values will take effect only when GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever an I frame is encoded, MxEncH264 will generate a random number in this range for each macroblock. */ + NvU32 uiIMRFPMinValue; /**< Those values will take effect only when GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever a Macro Block counter is reduced to 0, an Intra Macro Block will be generated by MxEncH264. MxEncH264 will generate a random number in this range for this macroblock. */ + NvU32 uiIMRFPMaxValue; /**< Those values will take effect only when GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever a Macro Block counter is reduced to 0, an Intra Macro Block will be generated by MxEncH264. MxEncH264 will generate a random number in this range for this macroblock. */ + NvU32 uiIMRFDefaultCounter; /**< This value will be used as the new counter when the refresh counter in the matrix is decreased to 0. */ + NvU8 *pIMRFMatrix; /**< Pointer to an array that holds counter for each Macro Block. When this counter is decreased to 0, one Intra Macro Block will be inserted.*/ + + +} GFMXENCH264SETPICTURE, *PGFMXENCH264SETPICTURE; + +/** @name GFMxEncH264 API Setpicture::PictureInfo */ +//@{ +/**GFMXENCH264SETPICTURE::PictureInfo: When application enables this flag, application must set pic_init_qp, pic_init_qs and chroma_qp_index_offset.*/ +#define GF_MXENC_H264_PICTURE_CHANGE_INIT_QP 0x00000001 + +/**GFMXENCH264SETPICTURE::PictureInfo:Reduce the frame rate by skipping certain frames, Must set uiRNumerator and uiRDenominator.*/ +#define GF_MXENC_H264_PICTURE_REDUCE_FRAME_RATE 0x00000002 + +/**GFMXENCH264SETPICTURE::PictureInfo: Encode IDR as soon as possible .*/ +#define GF_MXENC_H264_PICTURE_ENCODE_IDR_ASAP 0x00000004 + +/**GFMXENCH264SETPICTURE::PictureInfo:When application set this flag, application must set uiMaxIDRQP, uiMinIDRQP, uiMaxNONIDRQP and uiMinNONIDRQP .*/ +#define GF_MXENC_H264_PICTURE_CHANGE_MIN_MAX_QP 0x00000008 + +/**GFMXENCH264SETPICTURE::PictureInfo:Application changes the counter range by setting this, flag and giving the range in uiIMRFIMinValue uiIMRFIMaxValue, uiIMRFPMinValue, and uiIMRFPMaxValue, Applications can turn on this flag only when GF_MXENC_H264_SEQUENCE_AUTO_IMRF_ENABLE is on.*/ +#define GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE 0x00000010 + +/**GFMXENCH264SETPICTURE::PictureInfo: Application must fill in uiIMRFDefaultCounter and pIMRFMatrix if this flag is on, Application can turn on flag only if GF_MXENC_H264_PICTURE_MC_IMRF_ENABLE is on .*/ +#define GF_MXENC_H264_PICTURE_LOAD_IMRF_MATRIX 0x00000020 + +/**GFMXENCH264SETPICTURE::PictureInfo: Enable 4 motion vectors, GFMxEncH264 will pick 1 MV or 4 MV, depends on which mode is more efficient.*/ +#define GF_MXENC_H264_PICTURE_4MV_ENABLE 0x00000040 + +/**GFMXENCH264SETPICTURE::PictureInfo: Enable half pel motion estimation search.*/ +#define GF_MXENC_H264_PICTURE_HALF_PEL_ENABLE 0x00000080 + +/**GFMXENCH264SETPICTURE::PictureInfo: Enable Deblocking.*/ +#define GF_MXENC_H264_PICTURE_DEBLK_FILTER_ENABLE 0x00000100 + +/**GFMXENCH264SETPICTURE::PictureInfo: Enable Multi Slicing. Mutli-slicing is not supported*/ +#define GF_MXENC_H264_PICTURE_MULTI_SLICE_ENABLE 0x00000200 +//@} + +/** typedef struct GFMXENCH264RCC_TAG */ +typedef struct GFMXENCH264RCC_TAG +{ + NvU16 uiIQP; /** + #GF_MXENC_H264_NALS_SEQUENCE_PARAMETER_SET + #GF_MXENC_H264_NALS_PICTURE_PARAMETER_SET + #GF_MXENC_H264_NALS_IDR_PIC + #GF_MXENC_H264_NALS_NON_IDR_PIC + #GF_MXENC_H264_NALS_BEGIN_ACCESS_UNIT + #GF_MXENC_H264_NALS_PARTIAL_ACCESS_UNIT + #GF_MXENC_H264_NALS_END_ACCESS_UNIT + #GF_MXENC_H264_NALS_DATA_NOT_READY + #GF_MXENC_H264_NALS_MORE_FETCH + #GF_MXENC_H264_NALS_MORE_NALS + + */ + NvU32 uiTime; /**< In milliseconds, the encoded picture's time stamp. First picture may start from 0. */ + NvU32 uiFetchedSize; /**< Number of available bytes */ +}GFMXENCH264FETCHNALS, *PGFMXENCH264FETCHNALS; + +/** @name GFMXENCH264FETCHNALS::uiNALsInfo definitions */ +//@{ + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current NAL unit is a Sequence Parameter Set. */ +#define GF_MXENC_H264_NALS_SEQUENCE_PARAMETER_SET 0x00000001 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current NAL unit is a Picture Parameter Set. */ +#define GF_MXENC_H264_NALS_PICTURE_PARAMETER_SET 0x00000002 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current NAL unit belongs to an IDR Pic. */ +#define GF_MXENC_H264_NALS_IDR_PIC 0x00000004 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current NAL unit belongs to a Non-IDR Pic. */ +#define GF_MXENC_H264_NALS_NON_IDR_PIC 0x00000008 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current data is the start of a new Access Unit. */ +#define GF_MXENC_H264_NALS_BEGIN_ACCESS_UNIT 0x00000010 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current data is a Partial Access Unit. */ +#define GF_MXENC_H264_NALS_PARTIAL_ACCESS_UNIT 0x00000020 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current data is the End of the Access Unit. */ +#define GF_MXENC_H264_NALS_END_ACCESS_UNIT 0x00000040 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Data of current NAL is not ready yet.*/ +#define GF_MXENC_H264_NALS_DATA_NOT_READY 0x00000080 + +/**GFMXENCH264FETCHNALS::uiNALsInfo: Present NAL unit is larger than application's buffer size. Call FetchNALs again to get remaining data.*/ +#define GF_MXENC_H264_NALS_MORE_FETCH 0x00000100 + +/** GFMXENCH264FETCHNALS::uiNALsInfo: More NALs are encoded and ready to be fetched by the application. */ +#define GF_MXENC_H264_NALS_MORE_NALS 0x00000200 + +//@} + +/** @name GFMxEncH264SetAttribute Definitions */ +//@{ + +/**GFMxEncH264SetAttribute_Definitions::MXENC_H264_ATTR_ROTATION: +GF4800 and subsequent generation of GPUs have rotator block which can rotate +video frame before encoding. In a normal mode a Encoder doesn't need to +capture whole video frame before encoding but in rotation mode, it needs to +capture full video frame (YUV4:2:0) before encoding. This means rotation +mode requires more memory. +This option can be used to enable rotation with 4 basic modes which can be +ORed with two h-flip and v-flip options. +Total of 8 unique combination of rotation modes are available. +*pInfo rotation degree used with MXENC_ATTR_ROTATION +*/ +#define MXENC_H264_ATTR_ROTATION 1 + +#define MXENC_H264_ATTR_ROTATE_0 0x0 /**< No rotation */ +#define MXENC_H264_ATTR_ROTATE_90 0x1 /**< Rotate by 90 degree */ +#define MXENC_H264_ATTR_ROTATE_180 0x2 /**< Rotate by 180 degree */ +#define MXENC_H264_ATTR_ROTATE_270 0x3 /**< Rotate by 270 degree */ +#define MXENC_H264_ATTR_H_FLIP 0x10 /**< Flip horizontally */ +#define MXENC_H264_ATTR_V_FLIP 0x20 /**< Flip vertically */ + +/**GFMxEncH264SetAttribute_Definitions:MXENC_H264_INTRAREFRESH_MODE +This option allows you to change the INTRA REFRESH mode while encoding is in progress. +With this option, the application can switch/Turn ON MXENC_H264_INTRAREFRESH_AUTO or +MXENC_H264_INTRAREFRESH_MC. After switching to MXENC_H264_INTRAREFRESH_MC mode, the application +has to call GFMxEncH264SetPicture() with pPicture:pIMRFMatrix specifying the Intra Refresh pattern +*/ +#define MXENC_H264_INTRAREFRESH_MODE 2 +#define MXENC_H264_INTRAREFRESH_AUTO 0x1 /**< Set Intrarefresh pattern in Auto mode */ +#define MXENC_H264_INTRAREFRESH_MC 0x2 /**< Set Intrarefresh pattern in Motion Compensated mode */ + +//@} + +/** typedef enum GFMX_ENC_H264_INTERRUPT_OPERATION_TYPE : Set Interrupt Operation to perform */ +typedef enum +{ + GFMX_ENC_H264_INTERRUPT_ENABLE, /**< Enable Interrupt */ + GFMX_ENC_H264_INTERRUPT_DISABLE, /**< Disable Interrupt */ + GFMX_ENC_H264_INTERRUPT_CLEAR /**< Clear Interrupt */ +} GFMX_ENC_H264_INTERRUPT_OPERATION_TYPE; // Interrupt operation. + +/** typedef enum GFMX_ENC_H264_INTERRUPT_TYPE : Interrupt type*/ +typedef enum +{ + GFMX_ENC_H264_FRAME_ENCODE_DONE_INTR /**< Frame Encode Done Interrupt */ +} GFMX_ENC_H264_INTERRUPT_TYPE; + + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif + + /** MxEncH264API virtual function pointer table. + These functions serve as the entry point to the MxEncH264API from the application. + */ + typedef struct _GFMXEncH264TABLE + { + GF_RETTYPE (* MxEncH264GetProperty)(GFMxEncH264Handle hMxEncH264, PGFPROPERTY pMXProp ); + /**< This function returns a variety of information, including the version of the + GFMxEncH264API encoder module. It is a good practice to call this function to query + for the GFMxEncH264API version and its capabilities before using the rest of the + GFMxEncH264API functions. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pMXProp (PGFPROPERTY) Pointer to GFPROPERTY. + MxEncH264API property flag below. + + MxEncH264API property flag: + + + + + + + + + + + + +
      #GF_MXENC_H264_CAP_BASELINE
      #GF_MXENC_H264_CAP_MAIN
      #GF_MXENC_H264_CAP_EXTENDED
      #GF_MXENC_H264_CAP_HIGH10
      #GF_MXENC_H264_CAP_HIGH422
      #GF_MXENC_H264_CAP_HIGH444
      #GF_MXENC_H264_CAP_LEVEL_IDC
      #GF_MXENC_H264_CAP_DATA_PARTITIONING
      #GF_MXENC_H264_CAP_RATE_CONTROL
      #GF_MXENC_H264_CAP_IMRF
      #GF_MXENC_H264_CAP_ROTATION
      + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxEncH264API functions. + */ + + GF_RETTYPE (* MxEncH264GetStatus)(GFMxEncH264Handle hMxEncH264, NvU32 * pStatus); + /**< This function returns the hardware encoder’s status. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pStatus (NvU32 * ) Status returned by the encoder. @see GFMxEncH264GetStatus Definitions. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264SetSequence)(GFMxEncH264Handle hMxEncH264, PGFMXENCH264SETSEQUENCE pSequence); + /**< This function sets the characteristics of a new H264 video sequence and + tells the GFMxEncH264API the sequence information. The GFMxEncH264API does not + generate a sequence bit stream. The application needs to prepare a sequence by itself. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pSequence (PGFMXENCH264SETSEQUENCE ) Set new sequence information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264SetPicture)(GFMxEncH264Handle hMxEncH264, PGFMXENCH264SETPICTURE pPicture); + /**< This function sets the characteristics of a new picture. This + function should be called after GFMxEncH264SetSequence() and before + GFMxEncH264Start(). If the application decides to change any picture information + during the encoding time (after GFMxEncH264Start()), the application can call + this function to pass the new picture information to the GFMxEncH264API. + Otherwise, the application should not call this function, allowing the + GFMxEncH264API to reduce overhead. + + @paramhMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pPicture (PGFMXENCH264SETPICTURE ) Set new picture information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264RateControlConfig)(GFMxEncH264Handle hMxEncH264, PGFMXENCH264RCC pRCC); + /**< This function initializes the GFMxEncH264API rate control block. This function is + optional for application because the GFMxEncH264API automatically initializes + the rate control block. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pRCC (PGFMXENCH264RCC ) Set rate control information.. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264FeedImage)(GFMxEncH264Handle hMxEncH264, + PGFMXENCH264FEEDIMAGE pFeedImage); + /**< The application can call this function if the application has the source image to feed to the encoder. + This function should not be called if the image comes directly from the video + input port (VIP), for example, from a camera. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pStatus (PGFMXENCH264FEEDIMAGE ) New image information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264FetchNALs)(GFMxEncH264Handle hMxEncH264, + PGFMXENCH264FETCHNALS pFetchNALs); + /**< An application should call this function to fetch the encoded NAL bit stream + or encoded raw data. If the source image is from the host, the application + should call this function after GFMxEnch264FeedImage(). If the source image is + from a video camera connected to the VIP and the application is using a + polling scheme, the application should call this function at least at the + camera’s frame rate. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pFetchNALs (PGFMXENCH264FETCHNALS ) Structure to hold encoded NAL information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264Start)(GFMxEncH264Handle hMxEncH264); + /**< This function starts the GFMxEncH264API module for encoding the bit stream. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + GF_RETTYPE (* MxEncH264Pause)(GFMxEncH264Handle hMxEncH264); + /**< This function pauses the encoding process until GFMxEnch264Pause() is called + again to Resume encoding, or GFMxEncH264Stop() is called to totally stop encoding. + + @param hMxEnc (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264Stop)(GFMxEncH264Handle hMxEncH264); + /**< This function stops the encoding process. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264SetupInterrupt)(GFMxEncH264Handle hMxEncH264, + void (*Inter)(void *), void * IPara); + /**< An application can use this function to set up the interrupt callback function. + + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param (*Inter)(void *) (void) Pointer to encoder application’s interrupt callback function. + @param IPara (void *) Pointer to parameter of encoder application’s interrupt callback function. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264SetAttribute)(GFMxEncH264Handle hMxEncH264, NvU32 uiFeature, NvU32* pInfo); + /**< This function sets a feature of the H264 encoder. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param uiFeature (NvU32) @see GFMxEncH264SetAttribute Definitions + @param pInfo (NvU32*) Pointer to the information buffer. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + + GFMxEncH264SetAttribute_Definitions: + + + +
      #MXENC_H264_ATTR_ROTATION
      #MXENC_H264_INTRAREFRESH_MODE
      + + + */ + GF_RETTYPE (* MxEncH264GetAttribute)(GFMxEncH264Handle hMxEncH264, NvU32 uiFeature, NvU32* pInfo); + /**< This function gets a feature of the H264 encoder. + + @param hMxEnc (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param uiFeature (NvU32) see GFMxEncH264GetAttribute_Definitions below. + @param pInfo (NvU32*) Pointer to the information buffer. + + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes + + */ + + }GFMXENCH264TABLE, *PGFMXENCH264TABLE; + + // Typesafe functions for opening and closing this component + GF_RETTYPE GFMxEncH264Open(GFRmHandle hRm, GFMxEncH264Handle *phMxEncH264, + GF_STATE_TYPE state, GFRmChHandle hCh); + /**< Typesafe function for opening the H264 Encoder component. + + @param hRm (GFRmHandle) RM Handle got from GFRmOpen. + @param phMxEncH264 (GFMxEncH264Handle *) Handle specific to the GFMxEncH264API is returned in this. + @param state (GF_STATE_TYPE) . + @param hCh (GFRmChHandle) Channel handle + */ + + void GFMxEncH264Close(GFMxEncH264Handle *phMxEncH264); + /**< Typesafe function for closing the H264 Encoder component. + + @param phMxEncH264 (GFMxEncH264Handle *) Pointer to handle specific to H264 encoder component. + */ + + /** @name GFMxEncH264GetStatus Definitions */ + //@{ +#define GF_ENCODER_BUSY 0x00000001 /**< Encoder is busy */ +#define GF_ENCODER_VOP_READY 0x00000002 /**< At least one VOP is ready for fetching */ + //@} + +/** @name GFMxEncH264API Helper Macros. */ + //@{ + +#define GFMxEncH264GetProperty(hMxEncH264, pMXProp) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264GetProperty(hMxEncH264, pMXProp) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264GetProperty + */ + +#define GFMxEncH264GetStatus(hMxEncH264, pStatus) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264GetStatus(hMxEncH264, pStatus) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264GetStatus + */ + +#define GFMxEncH264SetSequence(hMxEncH264, pSequence) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264SetSequence(hMxEncH264, pSequence) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264SetSequence + */ + +#define GFMxEncH264SetPicture(hMxEncH264, pPicture)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264SetPicture(hMxEncH264, pPicture) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264SetPicture + */ + +#define GFMxEncH264RateControlConfig(hMxEncH264, pRCC)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264RateControlConfig(hMxEncH264, pRCC) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264RateControlConfig + */ + +#define GFMxEncH264FeedImage(hMxEncH264, pFeedImage)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264FeedImage(hMxEncH264, pFeedImage) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264FeedImage + */ + +#define GFMxEncH264FetchNALs(hMxEncH264, pFetchNALs)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264FetchNALs(hMxEncH264, pFetchNALs) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264FetchNALs + */ + +#define GFMxEncH264Start(hMxEncH264)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264Start(hMxEncH264) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264Start + */ + +#define GFMxEncH264Pause(hMxEncH264)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264Pause(hMxEncH264) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264Pause + */ + +#define GFMxEncH264Stop(hMxEncH264)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264Stop(hMxEncH264) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264Stop + */ + +#define GFMxEncH264SetupInterrupt(hMxEncH264, Inter,IPara)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264SetupInterrupt(hMxEncH264, Inter,IPara) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264SetupInterrupt + */ + +#define GFMxEncH264SetAttribute(hMxEncH264, uiFeature, pInfo) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264SetAttribute(hMxEncH264, uiFeature, pInfo) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264SetAttribute + */ + +#define GFMxEncH264GetAttribute(hMxEncH264, uiFeature, pInfo) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264GetAttribute(hMxEncH264, uiFeature, pInfo) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264GetAttribute + */ + + //@} + + /** @name GFMxEncH264API_Error_Codes + */ + //@{ + + /** GFMXEH264_SUCCESS*/ +#define GFMXEH264_SUCCESS GF_SUCCESS + /** GGFMXEH264_ERROR_NOT_SUPPORT_FORMAT*/ +#define GFMXEH264_ERROR_NOT_SUPPORT_FORMAT (GFMXEH264_ERROR | 0x00000001) + /** GFMXEH264_ERROR_INVALID_PARAMETER*/ +#define GFMXEH264_ERROR_INVALID_PARAMETER (GFMXEH264_ERROR | 0x00000002) + /** GFMXEH264_ERROR_NOT_ENOUGH_EMBEDDED_MEM*/ +#define GFMXEH264_ERROR_NOT_ENOUGH_EMBEDDED_MEM (GFMXEH264_ERROR | 0x00000003) + //@} + + + /*@}*/ + + /** @page pageMxEncH264AppNotes MxEncH264API Application Notes + + @section pageMxEncH264AppNotes1 Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start GFSDK usage. The description is for a typical case + where encoding of video being captured from a camera is done and preview shown on the display. + + 1. Initialize the display panel by using GFRmIxInit().\n + + 2. Open the display component by calling GFDxOpen() to get the GFMxDecAPI Dxhandle.\n + + 3. Initialize the display start address, stride and bits per pixel using GFDxSetDisplay().\n + + 4. Get the various attributes of the display panel (width, height, etc) using GFDxGetAttribute().\n + + 5. For clearing the screen, open the graphics component using GFGxOpen() and use GFGxFillRect() for filling the screen with + some color (say, green).\n + + 6. Open the Vx component using GFVxOpen() and get the GFVxAPI VxHandle. \n + + 7. Setup the camera. \n + + 8. Initialize VIP. \n + + 9. Obtain the handle specific to H264 encoder by calling GFMxEncH264Open(). \n + + 10. Call GFMxEncH264GetProperty() to query properties. Check whether this version can support the desired H264 profile and level. \n + + 11. If supported, call GFRmSurfaceAlloc() to allocate one surface for encoding purposes. \n + + 12. Call GFMxEncH264SetAttribute() if specific features need to be set. \n + + 13. Call GFMxEncH264SetSequence() for configuring the characteristics of a new H264 video sequence. \n + + 14. Call GFMxEncH264SetPicture() for setting the characteristics of a new picture. \n + + 15. If the current source image is from the CPU, the application should call GFMxEncH264FeedImage() to feed the + image to the GFMxEncH264API. If the current source image is coming from the VIP (for example. camera input), the + application should skip the GFMxEncH264FeedImage() call. + + 16. If the application uses an interrupt scheme, it must implement a callback function and set it up using GFMxEncH264SetupInterrupt. + Inside of the callback function, the application should call GFMxEncH264FetchNALs() to retrieve the encoded NALs. \n + + 17. Start the encoding by calling GFMxEncH264Start(). \n + + 18. The application should periodically call the callback function to get the data from the encoder. \n + + 19. The encoder can be paused by calling GFMxEncH264Pause() and can be resumed by calling GFMxEncH264Pause() again. \n + + 20. Before exiting, call GFMxEncH264Stop() to stop the encoder. \n + + 21. Call the callback function after waiting for some time to get the data for the last frame encoded. \n + + 22. Free all relevent resources and call GFMxEncH264Close() to free the H264 encoder component. \n + + */ + +#ifdef __cplusplus +} // only need to export C interface if +// used by C++ source code +#endif + +#endif //#ifndef _GF_MPEG_ENC_H264__ diff --git a/Start_WM/test6/inc/GFOSx.h b/Start_WM/test6/inc/GFOSx.h new file mode 100755 index 00000000..f3f48b0d --- /dev/null +++ b/Start_WM/test6/inc/GFOSx.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFOSx.h + GFSDK OS Abstraction API header file. +*/ + +#ifndef __GFOSx_H__ +#define __GFOSx_H__ + +#include "GFRmOEM.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupOSx OSxAPI OS Abstraction API +*/ +/*@{*/ + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFOSxOpen(GFRmHandle hRm, GFOSxHandle *phOSx, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFOSxClose(GFOSxHandle *phOSx); + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif // _GFOSx_H_ diff --git a/Start_WM/test6/inc/GFOption.h b/Start_WM/test6/inc/GFOption.h new file mode 100755 index 00000000..c54f0d7e --- /dev/null +++ b/Start_WM/test6/inc/GFOption.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFOption.h + GFSDK (Compile-time) Option header file. + Contains user level options and selected compile-time options. +*/ + +#ifndef __GFOPTION_H__ +#define __GFOPTION_H__ + +#include "cpuopsys.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +/*************************************************************************** + * Hardware Dependent Options and Compile-time selections + ***************************************************************************/ + +/** @name Device ID options and compile-time selection + @anchor DeviceIDs + #GF_DEVICE_ID_DEFAULT option is for selecting any ID. +@{*/ + +#define GF_DEVICE_ID_DEFAULT 0x0000 +#define GF_DEVICE_ID_SC11 0x0011 +#define GF_DEVICE_ID_SC15 0x0015 +#define GF_DEVICE_ID_SC14 0x0014 + +#ifndef GF_DEVICE_ID +#define GF_DEVICE_ID GF_DEVICE_ID_SC15 + // Primary chip id +#endif /* GF_DEVICE_ID */ + +#define GF_DEVICE_ID_MASK 0x0000FFFF +#define GF_DEVICE_ID_SHIFT 0 +#define GF_DEVICE_ID_VALUE( val ) \ + (((val) >> GF_DEVICE_ID_SHIFT) & GF_DEVICE_ID_MASK) +/*@}*/ + +/** @name Device Revision options and compile-time selection + @anchor DeviceRevisions + #GF_DEVICE_REV_DEFAULT is for selecting any revision. + Always use 16bit when referring Device Revision only. +@{*/ +#define GF_REV_A1 0x00A1 +#define GF_REV_A2 0x00A2 +#define GF_REV_A3 0x00A3 +#define GF_REV_A4 0x00A4 + +#define GF_DEVICE_REV_DEFAULT 0x0000 +#ifndef GF_DEVICE_REV +#define GF_DEVICE_REV GF_DEVICE_REV_DEFAULT + //!< Primary chip revision +#endif /* GF_DEVICE_REV */ + +#define GF_DEVICE_REV_MASK 0x0000FFFF +#define GF_DEVICE_REV_SHIFT 16 +#define GF_DEVICE_REV_VALUE( val ) \ + (((val) >> GF_DEVICE_REV_SHIFT) & GF_DEVICE_REV_MASK) + +/*@}*/ + +#if defined(NVCPU_XTENSA) + +// On DSP, we always use direct addressing. +#define GF_DEVICE_ADDRESS_DEFAULT GF_DEVICE_ADDRESS_DIRECT +#define GF_DEVICE_ADDRESS GF_DEVICE_ADDRESS_DIRECT + +#else + +// On host CPU, direct & indirect addressing are available in runtime. Default +// is direct addressing. +#ifndef GF_DEVICE_ADDRESS_DEFAULT +#define GF_DEVICE_ADDRESS_DEFAULT GF_DEVICE_ADDRESS_DIRECT +#endif /* GF_DEVICE_ADDRESS_DEFAULT */ + +#ifndef GF_DEVICE_ADDRESS +#define GF_DEVICE_ADDRESS ( GF_DEVICE_ADDRESS_DIRECT \ + | GF_DEVICE_ADDRESS_INDIRECT16 \ + | GF_DEVICE_ADDRESS_INDIRECT8 \ + | GF_DEVICE_ADDRESS_INDIRECT32) +#endif /* GF_DEVICE_ADDRESS */ + +#endif + + + +/*************************************************************************** + * Operating system Dependent Options + ***************************************************************************/ + +/* The bootloader has already initialized the chip and display. To avoid + * writing the hardware again (which can cause screen flicker and other + * symptoms that the customer doesn't like), define this variable to 1. + */ +#ifndef GF_BOOTLOADER_PRESENT +#define GF_BOOTLOADER_PRESENT 0 +#endif + + + + +// If we're compiling for the bootloader right now, of course the +// bootloader cannot be present +#ifdef GF_BOOT_LIB +#undef GF_BOOTLOADER_PRESENT +#define GF_BOOTLOADER_PRESENT 0 +#endif + +/************************************************************************** + * GFSDK Library Auto Compiler Options + * Attempts to set up enough options if none is specified by Build Project. + **************************************************************************/ + +// XXX We should get rid of NV_DEBUG, so we don't have both DEBUG and NV_DEBUG +#if defined(NV_WINDOWS) && !defined(NV_WINDOWS_CE) +#ifdef _DEBUG +#ifndef NV_DEBUG +#define NV_DEBUG 1 +#endif +#endif +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFOPTION_H__ */ + diff --git a/Start_WM/test6/inc/GFRm.h b/Start_WM/test6/inc/GFRm.h new file mode 100755 index 00000000..6669abcd --- /dev/null +++ b/Start_WM/test6/inc/GFRm.h @@ -0,0 +1,2039 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFRm.h + GFSDK Resource Manager API header file. +*/ + +#ifndef __GFRM_H__ +#define __GFRM_H__ + +#include "GF.h" +#include "GFRmError.h" + +/** @addtogroup groupRm RmAPI Resource Manager API +
        +
      • @ref pageRmAppNotes +
          +
        • @ref pageRmAppNotes1 +
        +
      +*/ +/*@{*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "GFRmScr.h" + +/** Hardware Module IDs. + List of all the modules in the SCXX chips. +*/ +typedef enum +{ +#define GFRM_MODULE(x,y) MODID_##x, +#include "gfrm_module_ids.h" +#undef GFRM_MODULE + GFNUMOFMODULEIDS +} eGFModuleIDs; + +/** @name Power Planes/Islands + List of all the power planes in the SCXX chips. +@{*/ + +/** Power Plane ID: Core Power Plane. */ +#define GFPPID_AOCVDD 0x00000001 + +/** Power Plane ID: Video Codec Power Plane. */ +#define GFPPID_VECVDD 0x00000002 + +/** Power Plane ID: SRAM Power Plane. */ +#define GFPPID_MMCVDD 0x00000004 + +/** Power Plane ID: 3D Power Plane. */ +#define GFPPID_TDCVDD 0x00000008 + +/** Power Plane ID: SRAM I/O Power Plane. */ +#define GFPPID_EMVDD 0x00000010 + +/** Power Plane ID: Mostly Bus Interface Power Plane. */ +#define GFPPID_HVDD 0x00000020 + +/** Power Plane ID: Video I/O Power Plane. */ +#define GFPPID_VVDD 0x00000040 + +/** Power Plane ID: LCD I/O Power Plane. */ +#define GFPPID_LVDD 0x00000080 + +/** Power Plane ID: Audio I/O Power Plane. */ +#define GFPPID_ACVDD 0x00000100 + +/** Power Plane ID: SD I/O Power Plane. */ +#define GFPPID_SDVDD 0x00000200 + +/** Power Plane ID: Oscillator Power Plane. */ +#define GFPPID_AVDDOSC 0x00000400 + +/** Power Plane ID: PLL1 Power Plane. */ +#define GFPPID_AVDDP1 0x00000800 + +/** Power Plane ID: PLL2 Power Plane. */ +#define GFPPID_AVDDP2 0x00001000 + +/** Power Plane ID: DRAM Power Plane. */ +#define GFPPID_DRAM 0x00002000 + +/** Number of power plane IDs. */ +#define GFNUMOFPPIDS 14 + +/*@}*/ + +/** @name States for Component Manager and general services +@{*/ + +/** State for registering Component. + @see GF_STATE_TYPE, GFRmComponentGet(). +*/ +#define GF_STATE_REGISTER 0x00000001 + +/** State for unregistering Component. + @see GF_STATE_TYPE, GFRmComponentRelease(). + */ +#define GF_STATE_UNREGISTER 0x00000002 + +/** State for unregistering all Components (internal used only). + @see GF_STATE_TYPE, GFRmComponentRelease(). + */ +#define GF_STATE_UNREGISTER_ALL 0x00000004 + +/** General Enable State. + @see GF_STATE_TYPE. +*/ +#define GF_STATE_ENABLE 0x00000008 + +/** General Disable State. + @see GF_STATE_TYPE. +*/ +#define GF_STATE_DISABLE 0x00000010 + +/** General Done State. + @see GF_STATE_TYPE. +*/ +#define GF_STATE_DONE 0x00000020 + +/** State for instantiating a new or share Component. + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_NEW_OR_SHARE 0x00000100 + +/** State for instantiating a new Component only. + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_NEW_ONLY 0x00000200 + +/** State for instantiating a share Component only. + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_SHARE_ONLY 0x00000400 + +/** State indicating special Block Device Component (internal use). + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_BLOCK_DEVICE 0x80000000 + +/** Default Component instantiation State. + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_DEFAULT GF_STATE_NEW_OR_SHARE + +/** Mask for the regular States. + @see GF_STATE_TYPE. +*/ +#define GF_STATE_MASK 0x000000FF + +/*@}*/ + + +/** Attributes ID/Values. + @see GFRmGetAttribute(), GFRmSetAttribute(). +*/ +typedef enum +{ + /** Attribute for changing device bus addressing (direct/indirect) mode. */ + GF_ATTRIB_DEVICE_ADDRESS, + + /** Attribute for mapped/virtual/usable I/O base address. */ + GF_ATTRIB_IO_MAP_BASE, + + /** Attribute for mapped/virtual/usable embedded memory base. */ + GF_ATTRIB_EMBEDDED_MEM_MAP_BASE, + + /** Attribute for initial embedded internal memory size. */ + GF_ATTRIB_INIT_EMBEDDED_MEM_TOTAL, + + /** Attribute for initial available embedded internal memory size. */ + GF_ATTRIB_INIT_EMBEDDED_MEM_AVAIL, + + /** Attribute for initial embedded extended memory size. */ + GF_ATTRIB_INIT_EXT_EMBEDDED_MEM_TOTAL, + + /** Attribute for user specific object 0. */ + GF_ATTRIB_USER_OBJECT_0, + + /** Attribute for user specific object 1. */ + GF_ATTRIB_USER_OBJECT_1, + + /** Attribute for user specific object 2. */ + GF_ATTRIB_USER_OBJECT_2, + + /** Attribute for user specific object 3. */ + GF_ATTRIB_USER_OBJECT_3, + + /** Attribute for swapping memory allocation with shared embedded memory + MAX CHUNK scheme. For advanced user only. */ + GF_ATTRIB_SWAP_SHARE_MEMORY_ALLOC_ON_MAX_CHUNK, + + /** Get device information structure. + GFRmGetAttribute() parameter \a AttribData is of type PGFRMDEVICEINFO. + */ + GF_ATTRIB_DEVICE_INFO_STRUCT, + + /** For internal use only. */ + GF_ATTRIB_RMC_FLAG, + + /** Enable/Disable Hardware Resource Constraint. */ + GF_ATTRIB_HW_RESOURCE_CONSTRAINT, + + /** Enable embedded extended memory. */ + GF_ATTRIB_ENABLE_EXTENDED_MEMORY, + + /** Disable RMC trace, closing any log files that might be opened */ + GF_ATTRIB_DISABLE_RMC_TRACE, + + /** Set/Clr surface with absolute rotation option. */ + GF_ATTRIB_SURFACE_ABSOLUTE_ROTATE, + + /** Primary surface freeing policy. */ + GF_ATTRIB_PRIMSURF_FREEING_POLICY, + + /** Primary surface allocation policy. */ + GF_ATTRIB_PRIMSURF_ALLOCATION_POLICY, + + /** Internal use. */ + GF_ATTRIB_EFUSE_PRODUCT_SKU_ID, + + /** Internal use. */ + GF_ATTRIB_MAIN_PANEL_INDEX, + + /** GFRm attribute: Set DSP2Host communication mode. + + This attribute can be used to control how components wait + for messages from the DSP. The following options for \a AttribData are available: + - #GF_ATTRIB_DSPCOMMODE_POLLING -- Register polling. + This mode is intended for debuging only, since it allows only one client + to use DSP2Host interrupts. + - #GF_ATTRIB_DSPCOMMODE_EVENT -- Receive DSP2Host messages via an interrupt framework. + This mode requires an ISR/IST to be setup, that handles DSP interrupts and calls + GFRmDispatchMessage(). + + The default setting is register polling. + + Attribute can be get and set. + + @see GFRmSetAttribute(), GFRmGetAttribute(), GFRmQueueSetHandler(), GFRmDispatchMessage() + */ + GF_ATTRIB_DSPCOMMODE, + + /** Set surface for DSP debug console output. + + This sets a surface which will be used to output text from the DSP debug console. + The DSP XRM must be initialized before this function can be called. + + GFRmSetAttribute() parameter \a AttribData is of type #PGFRMSURFACE and defines a pointer to a + surface descriptor. + + @retval GF_SUCCESS Successfully send message + @retval GF_WAIT_TIME_OUT Timeout sending message + @retval GFRM_ERROR_BAD_PARAMETER Bad parameters, e.g. surface color format is not supported + + @see GFRmSetAttribute() + + Attribute can be set only. + */ + GF_ATTRIB_DSPCONSOLE_SURFACE, + + /** Internal use. */ + GF_ATTRIB_USE_CAMERA_SCRIPT, + + /** Internal use. */ + GF_ATTRIB_DEVICE_TYPE, + + /** Timeout in ms for RM IST to wait for interrupts. + Set to 0 to disable timeout, default setting is 1000 ms. + GFRmSetAttribute() parameter \a AttribData is of type NvU32 and defines timout in ms. + */ + GF_ATTRIB_INTX_TIMEOUT, + + /** Enable debug printout for GPU memory allocations. + + GFRmSetAttribute() parameter \a AttribData is of type NvU32, + - 0 means disable log (default) + - !=0 means enable log + + This GFRmSetAttribute() call always succeeds. + + @see GFRmSetAttribute() + + Attribute can be set only. + */ + GF_ATTRIB_GPUMEM_ENABLELOG + +} GF_ATTRIBUTE_TYPE; + +/** DSP2Host communication modes, polling. + @see GF_ATTRIB_DSPCOMMODE +*/ +#define GF_ATTRIB_DSPCOMMODE_POLLING 0 +/** DSP2Host communication modes, OS event synchronization. + @see GF_ATTRIB_DSPCOMMODE +*/ +#define GF_ATTRIB_DSPCOMMODE_EVENT 1 + +/** GFSDK (low-level) device interface type. (Read Only) + * @see GF_ATTRIB_DEVICE_TYPE. + **/ +#define GF_ATTRIB_DEVICE_TYPE_HARDWARE 0x00000000 +#define GF_ATTRIB_DEVICE_TYPE_SIMULATOR 0x00001000 + + +/** @name Component Types + +@{*/ + +/** Component Type: EPP Component. + @anchor ComponentTypes +*/ +#define GF_EPPAPI 0x00000001L + +/** Component Type: Gx (2D) API Component. */ +#define GF_GXAPI 0x00000002L + +/** Component Type: Vx (general Video and Video Input Port) API Component. */ +#define GF_VXAPI 0x00000003L + +/** Component Type: JxE (JPEG Encode) API Component. */ +#define GF_JXEAPI 0x00000004L + +/** Component Type: JxE (JPEG Decode) API Component. */ +#define GF_JXDAPI 0x00000005L + +/** Component Type: MxE (MPEG Encode) API Component. */ +#define GF_MXEAPI 0x00000006L + +/** Component Type: MxD (MPEG Decode) API Component. */ +#define GF_MXDAPI 0x00000007L + +// 0x8 is unused + +/** Component Type: Dx (Display and Flat Panel) API Component. */ +#define GF_DXAPI 0x00000009L + +// 0xA is unused + +/** Component Type: ISP (Image Signal Processing) API Component. */ +#define GF_ISPAPI 0x0000000BL + +/** Component Type: FDev (Pseudo File System/Device) API Component. */ +#define GF_FDEVAPI 0x0000000CL + +/** Component Type: BDevSD (SD Block Device) Component. */ +#define GF_BDEVSDAPI 0x0000000DL + +// 0xE is unused +// 0xF is unused + +/** Component Type: OSx (Operating System) API COmponent */ +#define GF_OSXAPI 0x00000010L + +/** Component Type: I2C API Component */ +#define GF_I2CAPI 0x00000011L + +/** Component Type: I2S API COmponent */ +#define GF_I2SAPI 0x00000012L + +/** Component Type: MMProc (Audio) API COmponent */ +#define GF_MMPROCAPI 0x00000013L + +/** Component Type: CAM (Camera) API Component */ +#define GF_CAMAPI 0x00000014L + +/** Component Type: 3D API Component */ +#define GF_3DAPI 0x00000015L + +/** Component Type: INTx (Interrupt) API COmponent */ +#define GF_INTXAPI 0x00000016L + +/** Component Type: MXDH264 (H264 Decoder) API COmponent */ +#define GF_MXDH264API 0x00000017L + +/** Component Type: MXEH264 (H264 Encoder) API Component */ +#define GF_MXEH264API 0x00000018L + +/** Component Type: RM (Resource Manager) Services (listed only for return status). */ +#define GF_RMAPI 0x00000019L + +/** Component Type: GxFB (Gx/2D API with Frame Buffer rendering) API. Internal Use. */ +#define GF_GXFBAPI 0x0000001AL + +/** MXDRV9 (RV9 Decoder) API COmponent */ +#define GF_MXDRV9API 0x0000001BL + +/** Component Type: MXDVC1 (VC1 Decoder) API Component */ +#define GF_MXDVC1API 0x0000001CL + +/** Component Type: MXDEMTS (MPEG TS Demux) API Component */ +#define GF_MXDEMTSAPI 0x0000001DL + +/** Component Type: Minimal ISP API Component (NvIsp) */ +#define GF_MINIMALISPAPI 0x0000001EL + +/** Component Type: NvISP API Component ID -- only used for GF_TRACE */ +#define NV_ISPAPI 0x0000001FL + +/*@}*/ + +/** NULL driver related. Internal use. */ +#define GF_USE_NULL_DRIVER 0x1 + +/** NULL driver related. Internal use. */ +#define GF_USE_HW_DRIVER 0x2 + + +/** @name Hardware Resources + @anchor HardwareResources + Flags 'hwEngineReq' in GFRmHwResourceConstraint(). (not working yet). + @see GFRmHwResourceConstraint(). +@{*/ + +/** Hardware resource flag: MPEG Decoder Engine. */ +#define GF_HWR_MPEGD 0x00000001 + +/** Hardware resource flag: JPEG Decoder is same as MPEG Decoder Engine. */ +#define GF_HWR_JPEGD 0x00000001 + +/** Hardware resource flag: MPEG Encoder Engine. */ +#define GF_HWR_MPEGE 0x00000002 + +/** Hardware resource flag: JPEG Encoder shares FrontEnd and BackEnd with JPEG Enc Engine. */ +#define GF_HWR_JPEGE 0x00000002 + +/** Hardware resource flag: Video Input Port. */ +#define GF_HWR_VIP 0x00000004 + +/** Hardware resource flag: EPP */ +#define GF_HWR_EPP 0x00000008 + + + +/** Options for GFRmHwResourceConstraint(). + (not working yet!) + @see GFRmHwResourceConstraint(). +*/ +typedef enum +{ + /** check availability and allocate hardware resource. */ + GF_HRC_ALLOCATE, + + /** free hardware resource. */ + GF_HRC_FREE, + + /** check availability of hardware resource. */ + GF_HRC_CHECK +} GF_HRC_OPTIONS; + +/*@}*/ + +/** Component ID structure. */ +typedef struct _GFRMCOMPONENTID +{ + NvU32 ComponentType; /**< Component Type, see @ref ComponentTypes. */ + GFRmChHandle CxtHandle; +} GFRMCOMPONENTID, *PGFRMCOMPONENTID; + +/* Component */ + +/* forward declaration */ +typedef struct _GFRMCOMPONENT GFRMCOMPONENT, *PGFRMCOMPONENT; + +typedef GF_HANDLE (* GFOPENFUNCTIONTYPE)(GFRmHandle pRm, GFRmChHandle); +typedef GF_RETTYPE (* GFCLOSEFUNCTIONTYPE)(GF_HANDLE *); + +/** Component Registration structure. + Internal use. + @internal +*/ +struct _GFRMCOMPONENT +{ + GFRMCOMPONENTID id; /**< Structure defining component. */ + GFOPENFUNCTIONTYPE Open; /**< Component Open callback. Called from GFRmComponentGet(). */ + GFCLOSEFUNCTIONTYPE Close; /**< Component Close callback. Called from GFRmComponentRelease(). */ +}; + + +/** @name Surface Types + @anchor SurfaceTypes + @see GFRmSurfaceAlloc(). +@{*/ + +/** Surface Type: Surface rotation orientation at 0 degree. */ +#define GF_SURFACE_ROTATE_0 0x00000000 + +/** Surface Type: Surface rotation orientation at 90 degree (relative to _ROTATE_0). */ +#define GF_SURFACE_ROTATE_90 0x10000000 + +/** Surface Type: Surface rotation orientation at 180 degree (relative to _ROTATE_0). */ +#define GF_SURFACE_ROTATE_180 0x20000000 + +/** Surface Type: Surface rotation orientation at 270 degree (relative to _ROTATE_0). */ +#define GF_SURFACE_ROTATE_270 0x30000000 + +/* + * GF_SURFACE_H_FLIP and GF_SURFACE_V_FLIP can be ORed with above 4 rotation + * options to create 16 combinations but in reality there are only 8 unique + * combinations. + */ + +/** Surface Type: Horizontal Flip. You can or'ed this flag with _ROTATE_ flag above too. */ +#define GF_SURFACE_H_FLIP 0x40000000 + +/** Surface Type: Vertical Flip. You can or'ed this flag with _ROTATE_ flag above too. */ +#define GF_SURFACE_V_FLIP 0x80000000 + +/** Surface Type: internal use. */ +#define GF_SURFACE_ROTATE_MASK 0xF0000000 + +/** Surface Type: internal use. */ +#define GF_SURFACE_PLANAR_ROTATE_MASK 0x30000000 + +/** Surface Type: internal use. */ +#define GF_SURFACE_ROTATE_SHIFT 28 // bits[31:28] + +/** Surface Type: internal use. */ +#define GF_SURFACE_ROTATE_WRAP 8 + +/** Surface Type: Primary Surface (default rotate orientation). */ +#define GF_SURFACE_PRIMARY 0x00000001 //primary surface + +/** Surface Type: Primary Surface with 0 degree rotation. */ +#define GF_SURFACE_PRIMARY_0 (GF_SURFACE_PRIMARY| GF_SURFACE_ROTATE_0) + +/** Surface Type: Primary Surface with 90 degree rotation. */ +#define GF_SURFACE_PRIMARY_90 (GF_SURFACE_PRIMARY| GF_SURFACE_ROTATE_90) + +/** Surface Type: Primary Surface with 180 degree rotation. */ +#define GF_SURFACE_PRIMARY_180 (GF_SURFACE_PRIMARY| GF_SURFACE_ROTATE_180) + +/** Surface Type: Primary Surface with 180 degree rotation. */ +#define GF_SURFACE_PRIMARY_270 (GF_SURFACE_PRIMARY| GF_SURFACE_ROTATE_270) + +/** Surface Type: Overlay Surface. */ +#define GF_SURFACE_OVERLAY 0x00000002 + +/** Surface Type: Surface to reside in embedded (video) memory. */ +#define GF_SURFACE_VIDEO_MEMORY 0x00000004 + +/** Surface Type: Surface to reside in system memory. */ +#define GF_SURFACE_SYSTEM_MEMORY 0x00000008 + +/** Surface Type: Sub primary surface (for Sub LCD). */ +#define GF_SURFACE_PRIMARY_SUB 0x00000100 //Sub primary surface + +/** Surface Type: Surface to be allocated from "share" embedded memory for + advanced use only. + Cannot be used with #GF_SURFACE_PRIMARY. + No effect with #GF_SURFACE_SYSTEM_MEMORY. +*/ +#define GF_SURFACE_SHARE 0x00001000 + +/** Surface Type: Allocate surface with pre-allocated memory handle. */ +#define GF_SURFACE_PREALLOCATED_MEM 0x00002000 + +/** Request to use new API */ +#define GF_SURFACE_NEW_API 0x01000000 + +/* + * Note: GF_SURFACE_ROTATE_ refers to caller's view of current logical + * orientation relative to Primary Surface. And Primary surface is + * always set to GF_SURFACE_ROTATE_0 even though physical LCD Display + * panel may require different physical orientation. + */ + +/*@}*/ + +/** @name Surface Hints + @anchor SurfaceHints + @see GFRmSurfaceAlloc(). +@{*/ + +/** Surface Hint: Alloc from highest possible position. */ +#define GF_SURFACE_HINT_TOP_DOWN 0x1 + +/** Surface Hint: Alloc from lowest possible position. */ +#define GF_SURFACE_HINT_BOTTOM_UP 0x2 + +/** Surface Hint: Alloc max chunck of memory. */ +#define GF_SURFACE_HINT_MAX_CHUNK 0x4 + +/** Surface Hint: Try allocations from external memory first before internal memory */ +#define GF_SURFACE_HINT_EXT_MEMORY_PREFERRED 0x8 + +/** Surface Hint: Try allocations only from external memory. */ +#define GF_SURFACE_HINT_EXT_MEMORY_ONLY 0x10 + +/** Surface Hint: Try allocations only from internal memory. */ +#define GF_SURFACE_HINT_INT_MEMORY_ONLY 0x20 + +/** Surface Hint: Alloc from embedded memory, YUV in the same contiguous memory. + Valid only for GF_SURFACE_YUV420. +*/ +#define GF_SURFACE_HINT_CONTIGUOUS_MEMORY 0x40 + +/** Surface Hint: Try allocations from internal memory first before external memory */ +#define GF_SURFACE_HINT_INT_MEMORY_PREFERRED 0x80 + +/** Surface Hint: Hints to align stride to 4 bytes - default for YUV422 */ +#define GF_SURFACE_HINT_STRIDE_ALIGN4 0x100 + +/** Surface Hint: Hints to align stride to 8 bytes */ +#define GF_SURFACE_HINT_STRIDE_ALIGN8 0x200 + +/** Surface Hint: Hints to align stride to 16 bytes */ +#define GF_SURFACE_HINT_STRIDE_ALIGN16 0x400 + +/** Surface Hint: Hints to align stride to 32 bytes */ +#define GF_SURFACE_HINT_STRIDE_ALIGN32 0x800 + +/** Surface Hint: Surface will be used for direct read by the applications */ +#define GF_SURFACE_NEED_DIRECT_CPU_READ 0x1000 + +/** Surface Hint: Surface will be used for direct write by the applications */ +#define GF_SURFACE_NEED_DIRECT_CPU_WRITE 0x2000 + +/** Surface Hint: Surface will be used for direct access by the applications + both read and write actions are allowed + */ +#define GF_SURFACE_NEED_DIRECT_CPU_ACCESS \ + (GF_SURFACE_NEED_DIRECT_CPU_READ | GF_SURFACE_NEED_DIRECT_CPU_WRITE) +/*@}*/ + +/** @name Primary surface allocation and freeing policies + @see GFRmSetAttribute(). +@{*/ + +/** Any avaliable memory. Use with GF_ATTRIB_PRIMSURF_ALLOCATION_POLICY. */ +#define GF_ATTRIB_PRIMSURF_ALLOCP_NONE 0x0 + +/** Allocate Primary surface from embedded extended memory. + Use with GF_ATTRIB_PRIMSURF_ALLOCATION_POLICY. +*/ +#define GF_ATTRIB_PRIMSURF_ALLOCP_USE_EXT_MEM 0x1 + +/** Allocate Primary surface from internal memory (SRAM). + Use with GF_ATTRIB_PRIMSURF_ALLOCATION_POLICY. +*/ +#define GF_ATTRIB_PRIMSURF_ALLOCP_USE_INT_MEM 0x2 + +/** Use with GF_ATTRIB_PRIMSURF_FREEING_POLICY. */ +#define GF_ATTRIB_PRIMSURF_FREEP_NONE 0x0 + +/** Never free, Default policy. Use with GF_ATTRIB_PRIMSURF_FREEING_POLICY. */ +#define GF_ATTRIB_PRIMSURF_FREEP_NEVER_FREE 0x0 + +/** Free when the ref count is zero. Use with GF_ATTRIB_PRIMSURF_FREEING_POLICY. */ +#define GF_ATTRIB_PRIMSURF_FREEP_FREE_ON_EMPTY 0x1 + +/** Force free. Use with GF_ATTRIB_PRIMSURF_FREEING_POLICY. */ +#define GF_ATTRIB_PRIMSURF_FREEP_FORCE_FREE 0x2 + +/*@}*/ + +/** Surface structure. + @see GFRmSurfaceAlloc(), GFRmSurfaceFree(). +*/ +typedef struct _GFRMSURFACE +{ + NvU32 width; /**< Width in pixels. */ + NvU32 height; /**< Height in lines. */ + NvU32 SurfaceType; /**< Surface type, see @ref SurfaceTypes. */ + NvU32 ColorFormat; /**< Surface color format, see @ref SurfaceTypes. */ + + NvU32 YStride; /**< Stride for RGB, YUV422 surfaces, or Y plane. */ + NvU32 UStride; /**< U plane stride */ + NvU32 VStride; /**< V plane stride */ + + GFRmMemHandle YMemHandle; /**< Opaque handle for RGB, YUV422 surface, or Y plane memory. */ + GFRmMemHandle VMemHandle; /**< Opaque handle for V plane memory. */ + GFRmMemHandle UMemHandle; /**< Opaque handle for U plane memory. */ + + NvU32 YOffset; /**< Physical address of RGB, YUV422 surfae, or Y plane. */ + NvU32 UOffset; /**< Physical address of U plane. */ + NvU32 VOffset; /**< Physical address of U plane. */ + + /* Direct addressable pointer to the memory region. Don't + use these pointers, unless you want to run only in + "direct addressing mode". Instead, use handles for reading + or writing to the memory from the host, and offsets for + programming the hardware registers. */ + + NvU8 *pY; /**< Pointer to non-planar surface or Y plane of YUV420, valid only for direct addressing. */ + NvU8 *pU; /**< for YUV420 surface, valid only for direct addressing. */ + NvU8 *pV; /**< for YUV420 surface, valid only for direct addressing. */ + + NvU32 memUsed; /**< Total number of bytes used by surfaces. */ + + //void *reserved; // Reserved. Do not modify +} GFRMSURFACE, *PGFRMSURFACE; + +/** Surface Request + @see GFRmSurfaceAlloc(), GFRmSurfaceFree(). +*/ +typedef struct _GFRMSURFACEREQUEST +{ + NvU32 width; /**< Width in pixels. */ + NvU32 height; /**< Height in lines. */ + NvU32 SurfaceType;/**< Surface type, see @ref SurfaceTypes. */ + NvU32 ColorFormat;/**< Surface color format, see @ref SurfaceTypes. */ + NvU32 hint; /**< Allocation hint or 0, see @ref SurfaceHints. */ + NvU8 *pMem; /**< Pointer to pre-allocated memory from which + to allocate the surface planes. */ + NvU32 memSize; /**< Size of pre-allocated Y plane memory. */ + NvU32 id; /**< User defined ID to track allocated block, debugging use */ + + /* Reserved for future */ + /* GF_RETTYPE (* pSurfaceCallBack) + ( GFRmHandle RmHandle, PGFRMSURFACE pSurface); */ + /* Reserved for future */ + /* PGFRMSURFACE pSurfaceShare; */ +} GFRMSURFACEREQUEST, *PGFRMSURFACEREQUEST; + +/** Device Info */ +typedef struct _GFRMDEVICEINFO +{ + NvU32 MinorRev; + NvU32 MajorRev; + NvU32 ChipID; + NvU32 Family; +} GFRMDEVICEINFO, *PGFRMDEVICEINFO; + +/** @name Surface Update Flags + @anchor SurfaceUpdateFlags + @see GFRmSurfaceUpdate() +@{*/ + +/** GFRmSurfaceUpdate() attribute type: Update surface rotation. + + The following values are valid for parameter \a data of GFRmSurfaceUpdate(): +
      +    #GF_SURFACE_ROTATE_0
      +    #GF_SURFACE_ROTATE_90
      +    #GF_SURFACE_ROTATE_180
      +    #GF_SURFACE_ROTATE_270
      +    
      + + @see GFRmSurfaceUpdate() +*/ +#define GF_SURFACE_UPDATE_ROTATE 0x00000001 + +/** GFRmSurfaceUpdate() attribute type: Update surface width. + + Meaning of parameter \a data of GFRmSurfaceUpdate(): + New surface width in pixels. + + The number of bytes required for the new width must not exceed the + surface stride. It is the responsibility of the caller to ensure this. + + @see GFRmSurfaceUpdate() +*/ +#define GF_SURFACE_UPDATE_WIDTH 0x00000002 + +/** GFRmSurfaceUpdate() attribute type: Update surface height. + + Meaning of parameter \a data of GFRmSurfaceUpdate(): + New surface height in line. + + The set height * surface stride must not exceed the memory allocated + for the surface. It is the responsibility of the caller to ensure this. + + @see GFRmSurfaceUpdate() +*/ +#define GF_SURFACE_UPDATE_HEIGHT 0x00000003 + +/** GFRmSurfaceUpdate() attribute type: Update surface width and stride. + + Meaning of parameter \a data of GFRmSurfaceUpdate(): + New surface width in pixels. + + YStride, UStride, and VStride will be updated automatically according + to alignment requirements. Supported colour formats: + - GF_SURFACE_YUV420 + + @see GFRmSurfaceUpdate() +*/ +#define GF_SURFACE_UPDATE_WIDTH_STRIDE 0x00000004 + +/*@}*/ + + +/** @name Memory types + @anchor MemoryTypes + @see GFRMMEMORYREQUEST, GFRmMemHandleAlloc() +@{*/ + +/** Memory Type: Host system memory. */ +#define GF_MEMORY_SYSTEM 0x01 +/** Memory Type: Any GPU memory */ +#define GF_MEMORY_EMBEDDED 0x02 +/** Memory Type: Memory mapped memory. */ +#define GF_MEMORY_MEMMAPPED 0x04 +/** Memory Type: External GPU memory only. */ +#define GF_MEMORY_EMBEDDED_EXT_ONLY GF_MEMORY_EMBEDDED_EXT +#define GF_MEMORY_EMBEDDED_EXT 0x08 +/** Memory Type: Internal GPU memory only. */ +#define GF_MEMORY_EMBEDDED_INT_ONLY GF_MEMORY_EMBEDDED_INT +#define GF_MEMORY_EMBEDDED_INT 0x10 +/** Memory type: Internal or external memory with preference to internal memory. */ +#define GF_MEMORY_EMBEDDED_INT_PREFERRED 0x20 +/** Memory type: External or internal memory with preference to external memory. */ +#define GF_MEMORY_EMBEDDED_EXT_PREFERRED 0x40 +/** Memory type: Direct Read access */ +#define GF_MEMORY_DIRECT_CPU_READ_ACCESS 0x80 +/** Memory type: Direct Write access */ +#define GF_MEMORY_DIRECT_CPU_WRITE_ACCESS 0x100 + +/** Memory type: Direct Read/Write access */ +#define GF_MEMORY_DIRECT_CPU_ACCESS (GF_MEMORY_DIRECT_CPU_WRITE_ACCESS | GF_MEMORY_DIRECT_CPU_READ_ACCESS) + +/*@}*/ + +/** @name Memory Share Types + @anchor MemoryShare + @see GFRMMEMORYREQUEST, GFRmMemHandleAlloc() +@{*/ + +/** Memory Share Flag: Internal use, used in GFRmMemInfo only. */ +#define GF_MEMORY_SHARE 0x80 + +/*@}*/ + +/** @name Memory Alignment + @anchor MemoryAlignment + @see GFRMMEMORYREQUEST, GFRmMemHandleAlloc() +@{*/ + +/** Memory alignment types, must match log2 of alignment size. */ +enum +{ + GF_MEMORY_ALIGN_NONE = 0, /**< Memory Alignment: Don't care. */ + GF_MEMORY_ALIGN2, /**< Memory Alignment: Aligned to 2 byte boundary. */ + GF_MEMORY_ALIGN4, /**< Memory Alignment: Aligned to 4 byte boundary. */ + GF_MEMORY_ALIGN8, /**< Memory Alignment: Aligned to 8 byte boundary. */ + GF_MEMORY_ALIGN16, /**< Memory Alignment: Aligned to 16 byte boundary. */ + GF_MEMORY_ALIGN32, /**< Memory Alignment: Aligned to 32 byte boundary. */ + GF_MEMORY_ALIGN64, /**< Memory Alignment: Aligned to 64 byte boundary. */ + GF_MEMORY_ALIGN128, /**< Memory Alignment: Aligned to 128 byte boundary. */ + GF_MEMORY_ALIGN256, /**< Memory Alignment: Aligned to 256 byte boundary. */ + GF_MEMORY_ALIGN512, /**< Memory Alignment: Aligned to 512 byte boundary. */ + GF_MEMORY_ALIGN1024, /**< Memory Alignment: Aligned to 1024 byte boundary. */ + GF_MEMORY_ALIGN2048, /**< Memory Alignment: Aligned to 2048 byte boundary. */ + GF_MEMORY_ALIGN4096, /**< Memory Alignment: Aligned to 4096 byte boundary. */ + GF_MEMORY_ALIGN_DSP = 0xFF /**< Memory Alignment: Aligned properly for DSP cacheline size. */ +}; + +/*@}*/ + +/** @name Memory Allocation Hints + @anchor MemoryHints + @see GFRMMEMORYREQUEST, GFRmMemHandleAlloc() +@{*/ +/* Memory Hint - Follow Surface Hint */ +/** Memory Allocation Hint: Allocate from high to low addresses. */ +#define GF_MEMORY_HINT_TOP_DOWN GF_SURFACE_HINT_TOP_DOWN +/** Memory Allocation Hint: Allocate from low to high addresses. */ +#define GF_MEMORY_HINT_BOTTOM_UP GF_SURFACE_HINT_BOTTOM_UP +/** Memory Allocation Hint: Allocate from maximum available chunk. */ +#define GF_MEMORY_HINT_MAX_CHUNK GF_SURFACE_HINT_MAX_CHUNK +/** Memory Allocation Hint: Allocate at fixed address. */ +#define GF_MEMORY_HINT_FIXED (GF_MEMORY_HINT_MAX_CHUNK << 1) +/** Memory Allocation Hint: Allocate for 3D. */ +#define GF_MEMORY_HINT_3D (GF_MEMORY_HINT_MAX_CHUNK << 2) + +/* These options are for DRAM as extended memory. This option specifies + * bank the buffer should come from. This will avoid + * bank clobbering between two buffers that are accessed in lock + * step. + */ + +/** Memory Allocation Hint: Allocate from even banks in external memory. */ +#define GF_MEMORY_HINT_EVEN_BANK (GF_MEMORY_HINT_MAX_CHUNK << 3) +/** Memory Allocation Hint: Allocate from odd banks in external memory. */ +#define GF_MEMORY_HINT_ODD_BANK (GF_MEMORY_HINT_MAX_CHUNK << 4) +/*@}*/ + +/** Memory allocation request. + @see GFRmMemHandleAlloc() +*/ +typedef struct _GFRMMEMORYREQUEST +{ + NvU32 length; /**< Size in bytes. */ + NvU32 hint; /**< Allocation hint or 0, see @ref MemoryHints. */ + struct + { + NvU16 type; /**< Memory type, see @ref MemoryTypes. */ + NvU8 share; /**< Share flags or 0, see @ref MemoryShare. */ + NvU8 align; /**< Alignment flags, see @ref MemoryAlignment. */ + } + flag; + NvU32 id; /**< User defined ID to track allocated block, debugging use */ +} GFRMMEMORYREQUEST, *PGFRMMEMORYREQUEST; + +/** OS Critical Section bits 0-15 are general purpose use +bit 16-31 are for internal use */ +#define GF_CRITICAL_SECTION_HW 0x00000001 +/** RM internal use */ +#define GF_CRITICAL_SECTION_SW2 0x00000004 +/** RM internal use */ +#define GF_CRITICAL_SECTION_SW4 0x00000010 +/** I2C critical section */ +#define GF_CRITICAL_SECTION_I2C 0x00000020 +/** RM All channel lock, internal use */ +#define GF_CRITICAL_SECTION_ALL_CHANNELS 0x00000040 + +/** Ix internal use */ +#define GF_CRITICAL_SECTION_SW8 0x00000100 + +/** RM DSP to Host communication, internal use */ +#define GF_CRITICAL_SECTION_D2H 0x00000200 + +/** The SHUTDOWN_DSP lock protects the race between + * UpdateDSPFreq/DSPDisable and HandleInterrupt (IST). + * (Update and DSPDisable turn off the DSP, HandleInt reads + * DSP regs) + */ +#define GF_CRITICAL_SECTION_SHUTDOWN_DSP 0x00000400 +/** The DSP lock protects the race between + * AddTask and RemoveTask. + */ +#define GF_CRITICAL_SECTION_DSP 0x00000401 + +/** Define the ID for the kernel semaphore */ +#define GF_DSP_KERNEL_SEM_ID 0x0CAFEFAD + +/** Shared memory lock - used for internal purposes */ +#define GF_CRITICAL_SECTION_SHM 0x00000800 + +/** RM Host to DSP communication, internal use */ +#define GF_CRITICAL_SECTION_H2D 0x00001000 + +/** Rm internal use: lock for channel structures */ +#define GF_CRITICAL_SECTION_CHSTRUCT 0x00004000 + +/** Dx internal use */ +#define GF_CRITICAL_SECTION_DX 0x00008000 + +/** Vx internal use */ +#define GF_CRITICAL_SECTION_VX 0x00000080 + +#ifdef PROJECT_SEC_G1 +/** JxDec internal use */ +#define GF_CRITICAL_SECTION_JXDEC 0x00002000 +#endif + +/** Rm internal use: lock for DSP messages */ +#define GF_CRITICAL_SECTION_DSPMSG_MIN 0x00010000 +#define GF_CRITICAL_SECTION_DSPMSG_MAX 0x20000000 + +/** Audio Shared Memory lock - used for multiprocess OS */ +#define GF_CRITICAL_SECTION_SWAUDIO 0x10002000 + +/** Maximiun id */ +#define GF_CRITICAL_SECTION_SWMAX 0x00010000 + +/** OS IRQ Callback */ +typedef void (* GFRMOSIRQCALLBACK)( void *pData ); + +struct _GFRMCOMMONSTRUCT; +struct _GFRMENVIRONMENTVARIABLES; +struct _GFRMEXTDATASTRUCT; + +/** Definition of Ix powerplane operations + */ +typedef enum _GFIX_POWERPLANE_OP_TYPE + { + GFIX_POWERPLANE_OP_ENABLE = 0, + GFIX_POWERPLANE_OP_DISABLE, + GFIX_POWERPLANE_OP_QUERY +} GFIX_POWERPLANE_OP_TYPE; + +/** Configuration structure that may be passed to GFRmOpen(). + See GFRmOpen() for details. +*/ +typedef struct _GFRMOPENSTRUCT +{ + NvU32 isFirstProcess; + NvU32 isDeviceMapped; + GF_RETTYPE retStatus; //!< Return error reason code, in case GFRmOpen() fails + + /** Declare which driver HW or NULL driver to use. + This is for GFSDK compiled for NULL driver case. + */ + NvU32 useDriver; +} GFRMOPENSTRUCT; + +/** @name Interface Manager Returned Functions +@{*/ + +/** Write a 32-bit register in the device. + + @param base I/O base address + @param offset Offset of register + @param data Data to write + */ +typedef void (*GF_FUNC_WRITE_32BIT)(void * base, NvU32 offset, NvU32 data); + +/** Read a 32-bit register in the device. + + @param base I/O base address + @param offset Offset of register + + @retval #NvU32 register value + */ +typedef NvU32 (*GF_FUNC_READ_32BIT)(void * base, NvU32 offset); + +/*@}*/ + +/** Interface Options for Read/Write Embedded FIFO (for Jx/Mx APIs) */ +#define GF_EMBFIFO_SWAP_BYTE 0x00000001 +#define GF_EMBFIFO_SWAP_WORD 0x00000002 + +/** Interface FIFO flags */ +/** Front-End FIFO */ +#define GF_FIFO_FEND 0x00000001 +/** GE (2D/Primary) FIFO */ +#define GF_FIFO_SRC 0x00000002 + +/** Interface Helper macro to generate Address Pointer */ +#define GFMAKEADDR(base, offset) (void *)base, offset + +/** Utility Debug Flag */ +#define GF_DEBUG_DEFAULT 0 + +/** 4th argument for GFRmOSGetTickCount */ +#define GF_USEC_TICKS 0 +#define GF_MSEC_TICKS 1 +#define GF_SEC_TICKS 2 + +/** Flags for the Context manager GF_CTX_DEFAULT, GF_CTX_NEW */ +#define GF_CTX_DEFAULT 1 +#define GF_CTX_NEW 2 +#define GF_CTX_SHARED 3 + +/* + ######################################################################## + * Function Prototypes for GFSDK Resource Manager (RM) Services + ######################################################################## + */ + +/* Object Manager */ + +/** GFRmOpen - Starts Resource Manager and GFSDK. + + @param RmOpenHandle Must be NULL. + @return Resource manager handle, or NULL on failure. + + This must be called prior using any GFSDK component APIs and RM services. + This function can be called multiple times, for each successfull call + the application must also call GFRmClose(). + + If this function fails, and a pointer to an open structure is passed in + \a RmOpenHandle, the a failure reasoncode will be returned in GF_OPEN_RETTYPE::retStatus. +*/ +GFRmHandle GFRmOpen(GFRMOPENSTRUCT *RmOpenHandle); + +/** GFRmClose - Ends Resource Manager and GFSDK. + + @param pRmHandle Ptr to RmHandle to be closed. + @retval GF_RETTYPE #GF_SUCCESS if successful.
      + #GF_ERROR on error.
      + + All GFSDK resources will be freed related to this process. + Calls to GFRmOpen are reference counted, GFDSK will be closed only for + the last call to this function. + */ +void GFRmClose(GFRmHandle *pRmHandle); + +/** GFRmCleanUp - Frees resources allocated to a terminated Resource Manager session. + + @param RmProcessID RM Process ID to clean up after. + @retval GF_RETTYPE #GF_SUCCESS if successful.
      + #GF_ERROR on error.
      + + All GFSDK resources will be freed related to this + process. + */ +GF_RETTYPE +GFRmCleanUp( GFRmHandle RmHandle, NvU32 RmProcessID ); + +// FIXME: ripped off from the API doc. GFRmRecover is not implemented as of +// yet - there's null implementation in GFRmObj.c. +/** GFRmRecover - Handles ESD failures. + + @param RmHandle The handle to the Resource Manager. + @param option + @retval GF_RETTYPE #GF_SUCCESS if successful.
      + #GF_ERROR on error.
      + + This function is used to recover from an ESD (electrostatic discharge) + failure. If the system software finds that the GoForce processor is not + responding, the software uses the CPU GPIO to reset the GoForce processor + and then calls this function. GFRmRecover() only calls Recover() + functions of registered components. For example, the GFDxAPI and GFGxAPI + have registered Recover() functions that can bring the GoForce processor + back from the reset to normal working mode. + */ +GF_RETTYPE +GFRmRecover( GFRmHandle RmHandle, NvU32 option ); + +/** GFRmGetProperty - Returns properties of RM. + + @param pRmProp Caller passes ptr to GFPROPERTY that will be filled + upon return. + + @retval #GF_SUCCESS if successful. + */ +GF_RETTYPE +GFRmGetProperty( GFRmHandle RmHandle, + GFPROPERTY *pRmProp ); + +/** GFRmSetAttribute - Sets RM attribute. + + @param AttribType Attribute to get of type #GF_ATTRIBUTE_TYPE. + @param AttribData Data specific to AttribType. + + @retval #GF_SUCCESS if successful. + */ +GF_RETTYPE +GFRmSetAttribute(GFRmHandle RmHandle, + GF_ATTRIBUTE_TYPE AttribType, + NvU32 AttribData); + +/** GFRmGetAttribute - Gets RM attribute. + + @param AttribType Attribute to get of type #GF_ATTRIBUTE_TYPE. + @param AttribData Data specific to AttribType. + See GF_ATTRIBUTE_TYPE for interpretation. + May pass input and/or output parameters. + + @retval #GF_SUCCESS if successful. + */ +GF_RETTYPE +GFRmGetAttribute(GFRmHandle RmHandle, + GF_ATTRIBUTE_TYPE AttribType, + NvU32 *pAttribData); + +/** Claim or release a hardware resource. + + The GoForce GPU has a few hardware engines which are used by + different component API. If a component API is using that hardware + engine, then other API component should not be allowed to use that + engine. For example we have MPEG Decoder engine in the hardware which + is used by GFMxDecAPI and GFJxDecAPI components. If one of the API is + using MPEGD Engine and app/system software tries to use other engines, + it should not be allowed. + For SC4/SC5/SC10/SC12 GPU, we have following constraints: + GFMxDecAPI MPEGD, optional Auto Trigger SB + GFJxDecAPI MPEGD, optional Auto Trigger SB + Both of these component API share same engine so we should only allow + one component to be opened at a time. + + GFMxEncAPI MPEGE, EPP (planar converter) + GFJxEncAPI JPEGE, EPP (planar converter) + Both of these component API share same fron-end planar converter so we + should only allow one component to be opened. + + StetchBlt is represented by VxBlt(). SB has one context where auto + trigger SB can be set. Manual SB command uses same context for manual + command and then restores the auto context. + There is no need to check for manual VxBlt(). + Autotrigger need checking but it is difficult to check in the VxBlt() + function. + + This function only deals with Component level constraints. + Constraint checking can be enabled if GF_ATTRIB_HW_RESOURCE_CONSTRAINT. + + @param RmHandle Handle to the resource manager. + @param options Action code + @param hwEngineReq Flag bitmask specifying 0 or more HW engines, see @ref HardwareResources + + @retval GF_SUCCESS Hardware resource is available. + @retval GFRM_ERROR_HWRESOURCE_NOT_AVAILABLE Hardware resource is not available. + @retval GFRM_ERROR_BAD_PARAMETER Bad parameters passed +*/ +GF_RETTYPE +GFRmHwResourceConstraint( GFRmHandle RmHandle, + GF_HRC_OPTIONS options, + NvU32 hwEngineReq ); + +/* Context Manager */ + +/** GFRmContextGet - Retrieves either a default or new context. + + @param RmHandle Handle to the resource manager. + @param flags #GF_CTX_DEFAULT or #GF_CTX_NEW + @param pContext Pointer to the retreived context. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + */ +GF_RETTYPE +GFRmContextGet( GFRmHandle RmHandle, + NvU32 flags, + GFRmChHandle *pContext); + +/** GFRmChFree - Free a channel (same thing as a context). + + @param hRm Resource manager handle. + @param phCh Pointer to the channel handle. + + @see GFRmContextGet + */ +void GFRmChFree(GFRmHandle hRm, GFRmChHandle *phCh); + + +/* Component Manager */ + +/** GFRmComponentRegister - Register Component with Resource Manager + + @param pComponent Ptr to component to be registerd. + @param RegisterState Parameter of type GF_STATE_TYPE. + Usually, GF_STATE_REGISTER is passed. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + + */ +GF_RETTYPE +GFRmComponentRegister( GFRmHandle RmHandle, + GFRMCOMPONENT *pComponent, + GF_STATE_TYPE RegisterState ); + +/** GFRmComponentGet - Gets a registered component, associated with the passed + context. + + @param ComponentType Desired component type. + @param state Parameter of type #GF_STATE_TYPE. + @param pComponent Ptr to Handle to component available. + NULL if not available. + @param hCh Context Handle. Can be allocated by a call to + #GFRmContextGet function. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + + Depending on the requested state, a newly instantiated component or + a shared component is returned. GF_STATE_DEFAULT is the default option + for the state parameter. If the hCh passed is NULL, then a default + context is associalted with the component. + + */ +GF_RETTYPE +GFRmComponentGet(GFRmHandle hRm, + NvU32 ComponentType, + GF_HANDLE *pComponent, + GF_STATE_TYPE state, + GFRmChHandle hCh); + +/** GFRmComponentRelease - Releases the specified component handle. + + @param hRm Handle to the resource manager. + @param phComponent Pointer to component handle to be released. + + The handle pointed to by phComponent will be cleared to NULL as a side + effect of calling this function. Also, this function has no effect if + the handle pointed to by phComponent is already NULL, so it is not + necessary to check whether a component handle is NULL before releasing it. + */ +void GFRmComponentRelease(GFRmHandle hRm, GF_HANDLE *phComponent); + +/* Surface Manager */ + +/** GFRmSurfaceAlloc - Allocate a Surface without synchronization. + + @param pSurfaceReq Pointer to surface request structure #GFRMSURFACEREQUEST. + @param ppSurface Pointer to surface pointer. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + @retval #GF_OUT_OF_MEMORY when low on memory. + */ +GF_RETTYPE +GFRmSurfaceAlloc( GFRmHandle RmHandle, + GFRMSURFACEREQUEST *pSurfaceReq, + PGFRMSURFACE *ppSurface ); + +/** GFRmSurfaceFree - Frees an allocated surface. + + @param ppSurface Pointer to surface pointer. + + *ppSurface is cleared to NULL. + */ +void +GFRmSurfaceFree(GFRmHandle hRm, + PGFRMSURFACE *ppSurface); + +/** GFRmSurfaceQueryPrimaryInfo - Make a query on Primary Surface. + + @param ppSurface Pointer to Primary surface pointer. + @param pRotate Ptr to current Rotation orientation. + @retval GF_RETTYPE #GF_SUCCESS on success. + #GF_ERROR on error. + + Returned surface pointer is for quick reference only and is a + pointer to transient structure. In other words, this will not + increment the reference count as GFRmSurfaceAlloc does. + */ +GF_RETTYPE +GFRmSurfaceQueryPrimaryInfo( GFRmHandle RmHandle, + PGFRMSURFACE *ppSurface, + NvU32 *pRotate, + NvU32 subSurfaceType ); + +/** Update surface attributes. + + @param ppSurface Pointer to Primary surface pointer. + @param type Type of attribute to update: + + + + +
      #GF_SURFACE_UPDATE_ROTATESet surface rotation
      #GF_SURFACE_UPDATE_WIDTH Set surface width
      #GF_SURFACE_UPDATE_HEIGHTSet surface height
      + @param data Data specific to the type. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + + Currently only one update flag is defined #GF_SURFACE_UPDATE_ROTATE + + */ +GF_RETTYPE +GFRmSurfaceUpdate( GFRmHandle RmHandle, + PGFRMSURFACE pSurface, + NvU32 type, + NvU32 data ); + +/* Memory Manager */ + +/** Allocate a linear piece of internal memory block. + + @param pMemoryReq Pointer to Memory Request struct #GFRMMEMORYREQUEST. + @param pMemHandle A Pointer to the memory handle. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + */ +GF_RETTYPE +GFRmMemHandleAlloc(GFRmHandle RmHandle, + GFRMMEMORYREQUEST *pMemoryReq, + GFRmMemHandle *pMemHandle ); + +/** Frees an allocated internal memory block. + + @param phMem A Pointer to the memory handle. + */ +void +GFRmMemHandleFree(GFRmHandle hRm, + GFRmMemHandle *phMem); + +/** Current memory info. Only supports embedded memory. + + @param pTotalFree Pointer to NvU32 holding total free memoory available. + @param flag Type of memory. Can be one the + #GF_MEMORY_EMBEDDED + #GF_MEMORY_EMBEDDED_EXT + #GF_MEMORY_EMBEDDED_INT + @param pMaxChunk Size of the max chunk. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + + GF_MEMORY_EMBEDDED returns the free memory available in both internal + and external memory. + */ +GF_RETTYPE +GFRmMemInfo (GFRmHandle RmHandle, + NvU32 *pTotalFree, + NvU32 *pMaxChunk, + NvU32 flag ); + + +/** Get an handle for the entire internal memory. Used for debugging purposes + only. +*/ +GFRmMemHandle GFRmMemGetIntMemHandle(GFRmHandle RmHandle); + +/** Get an handle for the entire external memory. Used for debugging purposes + only. +*/ +GFRmMemHandle GFRmMemGetExtMemHandle(GFRmHandle RmHandle); + +/** Handle to offset(sc15 view of hw address) conversion. + */ +NvU32 GFRmMemGetOffset(GFRmMemHandle hMem); + +/** Handle to DSP offset(DSP address address map) conversion. + */ +NvU32 GFRmMemGetDSPOffset(GFRmMemHandle hMem); + +/** Handle to virtual address conversion. + + Returned pointer cannot be dereferenced excpet in direct + addressing mode. + */ +void *GFRmMemGetPointer(GFRmMemHandle hMem); + +/** Get the DSP address with a particular caching attribute for a given memory + handle. + */ +NvU32 GFRmMemGetUncachedDSPAddr(GFRmMemHandle hMem); +NvU32 GFRmMemGetWriteBackDSPAddr(GFRmMemHandle hMem); +NvU32 GFRmMemGetWriteThroughDSPAddr(GFRmMemHandle hMem); + +/** Memory Handle reverse lookup from offset. + + This can be used only for the embedded memory. + */ +GF_RETTYPE +GFRmMemOffsetToHandle(GFRmHandle RmHandle, NvU32 offset, GFRmMemHandle *MemHandle); + +/** Converts offset to virtual address. + + @param offset Hardware offset as seen by the SCxx chip. + @param ppMemory Pointer to Virtual address. + + */ +GF_RETTYPE +GFRmMemOffsetToVirt(GFRmHandle RmHandle, NvU32 offset, void **ppMemory); + +/** Converts virtual to offset (SCxx hw view) + + @param offset Hardware offset SCxx view. + @param ppMemory Virtual address. + */ +GF_RETTYPE +GFRmMemVirtToOffset(GFRmHandle RmHandle, void *ppMemory, NvU32 *offset); + +/** Test if the memory offset is from external memory. + + Returns NV_TRUE if the offset is comming from + external memory, otherwise NV_FALSE. + */ +NvBool +GFRmIsExternalMemoryOffset(GFRmHandle RmHandle, + NvU32 offset); + +/** Test if the memory handle is from external memory. + + Returns NV_TRUE if the handle is comming from + external memory, otherwise NV_FALSE. + */ +NvBool +GFRmIsExternalMemoryHandle(GFRmHandle RmHandle, + GFRmMemHandle memhandle); + +/** Test if the memory offset is valid. + @return NV_TRUE if valid, or NV_FALSE otherwise. + */ +NvBool GFRmIsMemoryOffsetValid(GFRmHandle hRm, NvU32 Offset); + +/** Test for bufferoverflows in allocated GPU memory. + This does nothing for release builds. In GFSDK debug build + each GPU memory block will be guarded by leading and trailing + 8 byte marker sequences: +
      +    Start of block: 0x0D,0xF0,0xAD,0xDE,0x0D,0xF0,0xAD,0xDE
      +    End   of block: 0xDE,0xAD,0xFO,0xOD,0xDE,0xAD,0xFO,0xOD
      +    
      + This call checks if these guard markers have been overwritten + @return Index of corrupted memory block, or -1 if all are ok. +*/ +int GFRmMemEmbVerify(GFRmHandle RmHandle); + +/* CPU bound memory fill functions: + These functions will use CPU cycles to write 16 to 32-bit fixed data + pattern into GPU memory. These API's will use user specified channel + apperture to access memory directly and are equipped with Lock and Unlock + routines to be thread safe. +*/ + +/** Fill memory with fixed data pattern on a particular channel. + Function locks and unlocks the channel automatically. + @param ChHandle User-specified channel to use. + @param memHandle GPU memory handle to write fixed 32-bit data. + @param offset Byte offset relative to memHandle block, + must be 32-bit aligned. + @param fill 32-bit fixed data pattern. + @param words Number of DWORDs to write. +*/ +void +GFRmChMemFill32(GFRmChHandle ChHandle, GFRmMemHandle memHandle, NvU32 offset, + NvU32 fill, NvU32 words); + +/** Fill memory with fixed data pattern on a particular channel. + Function locks and unlocks the channel automatically. + @param ChHandle User-specified channel to use. + @param memHandle GPU memory handle to write fixed 16-bit data. + @param offset Byte offset relative to memHandle block, + must be 32-bit aligned. + @param fill 16-bit fixed data pattern. + @param words Number of DWORDs to write. +*/ +void +GFRmChMemFill16(GFRmChHandle ChHandle, GFRmMemHandle memHandle, NvU32 offset, + NvU16 fill, NvU32 words); + +/** Save/Restore functions - These functions Save embedded memory to system memory. + * This memory can then be restored back to sys mem when required. These functions + * are used during DeepPowerDown. + */ +GF_RETTYPE GFRmSaveMemory(GFRmHandle pRm, + void *sysMemPtr, + NvU32 memSize); + +GF_RETTYPE GFRmRestoreMemory(GFRmHandle pRm, + void *sysMemPtr, + NvU32 memSize); + +/* Linear video memory functions: + + These functions are used for transferring system memory to video memory, + filling video memory, and video memory to video memory operations. These + set of functions use the "1d" engine in hardware. All operations use + channels and will be synchronized with other commands. Optionally each + operation can be passed a flag to insert a "clear/raise/wait" sequence + which will guarantee that the operation has completed before processing + more commands in the command stream. For example, if a texture is being + downloaded, it is useful that the download be complete prior to some other + engine (3d maybe) using this memory. + + Prior to using functions, the 1d engine must be enabled. Disabling + will cause the channel passed in to be idled. This is required by hardware + so that the command processors state can be updated when the 1d engine + has its clock disabled and put into reset. + +*/ + + +/** Callback prototype for GFRmChLinearSetDMACallback(). */ +typedef void (*GF_FUNC_DMA_CALLBACK)(void *dstAddr, void *srcAddr, NvU32 lengthInWords); + +/** Setup an DMA callback for downloading data to SRAM. + * + * This function allows for the user to to setup a DMA callback when + * downloading code to the frame buffer. + * + * The callback function should return AFTER all data has been transferred to + * the device. The downloader writes all data to the framebuffer through + * the registered frame buffer window. This window is 4KBytes in length, + * so there will be a callback once for each 4Kbytes (or less to handle alignment + * constraints). + * + * Also, it is possible for downloads to be occuring on multiple channels + * concurrently, which means that this Callback function must be able to + * handle calls from different threads, and do whatever arbitration is required. + * + * For indirect addressing modes, inside the GFSDK a semaphore will be taken + * and held for the duration of this transaction, as multiple threads cannot + * access the device concurrently when using an indirect addressing model. + * + * @param ChHandle The channel that will be used for the download (channel aperture is used) + * @param dmaCallback Pointer to the callback function that is called to do the download + */ +GF_RETTYPE +GFRmChLinearSetDMACallback(GFRmChHandle ChHandle, + GF_FUNC_DMA_CALLBACK dmaCallback); + +/** Flag for GFRmChLinearSysToVidMemcpy(): use a clear/raise/wait. */ +#define GF_RM_LINEAR_USE_CRW 0x01 + +/** Flag for GFRmChLinearSysToVidMemcpy(): don't synchronize with channel's pushbuffer. */ +#define GF_RM_LINEAR_NO_PB_SYNC 0x02 + +/** Enable 1D engine for GFRmChLinear* functions. + * + * Call before using any GFRmChLinear* function. This enables the hardware that is + * used for these functions. Internally there is a reference count, so it is safe + * to call this multiple times. + * + * @param ChHandle Any valid channel handle should work. + * @see GFRmChLinearDisable() + */ + +GF_RETTYPE +GFRmChLinearEnable(GFRmChHandle ChHandle); + + +/** Disable 1D engine for GFRmChLinear* functions. + * + * When the internal reference count reaches zero, the accelerator's clocks will be turned + * off to save power + * + * @param ChHandle Any valid channel should work. + * @see GFRmChLinearEnable() + */ + +GF_RETTYPE +GFRmChLinearDisable(GFRmChHandle ChHandle); + + + +/** Downloads a system memory buffer to the GPU memory buffer. + * + * The main reason for using this is that + * the copy to video memory is serialized with other operations. A typical use would be something + * like: 3d-driver issues draw commands that use a texture. 3d-driver issues a clear/raise/wait to + * know when draw is complete. 3d-driver issues a download to update the texture. + * + * @param pCtx : Current context (channel) + * @param memHandle : Handle returned from the memory allocator + * @param dstOffset : Offset from the beginning of the block referenced in memHandle + * @param pSrc : Source memory address in system memory + * @param len : Length in bytes to copy + * @param flags : Flags to optionally modify copy behavior + * + * flags can be one of: + * + * GF_RM_LINEAR_USE_CRW -- use a clear/raise/wait to make the operation finish prior to other command + * in the command stream being executed. + * GF_RM_LINEAR_NO_PB_SYNC -- This means the download does not need to be synchronous with the pushbuffer + * and the RM can optionally use different more efficient path + * than the pushbuffer. + * + * @return Returns GF_SUCCESS on success + */ +GF_RETTYPE +GFRmChLinearSysToVidMemcpy(GFRmChHandle pCtx, + GFRmMemHandle memHandle, + NvU32 dstOffset, + void *srcPtr, + NvU32 bytes, + NvU32 flags); + +/** Fills a region of GPU memory with a constant value, by memory handle. + * + * @param ctx Current context (or channel) + * @param memHandle Handle to the memory to fill + * @param dstOffset Offset inside the memory handle + * @param data32 The value being replicated in memory. This value is + * interpreted differently depending on the align parameter. + * if align==4 all of data32 is used + * if align==2 lower 16-bits of data32 is used + * if align==1 lower 8-bits of data32 is used + * + * @param bytes Number of bytes to fill + * @param align must 1,2,4 + * @param flags Can be 0 or GF_RM_LINEAR_USE_CRW + */ +GF_RETTYPE +GFRmChLinearVidMemFill(GFRmChHandle ctx, + GFRmMemHandle memHandle, + NvU32 dstOffset, + NvU32 data32, + NvU32 bytes, + NvU32 align, + NvU32 flags); + +/** Copies memory within GPU memory, by memory handle. + * + * @param ctx The channel handle + * @param dstMemHandle memory handle returned from memalloc + * @param dstOffset Offset from the beginning of dstMemHandle + * @param srcMemhandle memory handle of the src memory + * @param srcOffset Offset from the beginning of srcMemHandle + * @param bytes Number of bytes to be copied. + * @param flags Must be 0 or GF_RM_LINEAR_USE_CRW + * + */ +GF_RETTYPE +GFRmChLinearVidMemcpy(GFRmChHandle ctx, + GFRmMemHandle dstMemHandle, + NvU32 dstOffset, + GFRmMemHandle srcMemHandle, + NvU32 srcOffset, + NvU32 bytes, + NvU32 flags); + + +/** @name OS Manager +@{*/ + +/** Enter Critical section, extended version. + @param id GF_CRITICAL_SECTION_xxx + */ +void GFRmOSEnterCSExt(GFRmHandle hRm, NvU32 id); + +/** Exit Critical section, extended version. + @param id GF_CRITICAL_SECTION_xxx + */ +void GFRmOSExitCSExt(GFRmHandle hRm, NvU32 id); + +/** Enter Hardware Access Critical section. + */ +void GFRmOSEnterCS(GFRmHandle hRm); + +/** Exit Hardware Access Critical section. + */ +void GFRmOSExitCS(GFRmHandle hRm); + +/** Waits for some number of milliseconds. + @param msec Number of milliseconds to wait. + */ +void GFRmOSWaitMSec(NvU32 msec); + +/** Get the current OS tick counter. + @return Low 32 bits of millisecond counter. +*/ +NvU32 GFRmGetTickCountMSec(void); + +/** Get the current OS tick counter. + + NOTE: This function is NOT guaranteed to exist on all + platforms. Drivers should NOT call this function; it's + meant only for benchmarking. + + @return 64 bit microsecond counter. + */ +NvU64 GFRmGetTickCountUSec(void); + +/** Waits for a keypress with a timeout, and returns the key. + + @param timeOutMSec (NvU32) Milliseconds to wait for the keypress. + @retval (int) The code for the key, or zero if we timed out. + */ +int GFRmWaitKey(NvU32 timeOutMSec); + +/*@}*/ + +/** @name Read/Write functions + + We provide APIs to read and write GPU registers and memory, independent of + which bus addressing mode is in use (direct or indirect, 16 or 32). + + WARNING: These functions are not safe in all cases. + 1. They do not take into account handshake mode. With fixed timings it may + be unsafe, for example, to use GFRmMemRd/Wr32 to access external memory. + 2. They do not take into account limitations on the # of address bits. On + some direct addressing platforms, not all the address bits are wired up, + so it is impossible to directly access all of memory. For example, it + may be unsafe to use GFRmMemRd/Wr32 to access external memory. + 3. Some buses do not have full byte enable support. It is possible that + GFRmMemWr08, for example, may clobber the other byte in the word. + + It is believed that the first two pitfalls only apply to external memory. + You can probably use these APIs safely to access internal memory, subject to + caveat (3) (i.e. you should stick to 16-bit or 32-bit writes). For external + memory, "use at your own risk." + +@{*/ + +/** Read or write an 8-, 16-, or 32-bit register in the device. */ +NvU8 GFRmRegRd08(GFRmHandle hRm, NvU32 offset); +NvU16 GFRmRegRd16(GFRmHandle hRm, NvU32 offset); +NvU32 GFRmRegRd32(GFRmHandle hRm, NvU32 offset); +void GFRmRegWr08(GFRmHandle hRm, NvU32 offset, NvU8 data); +void GFRmRegWr16(GFRmHandle hRm, NvU32 offset, NvU16 data); +void GFRmRegWr32(GFRmHandle hRm, NvU32 offset, NvU32 data); + +/** Read or write 8, 16, or 32 bits of data to a given offset in a block of memory. + Offset is relative to the memory handle AND not the absolute one. + */ +NvU8 GFRmMemRd08(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset); +NvU16 GFRmMemRd16(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset); +NvU32 GFRmMemRd32(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset); +void GFRmMemWr08(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, NvU8 data); +void GFRmMemWr16(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, NvU16 data); +void GFRmMemWr32(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, NvU32 data); + +/** Read or write a region of a block of memory. Size is in bytes */ +void GFRmMemRead(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, + void *pDst, NvU32 size); +void GFRmMemWrite(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, + const void *pSrc, NvU32 size); + +/** Fill a block of memory with a given 8-, 16-, or 32-bit word. Size is in words, not bytes */ +void GFRmMemFill08(GFRmHandle hRm, GFRmMemHandle hMem, + NvU32 offset, NvU32 size, NvU8 data); +void GFRmMemFill16(GFRmHandle hRm, GFRmMemHandle hMem, + NvU32 offset, NvU32 size, NvU16 data); +void GFRmMemFill32(GFRmHandle hRm, GFRmMemHandle hMem, + NvU32 offset, NvU32 size, NvU32 data); + +/** Write to a FIFO in the chip. */ +void GFRmFifoWrite(GFRmHandle hRm, const void *srcPtr, + NvU32 dstOffset, NvU32 sizeIn32bits); + +/** Waits for the host to idle. + + @retval GF_SUCCESS on success + @retval GF_ERROR on error +*/ +GF_RETTYPE +GFRmWaitForHostIdle( GFRmHandle RmHandle ); + +/*@}*/ + +/** Dispatch DSP2Host messages. + + This function can be called from an IST in response to the DSP2Host + interrupt. It will perform the following sequence: + + - read the DSP2Host message from the DSP2Host registers, i.e. GFRmGetMessage() + - identify DSP task from the task ID in message parameter 0 + - add the message to that task's queue + - set an event registered with that task to notify it about the new message + - clear DSP2Host interrupt register, i.e. GFRmClearDspCommInterrupt() + + If the task ID from the message is unknown, the interrupt is still cleared, + but the message is ignored. + + @param ChHandle Channel to use, should be the protected channel (GF_PROTECTED_CHANNEL) + @return Returns the DSP task ID the received message belonged to, or 0 if unknown +*/ +NvU32 GFRmDispatchMessage(GFRmChHandle ChHandle); +NvU32 GFRmDispatchMessageDual(GFRmChHandle ChHandle, NvU32 dspModule); + +/** Descriptor for circular buffer in DSP memory. + This structure is intended for shared use between DSP tasks. + + If GF_RM_DSP_CBUFFER::wr == GF_RM_DSP_CBUFFER::rd, the circular buffer is empty. + If GF_RM_DSP_CBUFFER::wr != GF_RM_DSP_CBUFFER::rd, the buffer contains + (wr>=rd)?wr-rd:size+wr-rd bytes of data, starting at offset rd, wrapping on the buffer end. +*/ +typedef struct _GFRM_DSP_CIRCBUFFER +{ + NvU8* adr; //!< buffer address, DSP address space in GPU memory + NvU32 size; //!< Buffer size in bytes + NvU32 wr; //!< Current write offset relative to buffer address + NvU32 rd; //!< Current read offset relative to buffer address + NvU32 userData[4]; //!< User defined, specific depending on usage + +} GF_RM_DSP_CIRCBUFFER; + + +/* + * Pins that can be used as GPIOs once the corresponding module + * has been enabled + */ +typedef enum { + + /* SD PINS */ + GPIO_SD_PIN_DATA0 = 1, + GPIO_SD_PIN_DATA1, + GPIO_SD_PIN_DATA2, + GPIO_SD_PIN_DATA3, + GPIO_SD_PIN_CLK, + GPIO_SD_PIN_CMD, + GPIO_SD_PIN_SDGP0, + GPIO_SD_PIN_SDGP1, + + /* VI PINS */ + GPIO_VI_PIN_VD0, + GPIO_VI_PIN_VD1, + GPIO_VI_PIN_VD2, + GPIO_VI_PIN_VD3, + GPIO_VI_PIN_VD4, + GPIO_VI_PIN_VD5, + GPIO_VI_PIN_VD6, + GPIO_VI_PIN_VD7, + GPIO_VI_PIN_VD8, + GPIO_VI_PIN_VD9, + GPIO_VI_PIN_VD10, + GPIO_VI_PIN_VD11, + GPIO_VI_PIN_VSCK, + GPIO_VI_PIN_VHS, + GPIO_VI_PIN_VVS, + GPIO_VI_PIN_VGP0, + GPIO_VI_PIN_VGP1, + GPIO_VI_PIN_VGP2, + GPIO_VI_PIN_VGP3, + GPIO_VI_PIN_VGP4, + GPIO_VI_PIN_VGP5, + GPIO_VI_PIN_VGP6 + +} GFGPIOPin; + +/* + * I/O options for pins + */ +typedef enum { + GPIO_OPTION_DISABLE = 1, + GPIO_OPTION_INPUT, + GPIO_OPTION_OUTPUT +} GFGPIOOption; + +/* + * Enable/Disable I/O for GPIOS + */ +typedef enum { + GPIO_MODE_DISABLE = 1, + GPIO_MODE_ENABLE +} GFGPIOMode; + +/* + * Pin groups whose selects are tied together + */ +typedef enum { + GPIO_SD_PINGRP_D0_CLK_CMD = 1, + GPIO_SD_PINGRP_D1_D2 +} GFGPIOPinGrp; + +/* + * Pin select for GPIOS + */ +typedef enum { + GPIO_SELECT_GPIO = 1, + GPIO_SELECT_FUNC +} GFGPIOSelect; + +/** + * + * Sets all the pins of a specific module to GPIO mode + * + * @param RmHandle Handle specific to the GFRm + * @param modid Module + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIOEnable(GFRmHandle RmHandle, eGFModuleIDs modid); + +/** + * Initializes the GPIO API + * + * + * @param RmHandle Handle specific to the GFRm + * @param modid Module + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIODisable(GFRmHandle RmHandle, eGFModuleIDs modid); + +/** + * + * Modifies the pin's input/output modes + * + * @param ChHandle Channel to write to modules through + * @param pin Pin to set + * @param options One of GPIO_OPTION_DISABLE (ignores mode), + * GPIO_OPTION_INPUT, GPIO_OPTION_OUTPUT + * @param mode One of GPIO_MODE_ENABLE, GPIO_MODE_DISABLE + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIOSetPinMode(GFRmChHandle ChHandle, GFGPIOPin pin, GFGPIOOption option, GFGPIOMode mode); + +/** + * + * Sets a particular pin's output select + * + * @param ChHandle Channel to write to modules through + * @param pin Pin to set + * @param select One of GPIO_SELECT_GPIO, GPIO_SELECT_FUNC + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIOSetPinSelect(GFRmChHandle ChHandle, GFGPIOPin pin, GFGPIOSelect select); + +/** + * + * Sets a particular pin group's output select + * + * @param ChHandle Channel to write to modules through + * @param group Pin group to set + * @param select One of GPIO_SELECT_GPIO, GPIO_SELECT_FUNC + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIOSetPinGrpSelect(GFRmChHandle ChHandle, GFGPIOPinGrp group, GFGPIOSelect select); + +/** + * + * Sets the status (high/low) of a pin + * + * @param ChHandle Channel to write to modules through + * @param pin Pin to set + * @param value Value to write to pin + * + */ +void +GFRmGPIOSetPin(GFRmChHandle ChHandle, GFGPIOPin pin, NvU8 value); + +/** + * Gets the status (high/low) of a pin + * + * @param ChHandle Channel to write to modules through + * @param pin Pin to set + * + * @return Status (high/low) of pin + * + */ +NvU32 +GFRmGPIOGetPin(GFRmChHandle ChHandle, GFGPIOPin pin); + +/** @ name Bootflags + List of flags inidicating all the devices which are booted +@{*/ + +/** Chip is initalized in other words IxInit is called */ +#define GFRM_BOOT_IXINIT 0x1 + +/** Display is initalized */ +#define GFRM_BOOT_DXINIT 0x2 + +/*@}*/ + +/** + * Writes to some scratch register with a log of all the components which are + * initalized. GFRM_BOOT_* are passed as bootflags. + */ +GF_RETTYPE GFRmBootPostInit(GFRmHandle hRm, NvU32 bootflags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*@}*/ + +/** @page pageRmAppNotes RmAPI Application Notes + + @section pageRmAppNotes1 Todo + +*/ + +#endif /* __GFRM_H__ */ + diff --git a/Start_WM/test6/inc/GFRmError.h b/Start_WM/test6/inc/GFRmError.h new file mode 100755 index 00000000..7295b9f2 --- /dev/null +++ b/Start_WM/test6/inc/GFRmError.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFRmError.h + GFSDK Resource Manager API error code header file. +*/ + +#ifndef __GFRMERROR_H__ +#define __GFRMERROR_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** GFRM error code: Function not supported. */ +#define GFRM_ERROR_NO_SUPPORT (GFRM_ERROR | 0x02) +/** GFRM error code: Out of memory. */ +#define GFRM_ERROR_OUT_MEMORY (GFRM_ERROR | 0x03) +/** GFRM error code: Operation on primary surface, but primary surface not set. */ +#define GFRM_ERROR_NO_PRIMARY_SURFACE (GFRM_ERROR | 0x04) +/** GFRM error code: Bad parameters. */ +#define GFRM_ERROR_BAD_PARAMETER (GFRM_ERROR | 0x05) +/** GFRM error code: Out of memory in DSP XRM heap. */ +#define GFRM_ERROR_XRM_OUTMEMORY (GFRM_ERROR | 0x06) +/** GFRM error code: GFRM memory manager is not initialized. */ +#define GFRM_ERROR_MEM_MANAGER_NOT_INITIALIZED (GFRM_ERROR | 0x07) +/** GFRM error code: DSP2Host message queue overflow. */ +#define GFRM_ERROR_QUEUE_OVERFLOW (GFRM_ERROR | 0x08) +/** GFRM error code: DSP2Host message queue empty (not an error). */ +#define GFRM_ERROR_QUEUE_EMPTY (GFRM_ERROR | 0x09) +/** GFRM error code: DSP2Host message with unknown task ID received. */ +#define GFRM_ERROR_QUEUE_UNKNOWNTASK (GFRM_ERROR | 0x0A) +/** GFRM error code: Error getting GPU base address. */ +#define GFRM_ERROR_IXOPEN_GETADDRESS (GFRM_ERROR | 0x0C) +/** GFRM error code: Error opening file. */ +#define GFRM_ERROR_FILE_OPEN_FAILED (GFRM_ERROR | 0x0D) +/** GFRM error code: Cannot create XRM task. */ +#define GFRM_ERROR_XRM_CREATETASK (GFRM_ERROR | 0x0E) +/** GFRM error code: GFRmOSEventWait() failed. */ +#define GF_WAIT_ERROR (GFRM_ERROR | 0x0F) +/** GFRM error code: GFRmOSEventWait() timed out, the event was not set. */ +#define GF_WAIT_TIME_OUT (GFRM_ERROR | 0x10) +/** GFRM error code: RmEnableModule tried to enable a module that doesn't exist. */ +#define GFRM_ERROR_MODULE_NOT_EXIST (GFRM_ERROR | 0x11) +/** GFRM error code: HW Resource not available on GFRmHwResourceConstraint(). */ +#define GFRM_ERROR_HWRESOURCE_NOT_AVAILABLE (GFRM_ERROR | 0x12) +/** GFRM error code: Host2DSP task message queue overflow. */ +#define GFRM_ERROR_XRM_QUEUE_OVERFLOW (GFRM_ERROR | 0x13) +/** GFRM error code: Host2DSP task message queue empty. */ +#define GFRM_ERROR_XRM_QUEUE_EMPTY (GFRM_ERROR | 0x14) +/** GFRM error code: File not found */ +#define GFRM_ERROR_FILE_NOT_FOUND (GFRM_ERROR | 0x15) +/** GFRM error code: Create semaphore */ +#define GFRM_ERROR_CREATE_SEMAPHORE (GFRM_ERROR | 0x16) + +#ifdef __cplusplus +} +#endif + +#endif // __GFRMERROR_H__ + diff --git a/Start_WM/test6/inc/GFRmHelp.h b/Start_WM/test6/inc/GFRmHelp.h new file mode 100755 index 00000000..82c1fa5a --- /dev/null +++ b/Start_WM/test6/inc/GFRmHelp.h @@ -0,0 +1,515 @@ +/* + * Copyright 2003 NVIDIA Corporation. All Rights Reserved. + * + * BY INSTALLING THE SOFTWARE THE USER AGREES TO THE TERMS BELOW. + * + * User agrees to use the software under carefully controlled conditions + * and to inform all employees and contractors who have access to the software + * that the source code of the software is confidential and proprietary + * information of NVIDIA and is licensed to user as such. User acknowledges + * and agrees that protection of the source code is essential and user shall + * retain the source code in strict confidence.User shall restrict access to + * the source code of the software to those employees and contractors of user + * who have agreed to be bound by a confidentiality obligation which + * incorporates the protections and restrictions substantially set forth + * herein, and who have a need to access the source code in order to carry out + * the business purpose between NVIDIA and user. The software provided + * herewith to user may only be used so long as the software is used solely + * with NVIDIA products and no other third party products (hardware or + * software). The software must carry the NVIDIA copyright notice shown + * above. User must not disclose, copy, duplicate, reproduce, modify, + * publicly display, create derivative works of the software other than as + * expressly authorized herein. User must not under any circumstances, + * distribute or in any way disseminate the information contained in the + * source code and/or the source code itself to third parties except as + * expressly agreed to by NVIDIA. In the event that user discovers any bugs + * in the software, such bugs must be reported to NVIDIA and any fixes may be + * inserted into the source code of the software by NVIDIA only. User shall + * not modify the source code of the software in any way. User shall be fully + * responsible for the conduct of all of its employees, contractors and + * representatives who may in any way violate these restrictions. + * + * NO WARRANTY + * THE ACCOMPANYING SOFTWARE (INCLUDING OBJECT AND SOURCE CODE) PROVIDED BY + * NVIDIA TO USER IS PROVIDED "AS IS." NVIDIA DISCLAIMS ALL WARRANTIES, + * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. + + * LIMITATION OF LIABILITY + * NVIDIA SHALL NOT BE LIABLE TO USER, USER’S CUSTOMERS, OR ANY OTHER PERSON + * OR ENTITY CLAIMING THROUGH OR UNDER USER FOR ANY LOSS OF PROFITS, INCOME, + * SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT + * OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A + * WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. IN NO EVENT SHALL NVIDIA’S + * AGGREGATE LIABILITY TO USER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH + * OR UNDER USER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY USER TO NVIDIA + * FOR THE SOFTWARE PROVIDED HEREWITH. + */ + +/* + * File: GFRmHelp.inl + * GFSDK Resource Manager Helper Manager inline header file. + * #### The helper functions are highly dependent on Operating System #### + * #### and Compiler. A number of these functions are macros that #### + * #### maps to corresonding operating system functions directly. #### + */ + +#ifndef __GFRMHelp_INL__ +#define __GFRMHelp_INL__ + +#include "nvtypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* Defined in GFRMHelp.c */ +extern int GFStricmp(char *, char *); +extern int GFStrincmp(char *, char *, int); + +extern void *GFMalloc(int); +extern void GFFree(void *ptr); + +#if NVOS_IS_WINDOWS_CE + +#ifndef __KERNEL__ +#include +#include +#endif // __KERNEL__ + +/* String Helper functions */ +#define GFStrcpy(p1, p2) strcpy(p1, p2) +#define GFStrncpy(p1, p2, p3) strncpy(p1, p2, p3) +#define GFStrcat(p1, p2) strcat(p1, p2) +#define GFStrncat(p1, p2, p3) strncat(p1, p2, p3) +#define GFStrlen(p1) strlen(p1) +#define GFStrchr(p1, p2) strchr(p1, p2) +#define GFStrcmp(p1, p2) strcmp(p1, p2) +#define GFStrncmp(p1, p2, p3) strncmp(p1, p2, p3) +#define GFStrtok(p1, p2) strtok(p1, p2) +#define GFStrstr(p1, p2) strstr(p1, p2) +#define GFSscanf(p1, p2, p3) sscanf(p1, p2, p3) +#define GFToupper(p1) toupper(p1) +#define GFTolower(p1) tolower(p1) +#define GFAtoi(p1) atoi(p1) + +// convert char string to wchar_t +// p1 = src string of type char +// p2 = dst string of type wchar_t +// p3 = size of dst string in wchar_t unit +#define GFStrConvert(p1, p2, p3) \ + MultiByteToWideChar(CP_ACP, 0, p1, -1, p2, p3); + +// convert wchar_t string to char +// p1 = src string of type wchar_t +// p2 = dst string of type char +// p3 = size of dst string in char unit +#define GFWStrConvert(p1, p2, p3) \ + WideCharToMultiByte(CP_ACP, 0, p1, -1, p2, p3, NULL, NULL) + +/* Standard Helper functions */ +#define GFStrtol(p1, p2, p3) strtol(p1, p2, p3) +#define GFStrtod(p1, p2) strtod(p1, p2) + +/* Memory Helper functions */ +#define GFMemcpy( p1, p2, p3 ) memcpy( p1, p2, p3 ) +#define GFMemmove( p1, p2, p3 ) memmove( p1, p2, p3 ) +#define GFMemcmp( p1, p2, p3 ) memcmp( p1, p2, p3 ) +#define GFMemset( p1, p2, p3 ) memset( p1, p2, p3 ) + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +/* Debug Helper functions */ +#if !defined(PROJECT_SEC_G1) || defined(DEBUG) +#define GFPrintf printf +#else +#define GFPrintf +#endif +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintfVAL vprintf + +#ifdef DEBUG +extern void RmDebugBreak(void); +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + RmDebugBreak(); \ + } +#endif + +#elif NVOS_IS_LINUX + +#ifndef __KERNEL__ +void RmDebugBreak(void); +#ifdef DEBUG +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + RmDebugBreak(); \ + } +#endif + +#include +#define GFToupper toupper +#define GFTolower tolower + +#include +#ifndef GF_XTENSA_RM_TASK +#include +#endif +#define GFMemcpy memcpy +#define GFMemmove memmove +#define GFMemset memset +#define GFMemcmp memcmp +#define GFStrchr strchr +#define GFStrcmp strcmp +#define GFStrcpy strcpy +#define GFStrncpy strncpy +#define GFStrlen strlen +#define GFStrcat strcat +#define GFStrncmp strncmp +#define GFStrtok strtok +#define GFStrstr strstr +#define GFSscanf sscanf + +#include +#define GFPrintf printf +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintf printf +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintfVAL vprintf + +#include +#define GFStrtol strtol +#define GFStrtod strtod +#define GFAtoi atoi +#include + +/* Add or overload RMCTrace function here */ +#if defined(GF_ENABLE_RMC_TRACE) +#include +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#else /* kernel mode */ + +#include +#include + +#include +#define GFToupper toupper +#define GFTolower tolower + +#include +#define GFMemcpy memcpy +#define GFMemmove memmove +#define GFMemset memset +#define GFStrcpy strcpy +#define GFStrncpy strncpy +#define GFStrlen strlen +#define GFMemcmp memcmp +#define GFStrcmp strcmp +#define GFStrncmp strncmp +#define GFStrcat strcat +#define GFStrncat strncat + +#define GFStrstr strstr +#define GFSscanf sscanf + +#define GFPrintf printk +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintfVAL vprintf +#define GFAtoi atoi + +#if defined(GF_ENABLE_RMC_TRACE) +#include +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#endif /* KERNEL */ + +#elif NVOS_IS_WINDOWS + +#include +#include +#include +#include + +/* String functions */ +#define GFStrcpy(p1, p2) strcpy(p1, p2) +#define GFStrncpy(p1, p2, p3) strncpy(p1, p2, p3) +#define GFStrcat(p1, p2) strcat(p1, p2) +#define GFStrncat(p1, p2, p3) strncat(p1, p2, p3) +#define GFStrstr(p1, p2) strstr(p1, p2) +#define GFSscanf(p1, p2, p3) sscanf(p1, p2, p3) +#define GFStrlen(p1) strlen(p1) +#define GFStrchr(p1, p2) strchr(p1, p2) +#define GFStrcmp(p1, p2) strcmp(p1, p2) +#define GFStrncmp(p1, p2, p3) strncmp(p1, p2, p3) +#define GFStrtok(p1, p2) strtok(p1, p2) +#define GFToupper(p1) toupper(p1) +#define GFTolower(p1) tolower(p1) +#define GFStrConvert(p1, p2, p3) \ + strcpy(p2,p1) +// MultiByteToWideChar( CP_ACP, 0, p1, -1, p2, p3 ); + // convert char string to Wide + // p1 = src string of type char + // p2 = dst string of type wchar_t + // p3 = size of dst string in wchar_t unit + +/* Standard Helper functions */ +#define GFStrtol(p1, p2, p3) strtol(p1, p2, p3) +#define GFStrtod(p1, p2) strtod(p1, p2) + +/* Memory Helper functions */ +#define GFMemcpy( p1, p2, p3 ) memcpy( p1, p2, p3 ) +#define GFMemmove( p1, p2, p3 ) memmove( p1, p2, p3 ) +#define GFMemcmp( p1, p2, p3 ) memcmp( p1, p2, p3 ) +#define GFMemset( p1, p2, p3 ) memset( p1, p2, p3 ) + +#define GFAtoi( p1 ) atoi( p1 ) +/* Debug Helper functions */ +#if !defined(PROJECT_SEC_G1) || defined(DEBUG) +#define GFPrintf printf +#else +#define GFPrintf +#endif +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintfVAL vprintf + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +void RmDebugBreak(void); +#ifdef DEBUG +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + RmDebugBreak(); \ + } +#endif + +// Operating system running on the Xtensa +#elif NVCPU_IS_XTENSA + +#include + +/* Memory Helper functions */ +#define GFMemcpy( p1, p2, p3 ) memcpy(p1, p2, p3) +#define GFMemset( p1, p2, p3 ) memset(p1, p2, p3) + +#define GFRMCTrace(a) +#define GFRMCVTrace(a) + +#else + +#include +#include +#include +#include +#include + +/* String functions */ +extern char GFToupper(char); +extern char GFTolower(char); + +extern int GFAtoi(const char *); + +extern void *GFMemcpy(void *, const void *, int); +extern void *GFMemmove(void *, const void *, int); +extern void *GFMemset(void *, int, int); +extern int GFMemcmp(void *, void *, int); + +extern char *GFStrcpy(char *, const char *); +extern char *GFStrncpy(char *, const char *, int); + +extern char *GFStrcat(char *, const char *); +extern char *GFStrncat(char *, const char *, int); + +extern int GFStrlen(const char *); + +extern char *GFStrchr(const char *,int); +extern char *GFStrrchr(const char *,int); + +extern int GFStrcmp(const char *, const char *); +extern int GFStrncmp(const char *, const char *, int); + +extern char *GFStrstr(const char * string1, const char * string2); +extern int GFSscanf(char * string1, const char * string2, ...); + +extern char *GFStrtok(char *, const char *); + +extern long GFStrtol(const char *, char **, int); +extern double GFStrtod(const char *, char **); + +extern int GFPrintf(const char *, ... ); +extern int GFSprintf(char * , const char *, ... ); +extern int GFSprintfVAL(char *, const char *, va_list); +extern int GFPrintfVAL(const char *, va_list); + +#define GFStrConvert(p1, p2, p3) GFStrncpy(p1, p2, p3) + +#if defined(GF_ENABLE_RMC_TRACE) +#define GFRMCTrace(a) printf a +#define GFRMCVTrace(a) vprintf a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#ifdef DEBUG +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + } +#endif + +#endif /* GF_OS */ + +/* Virtual Key Mappings for Specific OS */ +#if NVOS_IS_LINUX +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 65 +#define GF_VKEY_LEFT 68 +#define GF_VKEY_RIGHT 67 +#define GF_VKEY_DOWN 66 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#elif NVOS_IS_WINDOWS_CE + +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 72 +#define GF_VKEY_LEFT 75 +#define GF_VKEY_RIGHT 77 +#define GF_VKEY_DOWN 80 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#elif NVOS_IS_WINDOWS +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 72 +#define GF_VKEY_LEFT 75 +#define GF_VKEY_RIGHT 77 +#define GF_VKEY_DOWN 80 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#else + +/* Virtual Keys */ +#define GF_VKEY_BACK 2 +#define GF_VKEY_FORWARD 3 +#define GF_VKEY_UP 4 +#define GF_VKEY_LEFT 5 +#define GF_VKEY_RIGHT 6 +#define GF_VKEY_DOWN 7 +#define GF_VKEY_SEND 8 +#define GF_VKEY_END 9 +#define GF_VKEY_0 10 +#define GF_VKEY_1 11 +#define GF_VKEY_2 12 +#define GF_VKEY_3 13 +#define GF_VKEY_4 14 +#define GF_VKEY_5 15 +#define GF_VKEY_6 16 +#define GF_VKEY_7 17 +#define GF_VKEY_8 18 +#define GF_VKEY_9 19 +#define GF_VKEY_STAR 20 +#define GF_VKEY_POUND 21 + +#endif /* GF_OS */ + +#ifndef GFDEBUG_ASSERT +#define GFDEBUG_ASSERT(x) do {} while (0) +#endif /* GFDEBUG_ASSERT */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFRMHelp_INL__ */ + diff --git a/Start_WM/test6/inc/GFRmHelp.inl b/Start_WM/test6/inc/GFRmHelp.inl new file mode 100755 index 00000000..4612fce2 --- /dev/null +++ b/Start_WM/test6/inc/GFRmHelp.inl @@ -0,0 +1,626 @@ +/* + * Copyright 2003 NVIDIA Corporation. All Rights Reserved. + * + * BY INSTALLING THE SOFTWARE THE USER AGREES TO THE TERMS BELOW. + * + * User agrees to use the software under carefully controlled conditions + * and to inform all employees and contractors who have access to the software + * that the source code of the software is confidential and proprietary + * information of NVIDIA and is licensed to user as such. User acknowledges + * and agrees that protection of the source code is essential and user shall + * retain the source code in strict confidence. User shall restrict access to + * the source code of the software to those employees and contractors of user + * who have agreed to be bound by a confidentiality obligation which + * incorporates the protections and restrictions substantially set forth + * herein, and who have a need to access the source code in order to carry out + * the business purpose between NVIDIA and user. The software provided + * herewith to user may only be used so long as the software is used solely + * with NVIDIA products and no other third party products (hardware or + * software). The software must carry the NVIDIA copyright notice shown + * above. User must not disclose, copy, duplicate, reproduce, modify, + * publicly display, create derivative works of the software other than as + * expressly authorized herein. User must not under any circumstances, + * distribute or in any way disseminate the information contained in the + * source code and/or the source code itself to third parties except as + * expressly agreed to by NVIDIA. In the event that user discovers any bugs + * in the software, such bugs must be reported to NVIDIA and any fixes may be + * inserted into the source code of the software by NVIDIA only. User shall + * not modify the source code of the software in any way. User shall be fully + * responsible for the conduct of all of its employees, contractors and + * representatives who may in any way violate these restrictions. + * + * NO WARRANTY + * THE ACCOMPANYING SOFTWARE (INCLUDING OBJECT AND SOURCE CODE) PROVIDED BY + * NVIDIA TO USER IS PROVIDED "AS IS." NVIDIA DISCLAIMS ALL WARRANTIES, + * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. + + * LIMITATION OF LIABILITY + * NVIDIA SHALL NOT BE LIABLE TO USER, USER’S CUSTOMERS, OR ANY OTHER PERSON + * OR ENTITY CLAIMING THROUGH OR UNDER USER FOR ANY LOSS OF PROFITS, INCOME, + * SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT + * OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A + * WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. IN NO EVENT SHALL NVIDIA’S + * AGGREGATE LIABILITY TO USER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH + * OR UNDER USER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY USER TO NVIDIA + * FOR THE SOFTWARE PROVIDED HEREWITH. + */ + +/* + * File: GFRmHelp.inl + * GFSDK Resource Manager Helper Manager inline header file. + * #### The helper functions are highly dependent on Operating System #### + * #### and Compiler. A number of these functions are macros that #### + * #### maps to corresonding operating system functions directly. #### + */ + +#ifndef __GFRMHelp_INL__ +#define __GFRMHelp_INL__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Define the macro GFRMHELP_IMPORTFUNC to import the helper functions + * referenced in GFSDK. Typically Target OS provides definitions for these + * functions. Sample definitions are provided in file RMHelpGeneric.c. + */ + +#if defined(GFRMHELP_ABSTRACTION) +extern char GFAToupper(char); +extern char GFATolower(char); + +extern void *GFMalloc(int); +extern void GFFree(void *ptr); + +extern void *GFMemcpy(void *, const void *, int); +extern void *GFMemmove(void *, const void *, int); +extern void *GFMemset(void *, int, int); +extern int GFMemcmp(void *, void *, int); + +extern char *GFAStrcpy(char *, const char *); +extern char *GFAStrncpy(char *, const char *, int); + +extern char *GFAStrcat(char *, const char *); +extern char *GFAStrncat(char *, const char *, int); + +extern char *GFAStrstr(const char * string1, const char * string2); +extern int GFASscanf(char * string1, const char * string2, ...); + +extern int GFAStrlen(const char *); + +extern char *GFAStrchr(const char *,int); + +extern int GFAStrcmp(const char *, const char *); +extern int GFAStrncmp(const char *, const char *, int); + +extern char *GFAStrtok(char *, const char *); + +extern long GFAStrtol(const char *, char **, int); +extern double GFAStrtod(const char *, char **); + +extern int GFAPrintf(const char *, ... ); + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +#define GFRMCTrace(a) GFRmRMCTrace a +#else +#define GFRMCTrace(a) +#endif + +#else + +/* Defined in GFRMHelp.c */ +extern int GFAStricmp(char *, char *); +extern int GFAStrincmp(char *, char *, int); + + +#if defined(NV_WINDOWS_CE) + +#ifndef __KERNEL__ +#include +#include +#include +#endif // __KERNEL__ + +/* String Helper functions */ +#define GFAStrcpy(p1, p2) strcpy(p1, p2) +#define GFAStrncpy(p1, p2, p3) strncpy(p1, p2, p3) +#define GFAStrcat(p1, p2) strcat(p1, p2) +#define GFAStrncat(p1, p2, p3) strncat(p1, p2, p3) +#define GFAStrlen(p1) strlen(p1) +#define GFAStrchr(p1, p2) strchr(p1, p2) +#define GFAStrcmp(p1, p2) strcmp(p1, p2) +#define GFAStrncmp(p1, p2, p3) strncmp(p1, p2, p3) +#define GFAStrtok(p1, p2) strtok(p1, p2) +#define GFAStrstr(p1, p2) strstr(p1, p2) +#define GFASscanf(p1, p2, p3) sscanf(p1, p2, p3) +#define GFAToupper(p1) toupper(p1) +#define GFATolower(p1) tolower(p1) +#define GFAAtoi(p1) atoi(p1) + +// convert char string to wchar_t +// p1 = src string of type char +// p2 = dst string of type wchar_t +// p3 = size of dst string in wchar_t unit +#define GFAStrConvert(p1, p2, p3) \ + MultiByteToWideChar(CP_ACP, 0, p1, -1, p2, p3); + +// convert wchar_t string to char +// p1 = src string of type wchar_t +// p2 = dst string of type char +// p3 = size of dst string in char unit +#define GFWStrConvert(p1, p2, p3) \ + WideCharToMultiByte(CP_ACP, 0, p1, -1, p2, p3, NULL, NULL) + +/* Standard Helper functions */ +#define GFAStrtol(p1, p2, p3) strtol(p1, p2, p3) +#define GFAStrtod(p1, p2) strtod(p1, p2) + +/* Memory Helper functions */ +#define GFMalloc( p1 ) malloc( p1 ) +#define GFFree( p1 ) free( p1 ) +#define GFMemcpy( p1, p2, p3 ) memcpy( p1, p2, p3 ) +#define GFMemmove( p1, p2, p3 ) memmove( p1, p2, p3 ) +#define GFMemcmp( p1, p2, p3 ) memcmp( p1, p2, p3 ) +#define GFMemset( p1, p2, p3 ) memset( p1, p2, p3 ) + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +/* Debug Helper functions */ +#define GFAPrintf printf +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintfVAL vprintf + +#ifdef DEBUG +extern void RmDebugBreak(void); +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + RmDebugBreak(); \ + } +#endif + +#elif defined(NV_LINUX) + +#ifndef __KERNEL__ +#ifdef DEBUG +#include +#define GFDEBUG_ASSERT(x) assert(x) +#endif + + +#define __declspec(x) + +#include +#define GFMalloc malloc +#define GFFree free + +#include +#define GFAToupper toupper +#define GFATolower tolower + +#include +#ifndef GF_XTENSA_RM_TASK +#include +#endif +#define GFMemcpy memcpy +#define GFMemmove memmove +#define GFMemset memset +#define GFMemcmp memcmp +#define GFAStrcmp strcmp +#define GFAStrcpy strcpy +#define GFAStrncpy strncpy +#define GFAStrlen strlen +#define GFAStrcat strcat +#define GFAStrncmp strncmp +#define GFAStrtok strtok +#define GFAStrstr strstr +#define GFASscanf sscanf + +#include +#define GFAPrintf printf +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintf printf +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintfVAL vprintf + +#include +#define GFAStrtol strtol +#define GFAStrtod strtod +#define GFAAtoi atoi +#include + +/* Add or overload RMCTrace function here */ +#if defined(GF_ENABLE_RMC_TRACE) +#include +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#else /* kernel mode */ + +#include +#include +#define GFMalloc(x) kmalloc((x), GFP_KERNEL) +#define GFFree kfree + +#include +#define GFAToupper toupper +#define GFATolower tolower + +#include +#define GFMemcpy memcpy +#define GFMemmove memmove +#define GFMemset memset +#define GFAStrcpy strcpy +#define GFAStrncpy strncpy +#define GFAStrlen strlen +#define GFMemcmp memcmp +#define GFAStrcmp strcmp +#define GFAStrncmp strncmp +#define GFAStrcat strcat +#define GFAStrncat strncat + +#define GFAStrstr strstr +#define GFASscanf sscanf + +#define GFAPrintf printk +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintfVAL vprintf +#define GFAAtoi atoi + +#if defined(GF_ENABLE_RMC_TRACE) +#include +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#endif /* KERNEL */ + +#elif defined(NV_WINDOWS) + +#include +#include +#include +#include +#include +#include + +/* String functions */ +#define GFAStrcpy(p1, p2) strcpy(p1, p2) +#define GFAStrncpy(p1, p2, p3) strncpy(p1, p2, p3) +#define GFAStrcat(p1, p2) strcat(p1, p2) +#define GFAStrncat(p1, p2, p3) strncat(p1, p2, p3) +#define GFAStrstr(p1, p2) strstr(p1, p2) +#define GFASscanf(p1, p2, p3) sscanf(p1, p2, p3) +#define GFAStrlen(p1) strlen(p1) +#define GFAStrchr(p1, p2) strchr(p1, p2) +#define GFAStrcmp(p1, p2) strcmp(p1, p2) +#define GFAStrncmp(p1, p2, p3) strncmp(p1, p2, p3) +#define GFAStrtok(p1, p2) strtok(p1, p2) +#define GFAToupper(p1) toupper(p1) +#define GFATolower(p1) tolower(p1) +#define GFAStrConvert(p1, p2, p3) \ + strcpy(p2,p1) +// MultiByteToWideChar( CP_ACP, 0, p1, -1, p2, p3 ); + // convert char string to Wide + // p1 = src string of type char + // p2 = dst string of type wchar_t + // p3 = size of dst string in wchar_t unit + +/* Standard Helper functions */ +#define GFAStrtol(p1, p2, p3) strtol(p1, p2, p3) +#define GFAStrtod(p1, p2) strtod(p1, p2) + +/* Memory Helper functions */ +#define GFMalloc( p1 ) malloc( p1 ) +#define GFFree( p1 ) free( p1 ) +#define GFMemcpy( p1, p2, p3 ) memcpy( p1, p2, p3 ) +#define GFMemmove( p1, p2, p3 ) memmove( p1, p2, p3 ) +#define GFMemcmp( p1, p2, p3 ) memcmp( p1, p2, p3 ) +#define GFMemset( p1, p2, p3 ) memset( p1, p2, p3 ) + +#define GFAAtoi( p1 ) atoi( p1 ) +/* Debug Helper functions */ +#define GFAPrintf printf +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintfVAL vprintf + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#ifdef DEBUG +#include "assert.h" +#define GFDEBUG_ASSERT( x ) assert( x ) +#endif + +// Operating system running on the Xtensa +#elif defined(NVCPU_XTENSA) + +#include + +#define GFAAtoi(p1) +/* String functions */ +#define GFAStrcpy(p1, p2) strcpy(p1, p2) +#define GFAStrncpy(p1, p2, p3) +#define GFAStrcat(p1, p2) +#define GFAStrncat(p1, p2, p3) +#define GFAStrlen(p1) +#define GFAStrchr(p1, p2) +#define GFAStrcmp(p1, p2) +#define GFAStrncmp(p1, p2, p3) + +#define GFAStrstr(p1, p2) +#define GFASscanf(p1, p2, p3) + +#define GFAStrncmp(p1, p2, p3) +#define GFAStrtok(p1, p2) +#define GFAToupper(p1) +#define GFATolower(p1) +#define GFAStrConvert(p1, p2, p3) +#define GFAAtoi(p1) + +/* Standard Helper functions */ +#define GFAStrtol(p1, p2, p3) +#define GFAStrtod(p1, p2) + +/* Memory Helper functions */ +#define GFMalloc( p1 ) +#define GFFree( p1 ) +#define GFMemcpy( p1, p2, p3 ) memcpy(p1, p2, p3) +#define GFMemmove( p1, p2, p3 ) memmove(p1, p2, p3) +#define GFMemcmp( p1, p2, p3 ) memcmp(p1, p2, p3) +#define GFMemset( p1, p2, p3 ) memset(p1, p2, p3) + +/* Debug Helper functions */ +#define GFAPrintf +#define GFASprintf +#define GFASprintfVAL +#define GFAPrintfVAL + +#define GFRMCTrace(a) +#define GFRMCVTrace(a) + +#else + +#include +#include +#include +#include +#include + +/* String functions */ +extern char GFAToupper(char); +extern char GFATolower(char); + +extern int GFAAtoi(const char *); +//#define GFMalloc( p1 ) malloc( p1 ) +//#define GFFree( p1 ) free( p1 ) +extern void *GFMalloc(int); +extern void GFFree(void *); + +extern void *GFMemcpy(void *, const void *, int); +extern void *GFMemmove(void *, const void *, int); +extern void *GFMemset(void *, int, int); +extern int GFMemcmp(void *, void *, int); + +extern char *GFAStrcpy(char *, const char *); +extern char *GFAStrncpy(char *, const char *, int); + +extern char *GFAStrcat(char *, const char *); +extern char *GFAStrncat(char *, const char *, int); + +extern int GFAStrlen(const char *); + +extern char *GFAStrchr(const char *,int); +extern char *GFAStrrchr(const char *,int); + +extern int GFAStrcmp(const char *, const char *); +extern int GFAStrncmp(const char *, const char *, int); + +extern char *GFAStrstr(const char * string1, const char * string2); +extern int GFASscanf(char * string1, const char * string2, ...); + +extern char *GFAStrtok(char *, const char *); + +extern long GFAStrtol(const char *, char **, int); +extern double GFAStrtod(const char *, char **); + +extern int GFAPrintf(const char *, ... ); +extern int GFASprintf(char * , const char *, ... ); +extern int GFASprintfVAL(char *, const char *, va_list); +extern int GFAPrintfVAL(const char *, va_list); + +#define GFAStrConvert(p1, p2, p3) GFAStrncpy(p1, p2, p3) + +#if defined(GF_ENABLE_RMC_TRACE) +#define GFRMCTrace(a) printf a +#define GFRMCVTrace(a) vprintf a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#ifdef DEBUG +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + } +#endif + +#endif /* GF_OS */ + +#endif /* GFRMHELP_ABSTRACTION */ + + +#define GFStrcpy GFAStrcpy +#define GFStrncpy GFAStrncpy +#define GFStrcat GFAStrcat +#define GFStrncat GFAStrncat +#define GFStrlen GFAStrlen +#define GFStrchr GFAStrchr +#define GFStrrchr GFAStrrchr +#define GFStrstr GFAStrstr +#define GFStrcmp GFAStrcmp +#define GFStricmp GFAStricmp +#define GFStrincmp GFAStrincmp +#define GFStrncmp GFAStrncmp +#define GFStrtok GFAStrtok +#define GFToupper GFAToupper +#define GFTolower GFATolower +#define GFStrConvert GFAStrConvert +#define GFPrintf GFAPrintf +#define GFSprintf GFASprintf +#define GFSprintfVAL GFASprintfVAL +#define GFPrintfVAL GFAPrintfVAL +#define GFStrtol GFAStrtol +#define GFStrtod GFAStrtod +#define GFSscanf GFASscanf +#define GFAtoi GFAAtoi + + +/* Virtual Key Mappings for Specific OS */ +#if defined(NV_LINUX) +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 65 +#define GF_VKEY_LEFT 68 +#define GF_VKEY_RIGHT 67 +#define GF_VKEY_DOWN 66 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#elif defined(NV_WINDOWS_CE) + +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 72 +#define GF_VKEY_LEFT 75 +#define GF_VKEY_RIGHT 77 +#define GF_VKEY_DOWN 80 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#elif defined(NV_WINDOWS) +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 72 +#define GF_VKEY_LEFT 75 +#define GF_VKEY_RIGHT 77 +#define GF_VKEY_DOWN 80 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#else + +/* Virtual Keys */ +#define GF_VKEY_BACK 2 +#define GF_VKEY_FORWARD 3 +#define GF_VKEY_UP 4 +#define GF_VKEY_LEFT 5 +#define GF_VKEY_RIGHT 6 +#define GF_VKEY_DOWN 7 +#define GF_VKEY_SEND 8 +#define GF_VKEY_END 9 +#define GF_VKEY_0 10 +#define GF_VKEY_1 11 +#define GF_VKEY_2 12 +#define GF_VKEY_3 13 +#define GF_VKEY_4 14 +#define GF_VKEY_5 15 +#define GF_VKEY_6 16 +#define GF_VKEY_7 17 +#define GF_VKEY_8 18 +#define GF_VKEY_9 19 +#define GF_VKEY_STAR 20 +#define GF_VKEY_POUND 21 + +#endif /* GF_OS */ + +#ifndef GFDEBUG_ASSERT +#define GFDEBUG_ASSERT(x) do {} while (0) +#endif /* GFDEBUG_ASSERT */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFRMHelp_INL__ */ + diff --git a/Start_WM/test6/inc/GFRmIx.h b/Start_WM/test6/inc/GFRmIx.h new file mode 100755 index 00000000..c2dddd0d --- /dev/null +++ b/Start_WM/test6/inc/GFRmIx.h @@ -0,0 +1,654 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFRmIx.h + Chip Initialization API header file. +*/ + +#ifndef __GFRMIX_H__ +#define __GFRMIX_H__ + +#include "GFRm.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupRmIx Chip Initialization API +*/ +/*@{*/ + +/* GPIO configurations + * Host GPIO1~GPIO7 correspond to HGP0~HGP6, C32KHZ. + * When configured as output, it is necessay to select output as data or + * Clocks or interrupt. + * GFIX_GPIO_CFG_OUTPUT can Or with GFIX_GPIO_CFG_OUTPUT_SEL_* + */ + +/* Host GPIO type enum */ +typedef enum +{ + GFIX_GPIO0 = 0, + GFIX_GPIO1, + GFIX_GPIO2, + GFIX_GPIO3, + GFIX_GPIO4, + GFIX_GPIO5, + GFIX_GPIO6, + GFIX_GPIO7 +} GFIX_GPIO_TYPE; + +/* Host GPIO operations. */ +#define GFIX_GPIO_GET_INPUT_ENABLE 0x80000000UL +#define GFIX_GPIO_GET_OUT_PUT_ENABLE 0x40000000UL +#define GFIX_GPIO_SET_DATA 0x20000000UL +#define GFIX_GPIO_CLR_DATA 0x10000000UL +#define GFIX_GPIO_GET_DATA 0x08000000UL + +#define GFIX_GPIO_SET_INPUT_ENABLE 0x04000000UL +#define GFIX_GPIO_CLR_INPUT_ENABLE 0x02000000UL +#define GFIX_GPIO_SET_OUTPUT_ENABLE 0x01000000UL +#define GFIX_GPIO_CLR_OUTPUT_ENABLE 0x00800000UL + +/* + * GPIO output select data, configure the pin as data output. + * Meaningful for pin0~pin4(HGP0~HGP4) + */ + +#define GFIX_GPIO_CFG_OUTPUT_SEL_DATA 0x00000000 + +/* + * GPIO output select interrupt, configure the pin as interrupt output. + * Meaningful for pin3(HGP3) only + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_INTR 0x00000040 + +/* + * GPIO output select RDY signal + * Meaningful for pin4(HGP4) only + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_RDY 0x00000100 + +/* + * For pin5 and pin6(HGP5, HGP6), config output clock or data on HGP5 and HGP6. + * + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP56_CLK 0x00000800 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP56_DATA 0x00000000 + +/* + * For pin5(HGP5) + * select monitor clock to HGP5 + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP5_PLL1 0x00000000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP5_PLL2 0x00001000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP5_PLLCOSC 0x00002000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP5_PLLROSC 0x00003000 + +/* + * For pin6(HGP6) + * select monitor clock to HGP6 + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP6_PLL2 0x00000000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP6_DCFCLK 0x00004000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP6_MCCLK 0x00008000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP6_DSPCLK 0x0000C000 + +/* + * For pin7(C32KHZ) + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_C32KHZ 0x00000000 + +/* + * Definition of attribute ids for Set/GetAttributes() + */ +typedef enum _GFIX_ATTR_TYPE + { + GFIX_ATTR_NONE = 0, + GFIX_ATTR_DEVICE_INFO, + GFIX_ATTR_DEVICE_INFO_STRUCT, /* Get Device ID & Rev */ + GFIX_ATTR_EFUSE_PRODUCT_SKU_ID, + GFIX_ATTR_DRAM_SELF_REFRESH, + GFIX_ATTR_DRAM_DEEP_POWER_DOWN +} GFIX_ATTR_TYPE; + +/* + * Definition of module frequency types. + */ +typedef enum _GFIX_MODULEFREQ_TYPE + { + GFIX_MODULEFREQ_OPTIMAL = 0, + GFIX_MODULEFREQ_MINIMUM, + GFIX_MODULEFREQ_MAXIMUM, + GFIX_MODULEFREQ_REQUESTED, + GFIX_MODULEFREQ_ACTUAL +} GFIX_MODULEFREQ_TYPE; + +/* + * Definition of module operations. + */ +#define GFIX_DISABLECLOCK 0x00000001 +#define GFIX_ENABLECLOCK 0x00000002 +#define GFIX_SPECIAL 0x00000004 +#define GFIX_FORCEDISABLECLOCK 0x00000008 +#define GFIX_FORCEENABLECLOCK 0x00000010 +#define GFIX_DYNAMICSWITCH 0x00000020 + +#define GFIX_FORCEDISABLEMODULE 0x00010000 +#define GFIX_FORCEENABLEMODULE 0x00020000 + +/* + * Clock selections, profile and options + */ +enum +{ +#define GFRM_CLOCK(x, y) GFIX_##x, +#define GFRM_CLOCK_PLL(x, y) GFIX_##x, +#include "gfrm_clock_ids.h" +#undef GFRM_CLOCK +#undef GFRM_CLOCK_PLL + GFNUMOFCLOCKIDS +}; + +enum +{ +#define GFRM_CLOCK(x, y) (1 << GFIX_##x )| +#define GFRM_CLOCK_PLL(x, y) (1 << GFIX_##x )| + GFIX_ALL_CLOCKS = +#include "gfrm_clock_ids.h" + 0, // | 0 to GFIX_ALL_CLOCKS +#undef GFRM_CLOCK +#undef GFRM_CLOCK_PLL + +#define GFRM_CLOCK(x, y) (1 << GFIX_##x )| +#define GFRM_CLOCK_PLL(x, y) + GFIX_NO_PLLS = +#include "gfrm_clock_ids.h" + 0, // | 0 to GFIX_NO_PLLS +#undef GFRM_CLOCK +#undef GFRM_CLOCK_PLL + +#define GFRM_CLOCK(x, y) +#define GFRM_CLOCK_PLL(x, y) (1 << GFIX_##x )| + GFIX_ONLY_PLLS = +#include "gfrm_clock_ids.h" + 0, // | 0 to GFIX_NO_PLLS +#undef GFRM_CLOCK +#undef GFRM_CLOCK_PLL + + GFIX_N_CLOCKSOURCES = GFNUMOFCLOCKIDS, + GFIX_NO_CLOCK = 0xFFFFFFFF, + GFIX_PLL_QUERY = 0x80000000 +}; + +#define GFIX_POWER 0x00010000 +#define GFIX_PERFORMANCE 0x00020000 + +#define GFIX_DEFAULTSLK 0x00000000 +#define GFIX_HIGHESTSLK 0x00000001 + +/** Module clock profile */ +typedef struct _GFIXMODULECONFIG +{ + NvU8 clockSelection; /**< Selection mode */ + NvU32 minFrequency; /**< Lowest frequency allowed */ + NvU32 optimalFrequency; /**< Optimal frequency */ + NvU32 maxFrequency; /**< Max frequency */ + NvU32 sourceClocks; /**< Bitfield of valid source clocks */ +} GFIXMODULECONFIG, *PGFIXMODULECONFIG; + +/** Module state */ + typedef struct _GFIXMODULESTATE +{ + NvU32 clkRefCount; /**< Reference counter used in GFRmIxEnableModuleClock */ + NvU32 clkSelect; /**< Clock selected for module (only valid when clkRefCount is non-zero) */ + /**< If clkSelect==GFIX_NO_CLOCK no clock is selected by this module */ + NvU32 enableRefCount; /**< Reference counter used in GFRmIxEnableModule */ +} GFIXMODULESTATE, *PGFIXMODULESTATE; + + +/** typedef for callback when the module is disabled */ + +typedef GF_RETTYPE (*GF_FUNC_RMIX_CALLBACK)(void *handle); + +/** Initializes the chip + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFRmIxInit() is the first function which touches the hardware, there are no + hardware accesses before GFRmIxInit(). It initializes some module's clocks + and as well as taking some modules out of reset. It also initializes + device-control registers. + + @see GFRmIxDeInit() +*/ +GF_RETTYPE +GFRmIxInit( GFRmHandle RmHandle ); + +/** De-initializes the chip + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFRmIxDeInit() does the reverse of GFRmIxInit(), it shut downs the chip. + All modules are put back in reset and clocks turned off. + + @see GFRmIxInit() +*/ +GF_RETTYPE +GFRmIxDeInit( GFRmHandle RmHandle ); + +/** This function enables a module's clock + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param modid (#eGFModuleIDs) ID of the module + @param option (NvU32) Bit field of options, GFIX_ENABLECLOCK, + GFIX_DISABLECLOCK, GFIX_FORCEENABLECLOCK, + GFIX_FORCEDISABLECLOCK, GFIX_DYNAMICSWITCH, GFIX_SPECIAL + @param special (NvU32) Specifies a module specific setting, only used when + option contains GFIX_SPECIAL + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function enables and disables a module's clock as well as enables the + module's source clock. There are two types of enables, the normal enable + and the force enable. When doing a normal enable the module's clock enable + reference count is increased as well as a call to GFRmIxEnableClockSource() + which ensures the module's source clock is enabled. When doing a force + enable/disable the modules reference counter is not touched, + GFRmIxEnableClockSource() is called which increases/deceases the source's + reference count. If the operation is to enable and the clock is currently + disabled, for the both normal enable and force disable GFRmIxEnableModuleClock + will attempt to find the best clock source and divider for the module. + + Some modules support a dynamic clock divider, that is the clock doesn't have + to be turned off before reprogramming the divider. To switch a module's + frequency that supports dynamic dividers without first turning the module + off set option to GFIX_DYNAMICSWITCH. GFRmIxEnableModuleClock will attempt + to find the closest frequency to the desired without changing clock sources. + + Some modules have special clock configurations such as VI, GFIX_SPECIAL can + be specified along with GFIX_ENABLECLOCK or by itself to configure the special + option for the module. +*/ +GF_RETTYPE +GFRmIxEnableModuleClock( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 option, + NvU32 special ); + +/** Same as GFRmIxEnableModuleClock, but takes a callback + function which will be called when the refcount goes + to zero. + + @param func Callback funtion of type GFRmIxEnableModuleClock + @param arg used as an argument to when callback function is called. + + @see GFRmIxEnableModuleClock() +*/ +GF_RETTYPE +GFRmIxEnableModuleClockEx( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 option, + NvU32 special, + GF_FUNC_RMIX_CALLBACK func, + void *arg); + +/** Enables a module + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param modid (#eGFModuleIDs) ID of the module + @param option (NvU32) If option is nonzero the module will be enabled + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function takes a module out of reset. Each module has a reference + count which is used to keep track of how many outstanding enables the + module has. The module will not be disabled until the reference counter + is returned to zero. +*/ +GF_RETTYPE +GFRmIxEnableModule( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 option ); + +/** Same as GFRmIxEnableModule() but calls the passing in callback + function when the refcount of the module goes to zero. + + @param callback Callback function of type GF_FUNC_RMIX_CALLBACK + @param arg Argument passed to the callback function. + + @see GFRmIxEnableModule() +*/ +GF_RETTYPE +GFRmIxEnableModuleEx( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 option, + GF_FUNC_RMIX_CALLBACK callback, + void *arg + ); + +/** Changes frequency of a clock. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param option (NvU32) GFIX_PLL1, GFIX_PLL2, GFIX_ROSC, GFIX_OSC, + GFIX_REFCLK0, GFIX_REFCLK1 or GFIX_PLL_QUERY + @param pFrequency (NvU32*) Pointer to 32-bit value in KHz to get three + digit MHz precision. Returns with newly set + current frequency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GF_ERROR_BAD_PARAMETER Bad parameter passed + + This function sets a clock to a certain frequency. If the clock cannot meet + the requested frequency then the closest one will be chosen. For the PLLs + this function determines the closest dividers to arrive at the requested + frequency. To determine the frequency that will be chosen without actually + setting it GFIX_PLL_QUERY can be Or'ed along with the clock ID. + + Some clocks only have one frequency that never changes; this function must + still be called at least once to allow the internal logic to know what the + frequency of the clock is. To disable the selection of a clock by a module, + a clock can be disabled by setting its frequency to zero; this will remove + it from consideration for all modules. + + This function will fail if a module is already using the clock. + + @see GFRmIxGetFrequency() +*/ +GF_RETTYPE +GFRmIxSetFrequency( GFRmHandle RmHandle, + NvU32 option, + NvU32 *pFrequency ); + +/** Retrieves frequency of a clock. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param option (NvU32) GFIX_PLL1, GFIX_PLL2, GFIX_ROSC, GFIX_OSC, + GFIX_REFCLK0, GFIX_REFCLK1 + @param pFrequency (NvU32*) Pointer to 32-bit value in KHz to get three + digit MHz precision. Returns with currently + set frequency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GF_ERROR_BAD_PARAMETER Bad parameter passed + + @see GFRmIxSetFrequency() +*/ +GF_RETTYPE +GFRmIxGetFrequency( GFRmHandle RmHandle, + NvU32 option, + NvU32 *pFrequency ); + +/** Sets the requested frequency of the module. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param modid (#eGFModuleIDs) ID of the module + @param frequency (NvU32) 32-bit value in KHz to get three digit MHz + precision + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function sets the requested frequency of a module, this value must + lie between the minimum and maximum frequencies specified in + GFRmIxSetModuleConfig(). This value is cached and used when + GFRmIxEnableModuleClock() is called attempting to enable the clock to the + module. + + @see GFRmIxSetModuleConfig() +*/ +GF_RETTYPE +GFRmIxSetModuleFrequency( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 frequency ); + +/** This function is used to retrieve clock frequency information about a module. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param modid (#eGFModuleIDs) ID of the module + @param type (#GFIX_MODULEFREQ_TYPE) Type of frequency + @param pFrequency (NvU32*) Pointer to 32-bit value in KHz to get three digit + MHz precision. Returns with currently frequency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +GF_RETTYPE +GFRmIxGetModuleFrequency( GFRmHandle RmHandle, + eGFModuleIDs modid, + GFIX_MODULEFREQ_TYPE type, + NvU32 *pFrequency ); + +/** This function enables and disables power plane(s). + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param ppID (NvU32) ID of power plane (More then one can be Or'ed to perform + operation in parallel) + @param operation (#GFIX_POWERPLANE_OP_TYPE) Operation to perform on the + power planes + @param states (NvU32*) Ptr to 32 bit value to store the resulting bit + field of a GFIX_POWERPLANE_OP_QUERY operation. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GF_ERROR_BAD_PARAMETER Bad parameter passed + + This function enables and disables power plane(s), multiple power planes can + be disabled in one function call. There is two versions of this functions + specified with the compilation flag GF_EXTERNAL_POWERPLANE_LOGIC. If this + flag is set to 1 then all the power plane logic is done in the platform code, + if 0 then all the logic is done in Ix. + + When internal power plane logic is chosen, each power plane has a reference + count. If the power plane is to be enabled or disabled, GFRmIxPowerPlane() + will call out to RmPowerPlane(), which will perform platform specific enabling. +*/ +GF_RETTYPE +GFRmIxPowerPlane( GFRmHandle RmHandle, + NvU32 ppID, + GFIX_POWERPLANE_OP_TYPE operation, + NvU32 *states ); + +/** Enable and disables clock sources. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param clockid (NvU32) ID of the clock + @param state (NvU32) 0 for disable, 1 for enable + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function enables and disables a clock's source. A reference counter is + used to ensure the clock's source won't be disabled until there is a matching + number of enable and disable operations. If a clocks source is to be enabled + or disabled, GFRmIxEnableClockSource() will call out to RmEnableClockSource() + to do the platform specific enabling or disabling. +*/ +GF_RETTYPE +GFRmIxEnableClockSource( GFRmHandle RmHandle, + NvU32 clockid, + NvU32 state ); + +/** This function sets the list of reference clocks that a PLL may choose. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param option (NvU32) GFIX_PLL1, GFIX_PLL2 + @param clocks (NvU32) Bitfield of clocks. (1< +
      +                                                      0    -> audio structs can be locate anywhere, dspcore will be allocated anywhere (default)
      +                                                      1    -> audio structs must be allocated in internal SRAM, dspcore will be allocated anywhere
      +                                                      0xMM -> MM is a 8 bit wide bitmask: b'10XXYYZZ (i.e. 0x80 | b'XXYYZZ)
      +
      +                                                      XX controls allocation of dspcore DSP image (about 100 kB)
      +                                                      YY to control allocation of GfSgl (about 90 kB, not required for encoding=ADTSINTERNAL)
      +                                                      ZZ controls allocation of GfGlobalParameters struct (about 36 kB)
      +
      +                                                      bitmask meaning:
      +                                                      b'00 no special requirement
      +                                                      b'01 force internal SRAM
      +                                                      b'10 force external SRAM
      +                                                      b'11 unused
      +                                                      
      + */ + + NvU32 AudioRecordEnable; //!< GFSDK_AUDIO_REC_ENABLE, Enable SC15 I2S Record, default : 0 + NvU32 AudioNoI2C; //!< Disable codec I2C access in GFAudioAPI + char I2SCodecInit[RM_ENV_MAXLEN]; //!< Codec init addr/data sequence comma delimited zero padded 32 bit hex values "xxxxxxxx,xxxxxxxx,..." up to 128 chars + char I2SCodecReset[RM_ENV_MAXLEN]; //!< Codec reset addr/data sequence comma delimited zero padded 32 bit hex values "xxxxxxxx,xxxxxxxx,..." up to 128 chars + //!< I2S "aaaaddrr" aaaa - i2s slave address, dd - 8 bit data, rr 7 bit i2s register + //!< AC97 "aaaadddd" aaaa - ac97 register address, dddd - 16 bit data value + NvU32 I2SCodecEnableSMCLK; + NvU32 SCInterfaceMode; + + NvU32 perfMode3D; // 3D perf mode. + NvU32 DxInitBypass; // This is used to tell DxSetDisplay() to initialize the + // software state without touching the hardware + NvU32 noDCPreLoadCtx; + NvU32 nulldriver2D; +#if NVOS_IS_WINDOWS_CE + NvU32 BackupMemory; +#endif + NvU32 IndirectAddrSet; +} GFRMENVIRONMENTVARIABLES, *PGFRMENVIRONMENTVARIABLES; + +/* Rm Public Services for platform only. May depend on GFPlat.h */ +enum +{ + RM_EXTDATA_INIT_TYPE = 0 +}; + +enum +{ + RM_EXTDATA_INIT_SCRIPT = 0, + RM_EXTDATA_RM_SCRIPT, + RM_EXTDATA_CAMERA_SCRIPT, + RM_EXTDATA_ENVVARS_SCRIPT, + RM_EXTDATA_DISPLAY_SCRIPT, + RM_EXTDATA_DISPLAY_SUB_SCRIPT, + RM_EXTDATA_AUTOCTRL_SCRIPT, + RM_EXTDATA_AVP_IMAGE_AUDIO_AVP1, + RM_EXTDATA_AVP_IMAGE_MP3_AVP1, + RM_EXTDATA_AVP_IMAGE_SBC_AVP1, + RM_EXTDATA_AVP_IMAGE_AAC_AVP1, + RM_EXTDATA_AVP_IMAGE_EAAC_AVP1, + RM_EXTDATA_AVP_IMAGE_AACLPSBR_AVP1, + RM_EXTDATA_AVP_IMAGE_AMRNB_AVP1, + RM_EXTDATA_AVP_IMAGE_AMRWB_AVP1, + RM_EXTDATA_AVP_IMAGE_WMA_AVP1, + RM_EXTDATA_AVP_IMAGE_AUDIO_AVP2, + RM_EXTDATA_AVP_IMAGE_MP3_AVP2, + RM_EXTDATA_AVP_IMAGE_SBC_AVP2, + RM_EXTDATA_AVP_IMAGE_AAC_AVP2, + RM_EXTDATA_AVP_IMAGE_EAAC_AVP2, + RM_EXTDATA_AVP_IMAGE_AACLPSBR_AVP2, + RM_EXTDATA_AVP_IMAGE_AMRNB_AVP2, + RM_EXTDATA_AVP_IMAGE_AMRWB_AVP2, + RM_EXTDATA_AVP_IMAGE_WMA_AVP2, + RM_EXTDATA_AVP_IMAGE_H264DEC_AVP1, + RM_EXTDATA_AVP_IMAGE_H264DEC_AVP2, + RM_EXTDATA_AVP_IMAGE_MP4DEC_AVP1, + RM_EXTDATA_AVP_IMAGE_MP4DEC_AVP2, + RM_EXTDATA_AVP_IMAGE_JPEGDEC_AVP1, + RM_EXTDATA_AVP_IMAGE_JPEGDEC_AVP2, + RM_EXTDATA_AVP_IMAGE_H264ENC_AVP1, + RM_EXTDATA_AVP_IMAGE_H264ENC_AVP2, + RM_EXTDATA_AVP_IMAGE_VC1DEC_AVP1, + RM_EXTDATA_AVP_IMAGE_VC1DEC_AVP2, + RM_EXTDATA_AVP_IMAGE_RV9DEC_AVP1, + RM_EXTDATA_AVP_IMAGE_RV9DEC_AVP2, + RM_EXTDATA_AVP_IMAGE_ISP3A_AE_AF_AVP1, + RM_EXTDATA_AVP_IMAGE_ISP3A_AWB_AVP1, + RM_EXTDATA_AVP_IMAGE_ISP3A_DVS_AVP1, + RM_EXTDATA_AVP_IMAGE_BEATNIK_AVP1, + RM_EXTDATA_AVP_IMAGE_BEATNIK_AVP2, + RM_EXTDATA_AVP_IMAGE_KERNEL_AVP1, + RM_EXTDATA_AVP_IMAGE_KERNEL_AVP2, + RM_EXTDATA_AVP_IMAGE_DSP_UNITTESTS, + RM_EXTDATA_AVP_IMAGE_TSDEM_AVP1, //!< SC15 version of GFMxDemTS DSP image + RM_EXTDATA_AVP_IMAGE_TSDEM_AVP2, //!< SC14 version of GFMxDemTS DSP image + RM_EXTDATA_AVP_IMAGE_ISP_AVP1 +}; + +enum +{ + RM_EXTDATA_FILE = 0, + RM_EXTDATA_FILE_WITH_SUBID, +}; + +#define DEFAULTSCRIPTNAME "default" + +#define RM_EXTDATA_READ 1 // Read in data +#define RM_EXTDATA_USEBUFFER 4 // RmAccessExternalData shouldn't handle + // allocation of buffer, the data is to + // be placed at the orginal buffer address +#define RM_EXTDATA_SIZE 8 // Query the size of the data +#define RM_EXTDATA_FILENAME 0x10 // return script file name +#define RM_EXTDATA_NAME 0x20 // return name of script without prefix and sub ID +#define RM_EXTDATA_IDLIST 0x40 // return array of script sub ID + +/* Fields in struct PGFRMEXTDATASTRUCT + * dataType : Type of the data + * dataID : ID of the data + * subID : Sub ID of script + * buffer : Pointer to pointer of the data address + * size : Address to store the resulting size. During a read operation if size + * is non-zero the amount of bytes read in will be stored there. If size + * or the value pointed to by size is zero all the data represented by + * dataID will be read in. + * option : flag that will change what is returned in buffer and size. + */ +typedef struct _GFRMEXTDATASTRUCT +{ + NvU32 dataType; // type of data + NvU32 dataID; // ID of data + NvU32 subID; // sub ID of data + void ** buffer; + NvU32 * size; + NvU32 option; +} GFRMEXTDATASTRUCT, *PGFRMEXTDATASTRUCT; + + + /** This function is called to get value from curent environment. + + @param envName environment name in env table + @param envType environment type + RM_ENV_DECIMAL // String should be parsed as a decimal + RM_ENV_HEX // String should be parsed as a hexadecimal + RM_ENV_CHAR // String should be parsed as a character + RM_ENV_STRING // String used as-is. + @param parsedval converted value. Only available while environment type is RM_ENV_DECIMAL or RM_ENV_HEX + @return a pointer to the environment table entry containing varname. + */ +// char * ReadEnvVars( const char *envName, int envType, NvU32 *parsedval); +GF_RETTYPE nvGetConfigUint32(const char *name, NvU32 *value); + +GF_RETTYPE nvGetConfigString( const char *envName, char **value); + +/** Retrieves the Process id of the current process. + + @param RmGetProcessID Pointer to NvU32 for returning the prcess id, + + @return GF_SUCCESS If the platforms support some sort of get process id API + @return GF_ERROR. if not support +*/ +GF_RETTYPE RmGetProcessID( NvU32 *RmProcessID ); + +/* Thread, Mutex, Event and Semaphore opaque handles */ +typedef struct GFMutex_t *GFMutex; +typedef struct GFSemaphore_t *GFSemaphore; +typedef struct GFEvent_t *GFEvent; +typedef struct GFThread_t *GFThread; + +/* Rm platform functions for OS abstraction */ + +/** Create Mutex object. + + @param id - Mutex identiifer. Used to cretate named objects. If the + id is 0, un named object is created. + + @return Handle to the event object, or 0 on failure. +*/ +GFMutex RmCreateMutex( NvU32 id ); + +/** Lock mutex object, blocks until mutex can be taken. Must always succeed if + given a valid mutex handle. + + @param mutex Mutex handle +*/ +void RmLockMutex(GFMutex mutex); + +/** Unlock mutex object. Must always succeed if given a valid mutex handle. + + @param mutex Mutex handle +*/ +void RmUnlockMutex(GFMutex mutex); + +/** Destroy mutex object. Must always succeed if given a valid mutex handle. + Must not crash (should do nothing) if given a NULL handle. + + @param mutex Mutex handle. +*/ +void RmDestroyMutex(GFMutex mutex ); + +/** Create semaphore object. + + @param id - Semaphore identifer. Used to create named objects. If the + id is 0, unnamed object is created. + + @param InitCount (NvU32) Initial count of semaphore. This value must be + greater than zero. + @param MaxCount (NvU32) Maximum count of semaphore. This value must be + greater than zero. + + @return Handle to semaphore object, or 0 on failure +*/ +GFSemaphore RmCreateSemaphore(NvU32 id, NvU32 InitCount, NvU32 MaxCount); + +/** Destroy semaphore object. Must always succeed if given a valid semaphore + handle. Must not crash (should do nothing) if given a NULL handle. + + @param sem Semaphore handle +*/ +void RmDestroySemaphore(GFSemaphore sem); + +/** Signal semaphore object. This function increments the semaphore's counter. + Must always succeed if given a valid semaphore handle. + + @param sem Semaphore handle +*/ +void RmSignalSemaphore(GFSemaphore sem); + +/** Wait on semaphore. + Function blocks while semaphore's count is 0. Once the count is non-zero, + the count is decremented by one and function returns. If timeout is passed + as 0, the function does not block. + + @param sem Semaphore handle + @param timeout Timeout in miliseconds, 0 for non-blocking, (NvU32)-1 for infinite wait. + @retutn GF_SUCCESS indicates that the semaphore was taken successfully, GF_WAIT_TIME_OUT + indicates timeout, any other return value indicates error. +*/ +GF_RETTYPE RmWaitOnSemaphore(GFSemaphore sem, NvU32 timeout); + + +/** Create event object. + + @return Handle to event object, or NULL on failure +*/ +GFEvent RmCreateEvent(void); + +/** Sets the event object to the signaled state. Must always succeed if given + a valid event handle. + + @param event Event handle +*/ +void RmSetEvent( GFEvent event ); + +/** Resets the event object to the nonsignaled state. Must always succeed if + given a valid event handle. + + @param event Event handle +*/ +void RmResetEvent( GFEvent event ); + +/** Function blocks until the event is signaled. + + @param event Event handle. + @param msec Milli seconds to wait. + + @retval GF_WAIT_GET_OBJECT Event was signaled, and the event object was acquired. + @retval GF_WAIT_TIME_OUT Timeout before event was signaled + @retval GF_WAIT_ERROR An error occured. +*/ +GF_RETTYPE RmWaitForEvent(GFEvent event, NvU32 msec ); + + +/** Destroys the event object. Must always succeed if given a valid event + handle. Must not crash (should do nothing) if given a NULL handle. + + @param event Event Handle. This is the handler returned by + the call to RmCreateEvent function. +*/ +void RmDestroyEvent( GFEvent event ); + +/** Creates a thread to execute within the calling process. + + @param func (NvU32 (*)(void *)) Pointer to a function to be executed + by the thread. + @param data (void *) Pointer to variable to be passed to the thread + + @return Handle to thread on success, otherwise 0 is returned. +*/ +GFThread RmCreateThread(NvU32 (*StartFunction)(void *), void *data); + +/** Blocks until the specified thread terminates, then frees system resources + associated with the thread. Must always succeed if given a valid thread + handle. Must not crash (should do nothing) if given a NULL handle. + + @param ThreadHandle Thread handle retruned by RmCreateThread call +*/ +void RmJoinThread(GFThread ThreadHandle); + +/** Yield execution to other threads. This will be called inside spin loops + that are waiting for the hardware to finish something. +*/ +void RmYield(void); + +/** Get full path of extended script data. Assume the script data is at same directory as bootload module. + @param modulename (char *)Bootloader module name. If the script data is not at same directory as module, could be NULL. + @param fullpath (char *)Pointer to extened script data path. + + @return GF_SUCCESS to signal success, or error code to signal failure +*/ +GF_RETTYPE + RmGetExtDataPath(char *modulename, char *fullpath ); + +/* File and File Search opaque handles */ +typedef struct GFFile_t *GFFile; +typedef struct GFFileSearch_t *GFFileSearch; + +/** Searches a directory for a file whose name matches the specified file name. + It examines subdirectory names as well as file names + @param filePath (char *) Pointer to a null-terminated string that specifies a valid directory or path and file name, + which can contain wildcard characters (* and ?) + @param filename (char *) pointer to the full path file/dir which match this search. + + @return If the function succeeds, the return value is a search handle used in a subsequent call to RmFindNextFile or RmFindClose, + NULL if the function failed. +*/ +GFFileSearch RmFindFirstFile(const char *filePath, char *fileName); + +/** Continues a file search from a previous call to the RmFindFirstFile function. + @param hFind (GFFileSearch ) Search handle returned by a previous call to the RmFindFirstFile function. + @param filename (char *) pointer to the filename with full path which match this search. + @return GF_SUCCESS to signal success, or error code to signal failure +*/ +GF_RETTYPE RmFindNextFile(GFFileSearch hFind, char *fileName); + +/** Closes the specified search handle. Must always succeed if given a valid + search handle. Must not crash (should do nothing) if given a NULL handle. + + @param hFind (GFFileSearch) Search handle returned by a previous call to the RmFindFirstFile function. +*/ +void RmFindClose(GFFileSearch hFind); + +/** Open file. + @param filename (const char *) Filename + @param fileSpec (const char *) Type of access permitted + @return Handle to the open file. A NULL pointer value indicates an error. +*/ +GFFile RmFileOpen(const char *fileName, const char *fileSpec); + +/** Close file. Must always succeed if given a valid file handle. Must not + crash (should do nothing) if given a NULL handle. + + @param fp Handle that RmFileOpen() returned +*/ +void RmFileClose(GFFile fp); + +/** Read data from file. + @param buffer (void *) Storage location for data + @param lSize (NvU32) Item size in bytes + @param lCount(NvU32) Maximum number of items to be read + @param fp (GFFile) Pointer that RmFileOpen() returned + @return Number of full items actually read, 0 if nothing is read out. +*/ +GF_RETTYPE RmFileRead(void *buffer, NvU32 lSize, NvU32 lCount, GFFile fp); + +/** Get file size. + @param fp(GFFile ) Pointer that RmFileOpen() returned + @return Current file size in bytes. +*/ +GF_RETTYPE RmFileSize(GFFile fp); + +/** Platform abstraction for millisecond sleep. + + @param msec Milliseconds to sleep. + */ +void RmWaitMSec(NvU32 msec); + +/** Waits for a keypress with a timeout, and returns the key. + + @param timeOutMSec Milliseconds to wait for the keypress. + @retval The code for the key, or zero if we timed out. + */ +int RmWaitKey(NvU32 timeOutMSec); + +/** Get the current OS tick counter. + @return Low 32 bits of millisecond counter. +*/ +NvU32 RmGetTickCountMSec(void); + +/** Get the current OS tick counter. + + NOTE: This function is NOT guaranteed to exist on all + platforms. Drivers should NOT call this function; it's + meant only for benchmarking. + + @return (NvU64) 64 bit microsecond counter. + */ +NvU64 RmGetTickCountUSec(void); + +/** SetupPlatform - It is called by RmSetupPlatform to setup any platform specific stuff. + + @param pOutput (PGFRMSETUPPLATFORM) output structure. Used to pass variables to high layer function RmSetupPlatform + @param penv (PGFRMENVIRONMENTVARIABLES) pass Environment Variable Configuration structure + + @return GF_SUCCESS to signal success, or error code to signal failure + +*/ +GF_RETTYPE SetupPlatform( PGFRMSETUPPLATFORM pOutput, PGFRMENVIRONMENTVARIABLES penv ); + +/** Called by RmExitPlatform to exit and clean-up any platform specific stuff, if any + + @param pUserObject0 (void *) Pointer to user specified object 0 from high layer function RmExitPlatform + + @return GF_SUCCESS to signal success, or error code to signal failure +*/ +GF_RETTYPE ExitPlatform( void *pUserObject0); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFRMOEM_H__ */ diff --git a/Start_WM/test6/inc/GFRmRDMA.h b/Start_WM/test6/inc/GFRmRDMA.h new file mode 100755 index 00000000..151ec65d --- /dev/null +++ b/Start_WM/test6/inc/GFRmRDMA.h @@ -0,0 +1,411 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @File: GFRmRDMA.h + GFSDK Read DMA memmory manager. + + */ + +#ifndef __GFRMRDMA_H__ +#define __GFRMRDMA_H__ + +#include "GF.h" + +/** @addtogroup groupRDMA RDMA ReadDMA API +
        +
      • @ref pageRDMAAppNotes +
      +*/ + +/*@{*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + + +/** eGFRmRDMAClientID: Enumeration of client id's. SC15 has 4 + RDMA (Read DMA) FIFO's. Modules specified below can be + attached to the RDMA FIFO's. See @ + */ +typedef enum +{ + RDMA_CLID_CPU = 0, + RDMA_CLID_DSP, + RDMA_CLID_I2S, + RDMA_CLID_SD, + RDMA_CLID_MPEGE, + RDMA_CLID_JPEGE, + RDMA_CLID_EPP, + RDMA_CLID_VI, + RDMA_CLIDS +} eGFRmRDMAClientID; + +/** RDMA buffer header. + + For non-rectangular (or linear) reads + RDMA expects a header in the memory. The header formart is as specified + below. GFRmRDMAReadHeader function returns the header in this format. + + @See GFRmRDMAReadHeader() + */ + +typedef struct _RDMA_BUF_HEADER +{ + NvU32 bufferSize; + NvU32 raiseVector; + NvU32 channel; + NvU8 raiseEnable; + NvU8 frameStart; + NvU8 frameEnd; + NvU8 largeHdr; + NvU32 extHeader; + +} RDMA_BUFFER_HEADER, *pRDMA_BUFFER_HEADER; + + +/* RDMA flags */ + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + No byte swap. +*/ +#define GF_RDMA_FLAGS_SWAP_NONE 0x00000000 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + Swap bytes in a word. example: 0xaabbccdd to 0xbbaaddcc. +*/ +#define GF_RDMA_FLAGS_SWAP_BYTE_IN_WORD 0x00000001 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + Swap bytes in dword: 0xaabbccdd to 0xddccbbaa. +*/ +#define GF_RDMA_FLAGS_SWAP_BYTE_IN_DWORD 0x00000002 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + Swap word in dword example: 0xaabbccdd to 0xccddaabb. +*/ +#define GF_RDMA_FLAGS_SWAP_WORD_IN_DWORD 0x00000003 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags bitmask: + mask out byte swap options GF_RDMA_FLAGS_SWAP_*. +*/ +#define GF_RDMA_FLAGS_SWAP_MASK 0x00000003 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + Tells the RDMA engine to output header. Will output a header into the data stream, + which has to be read with GFRmRDMAReadHeader() before calling GFRmRDMARead(). + This flag is relevant only in non-rectangular reads. + */ +#define GF_RDMA_FLAGS_STR_HEADER 0x00010000 + +/** RDMA_RECT + Setup information for the RDMA. + */ +typedef struct _RDMA_RECT +{ + /** physical addess of the buffer in the SC15 Memory view. 32-bit alignment + * required. */ + NvU32 baseOffset; + + /** client id. See @eGFRmRDMAClientID */ + eGFRmRDMAClientID clid; + + /** buffers/stride/width/lines of the rectangular buffer. + + Need to comply with the following constraints provided + by the hardware + - if width is not a multiple of 4 bytes (one word): + - stride equals width, stride should be the exact stride in bytes (eg. line_stride[1:0] not equal to 0) + - if stride is bigger than width, stride should be rounded down to the nearest word + (eg. line_stride[1:0] should be zero) + + For example: width = 42 bytes, stride = 82 -> stride should be programmed to 80 + width = 42 bytes, stride = 42 -> stride should be programmed to 42 + */ + NvU32 buffers; + NvU32 stride; + NvU32 width; + NvU32 lines; + + /* use the RDMA flags defined above as GF_RDMS_FLAGS_* */ + NvU32 flags; //!< Flagbits, see GF_RDMA_FLAGS_* + + /* Timeout in msec. If <=0, then no timeout */ + NvU32 timeout; + +} RDMA_RECT, *pRDMA_RECT; + +/** RDMA_NONRECT + + Setup structure for non-rectangular reads. + + */ +typedef struct _RDMA_NONRECT +{ + /** Physical addess of the buffer in the GPU address space. Needs to be + * 32-bit aligned. */ + NvU32 baseOffset; + + /** client id. See @eGFRmRDMAClientID */ + eGFRmRDMAClientID clid; + + NvU32 buffers; + NvU32 stride; + + /* use the RDMA flags defined above as GF_RDMS_FLAGS_* */ + NvU32 flags; //!< Flagbits, see GF_RDMA_FLAGS_* + + /* Timeout in msec. If =0, then no timeout */ + NvU32 timeout; + +} RDMA_NONRECT, *pRDMA_NONRECT; + + +/** There are four read dma channels, the RM manages the allocation/ + freeing of these channels. This function allocates a channel. + + @param RmHandle Handle to the Rm allocated via call to GFRmOpen. + @param DmaHandle Pointer to an allocated handle. + + @retval GF_SUCCESS if a RDMA channel is available, and returns + RDMA handle on allocation. + + The release function will return GF_ERROR + if the read dma is already released. + */ + +GF_RETTYPE +GFRmRDMAAlloc(GFRmHandle RmHandle, GFRmRdmaHandle *DmaHandle); + +/** There are four read dma channels, the RM manages the allocation/ + freeing of these channels. This function frees an allocated + channel. + + @param hRm Handle to the Rm allocated via call to GFRmOpen. + @param phDma Pointer to the DMA handle to be released. + */ +void +GFRmRDMARelease(GFRmHandle hRm, GFRmRdmaHandle *phDma); + +/** Setup non-rectangular RDMA. + + When the flag GF_RDMA_FLAGS_STR_HEADER is set, buffer header is written to the + memory by the RDMA client. So, when the cpu reads the data, buffer + header comes first and then the data. Buffer header has the information + of buffer, like its size etc. + + + So, an example sequence would be + - Call setup with GF_RDMA_FLAGS_STR_HEADER flag set. + - Read header with the GFRmRDMAReadHeader(...) + - Read buffer size of data with GFRmRDMARead() funtion. + Buffer size is in the buffer header. + + If this flag is not set, then the there is no buffer header. + In this case it is assumed that the the size of the buffer is prefixed + and known to the module API writers. + + So, an example sequence would be + - Call setup GF_RDMA_FLAGS_STR_HEADER flag not set. + - Read buffer size of data with GFRmRDMARead() funtion. + Buffer size is known to the callers. + + baseOffset of pReq structure needs to be 32-bit aligned. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param pReq Populated RDMA req structure. See @RDMA_NONRECT +*/ + +GF_RETTYPE +GFRmRDMASetupNONRect(GFRmRdmaHandle DmaHandle, pRDMA_NONRECT pReq); + +/** Setup RDMA for rectangular read. + + Requirement: + baseOffset of pReq structure needs to be 32-bit aligned. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param pReq Populated RDMA req structure. See @RDMA_RECT +*/ +GF_RETTYPE +GFRmRDMASetupRect(GFRmRdmaHandle DmaHandle, pRDMA_RECT pReq); + +/** Reads the RDMA FIFO status register and returns the + available number of FIFO slots. A slot is 32-bit. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + */ +NvU32 GFRmRDMAFIFOAvailIn32Bits(GFRmRdmaHandle DmaHandle); + +/** Reads memory from SC15 internal/external + memory to the system memory pointed by the dstAddr. Need + to pass the same rectangular attributes passed, when the + RDMA is setup. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param dstAddr aligned or non-aligned dest pointer. Aligned + pointer results in faster reads. + @param width Width in bytes to read. + @param height Height of the rectangular region. + + @retval Returns GF_SUCCESS or GF_ERROR. + */ + +GF_RETTYPE +GFRmRDMARectRead(GFRmRdmaHandle DmaHandle, void *dstAddr, NvU32 width, NvU32 height); + + +/** Reads memory from SC15 internal/external + memory to the system memory pointed by the dstAddr. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param dstAddr aligned or non-aligned dest pointer. Aligned + pointer results in faster reads. + @param sizeInBytes Number of bytes to read. + + @retval Returns GF_SUCCESS or GF_ERROR. + */ + +GF_RETTYPE +GFRmRDMARead(GFRmRdmaHandle DmaHandle, void *dstAddr, NvU32 sizeInBytes); + +/** Reads buffer header. Once this info is read + API's will know how much data to read or expect. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param header Pointer to RDMA header structure. See @RDMA_BUFFER_HEADER + */ +GF_RETTYPE +GFRmRDMAReadHeader(GFRmRdmaHandle DmaHandle, pRDMA_BUFFER_HEADER header); + + +/** Cleanup the RDMA FIFO, by reading out any extra DOWRDS + GFRmRDMARead might not have read. + + In general this function need not be used. + */ + +GF_RETTYPE +GFRmRDMACleanup(GFRmRdmaHandle DmaHandle); + + +/** Gets the actual RDMA channel number from the DMA handle. This is + usefull for DSP development. Host code allocates the DMAHandle + gets the DMA number from that and creates the DMA handle on the + DSP side using GFXRmRDMAAlloc function. GFXRmRDMAAlloc needs to + know what DMA channel to use. + + @param DmaHandle RDMA handle. + @param dmaNumber RDMA channel number used the handle. + +*/ + +void +GFRmRDMAGetPortNumber(GFRmRdmaHandle DmaHandle, NvU32 *portNumber); + +#if NVCPU_IS_XTENSA + +// In XRM, it is expected that the dma handle is allocated on +// the Host side, and just the dma number is passed into code +// running on the Xtensa. These functions will setup a +// DMA handle that can used in the XRM. + + +GF_RETTYPE +GFXRmRDMAAlloc(NvU32 dmaNumber, GFRmRdmaHandle *DmaHandle); + + +GF_RETTYPE +GFXRmRDMARelease(GFRmRdmaHandle *DmaHandle); + +#endif // NVCPU_IS_XTENSA + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/*@}*/ + +/** @page pageRDMAAppNotes RDMA Application Notes + + General information about RDMA - RDMA is read DMA hw block. Unlike + traditional DMA, sw reads the data from the FIFO to system memory. This is + becasuse SC15 cannot bus master and write directly to the system memory. + RDMA will be faster becasue the data is buffered by the HOST1x Block and sw + reads back data in a tight loop. + + SC15 RDMA supports 2 modes - Linear(AKA NON-Rect) and Rect mode. + In both modes the sequence of programming same - setup and then read the data. + + RDMA setup is 2 step process. + - RDMA need to know which client will trigger the RDMA. It also need to other + parameters like which varies for linear and RECT modes. + In rect reads software has to setup the stride/width/number of lines. + This information is needed to describe a buffer. In case of non-rect + read a buffer header is expected, which describes the buffer. In both + cases one need to specify the number of buffers. + + - Client module also need to be setup, as it notifies the RDMA hw block when + the data is ready. This step is not needed for CPU triggered case, as the + data is already available in the memory. + + Sample program sequence: + + Setup RDMA + Setup Client side register (example - vi, SD etc...). Not needed when + setup for CLID CPU. + + wait till the data is available () + { + Read the data(..) + } + + Amount of data to read is either known a-priori (RECT mode) or read from + the header (linear mode). + + + As described ealier RDMA supports 2 modes + + Linear RDMA - RDMA expects a header in the memory right before the data, when + it is triggered. That header describes the length and the attributes of the + buffer. + + Depending on how the RDMA is setup, buffer header will be/will not be + (i.e RDMA_BUFFER_HEADER struct) readout. see #GF_RDMA_FLAGS_STR_HEADER + + When the header is returned the usage looks like + + RDMA_BUFFER_HEADER header; + GFRmRDMAReadHeader(...,&header); + While (header->bufferSize) + { + ... + GFRmReadRDMA(...) + } + + In this mode, it is important is to note that RDMA expect the buffer header + in the memory. So, this is not good for CPU triggerd case, as in that case + CPU should somehow write the buffer header to read the data already present + in the embedded memory. + + Rect RDMA - In this mode, there is no concept of buffer header. Exact size + should be programmed in the RDMA registers when the Setup is done. So, sw + should know how much data to pull out. Requests for data more than available + will result in timeout errors. + + A guideline: if an engine already generated the buffer for you, then use + non-rectangular read. Otherwise, use rect read. + +*/ + +#endif /* __GFRMRDMA_H__ */ diff --git a/Start_WM/test6/inc/GFRmScr.h b/Start_WM/test6/inc/GFRmScr.h new file mode 100755 index 00000000..1678ba09 --- /dev/null +++ b/Start_WM/test6/inc/GFRmScr.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#if !defined (__GFRMSCR_INC__) +#define __GFRMSCR_INC__ + +/* Surface ColorFormat - Follow GFBITMAP type (GF_BITMAP_xxx) */ + +#define GF_SURFACE_YUV420 1 +#define GF_SURFACE_YUV422 2 +#define GF_SURFACE_YUV444 4 +#define GF_SURFACE_ROTATED_YUV422 8 + +#define GF_SURFACE_YUYV (GF_SURFACE_YUV422|0x00000004) +#define GF_SURFACE_YVYU (GF_SURFACE_YUV422|0x00000008) +#define GF_SURFACE_UYVY (GF_SURFACE_YUV422|0x00000010) +#define GF_SURFACE_VYUY (GF_SURFACE_YUV422|0x00000020) +#define GF_SURFACE_MPEGDEC (GF_SURFACE_YUV420|0x00000040) + + +/** Image is for encoding purpose. Must combine with particular YUV format. */ +#define GF_SURFACE_MPEGENC 0x00000080 +#define GF_SURFACE_JPEGDEC (GF_SURFACE_YUV420|0x00000100) + +/** Image is for encoding purpose. Must combine with particular YUV format. */ +#define GF_SURFACE_JPEGENC 0x00000200 +#define GF_SURFACE_PLANAR_YUV422 0x400 +#define GF_SURFACE_RGB565 0x00010000 + +/** Used for 18 bpp (MSB bits) (18bpp MSB bits) case. */ +#define GF_SURFACE_RGB888 0x00020000 +#define GF_SURFACE_ARGB8888 0x00030000 +#define GF_SURFACE_ARGB1555 0x00040000 +#define GF_SURFACE_ARGB4444 0x00050000 + +/** Used for 18 bpp (LSB bits). */ +#define GF_SURFACE_RGB666 0x00060000 + +/** 8bpp surface. */ +#define GF_SURFACE_RGB8 0x00070000 +#define GF_SURFACE_RGB_MASK 0x000F0000 + +/** Bayer 8bit ColorFormat. */ +#define GF_SURFACE_BAYER8 0x00100000 + +/** Bayer 16bit ColorFormat. */ +#define GF_SURFACE_BAYER16 0x00200000 +#define GF_SURFACE_ABGR8888 0x00400000 + +/** YUV422 rotated averaging. */ +#define GF_SURFACE_PLANAR_YUV422RA 0x00800000 + +#endif diff --git a/Start_WM/test6/inc/GFTrace.h b/Start_WM/test6/inc/GFTrace.h new file mode 100755 index 00000000..4d50b3bd --- /dev/null +++ b/Start_WM/test6/inc/GFTrace.h @@ -0,0 +1,304 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* GFTrace.h: Tracing utility for GFSDK libraries. + * + * Features a suite of conditionally compilied tracing macros: + * + * GF_TRACE( a ): for "don't care" tracing - will be mapped + * to the DEBUG priority. + * + * And several others, each with a different priority. + * + * GF_TRACE_CRITICAL( a ) + * GF_TRACE_WARNING( a ) + * GF_TRACE_NORMAL( a ) + * GF_TRACE_VERBOSE( a ) + * GF_TRACE_DEBUG( a ) + * + * The trace macro parameter is treated as a printf style argument + * list, so it should be wrapped in double-parenthesis, such as: + * + * GF_TRACE(("Register value is: %x", reg)); + * + * Tracing is either handled via priorities (normal tracing). + * Tracing supports logging to a file (defaulting to "gfsdk.log") + */ + +#ifndef GF_RMTRACE_H +#define GF_RMTRACE_H + +/* Required for compilation: + * + * GF_TRACE_COMPONENTID [id] + * 'id' is a number 0 to GF_TRACE_COMPONENT_MAX. Tracing priorities + * and thresholds are set via the component id. + * + * Example usage of this header file: + * + * #define GF_TRACE_COMPONENTID GF_GXAPI + * #define GF_TRACE_ENABLE 1 + * #include "GFTrace.h" + * + * void + * foo( NvU32 x ) + * { + * GF_TRACE_DEBUG(("foo called with: %x", x )); + * } + * + */ + +#ifndef GF_TRACE_COMPONENTID +#error "GF_TRACE_COMPONENTID must be defined." +#endif + +#include +#include "GFRm.h" + +/* see GFRm.h for available component ids */ + +/* Compiliation options: + * + * GF_TRACE_ENABLE [0|1] + * If zero, will remove tracing for that file. + * + * GF_TRACE_GLOBAL_DISABLE + * If this is defined and set to 1 - tracing is force globally disabled. + * If not defined will be controlled by the GF_TRACE_ENABLE macro. + * + * GF_TRACE_GLOBAL_ENABLE + * If this is defined and set to 1 - tracing is force globally enabled. + * If not defined will be controlled by the GF_TRACE_ENABLE macro and + * GF_TRACE_GLOBAL_DISABLE macros. + * + * So, the precedence is GF_TRACE_GLOBAL_ENABLE > GF_TRACE_GLOBAL_DISABLE > + * GF_TRACE_ENABLE + * + * GF_TRACE_COMPONENTID_MAX [max] + * The maximum number of component ids that may exist for tracing. + * + * GF_TRACE_MESSAGESIZE_MAX [max] + * The maximum length of a tracing message, in bytes. + * + * GF_TRACE_DECORATE [0|1] + * Automatically add a newline, componentname and process ID to + * the output. + */ + +/* default for component id max */ +#ifndef GF_TRACE_COMPONENTID_MAX +#define GF_TRACE_COMPONENTID_MAX 32 +#endif + +/* default for message size max */ +#ifndef GF_TRACE_MESSAGESIZE_MAX +#define GF_TRACE_MESSAGESIZE_MAX 256 +#endif + +/* default for decoration is 1 */ +#ifndef GF_TRACE_DECORATE +#define GF_TRACE_DECORATE 1 +#endif + +#if defined(NV_MODS) + +/* By default enable everything for MODS */ +#undef GF_TRACE_ENABLE +#define GF_TRACE_ENABLE 1 + +#ifndef INCLUDED_GFMODS_H +#include "GFMods.h" +#endif + +#endif /* NV_MODS */ + +#if defined(GF_TRACE_GLOBAL_ENABLE) && defined(GF_TRACE_GLOBAL_DISABLE) +#error "Both GF_TRACE_GLOBAL_DISABLE and GF_TRACE_GLOBAL_ENABLE cannot be defined" +#endif + +/* global overrides */ +#ifdef GF_TRACE_GLOBAL_ENABLE + #undef GF_TRACE_ENABLE + #define GF_TRACE_ENABLE 1 +#endif + +#ifdef GF_TRACE_GLOBAL_DISABLE + #undef GF_TRACE_ENABLE + #define GF_TRACE_ENABLE 0 +#endif + +/* Several priorities from which to choose. Use the + * GFRmTrace*Threshold functions to limit tracing output. + * By deafult, all messages will be traced in a Debug build, + * only Warning, and Critical in a Release build. + * + * The priority numbers should exactly match the printing + * priorities in MODS. + */ +#define GF_TRACE_PRI_CRITICAL 5 +#define GF_TRACE_PRI_WARNING 4 +#define GF_TRACE_PRI_NORMAL 3 +#define GF_TRACE_PRI_VERBOSE 2 +#define GF_TRACE_PRI_DEBUG 1 + +/* Returns the current tracing threshold. + */ +NvU32 +GFRmTraceGetThreshold( NvU32 componentId ); + +/* Sets the current tracing threshold. All messages with an equal-to or + * greater-than priority will be traced. + */ +void +GFRmTraceSetThreshold( NvU32 componentId, NvU32 thresh ); + +/* Gets the current tracing priority. + */ +NvU32 +GFRmTraceGetPriority( NvU32 componentId ); + +/* Sets the current tracing priority for the given component. + */ +void +GFRmTraceSetPriority( NvU32 componentId, NvU32 pri ); + +/* Trace a message. Takes variable arguments that exactly match those + * of the libc printf family. Messages may or may not be controlled + * via a priority mechanism. + */ +void +GFRmTrace( NvU32 componentId, NvU32 priority, const char *msg, va_list args ); + +/* Tracing may be controlled via run-time as well as compile-time. + * The run-time options that are available (to be passed into + * GFRmTraceConfigure as the option flag) are: + * + * GF_TRACE_OPT_OUTPUT [ioname] + * The output device of normal tracing. Defaults to stdout. + * 'value' is a char *, max len is 256. Should be null-terminated. + * May be "default" or a filename. + * + * GF_TRACE_OPT_COMPONENT_ENABLE [id] [0|1] + * Component that have compiled in tracing can be turned off or + * back on. The configure value is a pointer to an array of two + * integers, the first is id, the second is the enable/disable. + * + * GF_TRACE_OPT_DECORATE [id] [0|1] + * Automatically add a newline and component id to the output. + * 1 for on, 0 for off. 'id' is the component id. + */ +#define GF_TRACE_OPT_OUTPUT 0 +#define GF_TRACE_OPT_COMPONENT_ENABLE 1 +#define GF_TRACE_OPT_DECORATE 2 + +/* Open the trace file. Called by GFRmOpen */ +GF_RETTYPE GFRmTraceOpen(void); + +/* Closes the trace file. Called by GFRmClose */ +void GFRmTraceClose(void); + +/* Run-time configuration for tracing. See the GF_TRACE_OPT + * flags for 'value' documentation. All configuration settings + * assigned via GFRmTraceConfigure() are global across all component + * ids, and should be synchronized if accessed by multiple threads. + * + * Returns 0 on failure, 1 otherwise. + */ +NvU32 +GFRmTraceConfigure( int option, void *value ); + +/* Returns a nice name for the component id. + * Note that this will always be defined (never compiled out). + */ +const char * +GFRmTraceGetComponentName( NvU32 componentId ); + +#if !GF_TRACE_ENABLE || NVCPU_IS_XTENSA + +#define GF_TRACE( a ) +#define GF_TRACE_CRITICAL( a ) +#define GF_TRACE_WARNING( a ) +#define GF_TRACE_NORMAL( a ) +#define GF_TRACE_VERBOSE( a ) +#define GF_TRACE_DEBUG( a ) + +#else /* tracing is enabled */ + +static NV_INLINE void GFRmTraceWithPriority(const char *msg, ...) +{ + va_list list; + NvU32 priority = 0; + + va_start( list, msg ); + + priority = GFRmTraceGetPriority( GF_TRACE_COMPONENTID ); + +#if !defined(NV_MODS) + GFRmTrace( GF_TRACE_COMPONENTID, priority, msg, list ); +#else + GFModsTrace( GF_TRACE_COMPONENTID, priority, msg, list ); +#endif + va_end( list ); +} + +/* component id will be defined to be -1 for the trace implementation. + * Each client must define component id before including this file. + * + * For a MODS build, GFRmTraceWithPriority() must call ModsDrvVPrintf(). + * See main/diag/mods/include/modsdrv.h for details. ModsDrvVPrintf() + * is called via GFModsTrace(). + */ +#if GF_TRACE_COMPONENTID >= 0 + +#define GF_TRACE( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_DEBUG ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_CRITICAL( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_CRITICAL ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_WARNING( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_WARNING ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_NORMAL( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_NORMAL ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_VERBOSE( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_VERBOSE ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_DEBUG( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_DEBUG ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) +#endif /* componentid check */ + +#endif /* enable trace */ + +#endif /* GFRMTRACE_H */ diff --git a/Start_WM/test6/inc/GFTypes.h b/Start_WM/test6/inc/GFTypes.h new file mode 100755 index 00000000..49145b10 --- /dev/null +++ b/Start_WM/test6/inc/GFTypes.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFTypes.h + * GFSDK standard data types. + */ + +#ifndef __GFTYPES_H__ +#define __GFTYPES_H__ + +#include "nvtypes.h" + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +/* Misc Helper macros on data types (deal with byte-endianness later ) */ +#ifndef MAKENvU32 +#define MAKENvU32(dataLo16, dataHi16) \ + (NvU32)(((NvU32)(dataHi16) << 16) | (NvU32)(dataLo16)) +#endif /* MAKENvU32 */ + +#ifndef MAKENvU16 +#define MAKENvU16(dataLo8, dataHi8) \ + (NvU16)(((NvU16)(dataHi8) << 8) | (NvU16)(dataLo8)) +#endif /* MAKENvU16 */ + +#if defined(__arm) +# define GFALIGN8 __align(1) +# define GFALIGN16 __align(2) +# define GFALIGN32 __align(4) +#elif defined(__IAR_SYSTEMS_ICC__) +# define GFALIGN8 +# define GFALIGN16 +# define GFALIGN32 +#elif defined(NV_LINUX) +# define GFALIGN8 +# define GFALIGN16 __attribute__ ((aligned (2))) +# define GFALIGN32 __attribute__ ((aligned (4))) +#elif defined(NVCPU_XTENSA) +# define GFALIGN8 +# define GFALIGN16 __attribute__ ((aligned (2))) +# define GFALIGN32 __attribute__ ((aligned (4))) +#elif defined(NV_WINDOWS) +# define GFALIGN8 +# define GFALIGN16 +# define GFALIGN32 +#else +# define GFALIGN8 +# define GFALIGN16 +# define GFALIGN32 +#endif + +#endif /* __GFTYPES_H__ */ diff --git a/Start_WM/test6/inc/GFVersion.h b/Start_WM/test6/inc/GFVersion.h new file mode 100755 index 00000000..399900be --- /dev/null +++ b/Start_WM/test6/inc/GFVersion.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFVersion.h + * GFSDK build version header file. + */ + +#ifndef __GFVERSION_H__ +#define __GFVERSION_H__ + +#define GF_MAJOR_VERSION 0x0017 +#define GF_MINOR_VERSION 0x0100 +#define GF_BUILD_NUMBER 1039 + + +#endif /* __GFVERSION_H__ */ + diff --git a/Start_WM/test6/inc/GFVx.h b/Start_WM/test6/inc/GFVx.h new file mode 100755 index 00000000..5af9e634 --- /dev/null +++ b/Start_WM/test6/inc/GFVx.h @@ -0,0 +1,3028 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFVx.h + GFSDK Video API header file. +*/ + +#ifndef __GFVX_H__ +#define __GFVX_H__ + +#include "GFRm.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "GFVxScr.h" + +/** @addtogroup groupVx VxAPI Video API +
        +
      • @ref pageVxOverview +
          +
        • @ref pageVxOverview1 +
        • @ref pageVxOverview2 +
        • @ref pageVxOverview3 +
        +
      • @ref pageVxAppNotes +
          +
        • @ref pageVxAppNotes1 +
        +
      +*/ +/*@{*/ + +/* GFVX Property Capability */ + +/** VxAPI property flag: Color space conversion supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_CSC 0x00000001 + +/** VxAPI property flag: VIP functions available. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_VIP 0x00000002 + +/** VxAPI property flag: Enlarge source image via VIP supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_ENLARGE 0x00000004 + +/** VxAPI property flag: Shrink source image via VIP supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_SHRINK 0x00000008 + +/** VxAPI property flag: Overlay supported. + The GoForce processor version supports overlay display. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_OVERLAY 0x00000020 + +/** VxAPI property flag: MPEG4 decoder supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_MPEGDEC 0x00000040 + +/** VxAPI property flag: MPEG4 encoder supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_MPEGENC 0x00000080 + +/** VxAPI property flag: JPEG decoder supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_JPEGDEC 0x00000100 + +/** VxAPI property flag: JPEG encoder supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_JPEGENC 0x00000200 + +/** VxAPI property flag: Alpha blending supported. + @version SC12 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_ALPHA_BLEND 0x00000400 + +/** VxAPI property flag: Extended RGB format 32 bpp supported. + @version SC12 above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_EXTEND_RGB 0x00000800 + +/** VxAPI property flag: Variable sized data camera interface (Type A/B/C) + supported. See section @ref pageVxOverview2 for information on Type A/B/C + camera interfaces. + @version SC12 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability, +*/ +#define GFVX_CAP_ENCODE_TYPE 0x00001000 + +/** VxAPI property flag: Bayer type camera interface supported. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability, +*/ +#define GFVX_CAP_BAYER_TYPE 0x00002000 // support bayer type input + +/** VxAPI property flag: YUV Overlay supported. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_OVERLAY_YUV 0x00004000 + +/** VxAPI property flag: Overlay with scaling supported. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_OVERLAY_SCALE 0x00008000 + +/** VxAPI property flag: Multiple Overlay supported. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_OVERLAY_MULTIPLE 0x00010000 + +/** VxAPI property flag: Per pixel alpha supported. + Used when application wants to use weight (overlay and blend) + defined in pixels alpha bits. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_PER_PIXEL_ALPHA 0x00020000 + +/** VxAPI GFVXBLT::BltOption flagbit: Disable VSync wait. + Disable GFVxBlt() synchronization with VSync. The default behaviour of + GFVxBlt() is to wait for VSync to prevent display flicker. Note that + if the display is disabled there is no VSync signal and GFVxBlt() + would block. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_DISABLE_WAIT_VSYNC 0x00000080 + +/** VxAPI GFVXBLT::BltOption flagbit: Source color key. + GFVxBlt() compares each pixel of the source surface with the color key. + If the colors match, the pixel is not copied to the destination surface. + + The source color key option is not very useful when scaling is used. + + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_SRC_KEY 0x00000100 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-blit at end of VIP frame. + If this flag is set, GFVxBlt() configures blit parameters for + VIP auto-blit. VIP auto-blit can be used to fire stretch blit automatically + at the end of the video input frame from the video input port (VIP). This + requires double buffering of the input and output of stretch blit. The use + of this flag is to be combined with GFVxVIPUpdate() flag + #GFVX_VIP_AUTO_TRIGER_BLT. + @see GFVXBLT, GFVxBlt(), #GFVX_VIP_AUTO_TRIGER_BLT +*/ +#define GFVX_AUTO_BLT 0x00000400 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-blit at end of VIP frame. + This flag is the same as #GFVX_AUTO_BLT + @version SC15 and above only + @see GFVXBLT, GFVxBlt(), #GFVX_VIP_AUTO_TRIGER_BLT, #GFVX_AUTO_BLT +*/ +#define GFVX_BLT_AUTO_VI 0x00000400 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-display destination surface. + The application does not need call GFVxFlip() to show the surface. + With the auto-display option, the VI module triggers stretch blit which + in turn sends the destination surface's buffer address to the display + controller (GC). VI input data goes into double buffers which become the + stretch blit source, the output of stretch blit is also double buffered. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_AUTO_DISPLAY 0x00000800 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-display destination surface. + This flag is the same as #GFVX_AUTO_DISPLAY + @version SC15 and above only + @see GFVXBLT, GFVxBlt(), #GFVX_AUTO_DISPLAY +*/ +#define GFVX_BLT_AUTO_DISPLAY 0x00000800 + +/** VxAPI GFVXBLT::BltOption flagbit: Set up parameters for partial blit + If this flag is set, GFVxBlt() configures blit parameters for + partial blit. The partial blit works only with circular buffers and + source and destination format are not YUV planar format. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_PARTIAL 0x00001000 + +/** VxAPI GFVXBLT::BltOption flagbit: Trigger partial blit + If this flag is set, GFVxBlt() will blit buffer specified + in buffer index option of circular buffers to destination surface. + The use of this flag is to be combined with GFVxBlt() flag + #GFVX_BLT_PARTIAL. + @see GFVXBLT, GFVxBlt(), #GFVX_BLT_PARTIAL +*/ +#define GFVX_BLT_PARTIAL_TRIGGER 0x00002000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit without rotation + If this flag is set, GFVxBlt() blits without rotation + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ROTATE_0 0x00004000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with 90 degree rotation + If this flag is set, GFVxBlt() blits with 90 degree rotation + Currently, SC15 doesn't support this feature. However, this flag + can be combined with flag GFVX_BLT_H_FLIP to blit with XY swap + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ROTATE_90 0x00008000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with 180 degree rotation + If this flag is set, GFVxBlt() blits with 180 degree rotation + Currently, SC15 doesn't support this feature. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ROTATE_180 0x00010000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with 270 degree rotation + If this flag is set, GFVxBlt() blits with 270 degree rotation + Currently, SC15 doesn't support this feature. However, this flag + can be combined with flag GFVX_BLT_V_FLIP to blit with XY swap + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ROTATE_270 0x00020000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with horizontal flip + If this flag is set, GFVxBlt() blits with horizontal flip + Currently, SC15 doesn't support this feature. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_H_FLIP 0x00040000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with vertical flip + If this flag is set, GFVxBlt() blits with vertical flip + Currently, SC15 doesn't support this feature + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_V_FLIP 0x00080000 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-display destination surface + using overlay window 2. This is exactly identical to #GFVX_AUTO_DISPLAY + except that it uses overlay window 2 instead of overlay window 1 (default). + + @version SC15 and above only + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_AUTO_DISPLAY_OVERLAY2 0x00100000 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-display destination surface + using overlay window 2. This flag is the same as #GFVX_AUTO_DISPLAY_OVERLAY2 + @version SC15 and above only + @see GFVXBLT, GFVxBlt(), #GFVX_AUTO_DISPLAY_OVERLAY2 +*/ +#define GFVX_BLT_AUTO_DISPLAY_OVERLAY2 0x00100000 + +/** VxAPI GFVXBLT::BltOption flagbit: Enables full range in color spce conversion + 0<= Y <=255, -128<= U <=127, -128<= V <=127 + YUV-->RGB conversion formula: + R = 1.000Y + 1.402V + G = 1.000Y - 0.344U - 0.714V + B = 1.000Y + 1.772U + This option is useful for decoded video from movies. + When this flag is not set, uses CCIR601 range (16-235) as follows: + 16<= Y <=235, 16<= U <=240, 16<= V <=240 + YUV-->RGB conversion formula: + R = 1.164(Y-16) + 1.596(Cr-128) + G = 1.164(Y-16) - 0.391(Cb-128) - 0.813(Cr-128) + B= 1.164(Y-16) + 2.018(Cb-128) + This option is useful for video from camera. + @version SC15 and above only + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_CSC_FULL_RANGE 0x00200000 + +/** VxAPI GFVXBLT::BltOption flagbit: Enable camera VSync wait. + Enable GFVxBlt() synchronization with camera VSync. Note that + if the camera is disabled there is no VSync signal and GFVxBlt() + would block. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ENABLE_WAIT_CAMERA_VSYNC 0x00400000 + +/** VxAPI GFVXBLT::BltOption flagbit: Disable vertical and horizontal filters + By default, the vertical and horizontal filters are enabled. If this flag + is set, GFVxBlt() blits with filters disabled + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_DISABLE_FILTERS 0x00800000 + +/** VxAPI option parameter of routines GFVxBltSetCSCCoefff() + and GFVxVIPSetCSCCoeff() to use CCIR601 range + + CSC_USE_CCIR601_RANGE (16-235) as follows: + 16<= Y <=235, 16<= U <=240, 16<= V <=240 + YUV-->RGB conversion formula: + + R = sat(KYRGB*(Y + YOF) + KUR*U + KVR*V) + G = sat(KYRGB*(Y + YOF) + KUG*U + KVG*V) + B = sat(KYRGB*(Y + YOF) + KUB*U + KVB*V) + + The CSC coefficients are: + + KYRGB, KUR, KVR 1.1644 0.0000 1.5960 + KYRGB, KUG, KVG = 1.1644 -0.3918 -0.8130 + KYRGB, KUB, KVB 1.1644 2.0172 0.0000 + + and YOF = -16.0000 + This option is useful for video from camera. + + @see GFVxBltSetCSCCoeff(), GFVxVIPSetCSCCoeff() +*/ +#define GFVX_SET_CSC_USE_CCIR601_RANGE 0x00800000 + +/** VxAPI option parameter of routines GFVxBltSetCSCCoefff() + and GFVxVIPSetCSCCoeff() to use full range in color space conversion + + CSC_USE_FULL_RANGE + 0<= Y <=255, -128<= U <=127, -128<= V <=127 + YUV-->RGB conversion formula: + + R = sat(KYRGB*(Y + YOF) + KUR*U + KVR*V) + G = sat(KYRGB*(Y + YOF) + KUG*U + KVG*V) + B = sat(KYRGB*(Y + YOF) + KUB*U + KVB*V) + + The CSC coefficients are: + + KYRGB, KUR, KVR 1.0000 0.0000 1.4020 + KYRGB, KUG, KVG = 1.0000 -0.3440 -0.7140 + KYRGB, KUB, KVB 1.0000 1.7720 0.0000 + + and YOF = 0.0000 + This option is useful for decoded video from movies. + @see GFVxBltSetCSCCoeff(), GFVxVIPSetCSCCoeff() +*/ +#define GFVX_SET_CSC_USE_FULL_RANGE 0x01000000 + +/** VxAPI option parameter of routines GFVxBltSetCSCCoefff() + and GFVxVIPSetCSCCoeff() to use user defined range + provided in option parameter pCoeff pointer to GFVXCSCCOEF struct + + @see GFVxBltSetCSCCoeff(), GFVxVIPSetCSCCoeff() +*/ +#define GFVX_SET_CSC_USE_USER_DEFINED_RANGE 0x02000000 +/** Structure to control GFVxBlt() behaviour. + @see GFVxBlt() +*/ + +typedef struct _GFVXBLT +{ + PGFRMSURFACE *ppDestSurf; /**< Pointer to an array of destination + surfaces of identical dimensions. + + For passing scaled YUV output data to + the planar block as input to the + JPEG/MPEG encoder, pass an array containing + one NULL pointer. + + Destination surface dimensions limitations: + + + + + + + +
      Minimum stride0 bytes
      Minimum width 1
      Minimum height1
      Maximum stride4095 bytes
      Maximum width 4064 (YUV) + (YUV data restricted by JPEG encoder),
      + 32767 (RGB) + (RGB data restricted by stride) +
      Maximum height32766, or unlimited + if \a pDestRect is specified
      + + If the destination color format is YUV (pass to + JPEG/MPEG EPP, and \a pDestRect is not specified, + the surface width must be a multiple of 2. + */ + PGFRMSURFACE *ppSrcSurf; /**< Pointer to an array of source surfaces + of identical dimensions. + Source surface dimensions limitations: + + + + + + + +
      Minimum stride0 bytes
      Minimum width 1
      Minimum height1
      Maximum stride4095 bytes
      Maximum width + 16383 (SC15), + 2032 (SC12), + 496 (SC5, RGB or YUV422), 512 (SC5), + 496 (SC10, SC4), + 312 (SC3 and below), + or unlimited if \a pSrcRect is specified +
      Maximum height32766, or unlimited + if \a pDestRect is specified
      + */ + PGFRECT pDestRect; /**< Destination rectangle, or NULL to blit + scaled to the size of the entire target + surface (size of first surface in + \a ppDestSurf is used). + Destination cropping rectangle limitations: + + + + + +
      Minimum width 1
      Minimum height1
      Maximum width 4064 (YUV), + 32767 (RGB) +
      Maximum height32766
      + + If the destination color format is YUV (pass to + JPEG/MPEG EPP), the destination cropping rectangle's + width must be a multiple of 2. + */ + PGFRECT pSrcRect; /**< Source cropping rectangle, or NULL for + no cropping and blit the entire source + surface (size of first surface in + \a ppSrcSurf is used). + Source cropping rectangle limitations: + + + + + +
      Minimum width 1
      Minimum height1
      Maximum width + 16383 (SC15), + 2032 (SC12), + 496 (SC5, RGB or YUV422), 512 (SC5), + 496 (SC10, SC4), + 312 (SC3 and below) +
      Maximum height32766
      + */ + NvU32 numofDestSurf;/**< Number of destination surfaces in array + \a ppDestSurf, used only if + #GFVX_AUTO_BLT flag set + */ + NvU32 numofSrcSurf; /**< Number of source surfaces in array + \a ppSrcSurf, used only if + #GFVX_AUTO_BLT flag or #GFVX_BLT_PARTIAL flag set + */ + NvU32 colorKey; /**< Color key value in RGB888 format */ + NvU32 BltOption; /**< Flag bitmask: + + + + + + + + + + + + + + + + +
      #GFVX_BLT_DISABLE_WAIT_VSYNCDisable VSync +
      #GFVX_BLT_SRC_KEYSource color key +
      #GFVX_AUTO_BLTAuto-blit at end of VIP frame +
      #GFVX_AUTO_DISPLAYAuto-show destination surface +
      #GFVX_AUTO_DISPLAY_OVERLAY2Auto-show destination surface from overlay window 2 +
      #GFVX_BLT_PARTIALConfigure partial blit parameters +
      #GFVX_BLT_PARTIAL_TRIGGERTrigger partial blit at end of circular buffer +
      #GFVX_BLT_ENABLE_WAIT_CAMERA_VSYNCEnable wait for camera VSYNC +
      + */ + // Fill The following fields if GFVX_BLT_PARTIAL_TRIGGER is set in BltOption + NvU32 FrameStart; /* @Notify start of frame. + Used only if #GFVX_BLT_PARTIAL_TRIGGER is set + in \a BltOption. + */ + NvU32 FrameEnd; /* @Notify end of frame. + Used only if #GFVX_BLT_PARTIAL_TRIGGER is set + in \a BltOption. + */ + NvU32 BufferIndex; /* @Specify which buffer of circular buffers is blitted. + Used only if #GFVX_BLT_PARTIAL_TRIGGER is set + in \a BltOption. + */ +} GFVXBLT, *PGFVXBLT; + +/** VxAPI GFVXFLIP::FlipOption flagbit: Flip uses second overlay window. + + By default, VxFlip associates foreground and background surfaces + to first overlay window and flips them. However, the application can override + the default behavior and use second overlay window by using this flag in FlipOption. + + This option should be used only if second overlay surface has been + previously set using UpdateOverlay(). . + + @version SC15 and above only + @see GFVXFLIP, GFVxFlip() +*/ +#define GFVX_FLIP_OVERLAY2 0x00000001 + +/** Structure to control GFVxFlip() behaviour. + @see GFVxFlip() +*/ +typedef struct _GFVXFLIP +{ + PGFRMSURFACE pBackGroundSurf; /**< Pointer to the surface to be flipped + to the background. This surface will + not be seen anymore after the + GFVxFlip() call. + */ + PGFRMSURFACE pForeGroundSurf; /**< Pointer to the surface to be flipped + to the foreground. This surface will + be seen after the GFVxFlip() call. + */ + NvU32 FlipOption; + /**< Flagbit mask controlling flip: + + + + + +
      0 Default. Flip uses first overlay window
      GFVX_FLIP_SECOND_OVERLAY Flip uses second overlay window
      + */ +} GFVXFLIP, *PGFVXFLIP; + + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay without rotation. + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_ROTATE_0 GF_SURFACE_ROTATE_0 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay with 180 degree rotation. + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_ROTATE_180 GF_SURFACE_ROTATE_180 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay with horizontal + flip. + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_H_FLIP 0x00000010 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay with vertical + flip. + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_V_FLIP 0x00000020 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Source color keying. + + A pixel from the source (overlay) surface is displayed only if pixel + color from the source surface matches the color key in + GFVXUPDATEOVERLAY::ColorKey. + + Source color keying is not useful for video overlay, because changing + video is the source. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay(), GFVX_UO_DEST_COLOR_KEY +*/ +#define GFVX_UO_SRC_COLOR_KEY 0x00010000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Destination color keying. + + A pixel from the source (overlay) surface is displayed only if pixel + color from the destination surface matches the color key in + GFVXUPDATEOVERLAY::ColorKey. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay(), GFVX_UO_SRC_COLOR_KEY +*/ +#define GFVX_UO_DEST_COLOR_KEY 0x00020000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Alpha blending. + Enable alpha blending. Alpha value is used from + GFVXUPDATEOVERLAY::AlphaValue. + + As AlphaVal increases, the weight of source (overlay) window increases + until the window reaches its maximum weight of 0xFF. + + Even though AlphaVal is a 32 bit number, alpha value can only be a 8 bit value. + Application should specify the same value in byte 1 (LSB), 2 and 3 else the API + will fail. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_ALPHA_BLENDING 0x00040000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay based on + destination alpha only. + + If destination is in 1-bit alpha format (eg ARGB1555), GFVXUPDATEOVERLAY::ColorKey bit[24] + contains the alpha value. GFVxUpdateOverlay() compares this value with + the target surface's alpha and ignores the RGB value. Overlay (source) surface + shows up in portions of the screen where the two match. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_COLOR_KEY_ALPHA_ONLY 0x00080000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay based on + destination alpha and color + + If destination is in 1-bit alpha format (eg ARGB1555), + GFVXUPDATEOVERLAY::ColorKey bit [24] contains alpha and + GFVXUPDATEOVERLAY::ColorKey bit [23:0] contains RGB color values. + GFVxUpdateOverlay() compares the key's alpha value and + color values with destination surface pixels. + + Overlay (source) surface shows up in portions of the screen where both + alpha and color values match. + + If neither #GFVX_UO_COLOR_KEY_ALPHA_ONLY nor #GFVX_UO_COLOR_KEY_ALPHA_COLOR are + set, GFVxUpdateOverlay() assumes the RGB values in + GFVXUPDATEOVERLAY::ColorKey to be valid and compares the RGB value with + surface's RGB value. Depending upon whether #GFVX_UO_SRC_COLOR_KEY or + #GFVX_UO_DEST_COLOR_KEY is defined, RGB value is compared with source or + destination pixels. If neither #GFVX_UO_SRC_COLOR_KEY nor #GFVX_UO_DEST_COLOR_KEY + is defined, overlay(source) surface is overlayed on top of destination surface + without any match. #GFVX_UO_COLOR_KEY_ALPHA_ONLY nor #GFVX_UO_COLOR_KEY_ALPHA_COLOR + if defined, are ignored. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_COLOR_KEY_ALPHA_COLOR 0x00100000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Alpha blending based on + destination alpha. + + If destination is in 1-bit alpha format (eg ARGB1555), + GFVXUPDATEOVERLAY::BlendingColorKey bit [24] contains an alpha value. + GFVxUpdateOverlay() compares this value with the destination surface's + alpha only and ignores the RGB value. + + If the two match, GFVXUPDATEOVERLAY::AlphaValue determines the weight + of source surface. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY 0x00200000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Alpha blending based on + destination alpha and color + + If destination is in 1-bit alpha format (eg ARGB1555), + GFVXUPDATEOVERLAY::BlendingColorKey bit [24] contains an alpha value and + GFVXUPDATEOVERLAY::BlendingColorKey bit [23:0] contains RGB values. + GFVxUpdateOverlay() compares alpha value and color value with the + destination surface's alpha and color value. + + Source and destination pixels appear blended in portions of the screen where both + alpha and color values match. GFVXUPDATEOVERLAY::AlphaValue determines the weight + of source surface. + + If neither #GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY nor #GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR + are set, GFVxUpdateOverlay() assumes the RGB portion in the key to be + valid and compares the RGB value with the surface's RGB value. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR 0x00400000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Enable Second overlay window + + SC15 supports two overlay windows. This flag is used to enable + the second overlay window. + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_OVERLAY2 0x00800000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Show this overlay window on top + + When more than one overlay windows are enabled and their destination rectangles + overlap, this flag can be defined to indicate which overlay window should appear + on top. + + By default, first overlay window will appear on top if destination + rectangles for the two windows overlap. However, application can override the + default behavior by specifying #GFVX_UO_ACTIVETOP flag in relevant windows's + UpdateOption. + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_ACTIVETOP 0x01000000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay and Blend weight + comes from per-pixel alpha channel. + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_COLOR_KEY_PER_PIXEL_ALPHA 0x02000000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Enable digital vibrance for + overlay. + + If this bit is set in UpdateOption, then dvRed, dvGreen and dvBlue must be + set in UpdateOverlay structure for overlay window. + + If this bit is set in UpdateOption2, then dvRed2, dvGreen2 and dvBlue2 must be + set in UpdateOverlay structure for overlay2 window. + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_DIGITAL_VIBRANCE 0x04000000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption2 flagbit: Enable AlphaValue2 + + If this bit is set in UpdateOption2, then the alpha value is used + from GFVXUPDATEOVERLAY::AlphaValue2 + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_USE_ALPHAVALUE2 0x08000000 + +/** Structure for controlling GFVxUpdateOverlay() behaviour. + @see GFVxUpdateOverlay() +*/ +typedef struct _GFVXUPDATEOVERLAY +{ + PGFRMSURFACE pDestSurf; /**< Destination surface pointer */ + PGFRMSURFACE pSrcSurf; /**< Source surface pointer, if this pointer + is NULL, disable overlay. + */ + PGFRECT pDestRect; /**< Destination rectangle */ + PGFRECT pSrcRect; /**< Source rectangle */ + NvU32 ColorKey; /**< Color key value in ARGB32 format. + Color keying takes effect only when + #GFVX_UO_SRC_COLOR_KEY or + #GFVX_UO_DEST_COLOR_KEY is set. + */ + NvU32 UpdateOption; + /**< Flagbit mask controlling rotation, color keying: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_UO_ROTATE_0 Overlay without rotation
      #GFVX_UO_ROTATE_180 Overlay with 180 degree rotation
      #GFVX_UO_H_FLIP Overlay with horizontal flip
      #GFVX_UO_V_FLIP Overlay with vertical flip
      #GFVX_UO_SRC_COLOR_KEY Source color keying
      #GFVX_UO_DEST_COLOR_KEY Destination color keying
      #GFVX_UO_ALPHA_BLENDING Alpha blending
      #GFVX_UO_COLOR_KEY_ALPHA_ONLY Overlay based on destination alpha
      #GFVX_UO_COLOR_KEY_ALPHA_COLOR Overlay based on destination alpha and color
      #GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY Alpha Blending based on destination alpha
      #GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR Alpha Blending based on destination alpha and color
      #GFVX_UO_OVERLAY2 Enable second overlay window
      #GFVX_UO_ACTIVETOP Show this overlay window on top
      #GFVX_UO_DIGITAL_VIBRANCE Enable digital vibrance for first overlay window
      + */ + NvU32 BlendingColorKey; + /**< Blending color key value in ARGB32 format. + Value takes effect only when #GFVX_UO_ALPHA_BLENDING and + (#GFVX_UO_SRC_COLOR_KEY or #GFVX_UO_DEST_COLOR_KEY) + are set. + */ + NvU32 AlphaValue; + /**< Alpha value for blending overlay. + Alpha value is used to do blending when + blending color key matches. Even though AlphaVal + is a 32 bit number, alpha value can only be a 8 bit value. + Application should specify the same value in byte 1 (LSB), + 2 and 3 else the API will fail. + */ + + PGFRMSURFACE pDestSurf2; /**< Destination surface pointer for second overlay */ + PGFRMSURFACE pSrcSurf2; /**< Source surface pointer for second overlay, + if this pointer is NULL, disable second overlay. + */ + PGFRECT pDestRect2; /**< Destination rectangle for second overlay */ + PGFRECT pSrcRect2; /**< Source rectangle for second overlay */ + NvU32 UpdateOption2; + /**< Flagbit mask controlling rotation, color keying for second overlay: + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_UO_ROTATE_0 Overlay without rotation
      #GFVX_UO_ROTATE_180 Overlay with 180 degree rotation
      #GFVX_UO_H_FLIP Overlay with horizontal flip
      #GFVX_UO_V_FLIP Overlay with vertical flip
      #GFVX_UO_SRC_COLOR_KEY Source color keying
      #GFVX_UO_DEST_COLOR_KEY Destination color keying
      #GFVX_UO_ALPHA_BLENDING Alpha blending
      #GFVX_UO_COLOR_KEY_ALPHA_ONLY Overlay based on destination alpha
      #GFVX_UO_COLOR_KEY_ALPHA_COLOR Overlay based on destination alpha and color
      #GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY Alpha Blending based on destination alpha
      #GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR Alpha Blending based on destination alpha and color
      #GFVX_UO_ACTIVETOP Show this overlay window on top
      #GFVX_UO_DIGITAL_VIBRANCE Enable digital vibrance for second overlay window
      + */ + NvU8 dvRed; /**< Digital vibrance amplification factor for R overlay. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvRed's valid value range + is 1 to 100. + */ + NvU8 dvGreen; /**< Digital vibrance amplification factor for G overlay. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvGreen's valid value range + is 1 to 100. + */ + NvU8 dvBlue; /**< Digital vibrance amplification factor for B overlay. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvBlue's valid value range + is 1 to 100. + */ + NvU8 dvRed2; /**< Digital vibrance amplification factor for R overlay2. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvRed2's valid value range + is 1 to 100. + */ + NvU8 dvGreen2; /**< Digital vibrance amplification factor for G overlay2. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvGreen2's valid value range + is 1 to 100. + */ + NvU8 dvBlue2; /**< Digital vibrance amplification factor for B overlay2. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvBlue2's valid value range + is 1 to 100. + */ + NvU32 AlphaValue2; + /**< Alpha value for blending Window C overlay. + Same restriction as for GFVXUPDATEOVERLAY::AlphaValue apply. + */ + +} GFVXUPDATEOVERLAY, *PGFVXUPDATEOVERLAY; + + +/** Parameter structure for GFVxVIPFeedImage(). + This structure describes the image data that is to be fed to the VIP + via the CPU host. + @see GFVxVIPFeedImage() +*/ +typedef struct _GFVXVIPFEEDIMAGE +{ + PGFRMSURFACE pSurf; /**< Surface to feed data from, must be in a YUV + format and accessible by the host CPU + */ + PGFRECT pSrcRect; /**< Source clipping rectangle for data feeding, or + NULL for no clipping + */ +} GFVXVIPFEEDIMAGE, *PGFVXVIPFEEDIMAGE; + + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP supports image shrinking. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_SHRINK 0x00000001 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP supports image enlarging. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_ENLARGE 0x00000002 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: Parallel video input supported. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_PARALLEL 0x00000004 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: Serial video input supported. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_SERIAL 0x00000008 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: Vertical and horizontal flip supported + for VIP output RGB image. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_RGB_VH_FLIP 0x00000010 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can supply VClock and VHSync + signals to the camera chip. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_OUTPUT_VCLOCK_VHSYNC 0x00000020 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can supply a master clock to the + camera chip. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_OUTPUT_MASTER_CLOCK 0x00000040 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept a JPEG bitstream from + a camera with type A interface. + See section @ref pageVxOverview2 for description of type A, B, and C + interfaces. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_TYPE_A 0x00000080 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept a JPEG bitstream from + a camera with type B interface. + See section @ref pageVxOverview2 for description of type A, B, and C + interfaces. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_TYPE_B 0x00000100 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept a JPEG bitstream from + a camera with type C interface. + See section @ref pageVxOverview2 for description of type A, B, and C + interfaces. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_TYPE_C 0x00000200 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept Bayer format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_BAYER 0x00000400 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept RGB565 format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_RGB565 0x00000800 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept RGB888 format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_RGB888 0x00001000 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept RGB444 format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_RGB444 0x00002000 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept YUV420NP format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_YUV420NP 0x00004000 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept JPEG image from camera + through type C_RAW interface. See section @ref pageVxOverview2. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_TYPE_C_RAW 0x00008000 + +/** Structure used by GFVxVIPGetProperty() to describe VIP capabilities. + @see GFVxVIPGetProperty() +*/ +typedef struct _GFVXVIPPROPERTY +{ + NvU32 Flag; /**< Flag bitmask describing VIP capabilities: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_VIP_CAP_SHRINKVIP supports image shrinking
      #GFVX_VIP_CAP_ENLARGEVIP supports image enlarging
      #GFVX_VIP_CAP_PARALLELParallel video input supported
      #GFVX_VIP_CAP_SERIALSerial video input supported
      #GFVX_VIP_CAP_RGB_VH_FLIPVertical and horizontal flip supported for VIP + output RGB image
      #GFVX_VIP_CAP_OUTPUT_VCLOCK_VHSYNCVIP can supply VClock and VHSync signals to the + camera chip
      #GFVX_VIP_CAP_OUTPUT_MASTER_CLOCKVIP can supply a master clock to the + camera chip
      #GFVX_VIP_CAP_TYPE_AVIP can accept a JPEG bitstream from a camera with + type A interface
      #GFVX_VIP_CAP_TYPE_BVIP can accept a JPEG bitstream from a camera with + type B interface
      #GFVX_VIP_CAP_TYPE_CVIP can accept a JPEG bitstream from a camera with + type C interface
      #GFVX_VIP_CAP_BAYERVIP can accept Bayer format input
      #GFVX_VIP_CAP_RGB565VIP can accept RGB565 format input
      #GFVX_VIP_CAP_RGB888VIP can accept RGB888 format input
      #GFVX_VIP_CAP_RGB444VIP can accept RGB444 format input
      #GFVX_VIP_CAP_YUV420NPVIP can accept YUV420NP format input
      #GFVX_VIP_CAP_TYPE_C_RAWVIP can accept JPEG image from Camera through + type C_RAW interface
      + */ + NvU32 DestFormat;/**< Supported color formats at VIP output, the returned + value is a logically OR'ed combination of the + following surface identifiers: + + + + + + + + + + + + + + + +
      #GF_SURFACE_YUYVYUV422 in YUYV order
      #GF_SURFACE_YVYUYUV422 in YVYU order
      #GF_SURFACE_UYVYYUV422 in UYVY order
      #GF_SURFACE_VYUYYUV422 in VYUY order
      #GF_SURFACE_RGB565RGB565, 16 bpp
      #GF_SURFACE_RGB888RGB888, 24 bpp
      #GF_SURFACE_ARGB8888ARGB8888, 32 bpp
      + To check if a specific colour format is + supported, logically AND \a DestFormat against the + format identifier and compare it as below: +
      +    if ((DestFormat & GF_SURFACE_RGB565) == GF_SURFACE_RGB565)
      +    {
      +        // RGB565 is supported
      +    }
      +    
      + */ + NvU32 HMaxNumerator; /**< Maximum horizontal numerator for VI + decimation. VI decimation is configured via + GFVxVIPSetVIP(), GFVXVIPINFO::HNumerator's + valid value range is 1 to \a HMaxNumerator. + */ + NvU32 HMaxDenominator; /**< Maximum horizontal denominator for VI + decimation. VI decimation is configured via + GFVxVIPSetVIP(), GFVXVIPINFO::HDenominator's + valid value range is 1 to \a HMaxDenominator. + */ + NvU32 VMaxNumerator; /**< Maximum vertical numerator for VI decimation. + VI decimation is configured via + GFVxVIPSetVIP(), GFVXVIPINFO::VNumerator's + valid value range is 1 to \a VMaxNumerator. + */ + NvU32 VMaxDenominator; /**< Maximum vertical denominator for VI decimation. + VI decimation is configured via + GFVxVIPSetVIP(), GFVXVIPINFO::VDenominator's + valid value range is 1 to \a VMaxDenominator. + */ +} GFVXVIPPROPERTY, *PGFVXVIPPROPERTY; + + +/** Structure used to describe the input frame size if input data format is Bayer. + This structure is not used when input source is VIP. + @see +*/ +typedef struct _GFVXBAYERINPUTFRAME +{ + NvU16 Width; /**< Host Input source width. */ + NvU16 Height; /**< Host Input source height. */ +} GFVXBAYERINPUTFRAME, *PGFVXBAYERINPUTFRAME; + +/** Structure used to describe ISP scan size if input data format is Bayer. + Scan size is camera specific. + + The application should populate this structure with + values filled by GFCameraSetup() in GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo. + The application should also configure ISP with values in + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ScanWidth and + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ScanHeight. + + This structure is used only when input source is VIP and input data format is Bayer. + + @see GFISPIMGTIMING +*/ +typedef struct _GFVXBAYERSCANSIZE +{ + NvU16 HScan; /**< VIP input signal horizontal scan size. */ + NvU16 VScan; /**< VIP input signal vertical scan size. */ +} GFVXBAYERSCANSIZE, *PGFVXBAYERSCANSIZE; + +/** Structure used to describe ISP Active Area if input data format is Bayer. + Active Area is camera specific. + + The application should populate this structure with + values filled by GFCameraSetup() in GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo. + The application should also configure ISP with values in + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ActiveFrameStart, + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ActiveLineStart, + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ActiveFrameHeight and + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ActiveLineWidth. + + Active Area rectangle should fall inside the Scan Size. + This structure is used only when input source is VIP and input data format is Bayer. + + @see GFISPIMGTIMING +*/ +typedef struct _GFVXBAYERACTIVEAREA +{ + NvU16 LineStart; /**< VIP input signal horizontal active offset. */ + NvU16 FrameStart; /**< VIP input signal vertical active offset. */ + NvU16 LineWidth; /**< VIP input signal horizontal active width. */ + NvU16 FrameHeight; /**< VIP input signal vertical active height. */ +} GFVXBAYERACTIVEAREA, *PGFVXBAYERACTIVEAREA; + +/** Structure used to describe ISP Output Area if input data format is Bayer. + + This structure is not used by VI. It is used to configure ISP. + Output Area rectangle can be equal to or less than Active Area rectangle. + This structure is used only when input source is VIP and input data format is Bayer. + + @see GFISPIMGTIMING +*/ +typedef struct _GFVXBAYEROUTPUTAREA +{ + NvU16 LineStart; /**< VIP input signal horizontal output offset. */ + NvU16 FrameStart; /**< VIP input signal vertical output offset. */ + NvU16 LineWidth; /**< VIP input signal horizontal output width. */ + NvU16 FrameHeight; /**< VIP input signal vertical output height. */ +} GFVXBAYEROUTPUTAREA, *PGFVXBAYEROUTPUTAREA; + + +/** Structure used to describe the rectangles needed by ISP to properly process Bayer input from camera. + This structure is used only when input source is VIP and input data format is Bayer. + + @see GFVXBAYERINPUTFRAME, GFVXBAYERSCANSIZE, GFVXBAYERACTIVEAREA, GFVXBAYEROUTPUTAREA +*/ +typedef struct _GFVXBAYERINFO +{ + PGFVXBAYERINPUTFRAME pInputFrameSize; /**< For VIP input, this field is not used. + */ + PGFVXBAYERSCANSIZE pScanSize; /**< ISP Scan Size. + Scan size is camera specific. This field is set + by GFCameraAPI in GFCAMERARESOLUTIONTYPE::pBayerInfo. + */ + PGFVXBAYERACTIVEAREA pActiveArea; /**< ISP Active Area. + Active Area is camera specific. This field is set + by GFCameraAPI in + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo. + Active Area rectangle should fall inside the Scan Size. + */ + PGFVXBAYEROUTPUTAREA pOutputArea; /**< ISP Output Area. This field is not used by VI. + Output Area rectangle can be equal to or less than + Active Area rectangle. + */ + NvU8 DemosaicKernelSize; /**< For VIP input, this field is not used. + */ + NvU16 IspDownscaleUsed; /**< Use Isp downscale (Only for sc17 and above) + */ +} GFVXBAYERINFO, *PGFVXBAYERINFO; + + +///////////Cindy: Following is CSI defination. + +/* flags optoins */ + +/** Pixel Parser stream is from CSI A +*/ +#define GFVX_CSI_SOURCE_CSI_A 0x00000001 + +/** Pixel Parser stream is from CSI B +*/ +#define GFVX_CSI_SOURCE_CSI_B 0x00000002 + +/** Pixel Parser stream is from HOST +*/ +#define GFVX_CSI_SOURCE_HOST 0x00000004 + +/** Pixel Parser stream is from VIP +*/ +#define GFVX_CSI_SOURCE_VIP 0x00000008 + +/** Pixel Parser A enable +*/ +#define GFVX_CSI_PPA_ENABLE 0x00000010 + +/** Pixel Parser B enable +*/ +#define GFVX_CSI_PPA_DISABLE 0x00000020 + +//#define GFVX_CSI_PPA_MASK 0x00000030 + +/** Pixel Parser A enable +*/ +#define GFVX_CSI_PPB_ENABLE 0x00000040 + +/** Pixel Parser B enable +*/ +#define GFVX_CSI_PPB_DISABLE 0x00000080 + +//#define GFVX_CSI_PPB_MASK 0x000000C0 + +/** whether packet header is sent in the beginning of packet or not. payload only mode: no header +*/ +#define GFVX_CSI_PACKET_HEADER_ENABLE 0x00000100 + +/** Check data_type and Virtural_Channel_ID or not +*/ +#define GFVX_CSI_DATA_IDENTIFIER_ENABLE 0x00000200 + +/** check WordCount from header or register +*/ +#define GFVX_CSI_WORD_COUNT_SELECT_HEADER 0x00000400 + +/** check ECC from header +*/ +#define GFVX_CSI_HEADER_EC_DISABLE 0x00000800 + +/** pad short line with 0 +*/ +#define GFVX_CSI_LINE_PAD_NONE 0x00001000 + +/** pad short line with 1 +*/ +#define GFVX_CSI_LINE_PAD_1 0x00002000 + +/** pad short frame with 0 +*/ +#define GFVX_CSI_FRAME_PAD_NONE 0x00004000 + +/** pad short frame with 1 +*/ +#define GFVX_CSI_FRAME_PAD_1 0x00008000 + +/** 2 bytes CRC Check enable +*/ +#define GFVX_CSI_CRC_CHECK 0x00010000 + +/** Embedded data enable +*/ +#define GFVX_CSI_EMBEDDED_DATA_ENABLE 0x00020000 + +/** enable timeout checking +*/ +#define GFVX_CSI_LINE_TIMEOUT_ENABLE 0x00040000 + +#define GFVX_CSI_VSYNC_START_MARK_VSYNC 0x00080000 + +#define GFVX_CSI_VI_HSYNC_CONTROL 0x00100000 + +#define GFVX_CSI_VI_VSYNC_CONTROL 0x00200000 + + +typedef struct _GFVXCSISET +{ + NvU32 flags; /** flag options see above */ + NvU32 HOffset; /**< VIP input signal horizontal offset. */ + NvU32 HActive; /**< VIP input signal horizontal active width. */ + NvU32 VOffset; /**< VIP input signal vertical offset. */ + NvU32 VActive; /**< VIP input signal vertical active height.*/ + NvU32 ColorFormat; /** convert to data type*/ + +// PIXEL_STREAM_PPA_COMMAND: + NvU32 StartMarkerFrameMin; //CSI_PPA_START_MARKER_FRAME_MIN; /** comment */ + NvU32 StartMarkerFrameMax; //CSI_PPA_START_MARKER_FRAME_MAX; /** comment */ + +// PIXEL_STREAM_A_CONTROL0: + NvU32 VirtualChannelID; //CSI_PPA_VIRTUAL_CHANNEL_ID; /** stream virtual ID number */ + NvU32 OutputFormatOpt; //CSI_PPA_OUTPUT_FORMAT_OPTIONS; /** output format */ + +// PIXEL_STREAM_A_CONTROL1: + NvU32 TopFieldFrame; //CSI_PPA_TOP_FIELD_FRAME; /** camera spec */ + NvU32 TopFieldFrameMask; //CSI_PPA_TOP_FIELD_FRAME_MASK; /** camera sepc */ + +// PIXEL_STREAM_A_GAP: + NvU32 LineMinGap; //PPA_LINE_MIN_GAP; /** gap between lines */ + NvU32 FrameMinGap; //PPA_FRAME_MIN_GAP; /** gat between frames */ + +// PIXEL_STREAM_A_EXPECTED_FRAME: + NvU32 LineTimeOutMaxClock; //PPA_MAX_CLOCKS; /** line time out value */ + +} GFVXCSISET, *PGFVXCSISET; + +/* CSI data types + *` Set by camera script to match + * stream supplied by camera + */ + +#define GFVX_CSI_DATA_YUV420_8 (24UL) +#define GFVX_CSI_DATA_YUV420_10 (25UL) +#define GFVX_CSI_DATA_LEG_YUV420_8 (26UL) +#define GFVX_CSI_DATA_YUV420CSPS_8 (28UL) +#define GFVX_CSI_DATA_YUV420CSPS_10 (29UL) +#define GFVX_CSI_DATA_YUV422_8 (30UL) +#define GFVX_CSI_DATA_YUV422_10 (31UL) +#define GFVX_CSI_DATA_RGB444 (32UL) +#define GFVX_CSI_DATA_RGB555 (33UL) +#define GFVX_CSI_DATA_RGB565 (34UL) +#define GFVX_CSI_DATA_RGB666 (35UL) +#define GFVX_CSI_DATA_RGB888 (36UL) +#define GFVX_CSI_DATA_RAW6 (40UL) +#define GFVX_CSI_DATA_RAW7 (41UL) +#define GFVX_CSI_DATA_RAW8 (42UL) +#define GFVX_CSI_DATA_RAW10 (43UL) +#define GFVX_CSI_DATA_RAW12 (44UL) +#define GFVX_CSI_DATA_RAW14 (45UL) +#define GFVX_CSI_DATA_ARB_DT1 (48UL) +#define GFVX_CSI_DATA_ARB_DT2 (49UL) +#define GFVX_CSI_DATA_ARB_DT3 (50UL) +#define GFVX_CSI_DATA_ARB_DT4 (51UL) + + +/** OutputFormatOpt */ +#define GFVX_CSI_OUTPUT_FORMAT_OPTIONS_ARBITRARY (0UL) +#define GFVX_CSI_OUTPUT_FORMAT_OPTIONS_PIXEL (1UL) +#define GFVX_CSI_OUTPUT_FORMAT_OPTIONS_PIXEL_REP (2UL) +#define GFVX_CSI_OUTPUT_FORMAT_OPTIONS_STORE (3UL) + +#define GFVX_INTERNAL_DEBUG 0x10000000 + +// Below defines are used only when input source is HOST and input format is Bayer +// Since this is not a valid customer use case, we will not add Doxygen comments to these defines + +// Minimum padding requirement for ISP +#define MIN_SCANSIZE_WIDTH_DIFF 20 +#define MIN_SCANSIZE_HEIGHT_DIFF 10 + +// The actual minimum padding has not been determined; +// however, 30 padding on all sides is not enough for +// Demosaic mode 4 (5X5BPNR) with M3 statistics gathering. +// 35 on right + 15 on top/left/bottom seems to +// work fine. +#define MIN_ACTIVE_AREA_LEFT_PADDING 15 +#define MIN_ACTIVE_AREA_RIGHT_PADDING 35 +#define MIN_ACTIVE_AREA_TOP_PADDING 15 +#define MIN_ACTIVE_AREA_BOTTOM_PADDING 15 + +// Active Rect must be a few pixels larger than Output Rect to avoid +// a halo effect where the outer pixels are wrong. +#define MIN_OUTPUT_AREA_PADDING_3X3 2 +#define MIN_OUTPUT_AREA_PADDING_5X5 3 + + +/** Parameter structure passed to GFVxVIPSetVIP(). + @see GFVxVIPSetVIP() +*/ +typedef struct _GFVXVIPINFO +{ + NvU32 Flag; + /**< Flag bitmask, OR'ed combination of: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_VIP_PARALLEL_INPUT8-bit/clock video data
      #GFVX_VIP_SERIAL_INPUTSerial input
      #GFVX_VIP_HVSYNC_IN_STREAMVHSYNC and VVSYNC in the data stream
      #GFVX_VIP_EXTERNAL_VHSYNCCamera VHSYNC asserted by external signal
      #GFVX_VIP_INTERNAL_VHSYNCCamera VHSYNC generated by GoForce chip
      #GFVX_VIP_EXTERNAL_VCLKVCLK generated externally
      #GFVX_VIP_INTERNAL_VCLKVCLK generated by GoForce chip
      #GFVX_VIP_DETECT_FIELDDetect field 0 or 1, will not work for internal VHSYNC + (#GFVX_VIP_INTERNAL_VHSYNC) +
      #GFVX_VIP_RGB_H_FLIPHorizontal flip
      #GFVX_VIP_RGB_V_FLIPVertical flip
      #GFVX_VIP_HOST_IMAGECPU feeds image to VIP
      #GFVX_VIP_CHANGE_DEFAULT_TIMINGChange the default timing for VHSYNC and VCLK
      #GFVX_VIP_ASK_FOR_MCLOCKCamera master clock provided by GoForce chip
      #GFVX_VIP_TYPE_AVIP input type A interface
      #GFVX_VIP_TYPE_BVIP input type B interface
      #GFVX_VIP_TYPE_CVIP input type C interface
      #GFVX_VIP_DEST_BYTE_SWAPEnable destination byte swap for YUV/RGB data written to + preview surface +
      #GFVX_VIP_TYPE_C_RAWDo not remove the 0xFF, 0x02 sequence when camera is + running at type C interface +
      #GFVX_VIP_VIP_ROTATE_0VI output without rotation
      #GFVX_VIP_VIP_ROTATE_90VI output with 90 degree rotation
      #GFVX_VIP_VIP_ROTATE_180VI output with 180 degree rotation
      #GFVX_VIP_VIP_ROTATE_270VI output with 270 degree rotation
      #GFVX_VIP_RGB565RGB565 input to EPP
      #GFVX_VIP_RGB888RGB888 input to EPP
      #GFVX_VIP_RGB444RGB444 input to EPP
      #GFVX_VIP_BYPASS_MCLOCK_PINBypass any manipulation on internal master clock generation + output pin +
      #GFVX_VIP_BYPASS_NON_MCLOCK_PINSBypass any manipulation on VCLK, VHSYNC, and VID[7:0] pins +
      #GFVX_VIP_PRE_GENERATE_MCLOCKPre-generation of master clock
      + */ + NvU32 HOffset; /**< VIP input signal horizontal offset. */ + NvU32 HActive; /**< VIP input signal horizontal active width. */ + NvU32 VOffset; /**< VIP input signal vertical offset. */ + NvU32 VActive; /**< VIP input signal vertical active height. */ + NvU32 ColorFormat; /**< VIP input color format identifier, see + GFRMSURFACE::ColorFormat. + */ + NvU32 SerialDelay; /**< VIP serial input delay, reserved for future + use. + */ + NvU32 NewTiming; /**< Flag bitmask configuring VIP input timing, used + only if flag #GFVX_VIP_CHANGE_DEFAULT_TIMING + set, OR'ed combination of: + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_VIP_PDL_FALLING_VCLKParallel data latched at falling edge + of VCLK (default is rising edge) +
      #GFVX_VIP_SDL_RISING_VCLKSerial data lacthed at rising edge of + VCLK (default is falling edge) +
      #GFVX_VIP_VHSYNC_ACTIVE_LOWVHSYNC active low (default is active + high) +
      #GFVX_VIP_VVSYNC_ACTIVE_LOWVVSYNC active low (default is active + high) +
      #GFVX_VIP_VHSYNC_ACTIVE_EDGE_LEADVHSYNC active leading edge (default + is trailing edge) +
      #GFVX_VIP_VVSYNC_ACTIVE_EDGE_LEADVVSYNC active leading edge (default + is trailing edge) +
      #GFVX_VIP_SFRAME_ACTIVE_LOWSerial video frame sync active low, + falling edge indicates start of data + frame (default is active high, rising + edge indicates start of data frame) +
      #GFVX_VIP_SFRAME_SIZE_16Serial video input is 16 bit per frame + (default is 8 bit per frame) +
      #GFVX_VIP_FILED_0_BOTTOMField 0 is bottom/even field + (default is top/odd field) +
      #GFVX_VIP_VCLK_OUTPUT_ACTIVE_LOWVCLK output from GoForce chip active + low (default is active high) +
      + */ + NvU32 HNumerator; /**< VI decimation horizontal numerator, number of + pixels to keep from a group of incoming + pixels. + */ + NvU32 HDenominator;/**< VI decimation horizontal denominator, group + size. + */ + NvU32 VNumerator; /**< VI decimation vertical numerator, number of + lines to keep from a group of incoming lines. + */ + NvU32 VDenominator;/**< VI decimation vertical numerator, group + size. + */ + NvU32 MClockFreq; /**< Master clock frequency supplied to camera from + GoForce chip, used only if + #GFVX_VIP_ASK_FOR_MCLOCK set. + */ + NvU32 VClockFreq; /**< Clock frequency required for VIP input signal. + */ + + // Fill The following fields if GFVX_VIP_INTERNAL_VHSYNC is set in Flag + NvU32 VHPulseWidth; /**< VHSYNC pulse width in number of VCLK cycles, + valid range is 1 to 8. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + NvU32 VHPulsePeriod;/**< VHSYNC pulse period in number of VCLK cycles, + valid range 32 to 2048. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + NvU32 VVPulseWidth; /**< VVSYNC pulse width in number of VCLK cycles + valid range is 1 to 8. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + NvU32 VVPulsePeriod;/**< VVSYNC pulse period in number of VCLK + valid range 32 to 1024. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + NvU32 VVDelay; /**< Number of VCLK cycles from the leading edge + of VHSYNC to the leading edge of VVSYNC, + valid range is -2 to 13. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + PGFVXBAYERINFO pBayerInfo; /**< Structure used to describe the rectangles needed by ISP + to properly process Bayer input from camera. This + structure is used only when input source is VIP and + input data format is Bayer. + */ + PGFVXCSISET pCSIInfo; /** Structure used to describe CSI stream info. Only used when input source is CSI stream + */ +} GFVXVIPINFO, *PGFVXVIPINFO; + + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Start VIP data feeding. + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_START 0x00000001 + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Stop VIP data feeding. + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_STOP 0x00000002 + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Start VIP data feeding with + synchronized auto-display surface after a frame is captured from VIP. + If no output surface is set (GFVXVIPUPDATE::ppSurf is NULL), this action + behaves in the same way as #GFVX_VIP_START. + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_AUTO_FLIP (0x00000004 | GFVX_VIP_START) + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Start VIP data feeding with + synchronized auto-blit from VIP output surface to another surface. + + Parameters for the blit have to be set up separately via GFVxBlt() with + flag #GFVX_AUTO_BLT. Auto-blit is triggered after a complete frame has + been captured from VIP. + + If no output surface is set (GFVXVIPUPDATE::ppSurf is NULL), this action + behaves in the same way as #GFVX_VIP_START. + + Once auto-blit has been enabled it can be disabled with GFVxVIPUpdate() + action identifier #GFVX_VIP_AUTO_TRIGER_BLT_OFF. + + @see GFVXVIPUPDATE, GFVxVIPUpdate(), #GFVX_VIP_AUTO_TRIGER_BLT_OFF, + #GFVX_AUTO_BLT +*/ +#define GFVX_VIP_AUTO_TRIGER_BLT (0x00000008 | GFVX_VIP_START) + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Stop auto-blit that has been + enabled earlier via #GFVX_VIP_AUTO_TRIGER_BLT. + + Note that this action only disables auto-blit. It does not disable the + VIP data feed. If also VIP is to be disabled, GFVxVIPUpdate() has to be + called again with action #GFVX_VIP_STOP. + + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_AUTO_TRIGER_BLT_OFF 0x00000010 + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Start VIP data feeding with + synchronized auto-display surface after a frame is captured from VIP. + Second Overlay Window is used instead of first. + If no output surface is set (GFVXVIPUPDATE::ppSurf is NULL), this action + behaves in the same way as #GFVX_VIP_START. + + @version SC15 and above only + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_AUTO_FLIP_OVERLAY2 (0x00000020 | GFVX_VIP_START) + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Capture one frame in VIP buffer + if it is combined with flag #GFVX_VIP_START + + @version SC15 and above only + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_CAPTURE_ONE_FRAME 0x00000040 + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Restart VIP without changes VI + state after stop VI + + @version SC15 and above only + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_RESTART 0x00000080 + +/** Parameter structure for GFVxVIPUpdate(). + @see GFVxVIPUpdate() +*/ +typedef struct _GFVXVIPUPDATE +{ + PGFRMSURFACE *ppSurf; /**< Pointer to an array of VIP output surfaces + pointers, or NULL to feed to MPEG/JPEG without + display. + */ + NvU32 numofSurf; /**< Number of surface pointers in \a ppSurf, valid + range is 1 to 2. + */ + NvU16 XStart; /**< Destination surface X position for the output + from VIP + */ + NvU16 YStart; /**< Destination surface Y position for the output + from VIP + */ + NvU32 UpdateOption; + /**< Action identifier, one of: + + + + + + + + + + + +
      #GFVX_VIP_STARTStart VIP data feeding
      #GFVX_VIP_STOPStop VIP data feeding
      #GFVX_VIP_AUTO_FLIPStart VIP data feeding and enable + auto-display of the last VIP target + surface +
      #GFVX_VIP_AUTO_TRIGER_BLTStart VIP data feeding and enable + auto-blit from the last target surface + to additional surfaces +
      #GFVX_VIP_AUTO_TRIGER_BLT_OFFDisable auto-blit
      + */ +} GFVXVIPUPDATE, *PGFVXVIPUPDATE; + +/** VxAPI VxBlt operation modes. + Constants to specify SB mode for a call to GFVxBltSetCSCCoeff(). + @see GFVxBltSetCSCCoeff(), GFVxBltGetCSCCoeff() +*/ +typedef enum +{ + /** Host full frame stretchblt trigger */ + GFVX_BLT_FULL_MODE, + + /** Host partial frame stretchblt trigger */ + GFVX_BLT_PARTIAL_MODE, + + /** Auto stretchblt trigger from VI */ + GFVX_BLT_AUTO_VI_MODE +} GFVXBLTMODE; + +/** VxAPI component level interrupt operation types. + Constants to specify operation for a call to GFVxInterruptControl(). + @see GFVX_INTERRUPT_TYPE, GFVxInterruptControl() +*/ +typedef enum +{ + /** Enable interrupt/status assertion for an interrupt type. */ + GFVX_INTERRUPT_ENABLE, + + /** Disable interrupt/status assertion for an interrupt type. */ + GFVX_INTERRUPT_DISABLE, + + /** Clear interrupt/status assertion for an interrupt type. */ + GFVX_INTERRUPT_CLEAR, + + /** Query for interrupt/status assertion for an interrupt type. */ + GFVX_INTERRUPT_QUERY_STATUS, + + /** Set Y-FIFO threshold. */ + GFVX_INTERRUPT_SET_Y_FIFO_THRESHOLD, + + /** Get Y-FIFO threshold. */ + GFVX_INTERRUPT_GET_Y_FIFO_THRESHOLD, + + /** Set V-counter threshold. */ + GFVX_INTERRUPT_SET_V_COUNTER_THRESHOLD, + + /** Get V-counter threshold. */ + GFVX_INTERRUPT_GET_V_COUNTER_THRESHOLD, + + /** Get all bits of VI interrupt status register. */ + GFVX_INTERRUPT_GET_ALL_STATUS, + + /** Clear all VI interrupt status bits. */ + GFVX_INTERRUPT_CLEAR_ON_ALL_STATUS + +} GFVX_INTERRUPT_OPERATION_TYPE; + +/** VxAPI interrupt types. + @see GFVX_INTERRUPT_OPERATION_TYPE, GFVxInterruptControl() +*/ +typedef enum +{ + /** VID[8] pin rising edge interrupt. */ + GFVX_VD8PIN_RISING_EDGE_INTR = 0x0100001, + /** VID[9] pin rising edge interrupt. */ + GFVX_VD9PIN_RISING_EDGE_INTR = 0x0100002, + /** VID[10] pin rising edge interrupt. */ + GFVX_VD10PIN_RISING_EDGE_INTR = 0x0100004, + /** VID[11] pin rising edge interrupt. */ + GFVX_VD11PIN_RISING_EDGE_INTR = 0x0100008, + /** VGP[4] pin rising edge interrupt. */ + GFVX_VGP4PIN_RISING_EDGE_INTR = 0x0100010, + /** VGP[5] pin rising edge interrupt. */ + GFVX_VGP5PIN_RISING_EDGE_INTR = 0x0100020, + /** VGP[6] pin rising edge interrupt. */ + GFVX_VGP6PIN_RISING_EDGE_INTR = 0x0100040, + /** VHSYNC pin rising edge interrupt. */ + GFVX_VHSYNC_RISING_EDGE_INTR = 0x0100080, + /** VVSYNC pin rising edge interrupt. */ + GFVX_VVSYNC_RISING_EDGE_INTR = 0x0100100, + + /** Vertical counter threshold interrupt. */ + GFVX_VERTICAL_COUNTER_THRESHOLD_INTR = 0x0000200, + /** Y-FIFO threshold int. */ + GFVX_Y_FIFO_THRESHOLD_INTR = 0x0000400, + /** Buffer done first output interrupt. */ + GFVX_BUFFER_FIRST_OUTPUT_INTR = 0x0000800, + /** Frame done first output interr upt. */ + GFVX_FRAME_FIRST_OUTPUT_INTR = 0x0001000, + /** Buffer done second output interrupt. */ + GFVX_BUFFER_SECOND_OUTPUT_INTR = 0x0002000, + /** Frame done second output interrupt. */ + GFVX_FRAME_SECOND_OUTPUT_INTR = 0x0004000, + /** VI to EPP error interrupt. */ + GFVX_EPP_ERROR_INTR = 0x0008000, + /** YUV420PA error interrupt. */ + GFVX_YUV420PA_ERROR_INTR = 0x0010000, + /** First output peer stall interrupt. */ + GFVX_FIRST_OUTPUT_PEER_STALL_INTR = 0x0020000, + /** Second output peer stall interrupt. */ + GFVX_SECOND_OUTPUT_PEER_STALL_INTR = 0x0040000, + /** DMA stall interrupt. */ + GFVX_DMA_STALL_INTR = 0x0080000, + + + /** VD[8] pin falling edge interrupt. */ + GFVX_VD8PIN_FALLING_EDGE_INTR = 0x0000001, + /** VD[9] pin falling edge interrupt. */ + GFVX_VD9PIN_FALLING_EDGE_INTR = 0x0000002, + /** VD[10] pin falling edge interrupt. */ + GFVX_VD10PIN_FALLING_EDGE_INTR = 0x0000004, + /** VD[11] pin falling edge interrupt. */ + GFVX_VD11PIN_FALLING_EDGE_INTR = 0x0000008, + /** VGP[4] pin falling edge interrupt. */ + GFVX_VGP4PIN_FALLING_EDGE_INTR = 0x0000010, + /** VGP[5] pin falling edge interrupt. */ + GFVX_VGP5PIN_FALLING_EDGE_INTR = 0x0000020, + /** VGP[6] pin falling edge interrupt. */ + GFVX_VGP6PIN_FALLING_EDGE_INTR = 0x0000040, + /** VHSYNC pin falling edge interrupt. */ + GFVX_VHSYNC_FALLING_EDGE_INTR = 0x0000080, + /** VVSYNC pin falling edge interrupt. */ + GFVX_VVSYNC_FALLING_EDGE_INTR = 0x0000100, + + /** VD[8] pin rising edge interrupt. */ + GFVX_VD8PIN_RISING_LEVEL_INTR = 0x1100001, + /** VD[9] pin rising edge interrupt. */ + GFVX_VD9PIN_RISING_LEVEL_INTR = 0x1100002, + /** VD[10] pin rising edge interrupt. */ + GFVX_VD10PIN_RISING_LEVEL_INTR = 0x1100004, + /** VD[11] pin rising edge interrupt. */ + GFVX_VD11PIN_RISING_LEVEL_INTR = 0x1100008, + /** VGP[4] pin rising edge interrupt. */ + GFVX_VGP4PIN_RISING_LEVEL_INTR = 0x1100010, + /** VGP[5] pin rising edge interrupt. */ + GFVX_VGP5PIN_RISING_LEVEL_INTR = 0x1100020, + /** VGP[6] pin rising edge interrupt. */ + GFVX_VGP6PIN_RISING_LEVEL_INTR = 0x1100040, + /** VHSYNC pin rising edge interrupt. */ + GFVX_VHSYNC_RISING_LEVEL_INTR = 0x1100080, + /** VVSYNC pin rising edge interrupt. */ + GFVX_VVSYNC_RISING_LEVEL_INTR = 0x1100100, + + /** VD[8] pin falling level interrupt. */ + GFVX_VD8PIN_FALLING_LEVEL_INTR = 0x1000001, + /** VD[9] pin falling level interrupt. */ + GFVX_VD9PIN_FALLING_LEVEL_INTR = 0x1000002, + /** VD[10] pin falling level interrupt. */ + GFVX_VD10PIN_FALLING_LEVEL_INTR = 0x1000004, + /** VD[11] pin falling level interrupt. */ + GFVX_VD11PIN_FALLING_LEVEL_INTR = 0x1000008, + /** VGP[4] pin falling level interrupt. */ + GFVX_VGP4PIN_FALLING_LEVEL_INTR = 0x1000010, + /** VGP[5] pin falling level interrupt. */ + GFVX_VGP5PIN_FALLING_LEVEL_INTR = 0x1000020, + /** VGP[6] pin falling level interrupt. */ + GFVX_VGP6PIN_FALLING_LEVEL_INTR = 0x1000040, + /** VHSYNC pin falling level interrupt. */ + GFVX_VHSYNC_FALLING_LEVEL_INTR = 0x1000080, + /** VVSYNC pin falling level interrupt. */ + GFVX_VVSYNC_FALLING_LEVEL_INTR = 0x1000100 + +} GFVX_INTERRUPT_TYPE; + +/** VxAPI related attributes. + @see GFVxGetAttribute() +*/ +typedef enum _GFVXATTRIBUTES +{ + /** VxAPI attribute: Video input interrupt status. + Use this attribute with GFVxGetAttribute() to read the current video + input interrupt status. + + Interpretation of associated attribute value: +
      +        NvU32 Bitmask with interrupt status
      +              For bitpositions see the VI status register in the GoForce
      +              technical manual (Register VI11 on SC12)
      +        
      + + Attribute is get only. + + @see GFVxGetAttribute() + */ + GFVX_ATTR_VIDEO_BUF, + + /** VxAPI attribute: Video VIP input status. + Use this attribute with GFVxGetAttribute() to read the current number + of frames received + */ + + GFVX_ATTR_VIP_INPUT_FRAME_COUNT, + + /** VxAPI attribute: Video VIP input status. + Use this attribute with GFVxGetAttribute() to read the current number + of lines received + */ + + GFVX_ATTR_VIP_INPUT_LINE_COUNT, + +} GFVXATTRIBUTES; + +/** YUV Color Space Conversion (CSC) coefficients. + Parameter structure for GFVxVIPSetCSCCoeff(), GFVxBltSetCSCCoeff(), + GFVxVIPGetCSCCoeff(), and GFVxBltGetCSCCoeff() + + YUV color space conversion is used when converting from a YUV formatted + surface to RGB formatted surface. The YUV color space conversion formular + appears as follows: + + R = sat(KYRGB*(Y + YOF) + KUR*U + KVR*V) + G = sat(KYRGB*(Y + YOF) + KUG*U + KVG*V) + B = sat(KYRGB*(Y + YOF) + KUB*U + KVB*V) + + By default, the YUV color space conversion coefficients are: + + KYRGB, KUR, KVR 1.1644 0.0000 1.5960 + KYRGB, KUG, KVG = 1.1644 -0.3918 -0.8130 + KYRGB, KUB, KVB 1.1644 2.0172 0.0000 + + and YOF = -16.0000 + + The value corresponding to each of these YUV color space conversion + coefficients is a Q16 (signed 15.16 fixed point value). + + For examples: + YOF = -16.0000, the value corresponding is 0xFFF00000 + KYRGB = 1.1644, the value corresponding is 0x00012A16 + KVR = 1.5960, the value corresponding is 0x00019893 + KUG = -0.3918, the value corresponding is 0xFFFF9BB3 + KVG = -0.8130, the value corresponding is 0xFFFF2FE0 + KUB = 2.0172, the value corresponding is 0x00020467 +*/ +typedef struct _GFVXCSCCOEF +{ + NvU32 YOF; + NvU32 KYRGB; + NvU32 KUR; + NvU32 KVR; + NvU32 KUG; + NvU32 KVG; + NvU32 KUB; + NvU32 KVB; +} GFVXCSCCOEF; + + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFVxOpen(GFRmHandle hRm, GFVxHandle *phVx, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFVxClose(GFVxHandle *phVx); + +/** @name Functions +@{*/ + +/** This function returns version and capabilities of API and hardware. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pVXProp (#PGFPROPERTY) Pointer to property structure to be + filled in + + @retval #GF_SUCCESS \a pJXProp filled in successfully + @retval #GF_ERROR Some error occured + + This function returns information about the VxAPI, including the following: + - VxAPI module version + - VIP support + - Overlay support + - MPEG decoding and encoding + - JPEG decoding and encoding + + The #GFPROPERTY structure passed with parameter \a pVXProp will be + filled in on successfull return. The #GFPROPERTY::Capability field + will hold a combination of flagbits indicating capabilities specific + to the VxAPI: + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_CAP_CSCColor space conversion supported
      #GFVX_CAP_VIPVIP functions available
      #GFVX_CAP_ENLARGEEnlarge source image supported
      #GFVX_CAP_SHRINKShrink source image supported
      #GFVX_CAP_COLOR_CONTROLColor control supported
      #GFVX_CAP_OVERLAYOverlay supported
      #GFVX_CAP_MPEGDECMPEG4 decoder supported
      #GFVX_CAP_MPEGENCMPEG4 encoder supported
      #GFVX_CAP_JPEGDECJPEG decoder supported
      #GFVX_CAP_JPEGENCJPEG encoder supported
      #GFVX_CAP_ALPHA_BLENDAlpha blending supported
      #GFVX_CAP_EXTEND_RGBExtended RGB format 32 bpp supported
      #GFVX_CAP_OVERLAY_YUVYUV overlay supported
      #GFVX_CAP_OVERLAY_SCALEOverlay with scaling supported
      #GFVX_CAP_OVERLAY_MULTIPLEMultiple overlay supported
      #GFVX_CAP_ENCODE_TYPEVariable sized data camera interface (Type A/B/C) supported
      + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the JxDecAPI functions. + + @see GFPROPERTY +*/ +GF_RETTYPE GFVxGetProperty(GFVxHandle VxHandle, PGFPROPERTY pVvProp); + +/** Stretch-blit rectangular area from source to destination surface. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pBlt (#PGFVXBLT) Pointer to #GFVXBLT structure + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function copies a rectangular area from a source surface to a + rectangle in the destination surface. If source and destination + rectangles differ in size, the GPU's stretch blit (SB) unit scales the + source data to fit the destination rectangle. If the source and destination + surfaces have different color formats, GFVxBlt() provides limited color + format conversions. + + Source and Destination surfaces have to be in GPU memory. Source surfaces + can be in YUV420, YUV422, or RGB565 format. Destination surfaces can be + in RGB565, RGB888 (SC12), or ARGB8888 (SC12 SC15) format. YUV output can also + be routed to EPP for encoding. + + Color format conversions from a YUV420 or YUV422 source are supported for these + destination formats: + - RGB565 + - ARGB8888 (SC12 SC15) + - RGB888 (SC12) + + A #GFVXBLT control structure is passed with parameter \a pBlt. + GFVXBLT::ppDestSurf points to an array of destination surface pointers, + with the number of pointers in this array specified by + GFVXBLT::numofDestSurf. GFVXBLT::ppSrcSurf points to an array of source + surface pointers, with the size of this array specified by + GFVXBLT::numofSrcSurf. + + When the destination surface pointer is NULL, output of SB goes + to EPP for encoding. + + See #GFVXBLT for minimum and maximum specifications of source and destination + rectangle sizes. + + Instant Blit Mode + + In this mode of operation, the blit is executed immediately via the command + FIFO. It is always performed from the first surface in GFVXBLT::ppSrcSurf + to the first surface in GFVXBLT::ppDestSurf. Other pointers in these + arrays are ignored. + + Auto Blit Mode + + VxBlt() can be used to enable auto-blit mode (flag #GFVX_AUTO_BLT + in GFVXBLT::BltOption). Whenever the end of a frame coming from VIP is + reached, SB will be fired automatically with the parameters set in GFVXBLT. + Auto-blit mode remains set until it is reset by another auto-blit command. + During auto-blit mode, manual SB commands should save and restore SB + registers (SC12 and below). This is not required for SC15 and above because + they have three hardware contexts: one for auto-blit, one for host trigger + (manual SB commands) and one for host partial trigger. + + The first time auto-blit is fired, the first surface in GFVXBLT::ppSrcSurf + is copied to the first surface in GFVXBLT::ppDestSurf. In subsequent blits, + the source and destination arrays are walked through subsequently. If + there is only one surface in the GFVXBLT::ppSrcSurf or GFVXBLT::ppDestSurf + arrays, only this one is used. + + Note that VxBlt() only sets auto-blit parameters. It is actually enabled by + GFVxVIPUpdate() using action #GFVX_VIP_AUTO_TRIGER_BLT, or GFMxDecSetMBs(). + + Auto Display + + If auto-display (#GFVX_AUTO_DISPLAY or #GFVX_AUTO_DISPLAY_OVERLAY2) is on, + GFVxBlt() automatically shows the destination surface on the screen. + The application does not need to call GFVxFlip() to show the surface. + Auto-display can be combined with both auto-blit and instant-blit modes. + + Color Keying + + If source color keying (#GFVX_BLT_SRC_KEY) is set, all pixels from the + source surface matching GFVXBLT::colorKey are transparent (not copied). + + VSync Synchronisation + + By default all blits are synchronized to display VSync. Note that blits + may block, if the display is disabled. Flag #GFVX_BLT_DISABLE_WAIT_VSYNC + can be used to disable VSync synchronisation. + + @see GFVXBLT +*/ +GF_RETTYPE GFVxBlt(GFVxHandle VxHandle, PGFVXBLT pBlt); + +/** Activate surface for display. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pFlip (#PGFVXFLIP) Pointer to #GFVXFLIP structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If ColorFormat is unsupported + + This function changes the display buffer address from one surface to + another. + + This function displays #GFVXFLIP::pForeGroundSurf. If + GFVXFLIP::pForeGroundSurf is an overlay surface, this function displays + that surface to the destination rectangle that has been set by + GFVxUpdateOverlay(). + + If GFVXFLIP::pForeGroundSurf is not an overlay surface, this function + displays the entire surface. In this case GFVxFlip() can show either the + primary surface or an offscreen surface on the display screen. + + If there is only one surface for primary or overlay, GFVxFlip() should not + be called. + + @see GFVXFLIP +*/ +GF_RETTYPE GFVxFlip(GFVxHandle VxHandle, PGFVXFLIP pFlip); + +/** Configure properties of overlay (WinB) display. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pOverlay (#PGFVXUPDATEOVERLAY) Pointer to #GFVXUPDATEOVERLAY structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_SURFACETYPE_NOT_SUPPORTED If Source SurfaceType is unsupported + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If Source ColorFormat is unsupported + @retval GFVX_ERROR_ILLEGAL_ALPHA_VALUE If Alpha Value is incorrect + + This function controls overlay (WinB) display, setting the following + features: + - Destination and source rectangle areas + - Rotation for overlay surface + - Color keying + - Alphablending Color Key (GoForce 4800 and above) + - Foreground and Background alpha values. (GoForce 4800 and above) + - Destination surface color format (RGB888, ARGB8888 for GoForce 4800 and + above) + + SC15 supports the following overlay surface orientations - 0 degree rotated, + 180 degree rotated, horizont flip, vertical flip. Overlay surface orientation + is always relative to the orientaton of primary surface. For eg. if primary + surface is 180 degree rotated and requested overlay surface orientation is + 0 degree rotated, then overlay surface will be 180 degree rotated. + + This function supports the following source surface type - GF_SURFACE_OVERLAY. + It supports the following source surface colorformats - RGB565, ARGB8888, ARGB1555, + ARGB4444. + + In order to work around a hardware bug in SC12, in which the GC displays + pixels at the end of the line that are 64 pixels back from the end of + the line, the overlay window width will be aligned to 4-pixels. + + If GFVXUPDATEOVERLAY::pSrcSurf is NULL then overlay display is disabled. + + This function will have no effect, if the GoForce media processor version + does not support overlays. This can be checked via the #GFVX_CAP_OVERLAY + attribute with GFVxGetProperty(). + + Color Keying + + With color keying pixels from the overlay surface can be masked (made + transparent). It can be enabled in different modes of operation by setting + one of the following flags in GFVXUPDATEOVERLAY::UpdateOption: + - #GFVX_UO_SRC_COLOR_KEY + - #GFVX_UO_DEST_COLOR_KEY + + The color key is passed in GFVXUPDATEOVERLAY::ColorKey. Refer to the flags' + documentation for details on modes of operation. + + An exotic color which does not conflict with other colors of a use-case + should be selected as the color key. Color keying for overlay display is + processed on the fly, no pixels in the surfaces are overwritten. + + If destination is in 1-bit alpha format (eg ARGB1555), application can + use two additional flags - #GFVX_UO_COLOR_KEY_ALPHA_ONLY and + #GFVX_UO_COLOR_KEY_ALPHA_COLOR. Refer to the flags' + documentation for details on modes of operation. + + Alpha Blending + + Overlay display with alpha blending can be enabled by setting + flag #GFVX_UO_ALPHA_BLENDING. + + Setting flag #GFVX_UO_ALPHA_BLENDING lets the overlay surface to appear + blended with the destination surface using the alpha value passed in + GFVXUPDATEOVERLAY::AlphaValue. Refer to the flags' documentation for details + on how to define AlphaVal. + + If destination is in 1-bit alpha format (eg ARGB1555), application can + use two additional flags - #GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY and + #GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR. Refer to the flags' + documentation for details on modes of operation. + + Just like overlay colorkey, an exotic color which does not conflict with + other colors of a use-case should be selected as the blending color key. + Blending is processed on the fly, no pixels in the surfaces are overwritten. + + If #GFVX_UO_DEST_COLOR_KEY is set, alpha blending enabled, and the + destination pixel color matches BlendingColorKey, the following equation + is used to generate the final pixel: +
      +    src * AlphaValue + dest * (1-AlphaValue)
      +    
      + Otherwise, the original pixel is not updated. + + Alpha blending is supported only on GoForce 4800 and above. + + SC15 supports alphablending with the following restriction - You cannot alpha-match + (alpha-blend) in non-key-match areas, at the same time you alpha-blend in key-match areas. + In other words, the following flag combinations will not work - + + #GFVX_UO_DEST_COLOR_KEY|#GFVX_UO_ALPHA_BLENDING|#GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY + #GFVX_UO_DEST_COLOR_KEY|#GFVX_UO_COLOR_KEY_ALPHA_COLOR|#GFVX_UO_ALPHA_BLENDING|#GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY + #GFVX_UO_DEST_COLOR_KEY|#GFVX_UO_COLOR_KEY_ALPHA_ONLY|#GFVX_UO_ALPHA_BLENDING + #GFVX_UO_DEST_COLOR_KEY|#GFVX_UO_COLOR_KEY_ALPHA_ONLY|#GFVX_UO_ALPHA_BLENDING|#GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR + + @see GFVXUPDATEOVERLAY +*/ +GF_RETTYPE GFVxUpdateOverlay(GFVxHandle VxHandle, + PGFVXUPDATEOVERLAY pOverlay); + +/** Feed image data from host to VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pImage (#PGFVXVIPFEEDIMAGE) Pointer to #GFVXVIPFEEDIMAGE parameter + structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If Source ColorFormat is unsupported + + This function feeds an image from the CPU host via the VI source FIFO to + the VIP. It supports YUV420, YUV422 (YUYV, YVYU, UYVY, VYUY), YUV422 planar and + Bayer (8, 12) formats. + + For an YUV420 image, it feeds Y-Fifo, U-Fifo, V-Fifo interleaved at 32 bit. + For an YUV422 image, it feeds the Y-Fifo only. + + This function is intended to be used for feeding YUV data to the JPEG + encoder, or for feeding input for VIP preview display (GFVxVIPSetVIP() + and GFVxVIPUpdate()). YUV data for MPEG encoding is fed with + GFMxEncFeedImage(). + + Parameter \a pImage passes a surface containing source image data and an + optional source clipping rectangle. Surface data has to reside in memory + accessible by the host CPU, e.g. a surface allocated as type + #GF_SURFACE_SYSTEM_MEMORY. + + @see GFVXVIPFEEDIMAGE, GFVX_VIP_HOST_IMAGE +*/ +GF_RETTYPE GFVxVIPFeedImage(GFVxHandle VxHandle, + PGFVXVIPFEEDIMAGE pImage); + +/** Setup partial feed image data from host to VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param colorFormat Color format of feed image surface + @param width Width of feed image + @param height Height of feed image + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_ILLEGAL_PARAMETER If width and height values are incorrect + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If color format of feed image surface is unsupported + + This function setups partial feed image from the CPU host via the VI source FIFO to + the VIP. It supports YUV420, YUV422 (YUYV, YVYU, UYVY, VYUY), YUV422 planar formats. + The partial image data is fed with + GFVxVIPPartialFeedImage(). + + @see GFVxVIPPartialFeedImage, GFVX_VIP_HOST_IMAGE +*/ +GF_RETTYPE GFVxVIPPartialFeedImageSetup(GFVxHandle VxHandle, + NvU32 colorFormat, + NvU32 width, + NvU32 height); + +/** Feed partial image data from host to VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pSrcSurf Pointer to source feed image surface + @param pSrcRect Pointer to a clip rectangle from source feed image surface + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_ILLEGAL_PARAMETER If pSrcSurf is NULL + + This function feeds a partial image from the CPU host via the VI source FIFO to + the VIP. It supports YUV420, YUV422 (YUYV, YVYU, UYVY, VYUY), YUV422 planar formats. + + For an YUV420 image, it feeds Y-Fifo, U-Fifo, V-Fifo interleaved at 32 bit. + For an YUV422 image, it feeds the Y-Fifo only. + + This function is intended to be used for feeding partial YUV data to the JPEG + encoder, or for feeding partial input for VIP preview display (GFVxVIPSetVIP() + and GFVxVIPUpdate()). YUV data for MPEG encoding is fed with + GFMxEncFeedImage(). + + Parameter \a pSrcRect is an optional source clipping rectangle. + Surface data has to reside in memory accessible by the host CPU, + e.g. a surface allocated as type + #GF_SURFACE_SYSTEM_MEMORY. +*/ +GF_RETTYPE GFVxVIPPartialFeedImage(GFVxHandle VxHandle, + PGFRMSURFACE pSrcSurf, + PGFRECT pSrcRect); + +/** Put video unit into sleep mode. + @param VxHandle (#GFVxHandle) Handle to VxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @note Not implemented by default, this function is intended to be + implemented only in GFSDK ports to platforms that are in need of + this feature. + + @see GFVxWakeup() +*/ +GF_RETTYPE GFVxSleep(GFVxHandle VxHandle); + +/** Wake up video unit from sleep mode. + @param VxHandle (#GFVxHandle) Handle to VxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @note Not implemented by default, this function is intended to be + implemented only in GFSDK ports to platforms that are in need of + this feature. + + @see GFVxSleep() +*/ +GF_RETTYPE GFVxWakeup(GFVxHandle VxHandle); + +/** This function enumerates capabilities of the Video Input Port (VIP). + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pVIPProp (#PGFVXVIPPROPERTY) Pointer to #GFVXVIPPROPERTY structure + to be filled in + + @retval #GF_SUCCESS \a pVIPProp filled in successfully + @retval #GF_ERROR Some error occured + + The #GFPROPERTY structure passed with parameter \a pVIPProp will be + filled in on successfull return. + + The following GoForce VIP features are described by this function: + - Image decimation (scaling) limits + - Image flipping + - Video input interface type + + Parameters that are passed with a #GFVXVIPINFO structure to GFVxVIPSetVIP() + must be within the limits returned by this function. + + @see GFVXVIPPROPERTY, GFVxVIPSetVIP(), GFVXVIPINFO +*/ +GF_RETTYPE GFVxVIPGetProperty(GFVxHandle VxHandle, + PGFVXVIPPROPERTY pVIPProp); + +/** Configure video input to VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pVIPInfo (#PGFVXVIPINFO) Pointer to GFVXVIPINFO parameter structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_ILLEGAL_BAYER_VALUES If values in BayerInfo structure are incorrect + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If Source ColorFormat is unsupported + + The following VIP properties can be configured using this function, see + #GFVXVIPINFO for details: + - Data source and format (CPU host or video input) + - VIP input cropping rectangle + - Image decimation + - Input (camera) color format + + After configuring video input, the flow of data has to be explicitly + enabled with GFVxVIPUpdate(). + + See GFVxVIPGetProperty() for how to test for VIP capabilities at runtime. + + This function returns GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED error if color format + is not supported. Supported color formats for HOST input are - YUV422, YUV422 Planar, + YUV420 and Bayer (8 and 12). YUV420 is not supported if input source is VIP. + + @see GFVXVIPINFO, GFVxVIPUpdate(), GFVxVIPGetProperty() +*/ +GF_RETTYPE GFVxVIPSetVIP(GFVxHandle VxHandle, + PGFVXVIPINFO pVIPInfo); + +/** Enable or disable video feeding through VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pUpdate (#GFVXVIPUPDATE) Pointer to a #GFVXVIPUPDATE structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If Source ColorFormat is unsupported + + This function enables or disables data feeding through VIP after it has + been configured with GFVxVIPSetVIP(). + + The action to be performed by this function is defined by the action + identifier passed in GFVXVIPUPDATE::UpdateOption of parameter \a pUpdate. + + + + + + + + + + + + + + + + + + +
      #GFVX_VIP_START + Enable VIP data feeding + + The structure passed via \a pUpdate controls the output of the VIP, setting + the following parameters: + - Destination surface(s) (single or double buffered) + - Top-left corner the output video is written to the destination surfaces + + GFVXVIPUPDATE::ppSurf passes an array of 1 or 2 destination surfaces to + capture the incoming video stream. If 2 surfaces are passed, the VIP target + surface is flipped after each frame of VIP input if #GFVX_VIP_AUTO_FLIP or + #GFVX_VIP_AUTO_FLIP_OVERLAY2 flag is specified. + + Color space conversion (CSC) is performed depending on the output surface + color formats: + - #GF_SURFACE_RGB565 (16 bpp): VI CSC is used. + - #GF_SURFACE_ARGB8888 (32 bpp): VI CSC is used, only available for SC12 + and above + - #GF_SURFACE_YUV422: (32 bits per two pixels): No CSC is used, data from + the VIP is stored as is in memory + - any other format is considered to be YUV422, and the data is stored as is + + If GFVXVIPUPDATE::ppSurf is NULL, data flow through the VIP is still enabled. + Data from the VIP is not written to target surfaces, but is is fed to the + MPEG or JPEG encoder pre-processor. This mode of operation is useful for the + following two cases: + - There is not enough memory for JPEG encoding. The application could turn + off the screen, enable this mode, and let the JPEG encoder utilize screen + memory (the primary surface). + - In single-shot mode, the application does not want to display the video + image on the screen after enabling the JPEG encoder, thus allowing faster + captures and power savings, and freeing bandwidth. After the image is + captured, the application enables the JPEG decoder to decode the captured + image and shows it on the screen. +
      #GFVX_VIP_AUTO_FLIP + Enable VIP data feeding with auto-display + + Behaviour is identical to #GFVX_VIP_START, additionally auto-display of the + last captured VIP frame is enabled. It is recommended to use this feature + in double buffer mode, passing 2 surfaces in GFVXVIPUPDATE::ppSurf. +
      #GFVX_VIP_AUTO_FLIP_OVERLAY2 + Enable VIP data feeding with auto-display from overlay window2 + + If surfaces to be flipped are overlay surfaces, they are associated with + first overlay surface unless #GFVX_VIP_AUTO_FLIP_OVERLAY2 flag is defined. + This flag should be used only if UpdateOverlay has been previously called + with #GFVX_UO_OVERLAY2 UpdateOption and VxFlip has been called with + #GFVX_FLIP_OVERLAY2 FlipOption. + +
      #GFVX_VIP_AUTO_TRIGER_BLT + Enable VIP data feeding with auto-blit + + Behaviour is identical to #GFVX_VIP_START, additionally auto-blit of the + last captured VIP frame is enabled. It is recommended to use this feature + in double buffer mode, passing 2 surfaces in GFVXVIPUPDATE::ppSurf. + + If #GFVX_VIP_AUTO_FLIP and #GFVX_VIP_AUTO_TRIGER_BLT are required at the + same time, these two action identifiers can be logically OR'ed and passed + in GFVXVIPUPDATE::UpdateOption. +
      #GFVX_VIP_STOP + Disable VIP data feeding + + Stop data feeding through VIP. All other flags and parameters passed in + \a pUpdate are ignored. +
      #GFVX_VIP_AUTO_TRIGER_BLT_OFF + Disable VIP auto-blit + + Stop auto-blit that has been enabled earlier with this function via + #GFVX_VIP_AUTO_TRIGER_BLT. This does not disable VIP data feed. +
      + + This function returns GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED error if destination + surface color format is not supported. Supported destination color formats are - + RGB565, ARGB8888, YUV422, YUV422P, YUV420P and YUV420PA. + + @see GFVXVIPUPDATE, GFVxVIPSetVIP() +*/ +GF_RETTYPE GFVxVIPUpdate(GFVxHandle VxHandle, + PGFVXVIPUPDATE pUpdate); + +/** Manipulate GPIO signals on VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param gpio (#GFVX_VIP_GPIO_TYPE) Signal (pin) to manipulate + @param operation (NvU32) Operation type, one of: + + + + + + + + + + + + + + + + + + Get output data. +
      #GF_GPIO_SET_INPUT_ENABLEInput enable set to 1
      #GF_GPIO_CLR_INPUT_ENABLEInput enable clr to 0.
      #GF_GPIO_GET_INPUT_ENABLEGet input enable.
      #GF_GPIO_SET_OUTPUT_ENABLEOutput enable set to 1.
      #GF_GPIO_CLR_OUTPUT_ENABLEOutput enable clr to 0.
      #GF_GPIO_GET_OUTPUT_ENABLEGet output enable.
      #GF_GPIO_SET_DATAOutput data set to 1.
      #GF_GPIO_CLR_DATAOutput data clr to 0.
      #GF_GPIO_GET_DATA
      + @param pGPIOStatus (#PGFGPIOSTATUS) Pointer to #GFGPIOSTATUS structure + returning pin status + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function manipulates the GPIO signals on the video input port (VIP). + The supported operations are clearing to 0, setting to 1, and getting the + status of the input enable, output enable, and data bits. + + @see GFGPIOSTATUS, GFVX_VIP_GPIO_TYPE +*/ +GF_RETTYPE GFVxVIPGPIO(GFVxHandle VxHandle, + GFGPIOPin gpio, + NvU32 operation, + PGFGPIOSTATUS pGPIOStatus); + +/** VxAPI component-level interrupt control. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param IntType (#GFVX_INTERRUPT_TYPE) VxAPI interrupt type + @param op (#GFVX_INTERRUPT_OPERATION_TYPE) VxAPI interrupt operation + @param pData (void*) Pointer to input or output data block, depending + on interrupt type and operation + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GFVX_ERROR_NO_SUPPORT Operation not supported + + Interpretation of the datablock passed with \a pData depends on the + interrupt operation. The following operations (parameter op) + are defined for this call, + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_INTERRUPT_ENABLEEnable interrupt/status assertion for interrupt type \a IntType. + \a pData is ignored. +
      #GFVX_INTERRUPT_DISABLEDisable interrupt/status assertion for interrupt type \a IntType. + \a pData is ignored. +
      #GFVX_INTERRUPT_DISABLEClear interrupt/status assertion for interrupt type \a IntType. + \a pData is ignored. +
      #GFVX_INTERRUPT_QUERY_STATUSQuery for interrupt/status assertion for interrupt type \a IntType. + + Interpretation of associated data block \a pData: +
      +        NvU32 Interrupt/status assertion state, one of:
      +              GF_INTERRUPT_ON_STATUS_TRUE = asserted
      +              GF_INTERRUPT_ON_STATUS_FALSE = not asserted
      +        
      +
      #GFVX_INTERRUPT_SET_Y_FIFO_THRESHOLD,
      + #GFVX_INTERRUPT_GET_Y_FIFO_THRESHOLD +
      Set or get DMA FIFO threshold value that controls interrupt/status + assertion for interrupt type #GFVX_Y_FIFO_THRESHOLD_INTR. If the + number of filled locations in the Y-FIFO is greater or equal + than the programmed value, #GFVX_Y_FIFO_THRESHOLD_INTR is asserted. + Note that the threshold value must not be changed within a frame. + + Parameter \a IntType is ignored. + + Interpretation of associated data block \a pData: +
      +        NvU32 Y-FIFO threshold value in range 0..31
      +        
      +
      #GFVX_INTERRUPT_SET_V_COUNTER_THRESHOLD,
      + #GFVX_INTERRUPT_GET_V_COUNTER_THRESHOLD +
      Set or get threshold value that controls interrupt/status assertion + for interrupt type #GFVX_VERTICAL_COUNTER_THRESHOLD_INTR. If the + vertical scanline position for data from parallel video input is + greater or equal than the programmed value, + #GFVX_VERTICAL_COUNTER_THRESHOLD_INTRis asserted. + + Parameter \a IntType is ignored. + + Interpretation of associated data block \a pData: +
      +        NvU32 Vertical counter threshold value in range 0..4095
      +        
      +
      #GFVX_INTERRUPT_GET_ALL_STATUSGet VI interrupt status bitmask. + + Parameter \a IntType is ignored. + + Interpretation of associated data block \a pData: +
      +        NvU32 Interrupt status bitmask,
      +              Logically OR'ed combination of:
      +              #GFVX_VID0PIN_RISING_EDGE_INTR
      +              #GFVX_VID1PIN_RISING_EDGE_INTR
      +              #GFVX_VID2PIN_RISING_EDGE_INTR
      +              #GFVX_VID3PIN_RISING_EDGE_INTR
      +              #GFVX_VID4PIN_RISING_EDGE_INTR
      +              #GFVX_VID5PIN_RISING_EDGE_INTR
      +              #GFVX_VID6PIN_RISING_EDGE_INTR
      +              #GFVX_VID7PIN_RISING_EDGE_INTR
      +              #GFVX_VERTICAL_COUNTER_THRESHOLD_INTR
      +              #GFVX_VHSYNC_RISING_INTR
      +              #GFVX_VVSYNC_RISING_INTR
      +              #GFVX_VIDEO_IN_FIELD_DATA_RECV_INTR
      +              #GFVX_EARLY_VIDEO_INTR
      +              #GFVX_Y_FIFO_THRESHOLD_INTR
      +        
      +
      #GFVX_INTERRUPT_CLEAR_ON_ALL_STATUSClear VI interrupt assertions. + + Parameter \a IntType is ignored. + + Interpretation of associated data block \a pData: +
      +        NvU32 Interrupt status bitmask,
      +              set bit   = clear this interrupt assertion
      +              unset bit = leave unchanged
      +
      +              Valid bits which can be logically OR'ed:
      +              #GFVX_VID0PIN_RISING_EDGE_INTR
      +              #GFVX_VID1PIN_RISING_EDGE_INTR
      +              #GFVX_VID2PIN_RISING_EDGE_INTR
      +              #GFVX_VID3PIN_RISING_EDGE_INTR
      +              #GFVX_VID4PIN_RISING_EDGE_INTR
      +              #GFVX_VID5PIN_RISING_EDGE_INTR
      +              #GFVX_VID6PIN_RISING_EDGE_INTR
      +              #GFVX_VID7PIN_RISING_EDGE_INTR
      +              #GFVX_VERTICAL_COUNTER_THRESHOLD_INTR
      +              #GFVX_VHSYNC_RISING_INTR
      +              #GFVX_VVSYNC_RISING_INTR
      +              #GFVX_VIDEO_IN_FIELD_DATA_RECV_INTR
      +              #GFVX_EARLY_VIDEO_INTR
      +              #GFVX_Y_FIFO_THRESHOLD_INTR
      +        
      +
      + + @see GFVX_INTERRUPT_TYPE, GFVX_INTERRUPT_OPERATION_TYPE, + GFVxInterruptHandler() +*/ +GF_RETTYPE GFVxInterruptControl(GFVxHandle VxHandle, + GFVX_INTERRUPT_TYPE IntType, GFVX_INTERRUPT_OPERATION_TYPE op, + void * pData); + +/** Get information about a feature of the VxAPI. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param aid (NvU32) Attribute type identifier, see table. + @param pAttr (NvU32*) Returns 32 bit attribute value, see attribute + type documentation for interpretation + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + + + + + + + +
      \b Attribute \b Direction \b Synopsis
      #GFVX_ATTR_VIDEO_BUFgetVideo input interrupt status
      + + @see GFVxSetAttribute() +*/ +GF_RETTYPE GFVxGetAttribute(GFVxHandle VxHandle, NvU32 aid, NvU32 *attr); + +/** Reset VI to a reset state. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +GF_RETTYPE GFVxReset(GFVxHandle); + +/** This function waits until the next camera vsync has occurred. + It is implemented with interrupt mode. Therefore, it assumes that + interrupt platform has already supported or taken care, + otherwise it will wait forever for interrupt event + + @param VxHandle (#GFVxHandle) Handle to VxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +GF_RETTYPE GFVxWaitCameraVSync(GFVxHandle); + +/** This function ensures synchronization between StretchBlt operations and others + modules operations. + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + When several modules share the same channel (like SB,JxDec,MxDec), + it may be necessary to synchronize the command flow with the StretchBlt (SB) + module execution. Putting a GFVxBltNotBusy() call after a SB operation ensures + that commands which follow the SB command are executed after full completion + of the SB command. + + As opposed to GFVxBltWaitNotBusy(), this function doesn't block the CPU thread. + stretchblt engine may not be idle when returning from the function. Control returns + to the CPU right after a wait command is placed in the stretchblt engine command FIFO. + The GoForce hardware begins executing the commands following the StretchBlt engine idle + command only after the stretchblt engine becomes idle. + + @see GFVxBltWaitNotBusy() +*/ +GF_RETTYPE GFVxBltNotBusy(GFVxHandle VxHandle); + +/** This function checks whether the stretchblt engine is busy or idle. + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The function will wait until the stretchblt engine is idle. For example, if you want + to stretchblt to the frame buffer but the stretchblt engine is busy the function can + be used to wait until it is idle. + + As opposed to GFVxBltNotBusy(), this function blocks the CPU thread while waiting for + the stretchblt engine to become idle. + + @see GFVxBltNotBusy() + +*/ +GF_RETTYPE GFVxBltWaitNotBusy(GFVxHandle VxHandle); + +/** This function sets the current state stretchblt color space converion (CSC) + coefficients that will be programmed to GPU after calling GFVxBlt to do + YUV color space conversion to RGB. + How to use this routine: + - GFVxBltGetCSCCoeff() to get default YUV CSC coefficients, save them + - GFVxBltSetCSCCoeff() to change to new YUV CSC coefficients + - GFVxBlt() to stretchblt image with your new YUV CSC coefficients to RGB, + then done whatever + - GFVxBltSetCSCCoeff() to restore back default YUV CSC coefficients + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + @param pCoef (GFVXCSCCOEF*) Pointer to #GFVXCSCCOEF structure + @param option (NvU32) Option type, one of: +
      +                - #GFVX_SET_CSC_USE_CCIR601_RANGE -- Use CCIR601 range.
      +                  This option will ignore parameter pCoef. It will use
      +                  pre-defined CSC CCIR601 coefficients values.
      +                - #GFVX_SET_CSC_USE_FULL_RANGE -- Use color full range.
      +                  This option will ignore parameter pCoef. It will use
      +                  pre-defined CSC full range coefficients values.
      +                - #GFVX_SET_CSC_USE_USER_DEFINED_RANGE -- Use user defined range.
      +                  This option will require parameter pCoef. It will use
      +                  CSC coefficients values provided from pCoef.
      +                
      + @param sbMode (#GFVXBLTMODE) StretchBlt mode, one of: +
      +                - GFVX_BLT_FULL_MODE: Host full frame stretchblt trigger
      +                - GFVX_BLT_PARTIAL_MODE: Host partial frame stretchblt trigger
      +                - GFVX_BLT_AUTO_VI_MODE: Auto stretchblt trigger from VI
      +                
      + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFVxBltSetCSCCoeff(GFVxHandle VxHandle, + GFVXCSCCOEF *pCoef, + NvU32 option, + GFVXBLTMODE sbMode); + +/** This function sets the current state VI color space converion (CSC) + coefficients that will be programmed to GPU after calling GFVxVIPUpdate + to do YUV color space conversion to RGB. + How to use this routine: + - GFVxVIPGetCSCCoeff() to get default YUV CSC coefficients, save them + - GFVxVIPSetCSCCoeff() to change to new YUV CSC coefficients + - GFVxVIPUpdate() to preview image with your new YUV CSC coefficients to RGB + - GFVxVIPSetCSCCoeff() to restore back default YUV CSC coefficients + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + @param pCoef (#GFVXCSCCOEF*) Pointer to #GFVXCSCCOEF structure + @param option (NvU32) Option type, one of: +
      +                - #GFVX_SET_CSC_USE_CCIR601_RANGE -- Use CCIR601 range.
      +                  This option will ignore parameter pCoef. It will use
      +                  pre-defined CSC CCIR601 coefficients values.
      +                - #GFVX_SET_CSC_USE_FULL_RANGE -- Use color full range.
      +                  This option will ignore parameter pCoef. It will use
      +                  pre-defined CSC full range coefficients values.
      +                - #GFVX_SET_CSC_USE_USER_DEFINED_RANGE -- Use user defined range.
      +                  This option will require parameter pCoef. It will use
      +                  CSC coefficients values provided from pCoef.
      +                
      + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFVxVIPSetCSCCoeff(GFVxHandle VxHandle, GFVXCSCCOEF *pCoef, NvU32 option); + +/** This function gets the current state stretchblt color space conversion (CSC) + coefficients + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + @param pCoef (#GFVXCSCCOEF*) Pointer to #GFVXCSCCOEF structure + @param sbMode (#GFVXBLTMODE) StretchBlt mode, one of: + - GFVX_BLT_FULL_MODE: Host full frame stretchblt trigger + - GFVX_BLT_PARTIAL_MODE: Host partial frame stretchblt trigger + - GFVX_BLT_AUTO_VI_MODE: Auto stretchblt trigger from VI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFVxBltGetCSCCoeff(GFVxHandle VxHandle, GFVXCSCCOEF *pCoef, GFVXBLTMODE sbMode); + +/** This function gets the current state VI color space conversion (CSC) coefficients + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + @param pCoef (#GFVXCSCCOEF*) Pointer to #GFVXCSCCOEF structure + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFVxVIPGetCSCCoeff(GFVxHandle VxHandle, GFVXCSCCOEF *pCoef); + +/** @page pageVxOverview VxAPI Overview + + The GFVxAPI is an abstraction layer for both the Video Scalar (StretchBlt) + and the Video Input (VI) module. The Video Scalar provides color space + conversion (CSC) and smooth scaling of video. The VI module, which connects + to the Video Input Port (VIP), accepts data from the VIP or the host CPU + through a FIFO mechanism. + + Video data, either decimated or not, can be sent from the VI to JPEG or + MPEG encoder, and at the same time can go to memory through CSC for previewing, + again either decimated or not. If a decimator is used in both the preview and + the encoder paths, it has to have same decimation factor. + + Video data can also be sent to EPP. RGB565, RGB444 and RGB888 data goes directly + and YUV422 data, pre or post decimated, is first converted to YUV444 by VI + before sending to EPP. + + If data coming from VIP is in Bayer format, VI first sends this data to ISP. + After processing, ISP returns YUV444 data to VI. VI converts output of ISP to + YUV422 before sending it to core for decimation or to memory or both. + + There are also options to crop, mirror and/or flip video data. + + The Video Scalar and the VI module accept YUV (4:2:2 or 4:2:0) and + RGB (565) data as input. YUV data can be converted to YUV planar data or + RGB data (RGB:565 for all processors, and RGB:888 or ARGB:8888 for GoForce + 3D 4800). RGB data can be scaled, but cannot be converted to YUV, for all + processors up to the GoForce 3D 4800. + + @section pageVxOverview1 Video Sources + + The video source for the VI module can be the host CPU or a camera + connected to the VIP. The video source for the Video Scalar can be the + video memory surface or the output of the JPEG or MPEG decoder through a + circular buffer. The GFVxAPI functions that deal only with the VIP have VIP + in their function names. + + @section pageVxOverview2 Video Camera Interface + + Usually a video camera connected through the VIP generates YUV 422 data + (CCIR656 format) which can be encoded by the NVIDIA GPU. Some cameras + generate JPEG-encoded images directly, and the GFSDK can be configured to + accept those JPEG-encoded bit streams. + + To control the JPEG input stream, VIP of newer NVIDIA GPUs supports the + following camera interface protocols for variably sized bitstream data: + - Type A interface: VHSync and VVSync length can be variable, and + VVClk should be kept running. (SC12 only) + - Type B interface: VHSync and VVSync length can be variable, and + VVClk can be stopped during the image transfer period. (SC12 only) + - Type C interface: VHSync and VVSync length are fixed, and VVClk + should be kept running. The camera can insert 0xff in the image as + padding. + + @section pageVxOverview3 Video Coordinate Systems (Regular and Rotated) + + A destination coordinate is always the same as a screen coordinate. The + source coordinate stays the same, even if there is rotation. +*/ + +/** @page pageVxAppNotes VxAPI Application Notes + + @section pageVxAppNotes1 Programming Sequence + + The easiest way to learn the VxAPI is by referring to the demonstration + application source code that come with the GFSDK package. A new application + can be started by creating a project at the same directory level as the + demo application source directory. This way the same directory tree + structure can be maintained. The general sequence for programming the + VxAPI is as follows: + + -# Make sure that the build project or file has the right paths to the + library and header files. Use relative directory addressing if possible. + The GFSDK/Inc directory must be included. + -# Include GFVx.h in the source file. This header is all that is needed to + access the exposed API functions. + -# Call GFRmOpen() before any other GFSDK functions (including the VxAPI). + -# Use the handle returned from the Resource Manager in the previous step + to call GFRmComponentGet() with #GF_VXAPI as the ComponentType in the + #GFRMCOMPONENT structure. The returned handle is the one to use + throughout all VxAPI calls. + -# To better utilize VxAPI functions, it is a good idea to call + GFVxGetProperty() to determine the version that you are using and the + available video memory. + -# Make calls to the appropriate VxAPI functions. Always remember to pass + the same #GFVxHandle returned from GFRmComponentGet(). + -# When all the VxAPI calls are completed, call GFRmComponentRelease(). + -# When exiting the application, call RmClose() to release everything + associated with the GFSDK. +*/ + +//////////////////Raw Capture Defination ////////////////////////// +/** Descriptor for raw data fetch buffers. + This structure describes a buffer and its fill status for Raw YUV transfered + from RDMA to the application. + It is used with GFVxRawCapture() and GFVxRawCaptureFetchImage() + in either polling or callback data fetch mode. + + @see GFVxCapture(), GFVxRawCaptureFetchImage() +*/ +typedef struct _GFVX_BUF { + NvU8 *pBuf; /**< Pointer to the buffer */ + NvU32 bufSize; /**< Size of the buffer in bytes */ + NvU32 nBytesCaptured; /**< Number of bytes captured, + app initializes to 0 + */ +} GFVX_BUF, *PGFVX_BUF; + + +/** Image source/target dimensions and data source for Raw data capturing. + + This structure is passed as parameter to GFVxRawCaptureStart() and describes + data source, source cropping rectangle and destination image size. + + @see GFVxRawCaptureStart() +*/ +typedef struct _GFVXRAWINFO +{ + PGFRMSURFACE pSrcSurf;/**< Surface to encode, + NULL for camera. + */ + PGFRECT pSrcRect; /**< Source image area need to capture */ + NvU32 DestWidth; /**< Final output data width */ + NvU32 DestHeight; /**< Final output data height */ + NvU32 uiOptions; /**< Bitmask of flags to control capturing + +
      + */ + NvU32 Error; /**< Returns detailed error code on GFVxRawCaptureStart() failure + + + + + + + +
      #GF_CAPT_ERROR_VIDEO_MEMORY_NOT_BIG_ENOUGHNot enough free video memory, try to release + unnecessary video surfaces
      #GF_CAPT_ERROR_WRONG_CONFIGWrong input parameters, for example srcRect + size greater than pSrcSurf dimensions
      #GF_CAPT_ERROR_NO_CALLBACKNo callback function available
      + */ + NvU32 colorFormat; +} GFVXRAWINFO, *PGFVXRAWINFO; + +/** GFVXRAWINFO uiOptions: +*/ +#define RAWCAPTURE_ATTR_RAW_DATA 0x00000010 +#define RAWCAPTURE_ATTR_RAW_JPEG_CAPTURE 0x00000020 +#define RAWCAPTURE_ATTR_RAW_DATA_STREAM 0x00000030 + +/** Raw data capture APIs +*/ +GF_RETTYPE GFVxRawCaptureStart( GFVxHandle VxHandle, + PGFVXRAWINFO pStart); + +GF_RETTYPE GFVxRawCaptureSetupInterrupt(GFVxHandle VxHandle, + void (*Inter)(void *), void *IPara); + +GF_RETTYPE GFVxRawCapture (GFVxHandle VxHandle, + PGFVX_BUF aBuf, NvU32 nBuf, NvU32 *pStatus ); + +GF_RETTYPE GFVxRawCaptureFetchImage (GFVxHandle pVx, + PGFVX_BUF aBuf, NvU32 nBuf, NvU32 *pStatus ); + +GF_RETTYPE GFVxRawCaptureEnd( GFVxHandle pVx ); + +//uiFrameStatus; + +/** Raw Capture data fetch status code: All data of the current frame was fetched. + @see GFVxRawCaptureFetchImage(), GFVxRawCapture() +*/ +#define RAWCAPTURE_DATA_COMPLETE 0x1 + +/** Raw Capture data fetch status code: Data was fetched only partially. + The application should make more calls to GFVxRawCaptureFetchImage() to fetch + the rest. + @see GFVxRawCaptureFetchImage(), GFVxRawCapture() +*/ +#define RAWCAPTURE_MORE_FETCH 0x2 + +/** Raw Capture data fetch status code: New frame was captured and is ready to + fetch. + @see GFVxRawCaptureFetchImage(), GFVxRawCapture() +*/ +#define RAWCAPTURE_NEW_FRAME 0x8 + +/** Raw Capture data fetch status code: Time out error occured while output data is fetching. + fetch. + @see GFVxRawCaptureFetchImage(), GFVxRawCapture() +*/ +#define RAWCAPTURE_TIME_OUT 0x10 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFVX_H__ */ + + diff --git a/Start_WM/test6/inc/GFVxError.h b/Start_WM/test6/inc/GFVxError.h new file mode 100755 index 00000000..7f81f255 --- /dev/null +++ b/Start_WM/test6/inc/GFVxError.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFVxError.h + GFVxAPI error codes +*/ + +#ifndef __GFVXERROR_H__ +#define __GFVXERROR_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define GFVX_ERROR_GET_COMPONENT (GFVX_ERROR | 0x00000001L) +/** GFVxAPI error code: Function not supported. */ +#define GFVX_ERROR_NO_SUPPORT (GFVX_ERROR | 0x00000002L) +#define GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED (GFVX_ERROR | 0x00000003L) +#define GFVX_ERROR_SURFACETYPE_NOT_SUPPORTED (GFVX_ERROR | 0x00000004L) +#define GFVX_ERROR_ILLEGAL_ALPHA_VALUE (GFVX_ERROR | 0x00000005L) +#define GFVX_ERROR_ILLEGAL_BAYER_VALUES (GFVX_ERROR | 0x00000006L) +#define GFVX_ERROR_ILLEGAL_PARAMETER (GFVX_ERROR | 0x00000007L) +#define GFVX_ERROR_DRIVER_NOT_SUPPORTED (GFVX_ERROR | 0x00000008L) +#define GFVX_ERROR_FLAG_NOT_SUPPORTED (GFVX_ERROR | 0x00000009L) +#define GFVX_ERROR_FAIL_ALLOCATE_MEMORY (GFVX_ERROR | 0x0000000AL) +#define GFVX_ERROR_ILLEGAL_VALUE (GFVX_ERROR | 0x0000000BL) + +#ifdef __cplusplus +} +#endif + +#endif // __GFVXERROR_H__ + + + diff --git a/Start_WM/test6/inc/GFVxScr.h b/Start_WM/test6/inc/GFVxScr.h new file mode 100755 index 00000000..394a33ef --- /dev/null +++ b/Start_WM/test6/inc/GFVxScr.h @@ -0,0 +1,311 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#if !defined (__GFVXSCR_INC__) +#define __GFVXSCR_INC__ + +/** VxAPI GFVXVIPINFO::Flag flagbit: 8-bit/clock video data. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_PARALLEL_INPUT 0x00000001 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Serial input. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_SERIAL_INPUT 0x00000002 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VHSYNC and VVSYNC in the data stream. + If this flag is set, vertical and horizontal sync for the camera picture + is contained in the data stream going into the data port of the VIP. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_HVSYNC_IN_STREAM 0x00000004 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Camera VHSYNC asserted by external signal. + If this flag is set, vertical and horizontal sync for the camera picture + is asserted to the GoForce chip by external signals, usually coming from + the camera chip. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_EXTERNAL_VHSYNC 0x00000008 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Camera VHSYNC generated by GoForce chip. + If this flag is set, vertical and horizontal sync is generated by the + GoForce chip, and not contained in the data stream. The following members + of GFVXVIPINFO have to be set to define the timing: + - GFVXVIPINFO::VHPulseWidth + - GFVXVIPINFO::VHPulsePeriod + - GFVXVIPINFO::VVPulseWidth + - GFVXVIPINFO::VVPulsePeriod + - GFVXVIPINFO::VVDelay + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_INTERNAL_VHSYNC 0x00000010 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VCLK generated externally. + If this flag is set, camera VCLK is provided from an external source, + and VLCK will be selected as clock source for VI module. + @see GFVXVIPINFO, GFVxVIPSetVIP(), GFVX_VIP_EXTERNAL_VCLK_PRESERVE_CLKSEL +*/ +#define GFVX_VIP_EXTERNAL_VCLK 0x00000020 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VCLK generated by GoForce chip. + If this flag is set, camera VCLK is provided by the GoForce chip. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_INTERNAL_VCLK 0x00000040 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Detect field 0 or 1, will not work for + internal VHSYNC (#GFVX_VIP_INTERNAL_VHSYNC). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_DETECT_FIELD 0x00000080 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Horizontal flip. + Flip VIP image horizontally. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB_H_FLIP 0x00000100 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Vertical flip. + Flip VIP image vertically. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB_V_FLIP 0x00000200 + +/** VxAPI GFVXVIPINFO::Flag flagbit: CPU feeds image to VIP. + This flag indicates to the VIP, that image data is fed from the + host interface. + @see GFVXVIPINFO, GFVxVIPSetVIP(), GFVxVIPFeedImage() +*/ +#define GFVX_VIP_HOST_IMAGE 0x00000400 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Change the default timing for VHSYNC and + VCLK. If this flag is set, VHSYNC and VCLK timing characteristics such as + polarity, active edge, serial frame polarity, size, field info are + overridden with GFVxVIPSetVIP() by the parameters passed in + GFVXVIPINFO::NewTiming. + + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CHANGE_DEFAULT_TIMING 0x00000800 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Camera master clock provided by GoForce + chip. When this flag is set, GFVXVIPINFO::MClockFreq must be set to the + ideal clock which the camera wants. Internally the best matching frequency + is provided to the camera. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ASK_FOR_MCLOCK 0x00001000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VIP input type A interface. + @see GFVXVIPINFO, GFVxVIPSetVIP(), pageVxOverview2 +*/ +#define GFVX_VIP_TYPE_A 0x00002000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VIP input type B interface. + @see GFVXVIPINFO, GFVxVIPSetVIP(), pageVxOverview2 +*/ +#define GFVX_VIP_TYPE_B 0x00004000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VIP input type C interface. + @see GFVXVIPINFO, GFVxVIPSetVIP(), pageVxOverview2 +*/ +#define GFVX_VIP_TYPE_C 0x00008000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Camera is running at type C interface + and do not remove the 0xFF, 0x02 sequence. + @see GFVXVIPINFO, GFVxVIPSetVIP(), pageVxOverview2 +*/ +#define GFVX_VIP_TYPE_C_RAW 0x00010000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Enable destination byte swap for YUV/RGB + data written to preview surface. + + This flag enables byte swap for 32 bit words of data coming from VIP and + going to a target RGB or YUV422 surface. The sequence of 4 byte groups in + (LSB)b0 b1 b2 b3(MSB) order is swapped to + (LSB)b1 b0 b3 b2(MSB). + + This flag only affects data written to a preview surface, i.e. VIP image + capture enabled with GFVxVIPSetVIP() and GFVxVIPUpdate(). It does not + affect raw data going to the JPEG/MPEG encoder. + + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_DEST_BYTE_SWAP 0x00020000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VI output without rotation + Rotate VIP image 0 degree + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ROTATE_0 0x00040000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VI output with 90 degree rotation + Rotate VIP image 90 degree + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ROTATE_90 0x00080000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VI output with 180 degree rotation + Rotate VIP image 180 degree + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ROTATE_180 0x00100000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VI output with 270 degree rotation + Rotate VIP image 270 degree + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ROTATE_270 0x00200000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: RGB565 input to EPP. + @todo clarify + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB565 0x00400000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: RGB888 input to EPP. + @todo clarify + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB888 0x00800000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: RGB444 input to EPP. + @todo clarify + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB444 0x01000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Preserve VI clock source but enable external VLCK pad. + This flag can be used in combination with GFVX_VIP_EXTERNAL_VCLK to enable + an external clock on VLCK, but keep the VI module clocksource. + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP(), GFVX_VIP_EXTERNAL_VCLK +*/ +#define GFVX_VIP_EXTERNAL_VCLK_PRESERVE_CLKSEL 0x02000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VIP input type D interface. + @version SC17 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_TYPE_D 0x04000000 + +#define GFVX_VIP_CSI_ENABLE 0x08000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Bypass any manipulation on internal master + clock generation output pin. + + This flag is mutually exclusive to #GFVX_VIP_PRE_GENERATE_MCLOCK and + #GFVX_VIP_ASK_FOR_MCLOCK. + + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_BYPASS_MCLOCK_PIN 0x20000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Bypass any manipulation on VCLK, VHSYNC, + and VID[7:0] pins. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_BYPASS_NON_MCLOCK_PINS 0x40000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Pre-generation of master clock. + Useful for scanning the I2C bus for a camera. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_PRE_GENERATE_MCLOCK 0x80000000 + +/** + Bypass ISP mode. +*/ +#define GFVX_VIP_BYPASS_ISP 0x10000000 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Parallel data latched at falling edge + of VCLK (default is rising edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_PDL_FALLING_VCLK 0x00000001 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Serial data lacthed at rising edge of + VCLK (default is falling edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_SDL_RISING_VCLK 0x00000001 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VHSYNC active low (default is active + high). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VHSYNC_ACTIVE_LOW 0x00000002 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VVSYNC active low (default is active + high). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VVSYNC_ACTIVE_LOW 0x00000004 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VHSYNC active leading edge (default + is trailing edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VHSYNC_ACTIVE_EDGE_LEAD 0x00000008 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VVSYNC active leading edge (default + is trailing edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VVSYNC_ACTIVE_EDGE_LEAD 0x00000010 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Serial video frame sync active low, + falling edge indicates start of data frame (default is active high, rising + edge indicates start of data frame). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_SFRAME_ACTIVE_LOW 0x00000020 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Serial video input is 16 bit per + frame (default is 8 bit per frame). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_SFRAME_SIZE_16 0x00000040 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Field 0 is bottom/even field + (default is top/odd field). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_FILED_0_BOTTOM 0x00000080 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VCLK output from GoForce chip active + low (default is active high). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VCLK_OUTPUT_ACTIVE_LOW 0x00000100 + +#define GFVX_VIP_VHSYNC_ACTIVE_LOW_RESET 0x00000200 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VVSYNC reset active low (default is active + high). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VVSYNC_ACTIVE_LOW_RESET 0x00000400 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VHSYNC reset active leading edge (default + is trailing edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ + + +#endif diff --git a/Start_WM/test6/inc/cpuopsys.h b/Start_WM/test6/inc/cpuopsys.h new file mode 100755 index 00000000..daa89a73 --- /dev/null +++ b/Start_WM/test6/inc/cpuopsys.h @@ -0,0 +1,309 @@ + +/*! \brief + * Define compile time symbols for CPU type and operating system type. + * This file should only contain preprocessor commands so that + * there are no dependencies on other files. + * + * cpuopsys.h + * + * Copyright (c) 2001, Nvidia Corporation. All rights reserved. + */ + +/*! + * Uniform names are defined for compile time options to distinguish + * CPU types and Operating systems. + * Distinctions between CPU and OpSys should be orthogonal. + * + * These uniform names have initially been defined by keying off the + * makefile/build names defined for builds in the OpenGL group. + * Getting the uniform names defined for other builds may require + * different qualifications. + * + * The file is placed here to allow for the possibility of all driver + * components using the same naming convention for conditional compilation. + */ + +#ifndef __cpuopsys_h_ +#define __cpuopsys_h_ + +/*****************************************************************************/ +// Define all OS/CPU-Chip related symbols + +// ***** DOS variations +#if defined(__DJGPP__) +# define NV_DOS +#endif + +// ***** WINDOWS variations +#if defined(_WIN32) || defined(_WIN16) +# define NV_WINDOWS + +# if defined(_WIN32_WINNT) +# define NV_WINDOWS_NT +# elif defined(_WIN32_WCE) +# define NV_WINDOWS_CE +# elif !defined(NV_MODS) +# define NV_WINDOWS_9X +# endif +#endif // _WIN32 || defined(_WIN16) + +// ***** Unix variations +#if defined(__linux__) && !defined(NV_LINUX) +# define NV_LINUX +#endif // defined(__linux__) + +// SunOS + gcc +#if defined(__sun__) && defined(__svr4__) +# define NV_SUNOS +#endif // defined(__sun__) && defined(__svr4__) + +// SunOS + Sun Compiler (named SunPro, Studio or Forte) +#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# define NV_SUNPRO_C +# define NV_SUNOS +# define __FUNCTION__ __func__ +# define NV_OPENGL_THREAD_UNSAFE // XXX To start with +#endif // defined(_SUNPRO_C) || defined(__SUNPRO_CC) + +#if defined(__FreeBSD__) +# define NV_BSD +#endif // defined(__FreeBSD__) + +// XXXar don't define NV_UNIX on MacOSX or vxworks or dos or QNX +#if (defined(__unix__) || defined(__unix) ) && !defined(macosx) && !defined(vxworks) && !defined(__DJGPP__) && !defined(NV_UNIX) && !defined(__QNX__) && !defined(__QNXNTO__)// XXX until removed from Makefiles +# define NV_UNIX +#endif // defined(__unix__) + +#if (defined(__QNX__) || defined(__QNXNTO__)) && !defined(NV_QNX) +# define NV_QNX +#endif + +// ***** Apple variations +#if defined(macintosh) || defined(__APPLE__) +# define NV_MACINTOSH +# if defined(__MACH__) +# define NV_MACINTOSH_OSX +# if !defined(NV_MODS) +# define NV_MACOSX_OPENGL +# endif +# else +# define NV_MACINTOSH_OS9 +# endif +# if defined(__LP64__) +# define NV_MACINTOSH_64 +# endif +#endif // defined(macintosh) + +// ***** VxWorks +// Tornado 2.21 is gcc 2.96 and #defines __vxworks. +// Tornado 2.02 is gcc 2.7.2 and doesn't define any OS symbol, so we rely on +// the build system #defining vxworks. +#if defined(__vxworks) || defined(vxworks) +# define NV_VXWORKS +# if (CPU==PENTIUM) +# define NV_VXWORKS_PENTIUM +# elif (CPU==PPC604) +# define NV_VXWORKS_PPC604 +# endif +#endif + +// ***** Integrity OS +#if defined(__INTEGRITY) +# if !defined(NV_INTEGRITY) +# define NV_INTEGRITY +# endif +#endif + +// ***** Processor type variations +// Note: The prefix NV_CPU_* is taken by \\sw\main\sdk\nvidia\inc\Nvcm.h + +#if ((defined(_M_IX86) || defined(__i386__) || defined(__i386)) && !defined(NVCPU_X86)) // XXX until removed from Makefiles + // _M_IX86 for windows, __i386__ for Linux (or any x86 using gcc) + // __i386 for Studio compiler on Solaris x86 +# define NVCPU_X86 // any IA32 machine (not x86-64) +#endif + +#if defined(_WIN32) && defined(_M_IA64) +# define NVCPU_IA64_WINDOWS // any IA64 for Windows opsys +#endif +#if defined(NV_LINUX) && defined(__ia64__) +# define NVCPU_IA64_LINUX // any IA64 for Linux opsys +#endif +#if defined(NVCPU_IA64_WINDOWS) || defined(NVCPU_IA64_LINUX) || defined(IA64) +# define NVCPU_IA64 // any IA64 for any opsys +#endif + +#if (defined(NV_MACINTOSH) && !(defined(__i386__) || defined(__x86_64__))) || defined(__PPC__) || defined(__ppc) +# ifndef NVCPU_PPC +# define NVCPU_PPC // any PowerPC architecture +# endif +# ifndef NV_BIG_ENDIAN +# define NV_BIG_ENDIAN +# endif +#endif + +#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) +# define NVCPU_X86_64 // any x86-64 for any opsys +#endif + +#if defined(__arm__) && !defined(NVCPU_ARM) +# define NVCPU_ARM +#endif + +#if defined(__XSCALE__) +#define NVCPU_XSCALE // for XSCALE ARM processors +#endif + +#if defined(__SH4__) +# ifndef NVCPU_SH4 +# define NVCPU_SH4 // Renesas (formerly Hitachi) SH4 +# endif +#endif + +// For Xtensa processors +#if defined(__XTENSA__) +# define NVCPU_XTENSA +# if defined(__XTENSA_EB__) +# define NV_BIG_ENDIAN +# endif +#endif + + +// Other flavors of CPU type should be determined at run-time. +// For example, an x86 architecture with/without SSE. +// If it can compile, then there's no need for a compile time option. +// For some current GCC limitations, these may be fixed by using the Intel +// compiler for certain files in a Linux build. + + +#if defined(NVCPU_IA64) || defined(NVCPU_X86_64) +# define NV_64_BITS // all architectures where pointers are 64 bits +#else + // we assume 32 bits. I don't see a need for NV_16_BITS. +#endif + +// NOTE: NV_INT64_OK is not needed in the OpenGL driver for any platform +// we care about these days. The only consideration is that Linux does not +// have a 64-bit divide on the server. To get around this, we convert the +// expression to (double) for the division. +#if (!(defined(macintosh) || defined(vxworks) || defined(__INTEL_COMPILER)) || defined(NV_LINUX)) && !defined(NV_INT64_OK) +#define NV_INT64_OK +#endif + +// For verification-only features not intended to be included in normal drivers +#if defined(NV_MODS) && defined(DEBUG) && !defined(NV_DOS) +#define NV_VERIF_FEATURES +#endif + + +/* + * New, safer family of #define's -- these ones use 0 vs. 1 rather than + * defined/!defined. This is advantageous because if you make a typo, say: + * + * #if NVCPU_IS_BIG_ENDAIN // Oops! Endian is misspelled + * + * ...some compilers can give you a warning telling you that you screwed up. + * The compiler can also give you a warning if you forget to #include + * "cpuopsys.h" in your code before the point where you try to use these + * conditionals. + * + * Also, the names have been prefixed in more cases with "CPU" or "OS" for + * increased clarity. You can tell the names apart from the old ones because + * they all use "_IS_" in the name. + * + * Finally, these can be used in "if" statements and not just in #if's. For + * example: + * + * if (NVCPU_IS_BIG_ENDIAN) x = Swap32(x); + * + * Maybe some day in the far-off future these can replace the old #define's. + */ +#if defined(NV_WINDOWS) +#define NVOS_IS_WINDOWS 1 +#else +#define NVOS_IS_WINDOWS 0 +#endif +#if defined(NV_WINDOWS_CE) +#define NVOS_IS_WINDOWS_CE 1 +#else +#define NVOS_IS_WINDOWS_CE 0 +#endif +#if defined(NV_LINUX) +#define NVOS_IS_LINUX 1 +#else +#define NVOS_IS_LINUX 0 +#endif +#if defined(NV_UNIX) +#define NVOS_IS_UNIX 1 +#else +#define NVOS_IS_UNIX 0 +#endif +#if defined(NV_QNX) +#define NVOS_IS_QNX 1 +#else +#define NVOS_IS_QNX 0 +#endif +#if defined(NV_MACINTOSH) +#define NVOS_IS_MACINTOSH 1 +#else +#define NVOS_IS_MACINTOSH 0 +#endif +#if defined(NV_VXWORKS) +#define NVOS_IS_VXWORKS 1 +#else +#define NVOS_IS_VXWORKS 0 +#endif +#if defined(NV_INTEGRITY) +#define NVOS_IS_INTEGRITY 1 +#else +#define NVOS_IS_INTEGRITY 0 +#endif +#if defined(NVCPU_X86) +#define NVCPU_IS_X86 1 +#else +#define NVCPU_IS_X86 0 +#endif +#if defined(NVCPU_IA64) +#define NVCPU_IS_IA64 1 +#else +#define NVCPU_IS_IA64 0 +#endif +#if defined(NVCPU_X86_64) +#define NVCPU_IS_X86_64 1 +#else +#define NVCPU_IS_X86_64 0 +#endif +#if defined(NVCPU_PPC) +#define NVCPU_IS_PPC 1 +#else +#define NVCPU_IS_PPC 0 +#endif +#if defined(NVCPU_ARM) +#define NVCPU_IS_ARM 1 +#else +#define NVCPU_IS_ARM 0 +#endif +#if defined(NVCPU_SH4) +#define NVCPU_IS_SH4 1 +#else +#define NVCPU_IS_SH4 0 +#endif +#if defined(NVCPU_XTENSA) +#define NVCPU_IS_XTENSA 1 +#else +#define NVCPU_IS_XTENSA 0 +#endif +#if defined(NV_BIG_ENDIAN) +#define NVCPU_IS_BIG_ENDIAN 1 +#else +#define NVCPU_IS_BIG_ENDIAN 0 +#endif +#if defined(NV_64_BITS) +#define NVCPU_IS_64_BITS 1 +#else +#define NVCPU_IS_64_BITS 0 +#endif + +/*****************************************************************************/ + +#endif /* __cpuopsys_h_ */ diff --git a/Start_WM/test6/inc/gfrm_clock_ids.h b/Start_WM/test6/inc/gfrm_clock_ids.h new file mode 100755 index 00000000..bd0d1209 --- /dev/null +++ b/Start_WM/test6/inc/gfrm_clock_ids.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file clock_ids.h + Clock List & string names +*/ + +GFRM_CLOCK(OSC,"osc") +GFRM_CLOCK(ROSC,"rosc") +GFRM_CLOCK_PLL(PLL1,"pll1") +GFRM_CLOCK_PLL(PLL2,"pll2") +GFRM_CLOCK(REFCLK0,"refclk0") +GFRM_CLOCK(REFCLK1,"refclk1") +GFRM_CLOCK(REFCLK2,"refclk2") +GFRM_CLOCK_PLL(PLL3,"pll3") + diff --git a/Start_WM/test6/inc/gfrm_module_ids.h b/Start_WM/test6/inc/gfrm_module_ids.h new file mode 100755 index 00000000..fb644b13 --- /dev/null +++ b/Start_WM/test6/inc/gfrm_module_ids.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file module_ids.h + Module List & string names +*/ + + +GFRM_MODULE(HOST1X, "host1x") +GFRM_MODULE(MPD,"mpd") +GFRM_MODULE(ME,"me") +GFRM_MODULE(JPEGE,"jpege") +GFRM_MODULE(VI,"vi") +GFRM_MODULE(EPP,"epp") +GFRM_MODULE(ISP,"isp") +GFRM_MODULE(DSPCORE,"dspcore") +GFRM_MODULE(GR2D,"gr2d") +GFRM_MODULE(GR3D,"gr3d") +GFRM_MODULE(DISPLAY,"display") +GFRM_MODULE(I2S,"i2s") +GFRM_MODULE(IC,"ic") +GFRM_MODULE(SD,"sd") +GFRM_MODULE(MC,"mc") +GFRM_MODULE(EMC,"emc") +GFRM_MODULE(DSP,"dsp") +GFRM_MODULE(EFUSE,"efuse") +GFRM_MODULE(AUDIO,"audio") +GFRM_MODULE(TVO,"tvo") +GFRM_MODULE(DISPLAYB,"displayb") +GFRM_MODULE(I2SB,"i2sb") +GFRM_MODULE(DSPB,"dspb") +GFRM_MODULE(CVE,"cve") +GFRM_MODULE(DSPBCORE,"dspbcore") +GFRM_MODULE(CSI,"csi") +GFRM_MODULE(TVDAC,"tvdac") +GFRM_MODULE(APB,"apb") +GFRM_MODULE(RESET, "reset") +GFRM_MODULE(SPROM, "sprom") +GFRM_MODULE(GPIO, "gpio") +GFRM_MODULE(CLK, "clk") +GFRM_MODULE(UART, "uart") +GFRM_MODULE(UART2, "uart2") +GFRM_MODULE(UART3, "uart3") +GFRM_MODULE(TIMER, "timer") +GFRM_MODULE(KBC, "kbc") +GFRM_MODULE(DMA, "dma") +GFRM_MODULE(USB, "usb") +GFRM_MODULE(CEATA, "ceata") +GFRM_MODULE(FLASH, "flash") +GFRM_MODULE(XHOST, "xhost") diff --git a/Start_WM/test6/inc/nvboard.h b/Start_WM/test6/inc/nvboard.h new file mode 100755 index 00000000..9277a904 --- /dev/null +++ b/Start_WM/test6/inc/nvboard.h @@ -0,0 +1,619 @@ +/* + * Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef NVBOARD_H +#define NVBOARD_H + +#include "nvcommon.h" +#include "nverror.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** NvBoard - Board Support Package + + NvBoard is designed to decouple customer platform specifics from generic + binary only drivers. + + The interface must be thread-safe. + */ + +typedef struct NvBoardAperture_t +{ + /* Physical Address */ + NvPhysAddr address; + + /* Size of Aperture */ + NvU32 size; +} NvBoardAperture; + +typedef struct NvBoardApertureIO_t +{ + void ( *Write8 )( void *pAddress, NvU8 data ); + void ( *Write16 )( void *pAddress, NvU16 data ); + void ( *Write32 )( void *pAddress, NvU32 data ); + void ( *Write64 )( void *pAddress, NvU64 data ); + NvU8 ( *Read8 )( void *pAddress ); + NvU16 ( *Read16 )( void *pAddress ); + NvU32 ( *Read32 )( void *pAddress ); + NvU64 ( *Read64 )( void *pAddress ); +} NvBoardApertureIO; + +typedef struct NvBoardApertures_t +{ + NvBoardAperture hostInterface; + + /* pIO is null unless the apertures cannot be dereferenced */ + NvBoardApertureIO *pIO; +} NvBoardApertures; + +typedef enum +{ + /* Bus type A */ + NvBoardBusType_A, + + /* Bus type C */ + NvBoardBusType_C, + + NvBoardBusType_Forceword = 0x7fffffff, +} NvBoardBusType; + +typedef enum +{ + /* Direct Addressing */ + NvBoardBusAddressing_Direct, + + /* Indirect Addressing */ + NvBoardBusAddressing_Indirect, + + NvBoardBusAddressing_Forceword = 0x7fffffff, +} NvBoardBusAddressing; + +typedef enum +{ + /* 16-bit bus */ + NvBoardBusWidth_16, + + /* 32-bit bus */ + NvBoardBusWidth_32, + + NvBoardBusWidth_Forceword = 0x7fffffff, +} NvBoardBusWidth; + +typedef enum +{ + /* Handshake mode. */ + NvBoardBusMode_Handshake, + + /* Fixed cycle mode. */ + NvBoardBusMode_FixedCycle, + + NvBoardBusMode_Forceword = 0x7fffffff, +} NvBoardBusMode; + +typedef enum +{ + /* Asynchronous. */ + NvBoardBusSynchronization_Asynchronous, + + /* Synchronous. */ + NvBoardBusSynchronization_Synchronous, + + NvBoardBusSynchronization_Forceword = 0x7fffffff, +} NvBoardBusSynchronization; + +typedef enum +{ + /* Active low. */ + NvBoardBusReadyPolarity_ActiveLow, + + /* Active high. */ + NvBoardBusReadyPolarity_ActiveHigh, + + NvBoardBusReadyPolarity_Forceword = 0x7fffffff, +} NvBoardBusReadyPolarity; + +typedef struct NvBoardMode_t +{ + NvBoardBusAddressing GPUaddressing; // Bus perspective from GPU + NvBoardBusWidth GPUwidth; + NvBoardBusAddressing CPUaddressing; // Bus perspective from CPU + NvBoardBusWidth CPUwidth; + NvBoardBusType type; + NvBoardBusMode mode; + NvBoardBusSynchronization synchronization; + NvBoardBusReadyPolarity readyPolarity; +} NvBoardMode; + +/** Stateless methods. Methods can be called before NvBoardInit */ + +/** NvBoardListSupportedModes - Method to enumerate the modes of the board + + Two calls should be made to this method. + + On the first call, the method populates the number of modes, for the + display. When this call is issued pMode should be NULL. + + On the second call, the length of the pMode array is indicated by + the value of *pNum. When pNum is less than the number of modes the + method populates the pMode array with only the first pNum modes. + When is more than the number of modes, the method populates the + pMode array with the number of modes and writes the number of modes + into pNum. + + The first mode enumerated by this method is the recommended / default mode + for the display. + + @param pNum unsigned integer value indicating the number of modes in + the array pMode. + + @param pMode pointer to an array of mode structures, where the size of + the array is determined by the value in pNum. + + @retval NvSuccess - on success + NvErrorBadParameter - when at least one parameter is incorrect + */ +NvError +NvBoardListSupportedModes( NvU32 *pNum, NvBoardMode *pMode ); + +/** Library Initialization */ + +/** NvBoardInit - platform initialization. Typically chip select is configured here. + + NvBoardInit uses a reference counter. The first invocation performs the + initialization, all future calls increment the counter. The counter is + decremented by NvBoardDeInit. + + This method is to be called before any other NvBoard methods can be used. + + @param pMode pointer to structure containing a mode to set on the board. + If mode is null, the recommended mode will be chosen. + */ +NvError +NvBoardInit( const NvBoardMode *pMode ); + +/** NvBoardDeInit - platform deinitialization. + */ +void +NvBoardDeInit( void ); + +/** Wince platform resume control */ +NvError +NvBoardResume( void ); + +/** Wince platform suspend control */ +NvError +NvBoardSuspend( void ); + +/** SD card detect status when card detect pin is connected to CPU GPIO pin */ +NvError +nvBoardSDCardDetectStatus(NvU32 *bCardInserted); + +/** SD card detect sysintr number if card detect pin is connected to CPU GPIO pin*/ +NvError +nvBoardSDCardDetectSysintr(NvU32 *dwSysintr); + +/** SD card socket power pin configuration + In general, this pin is connected to CPU GPIO pin, and we need to configure + GPIO input/output mode and setup default value +*/ +NvError +nvBoardSDSocketPowerInit(void); + +/** SD card socket power control*/ +NvError +nvBoardSDSocketPowerOnOff(NvU32 SDPowerOn); + +/** Camera(VI) interface power plane control*/ +NvError +nvBoardVIPowerOnOff(NvU32 VIPowerOn); + +/** OEM specific powerOn related calls after NV backlight ON. + + @retval ERROR_SUCCESS on success or appropriate wince error + codes. +*/ +NvError +nvBoard_PostOEMBacklightOn(void); + +/** OEM specific powerOff related calls after NV backlight Off. + + @retval ERROR_SUCCESS on success or appropriate wince error + codes. +*/ +NvError +nvBoard_PostOEMBacklightOff(void); + +/** NvBoardGetApertures - get apertures + */ +NvError +NvBoardGetApertures( NvBoardApertures *pApertures ); + +/** NvBoardGetMode - get current mode + */ +NvError +NvBoardGetMode( NvBoardMode *pMode ); + +/** Device Events -- Abstraction for interrupts */ + +/* NvDeviceEvent enumerates the types of events. NvBoard implementors should not + hardcode event names. The only enumerated value that should be used in the + implementation of NvBoard is NvDeviceEvent_Num. + */ +typedef enum NvDeviceEvent_t +{ + /* NOTE: Currently using unabstracted events until INTx is removed. */ + NvDeviceEvent_HOST = 0, + NvDeviceEvent_GRMPD, + NvDeviceEvent_ME, + NvDeviceEvent_JPEGE, + NvDeviceEvent_VI, + NvDeviceEvent_EPP, + NvDeviceEvent_ISP, + NvDeviceEvent_DSP, + NvDeviceEvent_GR2D, + NvDeviceEvent_GR3D, + NvDeviceEvent_DISPLAY, + NvDeviceEvent_I2S, + NvDeviceEvent_IC, + NvDeviceEvent_SD, + NvDeviceEvent_MC, + NvDeviceEvent_EMC, + + /* NUM should always be the 2nd last enumerated value */ + NvDeviceEvent_Num, + + NvDeviceEvent_Forceword = 0x7fffffff, +} NvDeviceEvent; + +/** NvBoardEnableEvent - Method to enable an event + + If the event is fired before a client is waiting, the event will be remembered + for the next NvBoardWaitForEvent invocation. + */ +NvError +NvBoardEnableEvent( NvDeviceEvent event ); + +/** NvBoardDisableEvent - Method to disable an event + */ +void +NvBoardDisableEvent( NvDeviceEvent event ); + +/** NvBoardWaitForEvent - This method blocks until the event is fired + + Each event may only have one client waiting on it. If more than one client + needs to be notified of an event, a broadcast layer will need to be + developed on top of this API. + + Once an event is fired, it is disabled. To reenable the event use + NvBoardEnableEvent. +*/ +NvError +NvBoardWaitForEvent( NvDeviceEvent event ); + +/** NvBoardWaitForEventWithTimeOut - NvBoardWaitForEvent with a timeout + + @param timeOut Unit is milliseconds + */ +NvError +NvBoardWaitForEventWithTimeOut( NvDeviceEvent event, NvU32 timeOut ); + +/** I2C I/O */ + +/** NvBoardI2CWrite - I2C write operation. Implementing this function is optional. + */ +NvError +NvBoardI2CWrite( NvU32 addr, const void *ptr, NvU32 size ); + +/** NvBoardI2CRead - I2C read operation. Implementing this function is optional. + */ +NvError +NvBoardI2CRead( NvU32 addr, void *ptr, NvU32 size ); + +/** Voltage and power control */ + +typedef enum NvBoardPowerPlane_t +{ + NvBoardPowerPlane_AOCVDD = 0, + NvBoardPowerPlane_VECVDD, + NvBoardPowerPlane_MMCVDD, + NvBoardPowerPlane_TDCVDD, + NvBoardPowerPlane_VVDD, + NvBoardPowerPlane_EMVDD, + NvBoardPowerPlane_ACVDD, + NvBoardPowerPlane_LVDD, + NvBoardPowerPlane_HVDD, + NvBoardPowerPlane_AUXVDD, + NvBoardPowerPlane_R1CVDD, + NvBoardPowerPlane_SDVDD, + NvBoardPowerPlane_DRAM, + + NvBoardPowerPlane_Forceword = 0x7fffffff, +} NvBoardPowerPlane; + +typedef enum NvBoardClock_t +{ + NvBoardClock_PLL1 = 0, + NvBoardClock_PLL2, + NvBoardClock_COSC, + NvBoardClock_ROSC, + NvBoardClock_REF1, + NvBoardClock_REF2, + + NvBoardClock_Forceword = 0x7fffffff, +} NvBoardClock; + +/** NvBoardSetVoltage - change voltage of hardware block + + @param voltage Unit is millivolts + */ +NvError +NvBoardSetVoltage( NvBoardPowerPlane block, NvU32 voltage ); + +/** NvBoardGetVoltage - get voltage of hardware block + + @param voltage Unit is millivolts + */ +NvError +NvBoardGetVoltage( NvBoardPowerPlane plane, NvU32 *voltage ); + +/** NvBoardPowerOn - enable power to block + */ +NvError +NvBoardPowerOn( NvBoardPowerPlane plane ); + +/** NvBoardPowerOff - disable power to block + */ +NvError +NvBoardPowerOff( NvBoardPowerPlane plane ); + +/** NvBoardClockOn - enable clock + */ +NvError +NvBoardClockOn( NvBoardClock clock ); + +/** NvBoardClockOff - disable clock + */ +NvError +NvBoardClockOff( NvBoardClock clock ); + +/** NvBoardSetFrequency - set frequency of clock + + @param frequency unit is KHz + */ +NvError +NvBoardSetFrequency( NvBoardClock clock, NvU32 frequency ); + + +/** Platfrom specific debug function. This like an ioctl to the platfrom + sepcific code. + */ +void NvBoardDebug(void *p, NvU32 op, NvU32 arg); + +/** Event notification */ + +typedef enum +{ + NvBoardDeviceType_Silicon, + NvBoardDeviceType_Emulator, + NvBoardDeviceType_Forceword = 0x7fffffff, +} NvBoardDeviceType; + +typedef struct NvBoardDeviceInfo_t +{ + NvU32 MinorRev; + NvU32 MajorRev; + NvU32 ChipID; + NvU32 Family; + NvBoardDeviceType Type; +} NvBoardDeviceInfo; + +/** NvBoardPostChipInit - Called after the chip is intialized. + + Chip specific timings can be programmed at this point. + + NvIrqPostChipInit should be called here. + */ +NvError +NvBoardPostChipInit( NvBoardDeviceInfo *deviceInfo ); + +/** NvBoardPreChipDeInit - Called before chip is shutdown. + + NvIrqPreChipDeInit should be called here. + */ +NvError +NvBoardPreChipDeInit( void ); + +/** NvBoardClockSwitch - Clock switch handling + + @param frequency Unit is kHz + */ +NvError +NvBoardClockSwitch( NvU32 frequency ); + +typedef enum NvBoardStateEvent_t +{ +#ifdef NV_WINDOWS_CE + NvBoardStateEvent_PreDeviceInit, + NvBoardStateEvent_PostDeviceInit, + NvBoardStateEvent_PrePanelInit, + NvBoardStateEvent_PostPanelInit, + NvBoardStateEvent_PreSetMode, + NvBoardStateEvent_PostSetMode, + NvBoardStateEvent_PreDisplayInit, + NvBoardStateEvent_PostDisplayInit, + NvBoardStateEvent_PreOEMPowerHandlerVideoPowerOff, + NvBoardStateEvent_PostOEMPowerHandlerVideoPowerOff, + NvBoardStateEvent_PreOEMPowerHandlerVideoPowerOn, + NvBoardStateEvent_PostOEMPowerHandlerVideoPowerOn, +#endif + + NvBoardStateEvent_Forceword = 0x7fffffff, +} NvBoardStateEvent; + +/** NvBoardGlobalStateNotification - Called during global state transitions + + Only used on Windows CE at the moment. + */ +NvError +NvBoardGlobalStateNotification( NvBoardStateEvent event ); + +void +NvBoardOsWaitUS( NvU32 usec ); + +void +NvBoardOsSleepMS( NvU32 msec ); + +typedef struct NvBoardOsMutex_t *NvBoardOsMutex; +typedef struct NvBoardOsSemaphore_t *NvBoardOsSemaphore; +typedef struct NvBoardOsThread_t *NvBoardOsThread; + +NvError +NvBoardOsMutexCreate( const char *key, NvBoardOsMutex *mutex ); + +void +NvBoardOsMutexLock( NvBoardOsMutex mutex ); + +void +NvBoardOsMutexUnlock( NvBoardOsMutex mutex ); + +void +NvBoardOsMutexDestroy( NvBoardOsMutex mutex ); + +typedef struct NvBoardOsSharedMemDescriptor_t *NvBoardOsSharedMemDescriptor; + +NvError +NvBoardOsSharedMemAlloc( const char *key, size_t size, + NvBoardOsSharedMemDescriptor *descriptor ); + +NvError +NvBoardOsSharedMemMap( NvBoardOsSharedMemDescriptor descriptor, size_t offset, + size_t size, void **ptr ); + +void +NvBoardOsSharedMemUnmap( void *ptr, size_t size ); + +void +NvBoardOsSharedMemFree( NvBoardOsSharedMemDescriptor descriptor ); + +void +NvBoardOsMemset( void *s, NvU8 c, size_t size ); + +int +NvBoardOsMemcmp( const void *s1, const void *s2, size_t size ); + +#define NVBOARDOS_KEY_MAX 128 + +#define NVBOARDOS_MEM_NONE 0x0 +#define NVBOARDOS_MEM_READ 0x1 +#define NVBOARDOS_MEM_WRITE 0x2 +#define NVBOARDOS_MEM_EXECUTE 0x4 +#define NVBOARDOS_MEM_READ_WRITE ( NVBOARDOS_MEM_READ | NVBOARDOS_MEM_WRITE ) + +typedef enum +{ + NvBoardOsMemAttribute_Uncached = 0, + NvBoardOsMemAttribute_WriteBack = 1, + NvBoardOsMemAttribute_WriteCombined = 2, + + NvBoardOsMemAttribute_Force32 = 0x7FFFFFFF +} NvBoardOsMemAttribute; + +NvError +NvBoardOsPhysicalMemMap( NvPhysAddr phys, size_t size, + NvBoardOsMemAttribute attrib, NvU32 flags, void **ptr ); + + +void +NvBoardOsPhysicalMemUnmap( void *ptr, size_t size ); + +NvError +NvBoardOsMemoryAlloc(void **ptr, size_t size); + +void +NvBoardOsMemoryFree(void *ptr, size_t size); + +NvError +NvBoardOsGetConfigU32( const char *name, NvU32 *value ); + +void * +NvBoardOsAlloc( size_t size ); + +void +NvBoardOsFree( void *ptr ); + +typedef void (*NvBoardOsThreadFunction)( void *args ); + +NvError +NvBoardOsThreadCreate( const char *name, NvBoardOsThreadFunction function, + void *args, NvBoardOsThread *thread ); + +void +NvBoardOsThreadJoin( NvBoardOsThread thread ); + +void +NvBoardOsThreadYield( void ); + +NvError +NvBoardOsSemaphoreCreate( const char *key, NvBoardOsSemaphore *semaphore, + NvU32 value ); + +void +NvBoardOsSemaphoreWait( NvBoardOsSemaphore semaphore ); + +void +NvBoardOsSemaphoreSignal( NvBoardOsSemaphore semaphore ); + +void +NvBoardOsSemaphoreDestroy( NvBoardOsSemaphore semaphore ); + +NvError +nvBoard_PreDisplayInit(void); + +NvError +nvBoard_PostDisplayInit(void); + +NvError +nvBoard_PrePanelInit(void); + +NvError +nvBoard_PostPanelInit(void); + +NvError +nvBoard_PreDeviceInit(void); + +NvError +nvBoard_PostDeviceInit(void); + +NvError +nvBoard_PreSetMode(void); + +NvError +nvBoard_PostSetMode(void); + +NvError +nvBoard_PreOEMPowerHandlerVideoPowerOff(void); + +NvError +nvBoard_PostOEMPowerHandlerVideoPowerOff(void); + +NvError +nvBoard_PreOEMPowerHandlerVideoPowerOn(void); + +NvError +nvBoard_PostOEMPowerHandlerVideoPowerOn(void); + +#ifdef __cplusplus +} +#endif + +#endif // NVBOARD_H diff --git a/Start_WM/test6/inc/nvcommon.h b/Start_WM/test6/inc/nvcommon.h new file mode 100755 index 00000000..ab79088f --- /dev/null +++ b/Start_WM/test6/inc/nvcommon.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2006 - 2007 NVIDIA Corporation. All Rights Reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef NVCOMMON_H +#define NVCOMMON_H + +#include "nvtypes.h" + +// Include headers that provide NULL, size_t, offsetof, and [u]intptr_t. In the +// event that the toolchain doesn't provide these, provide them ourselves. +#include +#if NVOS_IS_WINDOWS_CE +typedef int intptr_t; +typedef unsigned int uintptr_t; +#elif (NVOS_IS_LINUX && !defined(__KERNEL__)) || defined(__arm) +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** nvcommon.h contains standard definitions used by various interfaces + */ + +/** A physical address */ +#if NVOS_IS_WINDOWS +typedef NvU64 NvPhysAddr; +#else +typedef NvU32 NvPhysAddr; +#endif + +// For historical reasons that are hard to fix, nvtypes.h has an incorrect +// definition of NV_ALIGN_BYTES for Windows and Macintosh, and for other +// unsupported compilers like IAR. Provide a correct macro, which we call +// NV_ALIGN. This can be removed if and when nvtypes.h is fixed. +// Alternatively, we could use NV_DECLARE_ALIGNED... +#if NVOS_IS_WINDOWS +#define NV_ALIGN(size) __declspec(align(size)) +#elif defined(__GNUC__) || NVOS_IS_QNX +#define NV_ALIGN(size) __attribute__ ((aligned (size))) +#elif defined(__arm) +#define NV_ALIGN(size) __align(size) +#endif + +/** + * This macro wraps its argument with the equivalent of "#ifdef DEBUG", but also + * can be used where #ifdef's can't, like inside a macro. + */ +#if defined(DEBUG) +#define NV_DEBUG_CODE(x) x +#else +#define NV_DEBUG_CODE(x) +#endif + +/** Macro for determining the size of an array */ +#define NV_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/** Macro for taking min or max of a pair of numbers */ +#define NV_MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define NV_MAX(a,b) (((a) > (b)) ? (a) : (b)) + +/** + * By convention, we use this value to represent an infinite wait interval in + * APIs that expect a timeout argument. A value of zero should not be + * interpreted as infinite -- it should be interpreted as "time out immediately + * and simply check whether the event has already happened." + */ +enum { NV_WAIT_INFINITE = 0xFFFFFFFF }; + +/** + * Union that can be used to view a 32-bit word as your choice of a 32-bit + * unsigned integer, a 32-bit signed integer, or an IEEE single-precision float. + * Here is an example of how you might use it to extract the (integer) bitwise + * representation of a floating-point number: + * NvData32 data; + * data.f = 1.0f; + * printf("%x", data.u); + */ +typedef union NvData32Rec +{ + NvU32 u; + NvS32 i; + NvF32 f; +} NvData32; + +/** NvPoint structure is used to determine a location on a 2-dimensional + object, where the coordinate (0,0) is located at the top-left of the + object. The values of x and y are in pixels. + */ +typedef struct _NvPoint_t +{ + /** horizontal location of the point */ + NvS32 x; + + /** vertical location of the point */ + NvS32 y; + +} NvPoint; + + +/** NvRect structure is used to define a 2-dimensional rectangle + where the rectangle is bottom right exclusive (i.e. the right most + column, and the bottom row of the rectangle is not included) + */ +typedef struct _NvRect_t +{ + /** left column of a rectangle */ + NvS32 left; + + /** top row of a rectangle*/ + NvS32 top; + + /** right column of a rectangle */ + NvS32 right; + + /** bottom row of a rectangle */ + NvS32 bottom; + +} NvRect; + + +/** NvSize structure is used to define a 2-dimensional surface + where the surface is determined by it's height and width in + pixels + */ +typedef struct _NvSize_t +{ + /* width of the surface in pixels */ + NvS32 width; + + /* height of the surface in pixels */ + NvS32 height; + +} NvSize; + + +/** NvDeviceHandle is an opaque handle to a device + */ +typedef struct NvDeviceStruct_t *NvDeviceHandle; +#ifdef __cplusplus +} +#endif + +#endif /* NVCOMMON_H */ diff --git a/Start_WM/test6/inc/nverror.h b/Start_WM/test6/inc/nverror.h new file mode 100755 index 00000000..6ef69080 --- /dev/null +++ b/Start_WM/test6/inc/nverror.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006 NVIDIA Corporation. All Rights Reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef NVERROR_H +#define NVERROR_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* NvError_t enumeration contains ALL return / error codes. Error codes + are specifically explicit to make it easy to identify where an error + came from. + + All error codes are derived from the macros in NvErrVal.h + */ +typedef enum _NvError_t +{ + +#ifdef NVERROR +#undef NVERROR +#endif /* NVERROR */ + +#define NVERROR(_name_, _value_, _desc_) _name_ = _value_, + + /* header included for macro expansion of error codes */ + #include "nverrval.h" + + /* bogus error code used to padd the enum to 32bits */ + NvErrorMax = 0x7FFFFFFF + +#undef NVERROR + +} NvError; + + +#ifdef __cplusplus +} +#endif + +#endif /* NVERROR_H */ + diff --git a/Start_WM/test6/inc/nverrval.h b/Start_WM/test6/inc/nverrval.h new file mode 100755 index 00000000..2045dd83 --- /dev/null +++ b/Start_WM/test6/inc/nverrval.h @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2006 NVIDIA Corporation. All Rights Reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* NvErrVal.h is a header used for macro expansion of the errors defined for + the Nv methods & interfaces. + + This header is NOT protected from being included multiple times, as it is + used for C pre-processor macro expansion of error codes, and the + descriptions of those error codes. + + Each error code has a unique name, description and value to make it easier + for developers to identify the source of a failure. Thus there are no + generic or unknown error codes. +*/ + +/* common error codes */ +NVERROR(NvSuccess, 0x00000000, "success") +NVERROR(NvError_NotImplemented, 0x00000001, "method or interface is not implemented") +NVERROR(NvError_NotSupported, 0x00000002, "requested operation is not supported") +NVERROR(NvError_NotInitialized, 0x00000003, "method or interface is not initialized") +NVERROR(NvError_BadParameter, 0x00000004, "bad parameter to method or interface") +NVERROR(NvError_Timeout, 0x00000005, "not completed in the expected time") +NVERROR(NvError_InsufficientMemory, 0x00000006, "insufficient system memory") +NVERROR(NvError_ReadOnlyAttribute, 0x00000007, "cannot write a read-only attribute") +NVERROR(NvError_InvalidState, 0x00000008, "module is in invalid state to perform the requested operation") +NVERROR(NvError_InvalidAddress, 0x00000009, "invalid address") +NVERROR(NvError_InvalidSize, 0x0000000A, "invalid size") +NVERROR(NvError_BadValue, 0x0000000B, "illegal value specified for parameter") + +/* surface specific error codes */ +NVERROR(NvError_InsufficientVideoMemory, 0x00010000, "insufficient video memory") +NVERROR(NvError_BadSurfaceColorScheme, 0x00010001, "this surface scheme is not supported in the current controller") + +/* display specific error codes */ +NVERROR(NvError_DisplayIncompatible, 0x00020000, "display incompatible with method or interface") +NVERROR(NvError_NoCompatibleMode, 0x00020001, "no compatible mode exists for the attached displays") +NVERROR(NvError_ModeNotSupported, 0x00020002, "the mode is not supported by the display or controller") +NVERROR(NvError_ControllerActive, 0x00020003, "the controller is active and cannot perform the operation") +NVERROR(NvError_DisplayAlreadyAttached, 0x00020004, "the display is already attached to the controller") +NVERROR(NvError_DetachDisplayFirst, 0x00020005, "the display is already attached to another controller") +NVERROR(NvError_TooManyDisplays, 0x00020006, "the controller has not enough free display slots") +NVERROR(NvError_NoDisplaysAttached, 0x00020007, "there are no displays attached to this controller") +NVERROR(NvError_AlreadySuspended, 0x00020008, "the controller is already suspended") +NVERROR(NvError_NotSuspended, 0x00020009, "the controller is not suspended, so cannot resume it") +NVERROR(NvError_EmptyColorKeyRange, 0x00020010, "color key range that was set is empty") +NVERROR(NvError_NoMode, 0x00020011, "controller is not driving a mode, cannot perform the selected action") +NVERROR(NvError_NotInVerticalBlank, 0x00020012, "controller is not in vertical blank") + +/* DMA specific error codes */ +NVERROR(NvError_DmaTargetNotLocked, 0x00030000, "client does not have a lock for this target DMA controller") +NVERROR(NvError_DmaCommunicationError, 0x00030001, "the DMA controller had failed to communicate with the target") +NVERROR(NvError_DmaOpNotFinished, 0x00030002, "the DMA operation has not completed") +NVERROR(NvError_DmaChannelNotAvailable, 0x00030003, "the requested DMA channel is not available") +NVERROR(NvError_InvalidSourceId, 0x00030004, "invalid source ID") +NVERROR(NvError_InvalidDestinationId, 0x00030005, "invalid destination ID") + +/* NvOs error codes */ +NVERROR(NvError_FileWriteFailed, 0x00040000, "the file write operation failed") +NVERROR(NvError_FileReadFailed, 0x00040001, "the file read operation failed") +NVERROR(NvError_EndOfFile, 0x00040002, "the end of file has been reached") +NVERROR(NvError_FileOperationFailed, 0x00040003, "the file operation has failed") +NVERROR(NvError_DirOperationFailed, 0x00040004, "the directory operation has failed") +NVERROR(NvError_EndOfDirList, 0x00040005, "there are no more entries in the directory") +NVERROR(NvError_ConfigVarNotFound, 0x00040006, "the configuration variable is not present") +NVERROR(NvError_InvalidConfigVar, 0x00040007, "the configuration variable is corrupted") +NVERROR(NvError_LibraryNotFound, 0x00040008, "the dynamic library was not found for open") +NVERROR(NvError_SymbolNotFound, 0x00040009, "the symbol in a dyanmic library was not found") +NVERROR(NvError_MemoryMapFailed, 0x0004000a, "the memory mapping operation failed") +NVERROR(NvError_MutexCreateFailed, 0x0004000b, "the mutex create operation failed") +NVERROR(NvError_SemaphoreCreateFailed, 0x0004000c, "the semaphore create operation failed") +NVERROR(NvError_ThreadCreateFailed, 0x0004000d, "the thread create operation failed") +NVERROR(NvError_SharedMemAllocFailed, 0x0004000e, "the shared memory allocation operation failed") + +/* NvBoard error codes */ +NVERROR(NvError_I2CNotAcknowledged, 0x00050000, "I2C acknowledge was not received") +NVERROR(NvError_KernelDriverNotFound, 0x00050001, "unable to find kernel driver") +NVERROR(NvError_KernelDriverBadVersion, 0x00050002, "the kernel driver is out of date") +NVERROR(NvError_KernelDriverIOFailed, 0x00050003, "the driver operation failed") +NVERROR(NvError_ModeMismatched, 0x00050004, "conflicting board mode") +NVERROR(NvError_VoltageOutsideRange, 0x00050005, "requested voltage is outside valid range") +NVERROR(NvError_EventNotEnabled, 0x00050006, "the event is not enabled") +NVERROR(NvError_EventBusy, 0x00050007, "the event is busy") +NVERROR(NvError_InterruptInitFailed, 0x00050008, "error initializing interrupts") + +/* NvIrq error codes */ +NVERROR(NvError_EventNotFound, 0x00060000, "no event found") + +/* Nv2D error codes */ +NVERROR(NvError_InvalidSurface, 0x00070000, "invalid surface") +NVERROR(NvError_RopNotSupported, 0x00070001, "rop not supported") +NVERROR(NvError_SurfaceNotSupported, 0x00070002, "surface is not supported") +NVERROR(NvError_BitmapNotSupported, 0x00070003, "bitmap is not supported") + +/* NvPower error codes */ +NVERROR(NvError_ResourceAlreadyInUse, 0x00080000, "resource already in use") +NVERROR(NvError_ResourceNotInUse, 0x00080001, "resource not in use") +NVERROR(NvError_ResourceInUse, 0x00080002, "resource is in use") + +/* UART error codes */ +NVERROR(NvError_UartOverrun, 0x00090000, "overrun occurred when receiving the data") +NVERROR(NvError_UartFraming, 0x00090001, "data received had framing error") +NVERROR(NvError_UartParity, 0x00090002, "data received had parity error") +NVERROR(NvError_UartFifoError, 0x00090003, "FIFO error occurred during receive/transmit") +NVERROR(NvError_UartBreakReceived, 0x00090004, "received break signal") +NVERROR(NvError_UartTransmit, 0x00090005, "UART transmit error") + +/* NvRm error code */ +NVERROR(NvError_RmInitFailed, 0x000a0000, "rm failed to initialize") +NVERROR(NvError_RmChannelInitFailure, 0x000a0001, "channel init failed") +NVERROR(NvError_RmStreamInitFailure, 0x000a0002, "stream init failed") +NVERROR(NvError_RmSyncPointAllocFailure, 0x000a0003, "sync point alloc failed") +NVERROR(NvError_RmStreamFlushFailure, 0x000a0004, "stream flush failed") + +/* NvIsp error codes */ +NVERROR(NvError_ChannelAllocFailed, 0x000B0000, "channel allocation failed") +NVERROR(NvError_NoConnectedImager, 0x000B0001, "no imager connected") +NVERROR(NvError_UnsupportedResolution, 0x000B0002, "unsupported resolution") +NVERROR(NvError_I2CCommunicationError, 0x000B0003, "i2c communication failed") +NVERROR(NvError_IspConfigFileParseError, 0x000B0004, "isp config file parse error") +NVERROR(NvError_IspBusy, 0x000B0005, "isp 3A algorithm busy") +NVERROR(NvError_TooDark, 0x000B0006, "image too dark for 3A operation") + +/* NvTest error codes */ +NVERROR(NvError_TestApplicationFailed, 0x000c0000, "the test application failed") +NVERROR(NvError_TestNoUserInput, 0x000c0001, "no user input available") +NVERROR(NvError_TestCommandLineError, 0x000c0002, "command line parsing error") + +/* NvCam error codes */ +NVERROR(NvError_VmAllocFailed, 0x000D0000, "virtual machine allocation failed") +NVERROR(NvError_ScriptAccessFailed, 0x000D0001, "unable to access script") +NVERROR(NvError_GettingComponentFailed, 0x000D0002, "getting component failed") +NVERROR(NvError_VmBufferAllocFailed, 0x000D0003, "vm buffer allocation failed") +NVERROR(NvError_CameraScriptNotPresent, 0x000D0004, "camera script not present") +NVERROR(NvError_IllegalBayerValues, 0x000D0005, "illegal bayer values") +NVERROR(NvError_ColorFormatNotSupported, 0x000D0006, "color format not supported") + +/* USBF error codes */ +NVERROR(NvError_UsbfTxfrActive, 0x000E0000, "The endpoint has an active transfer in progress.") +NVERROR(NvError_UsbfTxfrComplete, 0x000E0001, "The endpoint has a completed transfer that has not been cleared.") +NVERROR(NvError_UsbfEpStalled, 0x000E0002, "The endpoint has been placed in a halted or stalled state.") +NVERROR(NvError_UsbfEpError, 0x000E0003, "The last transfer started on this endpoint failed to complete.") + +/* ^^^ ADD ALL NEW ERRORS RIGHT ABOVE HERE ^^^ */ + +NVERROR(NvErrorNotImplemented, 0x00000001, "remove me later!") +NVERROR(NvErrorNotSupported, 0x00000002, "remove me later!") +NVERROR(NvErrorNotInitialized, 0x00000003, "remove me later!") +NVERROR(NvErrorBadParameter, 0x00000004, "remove me later!") +NVERROR(NvErrorTimeout, 0x00000005, "remove me later!") +NVERROR(NvErrorInsufficientMemory, 0x00000006, "remove me later!") +NVERROR(NvErrorReadOnlyAttribute, 0x00000007, "remove me later!") +NVERROR(NvErrorInvalidState, 0x00000008, "remove me later!") +NVERROR(NvErrorInvalidAddress, 0x00000009, "remove me later!") +NVERROR(NvErrorInvalidSize, 0x0000000A, "remove me later!") +NVERROR(NvErrorBadValue, 0x0000000B, "remove me later!") + +/* surface specific error codes */ +NVERROR(NvErrorInsufficientVideoMemory, 0x00010000, "remove me later!") +NVERROR(NvErrorBadSurfaceColorScheme, 0x00010001, "remove me later!") + +/* display specific error codes */ +NVERROR(NvErrorDisplayIncompatible, 0x00020000, "remove me later!") +NVERROR(NvErrorNoCompatibleMode, 0x00020001, "remove me later!") +NVERROR(NvErrorModeNotSupported, 0x00020002, "remove me later!") +NVERROR(NvErrorControllerActive, 0x00020003, "remove me later!") +NVERROR(NvErrorDisplayAlreadyAttached, 0x00020004, "remove me later!") +NVERROR(NvErrorDetachDisplayFirst, 0x00020005, "remove me later!") +NVERROR(NvErrorTooManyDisplays, 0x00020006, "remove me later!") +NVERROR(NvErrorNoDisplaysAttached, 0x00020007, "remove me later!") +NVERROR(NvErrorAlreadySuspended, 0x00020008, "remove me later!") +NVERROR(NvErrorNotSuspended, 0x00020009, "remove me later!") +NVERROR(NvErrorEmptyColorKeyRange, 0x00020010, "remove me later!") +NVERROR(NvErrorNoMode, 0x00020011, "remove me later!") +NVERROR(NvErrorNotInVerticalBlank, 0x00020012, "remove me later!") + +/* DMA specific error codes */ +NVERROR(NvErrorDmaTargetNotLocked, 0x00030000, "remove me later!") +NVERROR(NvErrorDmaCommunicationError, 0x00030001, "remove me later!") +NVERROR(NvErrorDmaOpNotFinished, 0x00030002, "remove me later!") +NVERROR(NvErrorDmaChannelNotAvailable, 0x00030003, "remove me later!") +NVERROR(NvErrorInvalidSourceId, 0x00030004, "remove me later!") +NVERROR(NvErrorInvalidDestinationId, 0x00030005, "remove me later!") + +/* NvOs error codes */ +NVERROR(NvErrorFileWriteFailed, 0x00040000, "remove me later!") +NVERROR(NvErrorFileReadFailed, 0x00040001, "remove me later!") +NVERROR(NvErrorEndOfFile, 0x00040002, "remove me later!") +NVERROR(NvErrorFileOperationFailed, 0x00040003, "remove me later!") +NVERROR(NvErrorDirOperationFailed, 0x00040004, "remove me later!") +NVERROR(NvErrorEndOfDirList, 0x00040005, "remove me later!") +NVERROR(NvErrorConfigVarNotFound, 0x00040006, "remove me later!") +NVERROR(NvErrorInvalidConfigVar, 0x00040007, "remove me later!") +NVERROR(NvErrorLibraryNotFound, 0x00040008, "remove me later!") +NVERROR(NvErrorSymbolNotFound, 0x00040009, "remove me later!") +NVERROR(NvErrorMemoryMapFailed, 0x0004000a, "remove me later!") +NVERROR(NvErrorMutexCreateFailed, 0x0004000b, "remove me later!") +NVERROR(NvErrorSemaphoreCreateFailed, 0x0004000c, "remove me later!") +NVERROR(NvErrorThreadCreateFailed, 0x0004000d, "remove me later!") +NVERROR(NvErrorSharedMemAllocFailed, 0x0004000e, "remove me later!") + +/* NvBoard error codes */ +NVERROR(NvErrorI2CNotAcknowledged, 0x00050000, "remove me later!") +NVERROR(NvErrorKernelDriverNotFound, 0x00050001, "remove me later!") +NVERROR(NvErrorKernelDriverBadVersion, 0x00050002, "remove me later!") +NVERROR(NvErrorKernelDriverIOFailed, 0x00050003, "remove me later!") +NVERROR(NvErrorModeMismatched, 0x00050004, "remove me later!") +NVERROR(NvErrorVoltageOutsideRange, 0x00050005, "remove me later!") +NVERROR(NvErrorEventNotEnabled, 0x00050006, "remove me later!") +NVERROR(NvErrorEventBusy, 0x00050007, "remove me later!") +NVERROR(NvErrorInterruptInitFailed, 0x00050008, "remove me later!") + +/* NvIrq error codes */ +NVERROR(NvErrorEventNotFound, 0x00060000, "remove me later!") + +/* Nv2D error codes */ +NVERROR(NvErrorInvalidSurface, 0x00070000, "remove me later!") +NVERROR(NvErrorRopNotSupported, 0x00070001, "remove me later!") +NVERROR(NvErrorSurfaceNotSupported, 0x00070002, "remove me later!") +NVERROR(NvErrorBitmapNotSupported, 0x00070003, "remove me later!") + +/* NvPower error codes */ +NVERROR(NvErrorResourceAlreadyInUse, 0x00080000, "remove me later!") +NVERROR(NvErrorResourceNotInUse, 0x00080001, "remove me later!") +NVERROR(NvErrorResourceInUse, 0x00080002, "remove me later!") + +/* UART error codes */ +NVERROR(NvErrorUartOverrun, 0x00090000, "remove me later!") +NVERROR(NvErrorUartFraming, 0x00090001, "remove me later!") +NVERROR(NvErrorUartParity, 0x00090002, "remove me later!") +NVERROR(NvErrorUartFifoError, 0x00090003, "remove me later!") +NVERROR(NvErrorUartBreakReceived, 0x00090004, "remove me later!") +NVERROR(NvErrorUartTransmit, 0x00090005, "remove me later!") + +/* NvRm error code */ +NVERROR(NvErrorRmInitFailed, 0x000a0000, "remove me later!") +NVERROR(NvErrorRmChannelInitFailure, 0x000a0001, "remove me later!") +NVERROR(NvErrorRmStreamInitFailure, 0x000a0002, "remove me later!") +NVERROR(NvErrorRmSyncPointAllocFailure, 0x000a0003, "remove me later!") +NVERROR(NvErrorRmStreamFlushFailure, 0x000a0004, "remove me later!") + +/* NvIsp error codes */ +NVERROR(NvErrorChannelAllocFailed, 0x000B0000, "remove me later!") +NVERROR(NvErrorNoConnectedImager, 0x000B0001, "remove me later!") +NVERROR(NvErrorUnsupportedResolution, 0x000B0002, "remove me later!") +NVERROR(NvErrorI2CCommunicationError, 0x000B0003, "remove me later!") +NVERROR(NvErrorIspConfigFileParseError, 0x000B0004, "remove me later!") +NVERROR(NvErrorIspBusy, 0x000B0005, "remove me later!") +NVERROR(NvErrorTooDark, 0x000B0006, "remove me later!") + +/* NvTest error codes */ +NVERROR(NvErrorTestApplicationFailed, 0x000c0000, "remove me later!") +NVERROR(NvErrorTestNoUserInput, 0x000c0001, "remove me later!") +NVERROR(NvErrorTestCommandLineError, 0x000c0002, "remove me later!") + +/* NvCam error codes */ +NVERROR(NvErrorVmAllocFailed, 0x000D0000, "remove me later!") +NVERROR(NvErrorScriptAccessFailed, 0x000D0001, "remove me later!") +NVERROR(NvErrorGettingComponentFailed, 0x000D0002, "remove me later!") +NVERROR(NvErrorVmBufferAllocFailed, 0x000D0003, "remove me later!") +NVERROR(NvErrorCameraScriptNotPresent, 0x000D0004, "remove me later!") +NVERROR(NvErrorIllegalBayerValues, 0x000D0005, "remove me later!") +NVERROR(NvErrorColorFormatNotSupported, 0x000D0006, "remove me later!") + +/* USBF error codes */ +NVERROR(NvErrorUsbfTxfrActive, 0x000E0000, "remove me later!") +NVERROR(NvErrorUsbfTxfrComplete, 0x000E0001, "remove me later!") +NVERROR(NvErrorUsbfEpStalled, 0x000E0002, "remove me later!") +NVERROR(NvErrorUsbfEpError, 0x000E0003, "remove me later!") + + diff --git a/Start_WM/test6/inc/nvime.h b/Start_WM/test6/inc/nvime.h new file mode 100755 index 00000000..e533f47f --- /dev/null +++ b/Start_WM/test6/inc/nvime.h @@ -0,0 +1,849 @@ +/* + * Copyright (c) 2006 - 2007 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software and related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * nvime.h + * + * A collection of image enhancing functions that utilize the GoForce + * h/w. This file contains the common routines that are used by all + * image enhancing functions, as well as the APIs/enums/defines that are + * specific to all image enhancing functions. + * + * PLEASE NOTE: NvIme is not thread-safe. All API calls must be made in + * a single thread, or the application must explicitly protect each NvIme + * call with its own mutex. Any other usage is not guaranteed to work. + */ + +#ifndef NVIME +#define NVIME + +#include "nvtypes.h" +#include "GFRm.h" +#include "GFGx.h" +#include "GFVx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NvImeStruct_t *NvImeHandle; + +typedef enum { + NVIME_OK=0, + NVIME_OUT_OF_MEMORY=1, + NVIME_INIT_FAILED=2, + NVIME_INVALID_HANDLE=3, + NVIME_SURFACE_INDEX_OUT_OF_RANGE=4, + NVIME_INVALID_SURFACE=5, + NVIME_ILLEGAL_SURFACE_BASE=6, + NVIME_ILLEGAL_SURFACE_STRIDE=7, + NVIME_INVALID_ROTATION=8, + NVIME_INVALID_COORD=9, + NVIME_MISSING_SURFACE=10, + NVIME_INVALID_KERNEL=11, + NVIME_INVALID_KERNEL_SIZE=12, + NVIME_INVALID_PIXFMT=13, + NVIME_INVALID_LUT=14, + NVIME_UNSPECIFIED_OPERATION=15, + NVIME_UNSUPPORTED_OPERATION=16, + NVIME_OPERATION_FAILED=17, + NVIME_INVALID_FLAG=18, + NVIME_INVALID_GET=19, + NVIME_INVALID_SCALE=20, + NVIME_INVALID_BIAS=21, + NVIME_ILLEGAL_CSC_VALUES=22, + NVIME_ILLEGAL_COEFF=23, + NVIME_ILLEGAL_COEFF_ARRAY_SIZE=24, +} NvImeStatus; + + +// NvImeOpen() +// +// Initialize the library and return a handle to pass into all future +// API calls into this library. + +NvImeStatus NvImeOpen(GFRmHandle hRm, NvImeHandle *phIme); + + +// NvImeClose() +// +// Close down the library and relinquish all held resources. + +void NvImeClose(NvImeHandle *phIme); + + +// NvImeSetSourceSurface() +// +// Set a source surface. "index" can be in 0..NVIME_MAX_SOURCE_SURFACES-1. +// Because each source surface will be read as a texture by the 3D unit, +// each must abide by 3D's texture alignment restrictions. These +// restrictions are: +// +// SB1) Base of surface must begin at an aligned memory address. Use +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_ALIGNMENT_BYTES) +// to get this value. +// +// SB2) Stride must be a multiple of +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_STRIDE_BYTES) +// +// SB3) Stride must be a power of two +// +// SB4) Width must be between +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_MIN_WIDTH_PIXELS) and +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_MAX_WIDTH_PIXELS) +// +// SB5) Height must be between +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_MIN_HEIGHT_PIXELS) and +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_MAX_HEIGHT_PIXELS) +// +// Even though the 3D unit only understands textures that are powers of +// two in width and height, the width and height of the data contained +// within the source surfaces do NOT need to actually be a powers of two +// in size. Likewise, the height of the surface does not need to be a +// power of two (although the width always must be). +// +// If the width of the source data is not a power of two, then in addition +// to the above texture alignment restrictions, the following must be true: +// +// SBW1) Memory between the end of the data in a row and the end of the +// row must be allowed to be overwritten by this library. Because +// the 3D texture unit does bilinear interpolation, this library +// will need to replicate the last column of data out to the next +// (M/2) columns over, where M is the width of the kernel used. +// If width + (M/2) crosses over a power of two boundary, the +// adjusted width need only be as large as the power of two +// boundary. +// +// If the height of the source data is not a power of two, then in addition +// to the above texture alignment restrictions, the following must be true: +// +// SBH1) The height of the source surface does *not* need to be a power +// of two. +// +// SBH2) The height of the source surface needs to be large enough for the +// library to replicate the last row to the next (N/2) rows down, +// where N is the height of the kernel used. This area must be +// allowed to be overwritten by this library. If height + (N/2) +// crosses over a power of two boundary, the adjusted height need +// only be as large as the power of two boundary. +// +// Note that some image enhancing operations will only work on certain +// source pixel formats. The NvImeProcessRect() call will return an +// error code on a source pixel format mismatch. + +#define NVIME_MAX_SOURCE_SURFACES 5 +NvImeStatus NvImeSetSourceSurface(NvImeHandle hIme, + NvU32 index, + GFRMSURFACE *sourceSurface); + + +// NvImeSetDestSurface() +// +// Set the destination surface. Because the destination surface will be +// written by the 3D unit, each surface must abide by 3D's surface +// alignment restrictions. These restrictions are: +// +// DB1) Base of surface must begin at an aligned memory address. Use +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_ALIGNMENT_BYTES) +// to get this value. +// +// DB2) Stride must be a multiple of +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_STRIDE_BYTES) +// +// DB3) Width must be between +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_MIN_WIDTH_PIXELS) and +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_MAX_WIDTH_PIXELS) +// +// DB4) Height must be between +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_MIN_HEIGHT_PIXELS) and +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_MAX_HEIGHT_PIXELS) +// +// "rotation" specifies how to rotate the source surfaces onto the +// destination surface as part of the rendering process. "rotation" +// must be one of GFGx's fast rotation modes. Specifically these are: +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_IDENTITY | 0 | 1 | | 0 | 1 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 2 | 3 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_ROT_90 | 0 | 1 | | 1 | 3 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 0 | 2 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_ROT_180 | 0 | 1 | | 3 | 2 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 1 | 0 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_ROT_270 | 0 | 1 | | 2 | 0 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 3 | 1 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_FLIP_X | 0 | 1 | | 1 | 0 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 3 | 2 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_FLIP_Y | 0 | 1 | | 2 | 3 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 0 | 1 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_TRANS_LR | 0 | 1 | | 0 | 2 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 1 | 3 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_TRANS_RL | 0 | 1 | | 3 | 1 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 2 | 0 | +// +---+---+ +---+---+ +// +// Note that some image enhancing operations will only work on certain +// destination pixel formats. The NvImeProcessRect() call will return an +// error code on a destination pixel format mismatch. + +NvImeStatus NvImeSetDestSurface(NvImeHandle hIme, + GFRMSURFACE *destSurface, + NvU32 rotation); + + +// NvImeSetVxBltCSCCoeff() +// +// Set the Vx's color space conversion coefficients in the channel that +// NvIme is using. This API is nothing more than a pass-through to +// GFVxBltSetCSCCoeff(). However, it does need to be called if CSCCoeffs +// are desired to be changed. If GFVxBltSetCSCCoeff() is called directly +// by the application, the Vx issued commands in that channel will pick +// up the CSCCoeffs, but NvIme will not see them. +NvImeStatus NvImeSetVxBltCSCCoeff(NvImeHandle hIme, + GFVXCSCCOEF *pCoef, + NvU32 option); + + +// NvImeProcessRect() +// +// Render using the current algorithm. Application must call an NvIme +// API not contained within this header file that registers the algorithm +// to render with. +// +// "srcCoords" points to "numSrcCoords" GFRECTs. "srcCoords[i]" describes +// the region to use from the i'th sourceSurface. "dstCoord" points to a +// single GFRECT. If a coord extends beyond the size of the surface it +// refers to, it will be clamped to the surface boundaries. +// +// The range of pixels referred to in "dstCoord" and each "srcCoords[i]" +// do not have to match. Scaling up and down is supported. The quality +// of scaling up and down can vary with the particular image enhancing +// algorithm used. +// +// flags is used to pass down optional parameters to the renderer. +// +// NVIME_PR_FLAGS_DITHER_OUTPUT: dither color output to destination +// surface. This flag has no effect if destSurface->ColorFormat +// is GF_SURFACE_ARGB8888. + +#define NVIME_PR_FLAGS_DITHER_OUTPUT (1<<0) + +NvImeStatus NvImeProcessRect(NvImeHandle hIme, + NvU32 numSrcCoords, + GFRECT *srcCoords, + GFRECT *dstCoord, + NvU32 flags); + +// NvImeFinish() +// +// A blocking call that does not return until all previously called +// NvIme commands are complete. + +void NvImeFinish(NvImeHandle hIme); + + +// +// Kernel sizes +// +// When kernels are specified, they use row major order. For example a +// 3x3 kernel with weights arranged like so: +// +// w00 w01 w02 +// w10 w11 w12 +// w20 w21 w22 +// +// would be specified in memory in the following order: +// +// w00 w01 w02 w10 w11 w12 w20 w21 w22 + +typedef enum { + NVIME_KERNEL_SIZE_1x1=0, + NVIME_KERNEL_SIZE_3x1=1, + NVIME_KERNEL_SIZE_5x1=2, +} NvImeKernelSize; + + +// +// Pixel formats +// + +#define NVIME_COMPONENT_MASK(a) \ + (((1U << NVIME_PIXFMT_##a##_BITS) - 1) << NVIME_PIXFMT_##a##_SHIFT) + +#define NVIME_PIXFMT_L8_LUMINANCE_BITS 8 +#define NVIME_PIXFMT_L8_LUMINANCE_SHIFT 0 +#define NVIME_PIXFMT_L8_LUMINANCE_MASK NVIME_COMPONENT_MASK(L8_LUMINANCE) + +#define NVIME_PIXFMT_RGB565_BLUE_BITS 5 +#define NVIME_PIXFMT_RGB565_BLUE_SHIFT 0 +#define NVIME_PIXFMT_RGB565_BLUE_MASK NVIME_COMPONENT_MASK(RGB565_BLUE) +#define NVIME_PIXFMT_RGB565_GREEN_BITS 6 +#define NVIME_PIXFMT_RGB565_GREEN_SHIFT 5 +#define NVIME_PIXFMT_RGB565_GREEN_MASK NVIME_COMPONENT_MASK(RGB565_GREEN) +#define NVIME_PIXFMT_RGB565_RED_BITS 5 +#define NVIME_PIXFMT_RGB565_RED_SHIFT 11 +#define NVIME_PIXFMT_RGB565_RED_MASK NVIME_COMPONENT_MASK(RGB565_RED) + +#define NVIME_PIXFMT_RGB888_BLUE_BITS 8 +#define NVIME_PIXFMT_RGB888_BLUE_SHIFT 0 +#define NVIME_PIXFMT_RGB888_BLUE_MASK NVIME_COMPONENT_MASK(RGB888_BLUE) +#define NVIME_PIXFMT_RGB888_GREEN_BITS 8 +#define NVIME_PIXFMT_RGB888_GREEN_SHIFT 8 +#define NVIME_PIXFMT_RGB888_GREEN_MASK NVIME_COMPONENT_MASK(RGB888_GREEN) +#define NVIME_PIXFMT_RGB888_RED_BITS 8 +#define NVIME_PIXFMT_RGB888_RED_SHIFT 16 +#define NVIME_PIXFMT_RGB888_RED_MASK NVIME_COMPONENT_MASK(RGB888_RED) + +#define NVIME_PIXFMT_ARGB8888_BLUE_BITS 8 +#define NVIME_PIXFMT_ARGB8888_BLUE_SHIFT 0 +#define NVIME_PIXFMT_ARGB8888_BLUE_MASK NVIME_COMPONENT_MASK(ARGB8888_BLUE) +#define NVIME_PIXFMT_ARGB8888_GREEN_BITS 8 +#define NVIME_PIXFMT_ARGB8888_GREEN_SHIFT 8 +#define NVIME_PIXFMT_ARGB8888_GREEN_MASK NVIME_COMPONENT_MASK(ARGB8888_GREEN) +#define NVIME_PIXFMT_ARGB8888_RED_BITS 8 +#define NVIME_PIXFMT_ARGB8888_RED_SHIFT 16 +#define NVIME_PIXFMT_ARGB8888_RED_MASK NVIME_COMPONENT_MASK(ARGB8888_RED) +#define NVIME_PIXFMT_ARGB8888_ALPHA_SHIFT 24 +#define NVIME_PIXFMT_ARGB8888_ALPHA_MASK NVIME_COMPONENT_MASK(ARGB8888_ALPHA) + +#define NVIME_PIXFMT_BAYER10_BITS 10 +#define NVIME_PIXFMT_BAYER10_SHIFT 0 +#define NVIME_PIXFMT_BAYER10_MASK NVIME_COMPONENT_MASK(BAYER10) + +#define NVIME_PIXFMT_BAYER12_BITS 12 +#define NVIME_PIXFMT_BAYER12_SHIFT 0 +#define NVIME_PIXFMT_BAYER12_MASK NVIME_COMPONENT_MASK(BAYER12) + +#define NVIME_PIXFMT_BAYER14_BITS 14 +#define NVIME_PIXFMT_BAYER14_SHIFT 0 +#define NVIME_PIXFMT_BAYER14_MASK NVIME_COMPONENT_MASK(BAYER14) + +#define NVIME_PIXFMT_BAYER3D_LO_BITS 7 +#define NVIME_PIXFMT_BAYER3D_LO_SHIFT 0 +#define NVIME_PIXFMT_BAYER3D_LO_MASK NVIME_COMPONENT_MASK(BAYER3D_LO) +#define NVIME_PIXFMT_BAYER3D_HI_BITS 7 +#define NVIME_PIXFMT_BAYER3D_HI_SHIFT 8 +#define NVIME_PIXFMT_BAYER3D_HI_MASK NVIME_COMPONENT_MASK(BAYER3D_HI) + +typedef enum { + NVIME_PIXFMT_L8=0, // L=Luminance (R8=L8, G8=L8, B8=L8) + NVIME_PIXFMT_RGB565=1, + NVIME_PIXFMT_RGB888=2, + NVIME_PIXFMT_ARGB8888=3, + NVIME_PIXFMT_BAYER10=4, + NVIME_PIXFMT_BAYER12=5, + NVIME_PIXFMT_BAYER14=6, + NVIME_PIXFMT_BAYER3D=7, +} NvImePixelFormat; + + +// +// LUT values +// + +#define NVIME_LUT_ENTRIES 256 + + +// +// Scale factors +// + +typedef enum { + NVIME_SCALE_1_0=0, + NVIME_SCALE_2_0=1, + NVIME_SCALE_4_0=2, +} NvImeScaleFactor; + + +/* + * Below are APIs used to control the sharpening image enhancement + * operation. Sharpening takes in a YUV420p source surface and outputs + * to a destination surface of type RGB565, ARGB8888 or YUV420p. + * ==================================================================== + */ + +// NvImeSharpenGetIntegerv() +// +// Return the value or values of a selected parameter that apply to +// the YUV420p sharpen image enhancing operation. +// +// NVIME_SHARPEN_GET_SRC_SURF_ALIGNMENT_BYTES +// NVIME_SHARPEN_GET_DST_SURF_ALIGNMENT_BYTES +// +// "params" returns 1 value, the SOURCE/DEST surface's starting +// address must be aligned to this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_STRIDE_BYTES +// NVIME_SHARPEN_GET_DST_SURF_STRIDE_BYTES +// +// "params" returns 1 value, the SOURCE/DEST surface's stride must +// be a multiple of this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_MIN_WIDTH_PIXELS +// NVIME_SHARPEN_GET_DST_SURF_MIN_WIDTH_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's width in +// pixels must be greater than or equal to this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_MAX_WIDTH_PIXELS +// NVIME_SHARPEN_GET_DST_SURF_MAX_WIDTH_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's width in +// pixels must be less than or equal to this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_MIN_HEIGHT_PIXELS +// NVIME_SHARPEN_GET_DST_SURF_MIN_HEIGHT_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's height in +// pixels must be greater than or equal to this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_MAX_HEIGHT_PIXELS +// NVIME_SHARPEN_GET_DST_SURF_MAX_HEIGHT_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's height in +// pixels must be less than or equal to this value. + +typedef enum { + NVIME_SHARPEN_GET_SRC_SURF_ALIGNMENT_BYTES=0, + NVIME_SHARPEN_GET_SRC_SURF_STRIDE_BYTES=1, + NVIME_SHARPEN_GET_SRC_SURF_MIN_WIDTH_PIXELS=2, + NVIME_SHARPEN_GET_SRC_SURF_MAX_WIDTH_PIXELS=3, + NVIME_SHARPEN_GET_SRC_SURF_MIN_HEIGHT_PIXELS=4, + NVIME_SHARPEN_GET_SRC_SURF_MAX_HEIGHT_PIXELS=5, + NVIME_SHARPEN_GET_DST_SURF_ALIGNMENT_BYTES=6, + NVIME_SHARPEN_GET_DST_SURF_STRIDE_BYTES=7, + NVIME_SHARPEN_GET_DST_SURF_MIN_WIDTH_PIXELS=8, + NVIME_SHARPEN_GET_DST_SURF_MAX_WIDTH_PIXELS=9, + NVIME_SHARPEN_GET_DST_SURF_MIN_HEIGHT_PIXELS=10, + NVIME_SHARPEN_GET_DST_SURF_MAX_HEIGHT_PIXELS=11, +} NvImeSharpenGet; + +NvImeStatus NvImeSharpenGetIntegerv(NvImeHandle hIme, + NvImeSharpenGet name, + int *params); + + +// NvImeSharpenParams() +// +// Specify sharpen parameters to use during subsequent call to +// NvImeProcessRect(). +// +// When NvImeProcessRect() is called with sharpening in effect, there +// are additional restrictions are applied: +// +// 1) Only sourceSurfaces[0] is used. Which means that numSrcCoords +// must be 1. Stretching sub-regions of a surface is not +// supported. Because pixels will be replicated as needed to +// provide a buffer for the filter kernel, if one were to use +// a sub-region of a surface, valid data would be over-written. +// dstCoord can have arbitrary values that allow scaling within +// destSurface. +// +// 2) sourceSurfaces[0]->ColorFormat must be one of: +// +// GF_SURFACE_YUV420 +// GF_SURFACE_JPEGDEC +// GF_SURFACE_MPEGDEC +// +// 3) destSurface->ColorFormat must be one of: +// +// GF_SURFACE_RGB565 +// GF_SURFACE_ARGB8888 +// GF_SURFACE_YUV420 +// GF_SURFACE_JPEGDEC +// GF_SURFACE_MPEGDEC +// +// 4) The rotation value must be GFGXEX2_FAST_ROTATE_IDENTITY (any +// desired rotation must be performed after this library has +// finished its processing). +// +// The sharpening algorithm is described as follows: +// +// 1) The Y data in sourceSurfaces[0] is replicated as needed. The +// number of pixels replicated at the end of each row will be: +// +// MAX( (M/2), distance to next power-of-two ) +// +// where M is the width of the kernel. Note that if +// sourceSurfaces[0]'s width is a power-of-two, then the distance +// to the next power-of-two will be zero, and no pixels will be +// replicated. +// +// The number of pixels replicated at the bottom of each column +// will be: +// +// MAX( (N/2), distance to next power-of-two ) +// +// where N is the height of the kernel. Note that if +// sourceSurfaces[0]'s height is a power-of-two, then the distance +// to the next power-of-two will be zero, and no pixels will be +// replicated. +// +// 2) If destSurface->ColorFormat is GF_SURFACE_RGB565 or +// GF_SURFACE_ARGB8888, then a 2D StretchBlit is performed on +// sourceSurfaces[0] to destSurface. The full range of +// sourceSurfaces[0] will be scaled to the region indicated by +// dstCoord within destSurface. +// +// If destSurface->ColorFormat is GF_SURFACE_YUV420, +// GF_SURFACE_JPEGDEC or GF_SURFACE_MPEGDEC then no StretchBlit +// will be performed. The 3D stage of the algorithm will write +// the destination directly without blending to an RGB surface. +// +// 3) For each pixel in the region within destSurface specified by +// dstCoord, the 3D unit will perform a number of texture reads from +// sourceSurfaces[0] that matches the size of the kernel. Each +// texture read will be bilinearly filtered. The texture reads will +// be multiplied times the S1.8 kernel weights, summed together, +// scaled by one of 1.0, 2.0 or 4.0, a bias is added, and the result +// is clamped to the 0.0 to 1.0 range (note that intermediate values +// that exceed the h/w's S1.8 numeric range will be clamped to S1.8). +// The final clamped value will index into the provided LUT, which +// contains biased color values. +// +// When destSurface->ColorFormat is GF_SURFACE_RGB565 or ARGB8888: +// +// Each color channel from the LUT value will be multiplied by +// 2.0 and then have 1.0 subtracted from it. These unbiased +// colors will be added to the pixel in destSurface. +// +// When destSurface->ColorFormat is GF_SURFACE_YUV420, +// GF_SURFACE_JPEGDEC or GF_SURFACE_MPEGDEC: +// +// The red color channel from the LUT value will be multiplied +// by 2.0 and then have 1.0 subtracted from it. This unbiased +// color will be added to the Y value from sourceSurfaces[0] +// and be written to the Y pixel in destSurface. The U and V +// pixels in destSurface will be scaled by the 3D h/w using a +// 2x2 filter. No sharpening is applied to the U and V pixels. +// +// Below is a psuedo-code approximation for this part of the algorithm: +// +// // for each pixel +// for ( y=dstCoord->top ; x<=dstCoord->bottom ; y++ ) { +// for ( x=dstCoord->left ; x<=dstCoord->right ; x++ ) { +// +// // get proper indices for sourceSurfaces[0] +// srcX = sourcesSurfaces[0].width * x/destSurface.width; +// srcY = sourcesSurfaces[0].height * y/destSurface.height; +// +// // for each kernel entry +// idx = 0; +// for ( ky=0 ; ky 1.0) idx = 1.0; +// +// if ((destSurface->ColorFormat == GF_SURFACE_YUV420) || +// (destSurface->ColorFormat == GF_SURFACE_JPEGDEC) || +// (destSurface->ColorFormat == GF_SURFACE_MPEGDEC)) { +// // write the color value +// dstColor[x,y] = srcColor[srcX, srcY] + +// 2.0 * lut[NVIME_LUT_ENTRIES * idx] - 1.0; +// } else { +// // update color value +// dstColor[x,y] += 2.0 * lut[NVIME_LUT_ENTRIES * idx] - 1.0; +// } +// } +// } +// +// The supported kernel sizes are: +// +// NVIME_KERNEL_SIZE_1x1 +// NVIME_KERNEL_SIZE_3x1 +// NVIME_KERNEL_SIZE_5x1 +// +// Each value in the kernel must be in S1.8 format, which means values +// between -2 inclusive and +2 exclusive in increments of 1/256 are +// representable. +// +// The LUT must contain NVIME_LUT_ENTRIES entries, each of size NvU32. +// The supported LUT formats are: +// +// NVIME_PIXFMT_L8 +// NVIME_PIXFMT_RGB888 +// +// Refer to the NVIME_PIXFMT_* macros for appropriate color channel bit +// positions. When destSurface->ColorFormat is GF_SURFACE_YUV420, +// GF_SURFACE_JPEGDEC or GF_SURFACE_MPEGDEC the Y buffer is processed +// directly without going through an RGB space. Because the Y buffer is +// monochrome, only the red channel of an RGB888 LUT will be used when +// the destSurface->ColorFormat is GF_SURFACE_YUV420, GF_SURFACE_JPEGDEC +// or GF_SURFACE_MPEGDEC. +// +// The finalScale parameter can be any of NVIME_SCALE_1_0, NVIME_SCALE_2_0, +// or NVIME_SCALE_4_0. +// +// The finalBias parameter must be in S1.8 format. + +NvImeStatus +NvImeSharpenParams(NvImeHandle hIme, + NvImeKernelSize kernelSize, + NvU32 *kernel, + NvImePixelFormat lutFormat, + NvU32 *lut, + NvImeScaleFactor finalScale, + NvU32 finalBias); + + +/* + * Below are APIs used to control the anti-vignetting (also known as + * lens correction) image enhancement operation. Anti-vignetting takes + * in a BAYER3D source surface and outputs either BAYER10, BAYER12 or + * BAYER14 data to the same source surface. BAYER3D is format that has + * 14bits of data like BAYER14, but has unused bits at positions 8 and 16. + * So if your 16bits of data looked like --dcba9876543210, these would + * be stored in BAYER3D as -dcba987-6543210. + * ==================================================================== + */ + +// NvImeAntivigGetIntegerv() +// +// Return the value or values of a selected parameter that apply to +// the BAYER3D anti-vignetting image operation. +// +// NVIME_ANTIVIG_GET_SURF_ALIGNMENT_BYTES +// +// "params" returns 1 value, the SOURCE/DEST surface's starting +// address must be aligned to this value. +// +// NVIME_ANTIVIG_GET_SURF_STRIDE_BYTES +// +// "params" returns 1 value, the SOURCE/DEST surface's stride must +// be a multiple of this value. +// +// NVIME_ANTIVIG_GET_SURF_MIN_WIDTH_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's width in +// pixels must be greater than or equal to this value. +// +// NVIME_ANTIVIG_GET_SURF_MAX_WIDTH_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's width in +// pixels must be less than or equal to this value. +// +// NVIME_ANTIVIG_GET_SURF_MIN_HEIGHT_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's height in +// pixels must be greater than or equal to this value. +// +// NVIME_ANTIVIG_GET_SURF_MAX_HEIGHT_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's height in +// pixels must be less than or equal to this value. +// +// NVIME_ANTIVIG_GET_COEFF_ARRAY_MIN_WIDTH +// +// "params" returns 1 value, the minimum "widthCoeffArrays" that +// can be passed into NvImeAntivigParams. +// +// NVIME_ANTIVIG_GET_COEFF_ARRAY_MAX_WIDTH +// +// "params" returns 1 value, the maximum "widthCoeffArrays" that +// can be passed into NvImeAntivigParams. +// +// NVIME_ANTIVIG_GET_COEFF_ARRAY_MIN_HEIGHT +// +// "params" returns 1 value, the minimum "heightCoeffArrays" that +// can be passed into NvImeAntivigParams. +// +// NVIME_ANTIVIG_GET_COEFF_ARRAY_MAX_HEIGHT +// +// "params" returns 1 value, the maximum "heightCoeffArrays" that +// can be passed into NvImeAntivigParams. + +typedef enum { + NVIME_ANTIVIG_GET_SURF_ALIGNMENT_BYTES=0, + NVIME_ANTIVIG_GET_SURF_STRIDE_BYTES=1, + NVIME_ANTIVIG_GET_SURF_MIN_WIDTH_PIXELS=2, + NVIME_ANTIVIG_GET_SURF_MAX_WIDTH_PIXELS=3, + NVIME_ANTIVIG_GET_SURF_MIN_HEIGHT_PIXELS=4, + NVIME_ANTIVIG_GET_SURF_MAX_HEIGHT_PIXELS=5, + NVIME_ANTIVIG_GET_COEFF_ARRAY_MIN_WIDTH=6, + NVIME_ANTIVIG_GET_COEFF_ARRAY_MAX_WIDTH=7, + NVIME_ANTIVIG_GET_COEFF_ARRAY_MIN_HEIGHT=8, + NVIME_ANTIVIG_GET_COEFF_ARRAY_MAX_HEIGHT=9, +} NvImeAntivigGet; + +NvImeStatus NvImeAntivigGetIntegerv(NvImeHandle hIme, + NvImeAntivigGet name, + int *params); + + +// NvImeAntivigParams() +// +// Specify anti-vignetting parameters to use during subsequent call to +// NvImeProcessRect(). +// +// When NvImeProcessRect() is called with anti-vignetting in effect, +// there are additional restrictions that are applied: +// +// 1) Only sourceSurfaces[0] is used. Which means that numSrcCoords +// must be 1. +// +// 2) sourceSurfaces[0]->ColorFormat must be GF_SURFACE_BAYER16. +// The actual data contained in the surface must be in the +// BAYER3D format. BAYER3D has 14 bits of data, where bits 13 +// and 7 are ignored. So if your data value is --dcba9876543210, +// that would be stored in BAYER3D format as -dcba987-6543210. +// +// 3) The contents of the structure pointed to by destSurface must +// be equal to the contents of the structure pointed to by +// sourceSurfaces[0]. +// +// 4) The contents of the structure pointed to by dstCoord must be +// equal to the contents of the structure pointed to by +// srcCoords[0]. +// +// 5) The rotation value must be GFGXEX2_FAST_ROTATE_IDENTITY (any +// desired rotation must be performed after this library has +// finished its processing). +// +// The anti-vignetting algorithm is described below: +// +// 1) The 4 passed in coefficient arrays are scanned looking for the +// largest gain value. The largest gain is used to determine +// whether the overall coefficient range is in [0.0 .. 2.0], +// [0.0 .. 4.0], [0.0 .. 8.0] or [0.0 .. 16.0]. The lower the +// maximum gain, the more precise the output will be. Here is +// a table showing the output format as a function of the maximum +// gain value: +// +// Maximum gain Output pixel format +// ------------- ------------------- +// [0.0 .. 2.0] BAYER14 +// [0.0 .. 4.0] BAYER12 +// [0.0 .. 8.0] BAYER12 +// [0.0 .. 16.0] BAYER10 +// +// 2) After the maximum gain has been determined, the coefficient +// arrays are divided by their maximum value rounded up to a power +// of 2, and stored in an 8bit value. +// +// 3) When NvImeProcessRect is called, the 8bit gain values for the +// appropriate 00, 01, 10, 11 pixel are bilinearly interpolated. +// The result is multiplied times the BAYER3D pixel value from +// the source surface and then written back in place in a +// BAYER10/12/14 format. +// +// 4) NvImeProcessRect can process an entire BAYER3D buffer at a time, +// or a horizontal swath of the buffer. This is to support large +// buffers (like 5Mpixel) where it may not be practical (or even +// possible) to have multiple buffers residing in memory at the same +// time. +// +// NvImeAntivigAdjustScanline() modifies the access pattern of the +// 8bit gain values as if srcCoords[0].top were scanlineBias larger. +// This shifts the accesses down. +// +// For example, suppose you had a 2048x64 BAYER3D surface which is +// used to hold 32 pixel high swaths of a 2048x2048 surface in +// a double buffered manner. You would process the buffer like so: +// +// srcCoordsLow.top = 0; +// srcCoordsLow.left = 0; +// srcCoordsLow.right = 2047; +// srcCoordsLow.bottom = 31; +// +// srcCoordsHigh.top = 32; +// srcCoordsHigh.left = 0; +// srcCoordsHigh.right = 2047; +// srcCoordsHigh.bottom = 63; +// +// // Fill SourceSurface[0] rows [0..31] with camera rows [0..31] +// NvImeAntivigAdjustScanline(hIme, 0); +// NvImeProcessRects(hIme, 1, &srcCoordsLow, &srcCoordsLow, 0); +// +// // Fill SourceSurface[0] rows [32..63] with camera rows [32..63] +// NvImeProcessRects(hIme, 1, &srcCoordsHigh, &srcCoordsHigh, 0); +// +// // Fill SourceSurface[0] rows [0..31] with camera rows [64..95] +// NvImeAntivigAdjustScanline(hIme, 32); +// NvImeProcessRects(hIme, 1, &srcCoordsLow, &srcCoordsLow, 0); +// +// // Fill SourceSurface[0] rows [32..63] with camera rows [96..127] +// NvImeProcessRects(hIme, 1, &srcCoordsHigh, &srcCoordsHigh, 0); +// +// // Fill SourceSurface[0] rows [0..31] with camera rows [128..159] +// NvImeAntivigAdjustScanline(hIme, 64); +// NvImeProcessRects(hIme, 1, &srcCoordsLow, &srcCoordsLow, 0); +// +// // Fill SourceSurface[0] rows [32..63] with camera rows [160..191] +// NvImeProcessRects(hIme, 1, &srcCoordsHigh, &srcCoordsHigh, 0); +// +// // and so on... + +NvImeStatus +NvImeAntivigParams(NvImeHandle hIme, + NvU32 widthCoeffArrays, + NvU32 heightCoeffArrays, + float *coeffsPix00, + float *coeffsPix01, + float *coeffsPix10, + float *coeffsPix11, + NvU32 totalSurfaceWidth, + NvU32 totalSurfaceHeight, + NvImePixelFormat *outFormat); + +NvImeStatus +NvImeAntivigAdjustScanline(NvImeHandle hIme, NvU32 scanlineBias); + +#ifdef __cplusplus +} +#endif + +#endif /* NVIME */ diff --git a/Start_WM/test6/inc/nvirq.h b/Start_WM/test6/inc/nvirq.h new file mode 100755 index 00000000..d3bf5d8b --- /dev/null +++ b/Start_WM/test6/inc/nvirq.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef NVIRQ_H +#define NVIRQ_H + +/** NvIrq - Interrupt abstraction layer: + + This provides a simple interface for querying and masking abstract interrupt + events. The interface is designed to be used inside of the OEM's ISR or IST. + + NvIrq needs NvOsPhysicalMemMap and NvOsPhysicalMemUnmap (Only uncached + write-through functionality is used). NvOsSharedMem* is needed if NvIrq + isn't initialized as a singleton. + + NvIrq is not thread-safe. + */ + +#include "nvcommon.h" +#include "nverror.h" +#include "nvboard.h" + +/** NvIrqChannel enum defines available I/O channels. No two I/O operations can + safely occur at the same time on a channel. (This is only important in + indirect addressing. In direct address I/O operators are atomic and there + is no concept of channels). + */ +typedef enum +{ + /* Channel used while not in ISR. This channel is used by all user-mode code. */ + NvIrqChannel_Normal, + + /* Channel used in ISR context */ + NvIrqChannel_Isr +} NvIrqChannel; + +/* NvIrqInterruptPortInfo struct describes the MMIO layout of the interrupt + status registers */ +typedef struct NvIrqInterruptPortInfo_t +{ + /* Offset of status register */ + NvU32 statusOffset; + + /* Offset of mask register */ + NvU32 maskOffset; +} NvIrqInterruptPortInfo; + +/** NvIrqInit - Method to initialize the NvIrq API. + + This method is to be called before any other NvIrq methods can be used. + + If NvIrq is not initialized as a singleton, NvIrq will put its state in + shared memory. + */ +NvError +NvIrqInit( const NvBoardMode *pMode, const NvBoardApertures *pApertures, + NvBool singleton ); + +/** NvIrqDeInit - Method to deinitialize the NvIrq API. + */ +void +NvIrqDeInit( void ); + +/** NvIrqPostChipInit - To be called after the chip is intialized. + + This method should be called during NvBoardPostChipInit. If NvIrqInit succeeds + NvIrqEnableInterrupt() should be used to unmask the global interrupt line. + */ +NvError +NvIrqPostChipInit( NvIrqChannel channel ); + +/** NvIrqPreChipDeInit - To be called before chip is shutdown. + + This method should be called during NvBoardPreChipDeInit. NvIrqDisableInterrupt() + should be called before invoking this method. + */ +void +NvIrqPreChipDeInit( NvIrqChannel channel ); + +/** NvIrqFastScan - Method to quickly check if interrupt is pending + + This method is faster than NvIrqScanForEvent. It only checks whether an + interrupt is pending or not. NvIrqScanForEvent should be called from an + IST to do the actual decoding. This is useful when ISR latency is + important. + + If an interrupt is pending the global SCxx interrupt line is masked + and should reenabled using NvIrqEnableInterrupt after NvIrqScanForEvent + is called. + */ +NvBool +NvIrqFastScan( NvIrqChannel channel ); + +/** NvIrqScanForEvent - Method to check SCxx for pending events. + + This method should be called from an ISR or IST. If a pending event is + found, the event is masked. Once an upper layer clears the source of + the event in hardware, the event can be reenabled. + + @retval NvSuccess - on success + NvErrorEventNotFound - no event found + */ +NvError +NvIrqScanForEvent( NvIrqChannel channel, NvDeviceEvent *event ); + +/** NvIrqIsEventPending - Check whether the event is pending + */ +NvBool +NvIrqIsEventPending( NvIrqChannel channel, NvDeviceEvent event ); + +/** NvIrqEnableInterrupt - Method to unmask global interrupt line + */ +void +NvIrqEnableInterrupt( NvIrqChannel channel ); + +/** NvIrqDisableInterrupt - Method to mask global interrupt line + */ +void +NvIrqDisableInterrupt( NvIrqChannel channel ); + +/** NvIrqEnableEvent - Method to unmask an event + */ +void +NvIrqEnableEvent( NvIrqChannel channel, NvDeviceEvent event ); + +/** NvIrqDisableEvent - Method to mask an event + */ +void +NvIrqDisableEvent( NvIrqChannel channel, NvDeviceEvent event ); + +/** NvIrqQueryInterruptPortInfo - Method to query interrupt port info. Calling + this method should be strongly avoided. + */ +NvError +NvIrqQueryInterruptPortInfo( NvIrqInterruptPortInfo *pPortInfo ); + +#endif // NVIRQ_H diff --git a/Start_WM/test6/inc/nvtypes.h b/Start_WM/test6/inc/nvtypes.h new file mode 100755 index 00000000..ba01db2d --- /dev/null +++ b/Start_WM/test6/inc/nvtypes.h @@ -0,0 +1,258 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1998 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1998 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ + + + /***************************************************************************\ +|* *| +|* NV Architecture Interface *| +|* *| +|* defines common widths used to access hardware in of NVIDIA's *| +|* Unified Media Architecture (TM). *| +|* *| + \***************************************************************************/ + + +#ifndef NVTYPES_INCLUDED +#define NVTYPES_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpuopsys.h" + +#define NVRM_64 1 +#if defined(NV_64_BITS) +#define NVRM_TRUE64 1 +#endif + + /***************************************************************************\ +|* Typedefs *| + \***************************************************************************/ + +typedef unsigned char NvV8; /* "void": enumerated or multiple fields */ +typedef unsigned short NvV16; /* "void": enumerated or multiple fields */ +typedef unsigned char NvU8; /* 0 to 255 */ +typedef unsigned short NvU16; /* 0 to 65535 */ +typedef signed char NvS8; /* -128 to 127 */ +typedef signed short NvS16; /* -32768 to 32767 */ +typedef signed int NvS32; /* -2147483648 to 2147483647 */ +typedef float NvF32; /* IEEE Single Precision (S1E8M23) */ +typedef double NvF64; /* IEEE Double Precision (S1E11M52) */ + +/* mainly for 64-bit linux, where long is 64 bits + * and win9x, where int is 16 bit. + */ +#if (defined(NV_UNIX) || defined(vxworks) || defined(NV_WINDOWS_CE) || \ + defined(__arm) || defined(__IAR_SYSTEMS_ICC__) || defined(NV_QNX) || \ + defined(NV_INTEGRITY) || defined(NV_MODS) || defined(__GNUC__) ) && \ + !defined(NV_MACINTOSH) +typedef unsigned int NvV32; /* "void": enumerated or multiple fields */ +typedef unsigned int NvU32; /* 0 to 4294967295 */ +#else +typedef unsigned long NvV32; /* "void": enumerated or multiple fields */ +typedef unsigned long NvU32; /* 0 to 4294967295 */ +#endif + +/* 64-bit types for compilers that support them, plus some obsolete variants */ +#if defined(__GNUC__) || defined(__arm) || defined(__IAR_SYSTEMS_ICC__) || defined(__ghs__) || defined(_WIN64) +typedef unsigned long long NvU64; /* 0 to 18446744073709551615 */ +typedef long long NvS64; /* 2^-63 to 2^63-1 */ +#else +typedef unsigned __int64 NvU64; /* 0 to 18446744073709551615 */ +typedef __int64 NvS64; /* 2^-63 to 2^63-1 */ +#endif + +/* Boolean type */ +enum { NV_FALSE = 0, NV_TRUE = 1 }; +typedef NvU8 NvBool; + +/* Macros to extract the low and high parts of a 64-bit unsigned integer */ +/* Also designed to work if someone happens to pass in a 32-bit integer */ +#define NvU64_HI32(n) ((NvU32)(((NvU64)(n)) >> 32)) +#define NvU64_LO32(n) ((NvU32)((NvU64)(n))) +#define NvU40_HI32(n) ((NvU32)((((NvU64)(n))>>8)&0xffffffff)) +#define NvU40_HI24of32(n) ((NvU32)((((NvU64)(n)& 0xffffffff))&0xffffff00)) + + /***************************************************************************\ +|* *| +|* 64 bit type definitions for use in interface structures. *| +|* *| + \***************************************************************************/ + +#if defined(NV_64_BITS) + +typedef void* NvP64; /* 64 bit void pointer */ +typedef NvU64 NvUPtr; /* pointer sized unsigned int */ + +#define NvP64_VALUE(n) (n) + +#else + +typedef NvU64 NvP64; /* 64 bit void pointer */ +typedef NvU32 NvUPtr; /* pointer sized unsigned int */ + +#define NvP64_VALUE(n) ((void *)(NvUPtr)(n)) + +#endif + +// XXX Obsolete -- get rid of me... +typedef NvP64 NvP64_VALUE_T; +typedef NvUPtr NV_UINTPTR_T; +#define NvP64_LVALUE(n) (n) +#define NvP64_SELECTOR(n) (0) + +/* Useful macro to hide required double cast */ +#define NV_PTR_TO_NvP64(n) (NvP64)(NV_UINTPTR_T)(n) + +/* obsolete stuff */ +/* MODS needs to be able to build without these definitions because they collide + with some definitions used in mdiag. */ +#ifndef DONT_DEFINE_U032 +typedef NvV8 V008; +typedef NvV16 V016; +typedef NvV32 V032; +typedef NvU8 U008; +typedef NvU16 U016; +typedef NvU32 U032; +typedef NvS8 S008; +typedef NvS16 S016; +typedef NvS32 S032; +#endif +#if defined(MACOS) || defined(macintosh) || defined(__APPLE_CC__) || defined(NV_MODS) || defined(MINIRM) || defined(NV_UNIX) || defined (NV_QNX) +/* more obsolete stuff */ +/* need to provide these on macos9 and macosX */ +#if defined(__APPLE_CC__) /* gross but Apple osX already claims ULONG */ +#undef ULONG // just in case +#define ULONG unsigned long +#else +typedef unsigned long ULONG; +#endif +typedef unsigned char *PUCHAR; +#endif + +#if !defined(NV_PTR) + /* Supports 32bit libraries on Win64 + See drivers\opengl\include\nvFirst.h for explanation */ +#define NV_PTR +#define CAST_NV_PTR(p) p +#endif + +/* Aligns fields in structs so they match up between 32 and 64 bit builds */ +/* XXX Mac still uses structures without alignment -- needs to be fixed */ +#if (defined(__GNUC__) || defined(NV_QNX)) && !defined(NV_MACINTOSH) +#define NV_ALIGN_BYTES(size) __attribute__ ((aligned (size))) +#elif defined(__arm) +#define NV_ALIGN_BYTES(size) __align(ALIGN) +#else +// XXX This is dangerously nonportable! We really shouldn't provide a default +// version of this that doesn't do anything. +#define NV_ALIGN_BYTES(size) +#endif + +// NV_DECLARE_ALIGNED() can be used on all platforms. +// This macro form accounts for the fact that __declspec on Windows is required +// before the variable type, +// and NV_ALIGN_BYTES is required after the variable name. +#if defined(NV_WINDOWS) +#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) __declspec(align(ALIGN)) TYPE_VAR +#elif defined(__GNUC__) || defined(NV_QNX) +#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) TYPE_VAR __attribute__ ((aligned (ALIGN))) +#elif defined(__arm) +#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) __align(ALIGN) TYPE_VAR +#endif + + +/***************************************************************************\ +|* Function Declaration Types *| + \***************************************************************************/ + +// stretching the meaning of "nvtypes", but this seems to least offensive +// place to re-locate these from nvos.h which cannot be included by a number +// of builds that need them + +#if defined(NV_WINDOWS) + + #define NV_INLINE __inline + + #if _MSC_VER >= 1200 + #define NV_FORCEINLINE __forceinline + #else + #define NV_FORCEINLINE __inline + #endif + + #define NV_APIENTRY __stdcall + #define NV_FASTCALL __fastcall + #define NV_CDECLCALL __cdecl + #define NV_STDCALL __stdcall + +#else // defined(NV_WINDOWS) + + #if defined(__GNUC__) || defined(__INTEL_COMPILER) + #define NV_INLINE __inline__ + #elif defined (macintosh) + #define NV_INLINE inline + #elif defined(__arm) + #define NV_INLINE __inline + #else + #define NV_INLINE + #endif + + #if defined(__GNUC__) + // GCC 3.1 and beyond support the always_inline function attribute. + #if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) + #define NV_FORCEINLINE __inline__ __attribute__((always_inline)) + #else + #define NV_FORCEINLINE __inline__ + #endif + #else /* defined(__GNUC__) */ + #define NV_FORCEINLINE NV_INLINE + #endif + + #define NV_APIENTRY + #define NV_FASTCALL + #define NV_CDECLCALL + #define NV_STDCALL + +#endif // defined(NV_WINDOWS) + +#ifdef __cplusplus +}; +#endif + +#endif /* NVTYPES_INCLUDED */ diff --git a/Start_WM/test6/inc/vssver2.scc b/Start_WM/test6/inc/vssver2.scc new file mode 100755 index 0000000000000000000000000000000000000000..aaf2f3863685f3f430796c71bfeea422f9c199b3 GIT binary patch literal 1261 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

      JR#-<)Fs-)r*QZ6wv!E5}ZyjEA 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 +#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) +#define SHELL_AYGSHELL +#endif + +#ifdef _CE_DCOM +#define _ATL_APARTMENT_THREADED +#endif + +#include + +#include +#pragma comment(lib, "aygshell.lib") + + + +#include +#include + +#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) +#ifndef _DEVICE_RESOLUTION_AWARE +#define _DEVICE_RESOLUTION_AWARE +#endif +#endif + +#ifdef _DEVICE_RESOLUTION_AWARE +#include "DeviceResolutionAware.h" +#endif + +#if _WIN32_WCE < 0x500 && ( defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) ) + #pragma comment(lib, "ccrtrtti.lib") + #ifdef _X86_ + #if defined(_DEBUG) + #pragma comment(lib, "libcmtx86d.lib") + #else + #pragma comment(lib, "libcmtx86.lib") + #endif + #endif +#endif + +#include + +// TODO: reference additional headers your program requires here diff --git a/Start_WM/test6/test6.cpp b/Start_WM/test6/test6.cpp new file mode 100755 index 00000000..1769c2eb --- /dev/null +++ b/Start_WM/test6/test6.cpp @@ -0,0 +1,127 @@ +// test6.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include "windows.h" +#include "wingdi.h" +#include "GF.h" +#include "GFGx.h" +#include "GFDx.h" +#include "GFVx.h" +#include "GFDiag.h" +#include +#include + +// Rotation related defines +#define H_FLIP_BIT 0x00000001 +#define V_FLIP_BIT 0x00000002 +#define XYSWAP_BIT 0x00000004 +#define ROT_IDENTIY 0x0 +#define ROT_90 (XYSWAP_BIT | H_FLIP_BIT) +#define ROT_180 (H_FLIP_BIT | V_FLIP_BIT) +#define ROT_270 (XYSWAP_BIT | V_FLIP_BIT) +#define ROT_H_FLIP (H_FLIP_BIT) +#define ROT_V_FLIP (V_FLIP_BIT) +#define ROT_XYSWAP (XYSWAP_BIT) +#define ROT_SWAP_X_Y (XYSWAP_BIT | H_FLIP_BIT | V_FLIP_BIT) + +// Overlay options +#define NO_OVERLAY 0 +#define RGB565_WITH_VXBLT 1 +#define ARGB8888_WITH_VXBLT 2 +#define YUV_WITH_FR 3 //(FR = fast rotate) + +#define COLOR_KEY (255<<16 | 0<<8 | 255)//RGB888 + +//kbm gui 2.2 ¹Ý¿µ +#define BLEND_KEY (5<<16 | 18<<8 | 41)//RGB888 +//#define BLEND_KEY (37<<16 | 54<<8 | 84)//RGB888 + +#define BACKGROUND_RGB565 (0<<11 | 0<<5 | 0)//RGB565 + +#define ALPHA_VALUE (165<<16 |165<<8 | 165) +#define OVERLAY_SURF 2 + +#define DBGERROR 1 +#define DBGINFO 2 + +#define DEFAULT_LCD_WIDTH 800 +#define DEFAULT_LCD_HEIGHT 480 + +FILE *fp; +int tpos=0; +void text_d(LPWSTR s){ + + fwprintf(fp, L"debug: %s \n",s); + + HDC hd=GetDC(0); + RECT r; + r.left=0; + r.top=tpos; + r.right=480; + r.bottom=800; + if (!tpos){Rectangle(hd,0,0,480,800);} + tpos+=25; + DrawText(hd,s,wcslen(s),&r,0); + if (tpos>700){tpos=0;} + +} +int _tmain(int argc, _TCHAR* argv[]) +{ + + if (( fp= fopen("log10.txt", "w")) == NULL) { + printf("He óäàåòñÿ îòêðûòü ôàéë.\n"); + } + + + text_d(L"Started"); + GFRECT destRect; + GFRECT srcRect; + GFRECT srcXYRect; // src rect for an xyswapped src image + GF_RETTYPE status; + GFRMSURFACEREQUEST surfReq; + GFDXPROPERTY DxProp;// Dx Specific + NvU32 width, height, bpp, stride, startAddr; + GFRmHandle pm=GFRmOpen( NULL ); + GFDxHandle px; + GFDxOpen(pm, &(px), GF_STATE_DEFAULT, NULL); + + + GFDxGetAttribute(px ,LCD_MAIN, GFDX_ATTR_STARTADDR, &startAddr); + WCHAR buff[200]; + wsprintf(buff,L"%x",startAddr); + text_d(L"startAddr"); + text_d(buff); + text_d(L"fix"); + //GFDxSetAttributeWithCS + startAddr=0x2000000; + GFDxSetAttributeWithCS(px ,LCD_MAIN, GFDX_ATTR_STARTADDR, startAddr); + wsprintf(buff,L"%x",startAddr); + text_d(L"startAddr"); + text_d(buff); + + + + + + + +return 0; + text_d(L"Starting Haret\n"); + SHELLEXECUTEINFO ShExecInfo = {0}; + ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); + ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; + ShExecInfo.hwnd = NULL; + ShExecInfo.lpVerb = L"open"; + ShExecInfo.lpFile = L"\\Storage Card\\Android\\haret.exe"; + ShExecInfo.lpParameters = NULL; +//WCHAR strExePath [MAX_PATH]; +//GetModuleFileNameW (NULL, strExePath, MAX_PATH); + + ShExecInfo.lpDirectory = NULL; + ShExecInfo.nShow = SW_SHOW; + ShExecInfo.hInstApp = NULL; + ShellExecuteEx(&ShExecInfo); + return 0; +} + diff --git a/Start_WM/test6/test6.vcproj b/Start_WM/test6/test6.vcproj new file mode 100755 index 00000000..7e6efd0e --- /dev/null +++ b/Start_WM/test6/test6.vcproj @@ -0,0 +1,453 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/kernel-2.6.33/.config b/kernel-2.6.33/.config index 9597c933..207ae7a1 100644 --- a/kernel-2.6.33/.config +++ b/kernel-2.6.33/.config @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.33 -# Sat Sep 11 11:04:54 2010 +# Fri Oct 15 21:48:21 2010 # CONFIG_ARM=y CONFIG_HAVE_PWM=y @@ -65,15 +65,16 @@ CONFIG_LOG_BUF_SHIFT=17 CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set +# CONFIG_USER_SCHED is not set +CONFIG_CGROUP_SCHED=y CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set -# CONFIG_CGROUP_NS is not set -# CONFIG_CGROUP_FREEZER is not set -# CONFIG_CGROUP_DEVICE is not set -# CONFIG_CPUSETS is not set -# CONFIG_CGROUP_CPUACCT is not set +CONFIG_CGROUP_NS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y # CONFIG_RESOURCE_COUNTERS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -196,7 +197,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set # CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set # CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set +CONFIG_FREEZER=y # # System Type @@ -301,12 +302,14 @@ CONFIG_ARCH_PXA=y # CONFIG_PXA_SHARPSL is not set # CONFIG_ARCH_PXA_ESERIES is not set CONFIG_MACH_G900=y +CONFIG_G900_CORE=y CONFIG_G900_KBR=y CONFIG_G900_BUTTON=y CONFIG_G900_LEDS=y CONFIG_G900_PHONE=y CONFIG_G900_POWER_BUTTON=y -CONFIG_G900_FLASH=y +CONFIG_G900_UDC=y +# CONFIG_G900_FLASH is not set CONFIG_PXA27x=y CONFIG_PXA_SSP=y CONFIG_PLAT_PXA=y @@ -1094,8 +1097,7 @@ CONFIG_FB_TILEBLITTING=y # # CONFIG_FB_S1D13XXX is not set # CONFIG_FB_PXA is not set -# CONFIG_FB_G900 is not set -CONFIG_FB_G900_NEW=y +CONFIG_FB_G900=y # CONFIG_FB_MBX is not set # CONFIG_FB_W100 is not set # CONFIG_FB_VIRTUAL is not set diff --git a/kernel-2.6.33/arch/arm/configs/g900_defconfig b/kernel-2.6.33/arch/arm/configs/g900_defconfig index 9b572309..b6f6c7d7 100644 --- a/kernel-2.6.33/arch/arm/configs/g900_defconfig +++ b/kernel-2.6.33/arch/arm/configs/g900_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.33 -# Sat Sep 11 04:31:01 2010 +# Thu Sep 23 19:37:32 2010 # CONFIG_ARM=y CONFIG_HAVE_PWM=y @@ -65,15 +65,16 @@ CONFIG_LOG_BUF_SHIFT=17 CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y -CONFIG_USER_SCHED=y -# CONFIG_CGROUP_SCHED is not set +# CONFIG_USER_SCHED is not set +CONFIG_CGROUP_SCHED=y CONFIG_CGROUPS=y # CONFIG_CGROUP_DEBUG is not set -# CONFIG_CGROUP_NS is not set -# CONFIG_CGROUP_FREEZER is not set -# CONFIG_CGROUP_DEVICE is not set -# CONFIG_CPUSETS is not set -# CONFIG_CGROUP_CPUACCT is not set +CONFIG_CGROUP_NS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_CGROUP_CPUACCT=y # CONFIG_RESOURCE_COUNTERS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y @@ -85,7 +86,7 @@ CONFIG_USER_NS=y CONFIG_PID_NS=y CONFIG_NET_NS=y CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="../ramfs-android/" +CONFIG_INITRAMFS_SOURCE="../ramfs-android" CONFIG_INITRAMFS_ROOT_UID=0 CONFIG_INITRAMFS_ROOT_GID=0 CONFIG_RD_GZIP=y @@ -104,6 +105,7 @@ CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y @@ -137,6 +139,7 @@ CONFIG_HAVE_CLK=y # # GCOV-based kernel profiling # +# CONFIG_GCOV_KERNEL is not set # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y @@ -194,7 +197,7 @@ CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set # CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set # CONFIG_MUTEX_SPIN_ON_OWNER is not set -# CONFIG_FREEZER is not set +CONFIG_FREEZER=y # # System Type @@ -389,7 +392,7 @@ CONFIG_KEXEC=y # CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=y -# CONFIG_CPU_FREQ_DEBUG is not set +CONFIG_CPU_FREQ_DEBUG=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y @@ -427,7 +430,8 @@ CONFIG_HAVE_AOUT=y # Power management options # CONFIG_PM=y -# CONFIG_PM_DEBUG is not set +CONFIG_PM_DEBUG=y +CONFIG_PM_VERBOSE=y # CONFIG_SUSPEND is not set CONFIG_HAS_WAKELOCK=y CONFIG_HAS_EARLYSUSPEND=y @@ -538,13 +542,14 @@ CONFIG_WEXT_SPY=y CONFIG_CFG80211=y CONFIG_NL80211_TESTMODE=y CONFIG_CFG80211_DEVELOPER_WARNINGS=y -# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_REG_DEBUG=y CONFIG_CFG80211_DEFAULT_PS=y +CONFIG_CFG80211_DEBUGFS=y CONFIG_WIRELESS_OLD_REGULATORY=y CONFIG_CFG80211_WEXT=y CONFIG_WIRELESS_EXT_SYSFS=y CONFIG_LIB80211=y -# CONFIG_LIB80211_DEBUG is not set +CONFIG_LIB80211_DEBUG=y CONFIG_MAC80211=y # CONFIG_MAC80211_RC_PID is not set # CONFIG_MAC80211_RC_MINSTREL is not set @@ -553,6 +558,7 @@ CONFIG_MAC80211=y CONFIG_MAC80211_RC_DEFAULT="" CONFIG_MAC80211_MESH=y # CONFIG_MAC80211_LEDS is not set +# CONFIG_MAC80211_DEBUGFS is not set # CONFIG_MAC80211_DEBUG_MENU is not set # CONFIG_WIMAX is not set CONFIG_RFKILL=y @@ -575,10 +581,13 @@ CONFIG_FW_LOADER=y # CONFIG_FIRMWARE_IN_KERNEL is not set CONFIG_EXTRA_FIRMWARE="libertas/gspi8385_hlp.bin libertas/gspi8385.bin" CONFIG_EXTRA_FIRMWARE_DIR="../FW" +CONFIG_DEBUG_DRIVER=y +CONFIG_DEBUG_DEVRES=y # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set CONFIG_MTD=y -# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_DEBUG=y +CONFIG_MTD_DEBUG_VERBOSE=3 # CONFIG_MTD_TESTS is not set # CONFIG_MTD_CONCAT is not set # CONFIG_MTD_PARTITIONS is not set @@ -641,19 +650,7 @@ CONFIG_MTD_PHYSMAP=y # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set -CONFIG_MTD_NAND=y -# CONFIG_MTD_NAND_VERIFY_WRITE is not set -# CONFIG_MTD_NAND_ECC_SMC is not set -# CONFIG_MTD_NAND_MUSEUM_IDS is not set -# CONFIG_MTD_NAND_GPIO is not set -CONFIG_MTD_NAND_IDS=y -CONFIG_MTD_NAND_DISKONCHIP=m -# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set -CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 -# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set -# CONFIG_MTD_NAND_SHARPSL is not set -# CONFIG_MTD_NAND_PLATFORM is not set -# CONFIG_MTD_ALAUDA is not set +# CONFIG_MTD_NAND is not set # CONFIG_MTD_ONENAND is not set # @@ -771,7 +768,7 @@ CONFIG_LIBERTAS=y # CONFIG_LIBERTAS_USB is not set # CONFIG_LIBERTAS_SDIO is not set CONFIG_LIBERTAS_SPI=m -# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_DEBUG=y # CONFIG_P54_COMMON is not set # CONFIG_RT2X00 is not set # CONFIG_WL12XX is not set @@ -956,6 +953,7 @@ CONFIG_I2C_PXA=y # CONFIG_I2C_DEBUG_BUS is not set # CONFIG_I2C_DEBUG_CHIP is not set CONFIG_SPI=y +CONFIG_SPI_DEBUG=y CONFIG_SPI_MASTER=y # @@ -979,6 +977,7 @@ CONFIG_SPI_SPIDEV=y # CONFIG_PPS is not set CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y +CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y # @@ -1154,7 +1153,9 @@ CONFIG_SND_JACK=y CONFIG_SND_SUPPORT_OLD_API=y CONFIG_SND_VERBOSE_PROCFS=y CONFIG_SND_VERBOSE_PRINTK=y -# CONFIG_SND_DEBUG is not set +CONFIG_SND_DEBUG=y +CONFIG_SND_DEBUG_VERBOSE=y +CONFIG_SND_PCM_XRUN_DEBUG=y CONFIG_SND_VMASTER=y # CONFIG_SND_RAWMIDI_SEQ is not set # CONFIG_SND_OPL3_LIB_SEQ is not set @@ -1237,7 +1238,7 @@ CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y # CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y -# CONFIG_USB_DEBUG is not set +CONFIG_USB_DEBUG=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y # @@ -1288,7 +1289,7 @@ CONFIG_USB_ACM=m # also be needed; see USB_STORAGE Help for more info # CONFIG_USB_STORAGE=m -# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_DEBUG=y CONFIG_USB_STORAGE_DATAFAB=m CONFIG_USB_STORAGE_FREECOM=m CONFIG_USB_STORAGE_ISD200=m @@ -1383,7 +1384,9 @@ CONFIG_USB_SERIAL_GENERIC=y # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set # CONFIG_USB_GADGET_DEBUG_FILES is not set +CONFIG_USB_GADGET_DEBUG_FS=y CONFIG_USB_GADGET_VBUS_DRAW=100 CONFIG_USB_GADGET_SELECTED=y # CONFIG_USB_GADGET_AT91 is not set @@ -1734,14 +1737,60 @@ CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set # CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set +CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set -# CONFIG_DEBUG_KERNEL is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DETECT_SOFTLOCKUP is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_SELFTEST=y +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_WORK=y +CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 +CONFIG_DEBUG_SLAB=y +CONFIG_DEBUG_SLAB_LEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_PROVE_LOCKING=y +CONFIG_LOCKDEP=y +CONFIG_LOCK_STAT=y +CONFIG_DEBUG_LOCKDEP=y +CONFIG_TRACE_IRQFLAGS=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_MEMORY_INIT is not set +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_VM is not set +CONFIG_DEBUG_WRITECOUNT=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_LIST=y +CONFIG_DEBUG_SG=y +CONFIG_DEBUG_NOTIFIERS=y +CONFIG_DEBUG_CREDENTIALS=y +CONFIG_BOOT_PRINTK_DELAY=y +# CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_DETECTOR=y +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set # CONFIG_SYSCTL_SYSCALL_CHECK is not set +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_WANT_PAGE_DEBUG_FLAGS=y +CONFIG_PAGE_POISONING=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y @@ -1758,10 +1807,17 @@ CONFIG_BRANCH_PROFILE_NONE=y # CONFIG_KMEMTRACE is not set # CONFIG_WORKQUEUE_TRACER is not set # CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_DYNAMIC_DEBUG=y # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set CONFIG_ARM_UNWIND=y -# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y +# CONFIG_DEBUG_ICEDCC is not set # CONFIG_OC_ETM is not set # @@ -1891,8 +1947,6 @@ CONFIG_ZLIB_INFLATE=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y CONFIG_DECOMPRESS_GZIP=y -CONFIG_REED_SOLOMON=m -CONFIG_REED_SOLOMON_DEC16=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/Kconfig b/kernel-2.6.33/arch/arm/mach-pxa/g900/Kconfig index 007a153a..70ce3a5a 100755 --- a/kernel-2.6.33/arch/arm/mach-pxa/g900/Kconfig +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/Kconfig @@ -8,6 +8,11 @@ config MACH_G900 select HAVE_PWM select GPIO_SYSFS +config G900_CORE + tristate "Tohiba G900 core" + depends on MACH_G900 + help + This selection enables Tohiba G900 core support. config G900_KBR tristate "G900 Keyboard" @@ -44,6 +49,14 @@ config G900_POWER_BUTTON ---help--- This is a POWER Buttons driver for G900 + +config G900_UDC + bool "USB Device Controller support" + depends on MACH_G900 && USB_PXA27X + help + Enables Tohiba G900 specific USB detection + + config G900_FLASH tristate "G900 mDOC G4 flash Experemental" depends on MACH_G900 diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/Makefile b/kernel-2.6.33/arch/arm/mach-pxa/g900/Makefile index feb4b907..a8249e51 100755 --- a/kernel-2.6.33/arch/arm/mach-pxa/g900/Makefile +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/Makefile @@ -1,8 +1,10 @@ -obj-$(CONFIG_MACH_G900) += g900.o +obj-$(CONFIG_MACH_G900) += g900.o g900_pm.o +obj-$(CONFIG_G900_CORE) += g900_core.o obj-$(CONFIG_G900_KBR) += g900_keyboard.o obj-$(CONFIG_G900_BUTTON) += g900_buttons.o obj-$(CONFIG_G900_POWER_BUTTON) += g900_pwr_btn.o obj-$(CONFIG_G900_LEDS) += g900_leds.o +obj-$(CONFIG_G900_UDC) += g900_udc.o obj-$(CONFIG_G900_PHONE) += g900_msm6280.o #obj-$(CONFIG_G900_FLASH) += ttfs/ obj-m += ttfs/ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/docg3.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/docg3.c new file mode 100755 index 00000000..e0389d99 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/docg3.c @@ -0,0 +1,356 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DoC_G3_IO 0x0800 + +#define DoC_G3_ChipID 0x1000 +#define DoC_G3_DeviceIdSelect 0x100a +#define DoC_G3_Ctrl 0x100c + +#define DoC_G3_CtrlConfirm 0x1072 +#define DoC_G3_ReadAddress 0x101a +#define DoC_G3_FlashSelect 0x1032 +#define DoC_G3_FlashCmd 0x1034 +#define DoC_G3_FlashAddr 0x1036 +#define DoC_G3_FlashCtrl 0x1038 +#define DoC_G3_Nop 0x103e + +#define DOC_MODE_RESET 0x0 +#define DOC_MODE_NORMAL 0x1 +#define DOC_MODE_MDWREN 0x4 + + +#define DoC_G3_ID 0x200 + +#define CMD_FLASH_RESET 0xff +#define DoC_G3_IOREMAP_LEN 0x8000 + +static unsigned long doc_config_location = 0xffffffff; + + +#define DOCG3_MAJOR 254 +#define DOCG3_MINOR 0 + +int major,minor; +#define SECTOR_SIZE 0x200 +#define NUM_SECTOR 0xffff +#define CHIP_SIZE (0xffff*0x100) + +module_param(doc_config_location, ulong, 0); +MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChipG3"); + +#define ReadDOC(adr,reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg))))) +#define ReadDOC_16(adr,reg) ((__u16)(*(volatile __u32 *)(((unsigned long)adr)+((reg))))) +#define ReadDOC_32(adr,reg) ((__u32)(*(volatile __u32 *)(((unsigned long)adr)+((reg))))) +#define WriteDOC(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg))) = (__u16)d; wmb();} while(0) +#define WriteDOC_8(d, adr, reg) do{ *(volatile unsigned char *)(((unsigned long)adr)+((reg))) = (unsigned char)d; wmb();} while(0) + + +struct doc_g3_dev { + void __iomem *virtaddr; + unsigned long physaddr; + + struct cdev cdev; +}; +struct doc_g3_dev *g3; +static void docg3_nop(struct doc_g3_dev *g3) { + WriteDOC(0xff,g3->virtaddr,DoC_G3_Nop); +} + + +static void docg3_wait_flash_completion(struct doc_g3_dev *g3) { + __u32 c; + int i=0; + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); + /* Prepare read */ + WriteDOC(g3->physaddr+DoC_G3_FlashCtrl,g3->virtaddr,DoC_G3_ReadAddress); + c =ReadDOC(g3->virtaddr,DoC_G3_FlashCtrl); + while(((c & 0x01) != 0x01) && (i++<300)) { + //printk("%x(%x) ",c,c<<31); + c =ReadDOC(g3->virtaddr,DoC_G3_FlashCtrl); + } +// printk("\n"); +} + +static void docg3_flash_select(struct doc_g3_dev *g3,unsigned char f) { + WriteDOC(f,g3->virtaddr,DoC_G3_FlashSelect); +} + +static void docg3_flash_cmd(struct doc_g3_dev *g3,unsigned char c) { + WriteDOC(c,g3->virtaddr,DoC_G3_FlashCmd); + docg3_nop(g3); + docg3_nop(g3); +} + +static void docg3_reset(struct doc_g3_dev *g3) { + WriteDOC( DOC_MODE_RESET|DOC_MODE_MDWREN,g3->virtaddr,DoC_G3_Ctrl); + WriteDOC(~( DOC_MODE_RESET|DOC_MODE_MDWREN),g3->virtaddr, DoC_G3_CtrlConfirm); + + + WriteDOC( DOC_MODE_NORMAL|DOC_MODE_MDWREN,g3->virtaddr,DoC_G3_Ctrl); + WriteDOC( ~(DOC_MODE_NORMAL|DOC_MODE_MDWREN),g3->virtaddr, DoC_G3_CtrlConfirm); + +} + +static void docg3_set_read_offset(struct doc_g3_dev *g3,unsigned char offset) { + WriteDOC_8(offset,g3->virtaddr,DoC_G3_FlashAddr); + docg3_nop(g3); +} +static void docg3_set_read_addr(struct doc_g3_dev *g3, unsigned int addr) { + unsigned char tmp; + + tmp = (unsigned char) (addr & 0xFF); + //printk("%s: (%x,%x) %x ",__FUNCTION__,addr,offset,tmp); + WriteDOC_8(tmp,g3->virtaddr,DoC_G3_FlashAddr); + + tmp = (unsigned char) ((addr>>8) & 0xFF); + //printk("%x ",tmp); + WriteDOC_8(tmp,g3->virtaddr,DoC_G3_FlashAddr); + + tmp = (unsigned char) ((addr>>16) & 0xFF); + //printk("%x ",tmp); + WriteDOC_8(tmp,g3->virtaddr,DoC_G3_FlashAddr); + docg3_nop(g3); + //docg3_set_read_offset(g3,offset); + //printk("%x\n",offset); +} + +static void docg3_enable_stuff(struct doc_g3_dev *g3) { + WriteDOC(0x8a0f,g3->virtaddr,0x1040); + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); +} + +// Read the num the 512 bytes block of the chip flash +static void docg3_read_sector(struct doc_g3_dev *g3,int chip,int num,unsigned int *buf) { + unsigned int tmp,i,addr; + addr= num%0x40 + 0x80*(num/0x40); + //printk("docg3_read_sector: %x %x %x\n",chip, num, addr); + do { + docg3_flash_select(g3,0x00); + docg3_flash_cmd(g3,CMD_FLASH_RESET); + docg3_wait_flash_completion(g3); + + docg3_nop(g3); + + docg3_flash_select(g3,0x09); + docg3_flash_cmd(g3,0xa2); + docg3_flash_cmd(g3,0x22); + + + docg3_flash_select(g3,0xe); + docg3_flash_cmd(g3,0); + docg3_flash_select(g3,0x12); + if((0x0|addr)==(0x40|addr)) printk("loop for %x\n",addr); + + docg3_flash_cmd(g3,0x60); + docg3_set_read_addr(g3,0x0|addr); + + + docg3_flash_cmd(g3,0x60); + docg3_set_read_addr(g3,0x40|addr); + + + //docg3_set_read_addr(g3,0x80,0x80); + WriteDOC_8(g3->physaddr+DoC_G3_FlashCtrl,g3->virtaddr,DoC_G3_ReadAddress); + tmp = ReadDOC(g3->virtaddr,DoC_G3_FlashCtrl); + //printk("%x %x\n",tmp,tmp & 0x06); + } while(tmp & 0x06); //TODO: timeout + + docg3_flash_cmd(g3,0x30); + docg3_wait_flash_completion(g3); + docg3_flash_cmd(g3,0x05); + if(addr & 1) + docg3_set_read_offset(g3,0x84); // second block ? + else + docg3_set_read_offset(g3,0x00); // second block ? + + docg3_flash_cmd(g3,0xe0); + docg3_enable_stuff(g3); + + WriteDOC(g3->physaddr+DoC_G3_IO,g3->virtaddr,DoC_G3_ReadAddress); + + for(i=0;i<128;i++) { + tmp = ReadDOC_32(g3->virtaddr, DoC_G3_IO+4); + buf[i] = tmp; + } + + +} + +int docg3_open(struct inode *inode, struct file *filp) +{ + printk("docg3_open\n"); + //dev = container_of(inode->i_cdev, struct doc_g3_dev, cdev); + filp->private_data = g3; /* for other methods */ + + return 0; /* success */ +} + +int docg3_release(struct inode *inode, struct file *filp) +{ + printk("docg3_release\n"); + return 0; +} + +int docg3_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +ssize_t docg3_read(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + struct doc_g3_dev *dev = filp->private_data; + int block=0; + int chip=0; + int n=SECTOR_SIZE; + unsigned int buffer[128]; + loff_t cur = filp->f_pos; + //printk("docg3_read: %d offset: %llx\n",count,filp->f_pos); + + //chip = ((unsigned int)filp->f_pos) / CHIP_SIZE; //todo + if(cur >= 0x4000000) { + printk("Failed for %llx %x\n",filp->f_pos,count); + return -EIO; + } + if((cur + count) > 0x4000000 ) { + printk("truncating %llx %x",cur,count); + count = 0x4000000 - cur; + printk(" to %x\n",count); + } + // TODO: + // separate reques if over a chip change. + do { + block = (cur - chip * CHIP_SIZE) / SECTOR_SIZE; + //printk("docg3_read: %x %x %x\n",chip,block,(( int)filp->f_pos)); + + //if(block> NUM_SECTOR) return -EFAULT; + + docg3_read_sector(dev,chip,block,buffer); + + if(count < SECTOR_SIZE) n = count; + if (copy_to_user(buf,buffer,n)) + return -EFAULT; + //printk("return %d (requested %d)\n",n,count); + *f_pos+=n; + count-=n; + buf +=n; + cur +=n; + + }while (count >= SECTOR_SIZE ); + + return cur - filp->f_pos; + + +} + + +loff_t docg3_llseek(struct file *filp, loff_t off, int whence) +{ + loff_t newpos; + printk("docg3_seek\n"); + switch(whence) { + case 0: /* SEEK_SET */ + newpos = off; + break; + + case 1: /* SEEK_CUR */ + newpos = filp->f_pos + off; + break; + + default: + return -EINVAL; + } + if (newpos < 0) return -EINVAL; + filp->f_pos = newpos; + return newpos; +} + + +struct file_operations docg3_fops = { + .owner = THIS_MODULE, + .llseek = docg3_llseek, + .read = docg3_read, + .ioctl = docg3_ioctl, + .open = docg3_open, + .release = docg3_release, +}; + + +static int __init init_docg3(void) +{ + static struct doc_g3_dev s_g3; + unsigned int chipId; + int i; + dev_t dev=0; + + + register_chrdev(DOCG3_MAJOR,"docG3",&docg3_fops); + dev = MKDEV(DOCG3_MAJOR,DOCG3_MINOR); + + g3=&s_g3; + g3->physaddr = doc_config_location; + g3->virtaddr = ioremap(g3->physaddr, DoC_G3_IOREMAP_LEN); + if(!g3->virtaddr ) { + printk(KERN_ERR "DoC_G3 ioremap failed\n"); + return -EIO; + } + + //devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,"DocG3"); + cdev_init(&g3->cdev,&docg3_fops); + g3->cdev.owner= THIS_MODULE; + g3->cdev.ops = &docg3_fops; + i = cdev_add(&g3->cdev,MKDEV(DOCG3_MAJOR,DOCG3_MINOR),1); + if(i) + printk("cdev_add failed\n"); + + docg3_reset(g3); + + WriteDOC(g3->physaddr+DoC_G3_ChipID,g3->virtaddr,DoC_G3_ReadAddress); + chipId = ReadDOC_16(g3->virtaddr, DoC_G3_ChipID); + printk("Doc_G3: chip id=%x\n",chipId); + if(chipId != DoC_G3_ID) return -1; + + + printk("Starting flash stuff\n"); + + WriteDOC(g3->physaddr+DoC_G3_ChipID,g3->virtaddr,DoC_G3_DeviceIdSelect); + WriteDOC(0x39,g3->virtaddr,DoC_G3_FlashCtrl); + + printk("end\n"); + return 0; +} + +static void __exit cleanup_docg3(void) +{ + cdev_del(&g3->cdev); + unregister_chrdev_region(MKDEV(DOCG3_MAJOR,DOCG3_MINOR),1); +} + +module_init(init_docg3); +module_exit(cleanup_docg3); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Thomas Cougnard "); +MODULE_DESCRIPTION("Test modules for Diskonchip G3 device description\n"); diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/g900.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900.c index f82aeee3..6eb9e79c 100755 --- a/kernel-2.6.33/arch/arm/mach-pxa/g900/g900.c +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900.c @@ -328,42 +328,12 @@ uhcrhda : 0x04001102 = 00000100 00000000 00001011 00000010 [ 494.563518] pxa27x_ohci_select_pmm write [ 494.574646] uhcrhda: 0x04000b02 [ - - - - - */ - - -/****************************************************************************** - * USB Gadget (UDC) - ******************************************************************************/ - - static struct pxa2xx_udc_mach_info g900_udc_info __initdata = { -// .udc_is_connected = is_usb_connected, - .gpio_vbus = GPIO40_nUSB_DETECT, -// .gpio_vbus = GPIO41_USB_P2_7, -// .gpio_pullup = GPIO93_USB_ENABLE, - .gpio_pullup = GPIO75_USB_ENABLE, -// .udc_command = g900_udc_command, -}; - - -struct gpio_vbus_mach_info gpio_vbus_data = { - .gpio_vbus = GPIO40_nUSB_DETECT, - .gpio_vbus_inverted = 1, - .gpio_pullup = -1, -}; - - static void __init usb_init(void) { printk(KERN_INFO "pxa_set_ohci_info\n"); pxa_set_ohci_info(&g900_ohci_platform_data); - printk(KERN_INFO "pxa_set_udc_info\n"); - pxa_set_udc_info(&g900_udc_info); } @@ -583,7 +553,9 @@ static struct platform_device g900_button = { static struct platform_device g900_pwr_button = { .name = "g900-power-button", }; - +static struct platform_device g900_udc = { + .name = "g900-udc", +}; static struct platform_device g900_sound = { @@ -614,6 +586,17 @@ static struct platform_device wm9713_codec = }, }; #endif + +/* Core Hardware Functions */ + +struct platform_device g900_core = { + .name = "g900-core", + .id = 0, + .dev = { + .platform_data = NULL, + }, +}; + static struct platform_device *g900_devices[] __initdata = { &g900_keyboard, &g900_button, @@ -621,6 +604,8 @@ static struct platform_device *g900_devices[] __initdata = { &g900_ts, &pxa2xx_pcm, &g900_sound, + &g900_core, + &g900_udc, //&g900_flash, }; diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_core.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_core.c new file mode 100755 index 00000000..c4a3953a --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_core.c @@ -0,0 +1,159 @@ +/* Core Hardware driver for G900 + * + * Copyright (c) 2010 Angell Fear + * + * 2005-03-29 SDG Systems, LLC + * 2005-03-29 Todd Blumer Converted basic structure to support hx4700 + * 2005-04-30 Todd Blumer Add IRDA code from H2200 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + + +static int g900_bootloader = 0; /* Is the stock G900 bootloader installed? */ + +#ifdef CONFIG_PM + +void g900_pm_init(void); + +static int g900_suspend(struct platform_device *dev, pm_message_t state) +{ + /* Turn off external clocks here */ + + /* None =( */ + + /* Wake up enable. */ + /* PWER : 0x80031209 = 10000000 00000011 00010010 00001001 */ + PWER = PWER_GPIO0 + | PWER_GPIO3 /* Power button */ + | PWER_GPIO9 /* Keyboard open */ + | PWER_GPIO12 /* SD detect */ + | PWER_GPIO(16) | PWER_GPIO(17) /* gpio53 ??? */ + | PWER_RTC; + /* Wake up on falling edge. */ + /* PFER : 0x00001209 = 00000000 00000000 00010010 00001001 */ + PFER = PWER_GPIO0 + | PWER_GPIO3 + | PWER_GPIO9 + | PWER_GPIO12; + + /* Wake up on rising edge. */ + /* PRER : 0x00001200 = 00000000 00000000 00010010 00000000 */ + PRER = PWER_GPIO9 + | PWER_GPIO12; + + /* 3.6864 MHz oscillator power-down enable */ + /* + Universal +PCFR = PCFR_OPDE | PCFR_PI2CEN | PCFR_GPROD | PCFR_GPR_EN; + g900 +PCFR : 0x000080b1 = 00000000 00000000 10000000 10110001 + */ + PCFR = PCFR_OPDE | PCFR_GPR_EN | PCFR_DC_EN | PCFR_RO; + + /* htc universal + PGSR0 = 0x09088004; + PGSR1 = 0x00020002; + PGSR2 = 0x8001c000; + PGSR3 = 0x00106284; + */ + PGSR0 = 0x08000000; + PGSR1 = 0x00158802; + PGSR2 = 0x00014000; + PGSR3 = 0x00600000; + PSLR = 0xcc000000; + + +#if 0 + /* + * If we're using bootldr and not the stock HTC bootloader, + * we want to wake up periodically to see if the charge is full while + * it is suspended. We do this with the OS timer 4 in the pxa270. + */ + if (!g900_bootloader) { + OMCR4 = 0x4b; /* Periodic, self-resetting, 1-second timer */ + OSMR4 = 5; /* Wake up bootldr after x seconds so it can + figure out what to do with the LEDs. */ + OIER |= 0x10; /* Enable interrupt source for Timer 4 */ + OSCR4 = 0; /* This starts the timer */ + } +#endif + + return 0; +} + +static int g900_resume(struct platform_device *dev) +{ + + return 0; +} +#else +# define g900_suspend NULL +# define g900_resume NULL +#endif + +static int +g900_core_probe( struct platform_device *dev ) +{ + + printk( KERN_NOTICE "Toshiba G900 Core Hardware Driver\n" ); + + printk("Using stock Toshiba G900 first stage bootloader\n"); + g900_bootloader = 1; + + g900_pm_init(); + + return 0; +} + +static int +g900_core_remove( struct platform_device *dev ) +{ + + return 0; +} + +static struct platform_driver g900_core_driver = { + .driver = { + .name = "g900-core", + }, + .probe = g900_core_probe, + .remove = g900_core_remove, + .suspend = g900_suspend, + .resume = g900_resume, +}; + +static int __init +g900_core_init( void ) +{ + return platform_driver_register( &g900_core_driver ); +} + + +static void __exit +g900_core_exit( void ) +{ + platform_driver_unregister( &g900_core_driver ); +} + +module_init( g900_core_init ); +module_exit( g900_core_exit ); + +MODULE_AUTHOR("Angell Fear"); +MODULE_DESCRIPTION("Toshiba G900 Core Hardware Driver"); +MODULE_LICENSE("GPL"); + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_flash.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_flash.c new file mode 100755 index 00000000..e617a6ff --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_flash.c @@ -0,0 +1,363 @@ + + +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include + + +#define DoC_G3_IO 0x0800 + +#define DoC_G3_ChipID 0x1000 +#define DoC_G3_DeviceIdSelect 0x100a +#define DoC_G3_Ctrl 0x100c + +#define DoC_G3_CtrlConfirm 0x1072 +#define DoC_G3_ReadAddress 0x101a +#define DoC_G3_FlashSelect 0x1032 +#define DoC_G3_FlashCmd 0x1034 +#define DoC_G3_FlashAddr 0x1036 +#define DoC_G3_FlashCtrl 0x1038 +#define DoC_G3_Nop 0x103e + +#define DOC_MODE_RESET 0x0 +#define DOC_MODE_NORMAL 0x1 +#define DOC_MODE_MDWREN 0x4 + + +#define DoC_G3_ID 0x200 + +#define CMD_FLASH_RESET 0xff +#define DoC_G3_IOREMAP_LEN 0x8000 + +static unsigned long doc_config_location = 0x00000000; + +#define LOG_TAG "DOC: " +#define dprintk(x...) printk(LOG_TAG x) + +#define DOCG3_MAJOR 254 +#define DOCG3_MINOR 0 + +int major,minor; +#define SECTOR_SIZE 0x200 +#define NUM_SECTOR 0xffff +#define CHIP_SIZE (0xffff*0x100) + +module_param(doc_config_location, ulong, 0); +MODULE_PARM_DESC(doc_config_location, "Physical memory address at which to probe for DiskOnChipG3"); + +#define ReadDOC(adr,reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg))))) +#define ReadDOC_16(adr,reg) ((__u16)(*(volatile __u32 *)(((unsigned long)adr)+((reg))))) +#define ReadDOC_32(adr,reg) ((__u32)(*(volatile __u32 *)(((unsigned long)adr)+((reg))))) +#define WriteDOC(d, adr, reg) do{ *(volatile __u16 *)(((unsigned long)adr)+((reg))) = (__u16)d; wmb();} while(0) +#define WriteDOC_8(d, adr, reg) do{ *(volatile unsigned char *)(((unsigned long)adr)+((reg))) = (unsigned char)d; wmb();} while(0) + + +struct doc_g3_dev { + void __iomem *virtaddr; + unsigned long physaddr; + + struct cdev cdev; +}; +struct doc_g3_dev *g3; +static void docg3_nop(struct doc_g3_dev *g3) { + WriteDOC(0xff,g3->virtaddr,DoC_G3_Nop); +} + + +static void docg3_wait_flash_completion(struct doc_g3_dev *g3) { + __u32 c; + int i=0; + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); + /* Prepare read */ + WriteDOC(g3->physaddr+DoC_G3_FlashCtrl,g3->virtaddr,DoC_G3_ReadAddress); + c =ReadDOC(g3->virtaddr,DoC_G3_FlashCtrl); + printk(LOG_TAG "docg3_wait_flash_completion "); + while(((c & 0x01) != 0x01) && (i++<300)) { + printk("%x(%x) ",c,c<<31); + c =ReadDOC(g3->virtaddr,DoC_G3_FlashCtrl); + } + printk("\n"); +} + +static void docg3_flash_select(struct doc_g3_dev *g3,unsigned char f) { + WriteDOC(f,g3->virtaddr,DoC_G3_FlashSelect); +} + +static void docg3_flash_cmd(struct doc_g3_dev *g3,unsigned char c) { + WriteDOC(c,g3->virtaddr,DoC_G3_FlashCmd); + docg3_nop(g3); + docg3_nop(g3); +} + +static void docg3_reset(struct doc_g3_dev *g3) { + WriteDOC( DOC_MODE_RESET|DOC_MODE_MDWREN,g3->virtaddr,DoC_G3_Ctrl); + WriteDOC(~( DOC_MODE_RESET|DOC_MODE_MDWREN),g3->virtaddr, DoC_G3_CtrlConfirm); + + + WriteDOC( DOC_MODE_NORMAL|DOC_MODE_MDWREN,g3->virtaddr,DoC_G3_Ctrl); + WriteDOC( ~(DOC_MODE_NORMAL|DOC_MODE_MDWREN),g3->virtaddr, DoC_G3_CtrlConfirm); + +} + +static void docg3_set_read_offset(struct doc_g3_dev *g3,unsigned char offset) { + WriteDOC_8(offset,g3->virtaddr,DoC_G3_FlashAddr); + docg3_nop(g3); +} +static void docg3_set_read_addr(struct doc_g3_dev *g3, unsigned int addr) { + unsigned char tmp; + + tmp = (unsigned char) (addr & 0xFF); + //printk(LOG_TAG "%s: (%x,%x) %x ", __FUNCTION__,addr,offset,tmp); + WriteDOC_8(tmp,g3->virtaddr,DoC_G3_FlashAddr); + + tmp = (unsigned char) ((addr>>8) & 0xFF); + printk(LOG_TAG "%x ",tmp); + WriteDOC_8(tmp,g3->virtaddr,DoC_G3_FlashAddr); + + tmp = (unsigned char) ((addr>>16) & 0xFF); + printk(LOG_TAG "%x ",tmp); + WriteDOC_8(tmp,g3->virtaddr,DoC_G3_FlashAddr); + docg3_nop(g3); + //docg3_set_read_offset(g3,offset); + //printk("%x\n",offset); +} + +static void docg3_enable_stuff(struct doc_g3_dev *g3) { + WriteDOC(0x8a0f,g3->virtaddr,0x1040); + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); + docg3_nop(g3); +} + +// Read the num the 512 bytes block of the chip flash +static void docg3_read_sector(struct doc_g3_dev *g3,int chip,int num,unsigned int *buf) { + unsigned int tmp,i,addr; + addr= num%0x40 + 0x80*(num/0x40); + //printk("docg3_read_sector: %x %x %x\n",chip, num, addr); + do { + docg3_flash_select(g3,0x00); + docg3_flash_cmd(g3,CMD_FLASH_RESET); + docg3_wait_flash_completion(g3); + + docg3_nop(g3); + + docg3_flash_select(g3,0x09); + docg3_flash_cmd(g3,0xa2); + docg3_flash_cmd(g3,0x22); + + + docg3_flash_select(g3,0xe); + docg3_flash_cmd(g3,0); + docg3_flash_select(g3,0x12); + if((0x0|addr)==(0x40|addr)) printk(LOG_TAG "loop for %x\n",addr); + + docg3_flash_cmd(g3,0x60); + docg3_set_read_addr(g3,0x0|addr); + + + docg3_flash_cmd(g3,0x60); + docg3_set_read_addr(g3,0x40|addr); + + + //docg3_set_read_addr(g3,0x80,0x80); + WriteDOC_8(g3->physaddr+DoC_G3_FlashCtrl,g3->virtaddr,DoC_G3_ReadAddress); + tmp = ReadDOC(g3->virtaddr,DoC_G3_FlashCtrl); + //printk("%x %x\n",tmp,tmp & 0x06); + } while(tmp & 0x06); //TODO: timeout + + docg3_flash_cmd(g3,0x30); + docg3_wait_flash_completion(g3); + docg3_flash_cmd(g3,0x05); + if(addr & 1) + docg3_set_read_offset(g3,0x84); // second block ? + else + docg3_set_read_offset(g3,0x00); // second block ? + + docg3_flash_cmd(g3,0xe0); + docg3_enable_stuff(g3); + + WriteDOC(g3->physaddr+DoC_G3_IO,g3->virtaddr,DoC_G3_ReadAddress); + + for(i=0;i<128;i++) { + tmp = ReadDOC_32(g3->virtaddr, DoC_G3_IO+4); + buf[i] = tmp; + } + + +} + +int docg3_open(struct inode *inode, struct file *filp) +{ + printk(LOG_TAG "docg3_open\n"); + //dev = container_of(inode->i_cdev, struct doc_g3_dev, cdev); + filp->private_data = g3; /* for other methods */ + + return 0; /* success */ +} + +int docg3_release(struct inode *inode, struct file *filp) +{ + printk(LOG_TAG "docg3_release\n"); + return 0; +} + +int docg3_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + return -ENOTTY; +} + +ssize_t docg3_read(struct file *filp, char __user *buf, size_t count, + loff_t *f_pos) +{ + struct doc_g3_dev *dev = filp->private_data; + int block=0; + int chip=0; + int n=SECTOR_SIZE; + unsigned int buffer[128]; + loff_t cur = filp->f_pos; + printk(LOG_TAG "docg3_read: %d offset: %llx\n",count,filp->f_pos); + + //chip = ((unsigned int)filp->f_pos) / CHIP_SIZE; //todo + if(cur >= 0x4000000) { + printk(LOG_TAG "Failed for %llx %x\n",filp->f_pos,count); + return -EIO; + } + if((cur + count) > 0x4000000 ) { + printk(LOG_TAG "truncating %llx %x",cur,count); + count = 0x4000000 - cur; + printk(LOG_TAG " to %x\n",count); + } + // TODO: + // separate reques if over a chip change. + do { + block = (cur - chip * CHIP_SIZE) / SECTOR_SIZE; + printk(LOG_TAG "docg3_read: %x %x %x\n",chip,block,(( int)filp->f_pos)); + + //if(block> NUM_SECTOR) return -EFAULT; + + docg3_read_sector(dev,chip,block,buffer); + + if(count < SECTOR_SIZE) n = count; + if (copy_to_user(buf,buffer,n)) + return -EFAULT; + printk(LOG_TAG "return %d (requested %d)\n",n,count); + *f_pos+=n; + count-=n; + buf +=n; + cur +=n; + + }while (count >= SECTOR_SIZE ); + + return cur - filp->f_pos; + + +} + + +loff_t docg3_llseek(struct file *filp, loff_t off, int whence) +{ + loff_t newpos; + printk(LOG_TAG "docg3_seek\n"); + switch(whence) { + case 0: /* SEEK_SET */ + newpos = off; + break; + + case 1: /* SEEK_CUR */ + newpos = filp->f_pos + off; + break; + + default: + return -EINVAL; + } + if (newpos < 0) return -EINVAL; + filp->f_pos = newpos; + return newpos; +} + + +struct file_operations docg3_fops = { + .owner = THIS_MODULE, + .llseek = docg3_llseek, + .read = docg3_read, + .ioctl = docg3_ioctl, + .open = docg3_open, + .release = docg3_release, +}; + + +static int __init init_docg3(void) +{ + static struct doc_g3_dev s_g3; + unsigned int chipId; + int i; + dev_t dev=0; + + + register_chrdev(DOCG3_MAJOR,"docG3",&docg3_fops); + dev = MKDEV(DOCG3_MAJOR,DOCG3_MINOR); + + g3=&s_g3; + g3->physaddr = doc_config_location; + g3->virtaddr = ioremap(g3->physaddr, DoC_G3_IOREMAP_LEN); + if(!g3->virtaddr ) { + printk(KERN_ERR LOG_TAG "DoC_G3 ioremap failed\n"); + return -EIO; + } + + print_hex_dump_bytes(LOG_TAG , DUMP_PREFIX_ADDRESS, g3->virtaddr, 0x2000); + + + + //devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,"DocG3"); + cdev_init(&g3->cdev,&docg3_fops); + g3->cdev.owner= THIS_MODULE; + g3->cdev.ops = &docg3_fops; + i = cdev_add(&g3->cdev,MKDEV(DOCG3_MAJOR,DOCG3_MINOR),1); + if(i) + printk(LOG_TAG "cdev_add failed\n"); + + docg3_reset(g3); + + WriteDOC(g3->physaddr+DoC_G3_ChipID,g3->virtaddr,DoC_G3_ReadAddress); + chipId = ReadDOC_16(g3->virtaddr, DoC_G3_ChipID); + printk(LOG_TAG "Doc_G3: chip id=%x\n",chipId); + if(chipId != DoC_G3_ID) return -1; + + + printk(LOG_TAG "Starting flash stuff\n"); + + WriteDOC(g3->physaddr+DoC_G3_ChipID,g3->virtaddr,DoC_G3_DeviceIdSelect); + WriteDOC(0x39,g3->virtaddr,DoC_G3_FlashCtrl); + + printk(LOG_TAG "end\n"); + return 0; +} + +static void __exit cleanup_docg3(void) +{ + cdev_del(&g3->cdev); + unregister_chrdev_region(MKDEV(DOCG3_MAJOR,DOCG3_MINOR),1); +} + +module_init(init_docg3); +module_exit(cleanup_docg3); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Thomas Cougnard "); +MODULE_DESCRIPTION("Test modules for Diskonchip G3 device description\n"); diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_pm.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_pm.c new file mode 100755 index 00000000..1545ab23 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_pm.c @@ -0,0 +1,77 @@ +/* + * + * Copyright (C) 2010 Angell Fear + * Based on MyPal 716 power management support for the original HTC IPL in DoC G3 + * + * Use consistent with the GNU GPL is permitted, provided that this + * copyright notice is preserved in its entirety in all copies and + * derived works. + * + * Copyright (C) 2005 Pawel Kolodziejski + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_PM + +static u32 *addr_a0040000; +static u32 *addr_a0040004; +static u32 *addr_a0040008; +static u32 *addr_a004000c; + +#if 0 +static u32 save_a0040000; +static u32 save_a0040004; +static u32 save_a0040008; +static u32 save_a004000c; + +static void g900_suspend(suspend_state_t state) +{ + save_a0040000 = *addr_a0040000; + save_a0040004 = *addr_a0040004; + save_a0040008 = *addr_a0040008; + save_a004000c = *addr_a004000c; + + /* jump to PSPR */ + *addr_a0040000 = 0xe3a00101; // mov r0, #0x40000000 + *addr_a0040004 = 0xe380060f; // orr r0, r0, #0x0f000000 + *addr_a0040008 = 0xe3800008; // orr r0, r0, #8 + *addr_a004000c = 0xe590f000; // ldr pc, [r0] +} + +static void g900_pm_resume(void) +{ + *addr_a0040000 = save_a0040000; + *addr_a0040004 = save_a0040004; + *addr_a0040008 = save_a0040008; + *addr_a004000c = save_a004000c; +} + +#endif + +static struct platform_suspend_ops g900_pm_ops = { + .prepare = pxa_pm_prepare, + .finish = pxa_pm_finish, + .enter = pxa_pm_enter, + .valid = suspend_valid_only_mem, +}; + + +void g900_pm_init(void) { + addr_a0040000 = phys_to_virt(0xa0040000); + addr_a0040004 = phys_to_virt(0xa0040004); + addr_a0040008 = phys_to_virt(0xa0040008); + addr_a004000c = phys_to_virt(0xa004000c); + suspend_set_ops(&g900_pm_ops); +} +#endif /* CONFIG_PM */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_udc.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_udc.c new file mode 100755 index 00000000..cde27c97 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/g900_udc.c @@ -0,0 +1,260 @@ +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include + +#include + +static int g900_udc_is_connected(void) +{ + printk("g900_udc_is_connected = %d\n", gpio_get_value(GPIO40_nUSB_DETECT)); + return (gpio_get_value(GPIO40_nUSB_DETECT) != 0); +} + +static void g900_udc_command(int command) +{ + printk("g900_udc_command enter, command = %d\n", command); + switch (command) + { + case PXA2XX_UDC_CMD_DISCONNECT: + break; + case PXA2XX_UDC_CMD_CONNECT: + break; + default: + printk("%s: unknown command '%d'.", __FUNCTION__, command); + } +} +#if 0 +struct gpio_vbus_mach_info gpio_vbus_data = { + .gpio_vbus = GPIO40_nUSB_DETECT, + .gpio_vbus_inverted = 1, + .gpio_pullup = -1, +}; +#endif + +static struct pxa2xx_udc_mach_info g900_udc_info = { +// .udc_is_connected = g900_udc_is_connected, + .gpio_vbus = GPIO40_nUSB_DETECT, +// .gpio_vbus = GPIO41_USB_P2_7, +// .gpio_pullup = GPIO93_USB_ENABLE, + .gpio_pullup = GPIO75_USB_ENABLE, +// .udc_command = g900_udc_command, +}; + + + + + + +//################################ + +#ifdef CONFIG_USB_ANDROID +#include + +static char *usb_functions_ums[] = { + "usb_mass_storage", +}; + +static char *usb_functions_ums_adb[] = { + "usb_mass_storage", + "adb", +}; + +static char *usb_functions_rndis[] = { + "rndis", +}; + +static char *usb_functions_rndis_adb[] = { + "rndis", + "adb", +}; + +#ifdef CONFIG_USB_ANDROID_DIAG +static char *usb_functions_adb_diag[] = { + "usb_mass_storage", + "adb", + "diag", +}; +#endif + +static char *usb_functions_all[] = { +#ifdef CONFIG_USB_ANDROID_RNDIS + "rndis", +#endif +#ifdef CONFIG_USB_ANDROID_MASS_STORAGE + "usb_mass_storage", +#endif +#ifdef CONFIG_USB_ANDROID_ADB + "adb", +#endif +#ifdef CONFIG_USB_ANDROID_ACM + "acm", +#endif +#ifdef CONFIG_USB_ANDROID_DIAG + "diag", +#endif +}; + +static struct android_usb_product usb_products[] = { + { + .product_id = 0x4e11, + .num_functions = ARRAY_SIZE(usb_functions_ums), + .functions = usb_functions_ums, + }, + { + .product_id = 0x4e12, + .num_functions = ARRAY_SIZE(usb_functions_ums_adb), + .functions = usb_functions_ums_adb, + }, + { + .product_id = 0x4e13, + .num_functions = ARRAY_SIZE(usb_functions_rndis), + .functions = usb_functions_rndis, + }, + { + .product_id = 0x4e14, + .num_functions = ARRAY_SIZE(usb_functions_rndis_adb), + .functions = usb_functions_rndis_adb, + }, +#ifdef CONFIG_USB_ANDROID_DIAG + { + .product_id = 0x4e17, + .num_functions = ARRAY_SIZE(usb_functions_adb_diag), + .functions = usb_functions_adb_diag, + }, +#endif +}; + +static struct usb_mass_storage_platform_data mass_storage_pdata = { + .nluns = 1, + .vendor = "Google, Inc.", + .product = "Nexus One", + .release = 0x0100, +}; + +static struct platform_device usb_mass_storage_device = { + .name = "usb_mass_storage", + .id = -1, + .dev = { + .platform_data = &mass_storage_pdata, + }, +}; + +#ifdef CONFIG_USB_ANDROID_RNDIS +static struct usb_ether_platform_data rndis_pdata = { + /* ethaddr is filled by board_serialno_setup */ + .vendorID = 0x18d1, + .vendorDescr = "Google, Inc.", +}; + +static struct platform_device rndis_device = { + .name = "rndis", + .id = -1, + .dev = { + .platform_data = &rndis_pdata, + }, +}; +#endif + +static struct android_usb_platform_data android_usb_pdata = { + .vendor_id = 0x18d1, + .product_id = 0x4e11, + .version = 0x0100, + .product_name = "Nexus One", + .manufacturer_name = "Google, Inc.", + .num_products = ARRAY_SIZE(usb_products), + .products = usb_products, + .num_functions = ARRAY_SIZE(usb_functions_all), + .functions = usb_functions_all, +}; + +static struct platform_device android_usb_device = { + .name = "android_usb", + .id = -1, + .dev = { + .platform_data = &android_usb_pdata, + }, +}; + + +static struct platform_device *g900_udc_devices[] __initdata = { +#ifdef CONFIG_USB_ANDROID_MASS_STORAGE + &usb_mass_storage_device, +#endif +#ifdef CONFIG_USB_ANDROID_RNDIS + &rndis_device, +#endif + &android_usb_device, +}; + +void __init add_usb_devices(void) +{ + + platform_add_devices(g900_udc_devices,ARRAY_SIZE(g900_udc_devices)); + +} + + + + + +#endif + +//############################# + + + + +static int g900_udc_probe(struct platform_device *pdev) +{ + printk("******Probing Toshiba g900 UDC*****\n"); + pxa_set_udc_info(&g900_udc_info); + return 0; +} + +static int g900_udc_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver g900_udc_driver = { + .driver = { + .name = "g900-udc", + }, + .probe = g900_udc_probe, + .remove = g900_udc_remove, + //.suspend = g900_udc_suspend, + //.resume = g900_udc_resume, +}; + +static int __init g900_udc_init(void) +{ + if (!machine_is_g900()) return -ENODEV; + platform_driver_register(&g900_udc_driver); +#ifdef CONFIG_USB_ANDROID + add_usb_devices(); +#endif + return 0; + +} + +static void __exit g900_udc_exit(void) +{ + return; +} + +module_init(g900_udc_init); +module_exit(g900_udc_exit); + +MODULE_AUTHOR("Xiao Huang BDevGetProperty( BDevHandle, pBDevProp ) + +/** Initializes the SD device and run-time support structure. + @param BDevHandle (#GFBDevHandle) Handle to the Block Device API + @param pDrvInfo (#GFDRV_INFO) run-time support struct + + This creates and assigns a #GFDRV_INFO into + the given BDevHandle (actually a #BDEVSDTABLE). + Read and Write functions are assinged into the #GFDRV_INFO which + should be used by higher-level file systems to access the SD + device. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +#define GFBDevMount( BDevHandle, pDrvInfo ) \ + ((PGFBDEVTABLE)BDevHandle)->BDevMount( BDevHandle, pDrvInfo ) + +/** Uninitializes the SD device. + @param BDevHandle (#GFBDevHandle) Handle to the Block Device API + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +#define GFBDevUnmount( BDevHandle ) \ + ((PGFBDEVTABLE)BDevHandle)->BDevUnmount( BDevHandle ) + +/*@}*/ +/*@}*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* GF_BDEV_H */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFBitmap.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFBitmap.h new file mode 100755 index 00000000..22286e00 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFBitmap.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFBitmap.h + * GFSDK Bitmap header file. + */ + + +#ifndef __GFBITMAP_H__ +#define __GFBITMAP_H__ + +/* Bitmap Color Format - Follow Surface Format GF_SURFACE_xxx */ +#define GF_BITMAP_YUV420 0x00000001 +#define GF_BITMAP_YUV422 0x00000002 +#define GF_BITMAP_YUYV (GF_BITMAP_YUV422|0x00000004) +#define GF_BITMAP_YVYU (GF_BITMAP_YUV422|0x00000008) +#define GF_BITMAP_UYVY (GF_BITMAP_YUV422|0x00000010) +#define GF_BITMAP_VYUY (GF_BITMAP_YUV422|0x00000020) +#define GF_BITMAP_MPEGDEC (GF_BITMAP_YUV420|0x00000040) +#define GF_BITMAP_RGB565 0x00010000 +#define GF_BITMAP_RGB8 0x00070000 +#define GF_BITMAP_ARGB8888 0x00030000 +#define GF_BITMAP_ARGB6666 0x000F0000 + +/* Bitmap */ +typedef struct _GFBITMAP +{ + NvU16 width; + NvU16 height; + NvS32 stride; + NvU32 format; + NvU8 bpp; // Bits per pixel + NvU8 reserved; + NvU16 offset; // Offset from beginning of bitmap to data + NvU8 data; // Real data starts from "Offset" location +} GFBITMAP, *PGFBITMAP; + +#endif /* __GFBITMAP_H__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFCamera.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFCamera.h new file mode 100755 index 00000000..f7730b5a --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFCamera.h @@ -0,0 +1,367 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFCamera.h + GFSDK Camera API header file. +*/ + +#ifndef __CAMERA_H__ +#define __CAMERA_H__ + +#include "GF.h" +#include "GFVx.h" +#include "GFCameraScr.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupCamera CameraAPI Camera API +

        +
      • @ref pageCameraAppNotes +
          +
        • @ref pageCameraAppNotes1 +
        +
      +*/ +/*@{*/ + + +/* Helper Macros - Do not assume bytes are properly aligned! */ +#ifndef MAKENvU8S16 +#define MAKENvU8S16( data16 ) \ + (NvU8)((data16) & 0xFF), (NvU8)(((data16) >> 8) & 0xFF) +#endif /* MAKENvU8S16 */ +#ifndef MAKENvU8S32 +#define MAKENvU8S32( data32 ) \ + (NvU8)((data32) & 0xFF), \ + (NvU8)(((data32) >> 8) & 0xFF), \ + (NvU8)(((data32) >> 16) & 0xFF), \ + (NvU8)(((data32) >> 24) & 0xFF) +#endif /* MAKENvU8S32 */ +#ifndef MAKE16 +#define MAKE16( ptr ) \ + ((NvU16)(*ptr) | ((NvU16)(*(ptr+1)) << 8)) +#endif /* MAKE16 */ +#ifndef MAKE32 +#define MAKE32( ptr ) \ + ((NvU32)MAKE16( ptr ) | (NvU32)MAKE16( (ptr+2) ) << 16) +#endif /* MAKE32 */ + +/* GFCAMERA instruction (special) */ +#define GFCAMERA_NONE 0x00 +#define GFCAMERA_NORMAL_WRITE 0x01 +#define GFCAMERA_DELAY_MSEC 0x02 +#define GFCAMERA_NEED_MCLOCK 0x03 + +/* GFCameraSetResolution Options */ +#define GFCAMERA_POWERON_OPTION 0x00000001 + +/* GFCAMERA Error codes */ +#define GFCAM_ERROR_ILLEGAL_PARAMETER (GFCAM_ERROR | 0x00000001L) +#define GFCAM_ERROR_ALLOC_FAILED (GFCAM_ERROR | 0x00000002L) +#define GFCAM_ERROR_VM_ALLOC_FAILED (GFCAM_ERROR | 0x00000003L) +#define GFCAM_ERROR_SCRIPT_ACCESS_FAILED (GFCAM_ERROR | 0x00000004L) +#define GFCAM_ERROR_NATIVE_FUNCTION_FAILED (GFCAM_ERROR | 0x00000005L) +#define GFCAM_ERROR_GETTING_COMPONENT (GFCAM_ERROR | 0x00000006L) +#define GFCAM_ERROR_VM_BUFFER_ALLOC_FAILED (GFCAM_ERROR | 0x00000007L) +#define GFCAM_ERROR_CAMERA_SCRIPT_NOT_PRESENT (GFCAM_ERROR | 0x00000008L) +#define GFCAM_ERROR_FUNCTION_NOT_SUPPORTED (GFCAM_ERROR | 0x00000009L) + +/* GFCAMERAINSTRTYPE */ +typedef struct _GFCAMERAINSTRTYPE +{ + NvU16 skip; // IMPORTANT: Multiple instructions + // must be in ascending skip order + NvU8 type; + NvU16 size; + NvU32 data; +} GFCAMERAINSTRTYPE, *PGFCAMERAINSTRTYPE; + +/* GFCAMERABAYERINFO - BayerInfo struct */ +typedef struct _GFCAMERABAYERINFO +{ + NvU16 ScanWidth; + NvU16 ScanHeight; + + NvU16 ActiveLineStart; + NvU16 ActiveLineWidth; + NvU16 ActiveFrameStart; + NvU16 ActiveFrameHeight; + NvU8 hSyncEdge; + NvU8 vSyncEdge; + NvU16 bayerSel; + +} GFCAMERABAYERINFO, *PGFCAMERABAYERINFO; + +/* GFCAMERARESOLUTIONTYPE - Resolution struct */ +typedef struct _GFCAMERARESOLUTIONTYPE +{ + NvU16 x; + NvU16 y; + NvU8 numInstr; + GFCAMERAINSTRTYPE *pInstr; + GFCAMERABAYERINFO *pBayerInfo; +} GFCAMERARESOLUTIONTYPE, *PGFCAMERARESOLUTIONTYPE; + + + +/* GFCAMERATABLETYPE - Camera Table */ +#define GFCAMERA_NAME_SIZE 32 +typedef struct _GFCAMERATABLETYPE +{ + NvU16 id; + NvU16 ver; + NvU32 scriptSubID; + char name[GFCAMERA_NAME_SIZE]; + // variable name char string always + // ends with a '0' + NvU32 VIPFlag; + NvU32 VIPNewTiming; + NvU32 VIPColorFormat; + NvU8 VIPHOffset; + NvU8 VIPVOffset; + NvU8 numI2CBytes; //bytes per transfer/packet + NvU8 numRes; + GFCAMERARESOLUTIONTYPE *pResData; + NvU16 initDataSize; + NvU8 *pInitData; +// GFCAMERABAYERINFO *pBayerInfo; + struct _GFCAMERATABLETYPE *pNext; +} GFCAMERATABLETYPE, *PGFCAMERATABLETYPE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFCameraOpen(GFRmHandle hRm, GFCameraHandle *phCamera, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFCameraClose(GFCameraHandle *phCamera); + +/** This routine returns the camera's properties and capabilities. + These properties are returned in the GFPROPERTY structure. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param pProp (PGFPROPERTY) Pointer to GFPROPERTY structure. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see GFPROPERTY +*/ +GF_RETTYPE GFCameraGetProperty(GFCameraHandle CameraHandle, + PGFPROPERTY pProp); + +/** This routine programs the camera's registers based on the data + contained in the camera table. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param resX (NvU16) Horizontal resolution + @param resY (NvU16) Vertical resolution + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see PGFCAMERATABLETYPE +*/ +GF_RETTYPE GFCameraSetup(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + NvU16 resX, + NvU16 resY ); + +/** This routine programs the camera's registers for a resolution change. + The main difference from GFCameraSetup() is the lack of camera power on. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param resX (NvU16) Horizontal resolution + @param resY (NvU16) Vertical resolution + @param poweron (NvU32) flag indicates whether camera power on should be executed + @param option (NvU32) flag passed to camera script SetResolution function + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see PGFCAMERATABLETYPE +*/ +GF_RETTYPE GFCameraSetResolution(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + NvU16 resX, + NvU16 resY, + NvU32 poweron, + NvU32 option); + +/** This routine allocates the run-time camera table structure from the + camera scripts. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pTable (NvU8) Pointer to camera configuration table, ignored for GFSDK SC15. + Camera configurations are passed via scripts. + @param *ppCamera (PGFCAMERATABLETYPE) Returns pointer to linked list of camera description tables + + @return On success the number of cameras in the linked list is returned. This can be 0. + On failure an error code is returned. To distinguish between success and failure, + use macro #ISGFERROR() or #ISGFSUCCESS(). + + @see PGFCAMERATABLETYPE +*/ +GF_RETTYPE GFCameraTableAlloc(GFCameraHandle CameraHandle, + NvU8 *pTable, + PGFCAMERATABLETYPE *ppCamera); + +/** This routine frees the camera table structure created by + GFCameraTableAlloc(). + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *ppCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see PGFCAMERATABLETYPE +*/ +GF_RETTYPE GFCameraTableFree(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE *ppCamera); + +GF_RETTYPE GFCameraTableDump(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera); + +/** This routine finds a camera that is contained in the camera table structure. + It does so using various parameters that refer to entries in the table. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param *pWanted (PGFCAMERATABLETYPE) Pointer to the found PGFCAMERATABLETYPE structure. + @param id (NvU32) Unique I2C slave ID for the camera. + @param *name (Char) pointer to name. + @param resX (NvU16) Horizontal resolution + @param resY (NvU16) Vertical resolution + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFCameraFind(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + PGFCAMERATABLETYPE *pWanted, + NvU32 id, + char *name, + NvU16 resX, + NvU16 resY ); + +/** This routine scans for a camera that is contained in the + table structure created by GFCameraTableAlloc(). + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pTable (NvU8) Pointer to camera table. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFCameraScan(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera); + +/** This routine uses the script subID parameter to find a camera + that is contained in the camera table structure. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param *pWanted (PGFCAMERATABLETYPE) Pointer to the found PGFCAMERATABLETYPE structure. + @param subID (NvU32) Camera script subID. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFCameraScriptFind(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + PGFCAMERATABLETYPE *pWanted, + NvU32 subID); + +/** This routine calls the camera script function to operate on a user defined + camera attribute. A shared buffer is used to pass parameters to and from + the camera script function. + + The shared buffer and may contain data used by the script function + to perform the requested operation. The first data should indicate + the primary setting of the operation. The convention is to use ranges + that are normalized from 0 to 100. Where specific data is required, + that data must match that which is allowable by the camera in use. + If not, the error code GFCAM_ERROR_ILLEGAL_PARAMETER is returned. + + The attribute may be one of the defined flags listed below. + GFCAMERA_CAMERACONTROL_PAN + GFCAMERA_CAMERACONTROL_TILT + GFCAMERA_CAMERACONTROL_ROLL + GFCAMERA_CAMERACONTROL_ZOOM + GFCAMERA_CAMERACONTROL_EXPOSURE + GFCAMERA_CAMERACONTROL_IRIS + GFCAMERA_CAMERACONTROL_FOCUS + GFCAMERA_CAMERACONTROL_FLASH + GFCAMERA_VIDEOPROCAMP_BRIGHTNESS + GFCAMERA_VIDEOPROCAMP_CONTRAST + GFCAMERA_VIDEOPROCAMP_HUE + GFCAMERA_VIDEOPROCAMP_SATURATION + GFCAMERA_VIDEOPROCAMP_SHARPNESS + GFCAMERA_VIDEOPROCAMP_GAMMA + GFCAMERA_VIDEOPROCAMP_COLORENABLE + GFCAMERA_VIDEOPROCAMP_WHITEBALANCE + GFCAMERA_VIDEOPROCAMP_BACKLIGHT_COMPENSATION + GFCAMERA_VIDEOPROCAMP_GAIN + + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param attribute (NvU32) Attribute flag indicates operation. + @param *sharedBuffer (NvU32) pointer to a shared buffer. + @param bufferSize (NvU32) Size of shared buffer. + @param *readValue (NvU32) pointer to the returned value from the camera script function. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GFCAM_ERROR_FUNCTION_NOT_SUPPORTED Attribute not supported + @retval #GFCAM_ERROR_ILLEGAL_PARAMETER Parameter out of range + +*/ +GF_RETTYPE GFCameraScriptSetAttribute(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + NvU32 attribute, + NvU32 *sharedBuffer, + NvU32 bufferSize, + NvU32 *readValue); + +/** This routine uses the camera script function to execute a powerup or + powerdown sequence. + + @param CameraHandle (#GFCameraHandle) Handle to CameraAPI + @param *pCamera (PGFCAMERATABLETYPE) Pointer to camera entry. + @param poweron (NvU32) If set to '0' execute powerdown, if '1', execute powerup. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFCameraPower(GFCameraHandle CameraHandle, + PGFCAMERATABLETYPE pCamera, + NvU32 poweron); + +/*@}*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** @page pageCameraAppNotes CameraAPI Application Notes + + @section pageCameraAppNotes1 Todo + +*/ + +#endif /* __CAMERA_H__ */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFCameraScr.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFCameraScr.h new file mode 100755 index 00000000..b34eb21b --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFCameraScr.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#if !defined (__GFCAMERASCR_INC__) +#define __GFCAMERASCR_INC__ + +/* Camera Script error codes */ +#define GFCAMERA_NOT_SUPPORTED 0x80000000 //return error code for attribute +#define GFCAMERA_PARAMETER_ERROR 0x80000001 //return out of range parameter + +/** Camera script attribute flags, for camera control functions + @see GFCameraScriptSetAttribute() +*/ +#define GFCAMERA_CAMERACONTROL_PAN 0x00000001 +#define GFCAMERA_CAMERACONTROL_TILT 0x00000002 +#define GFCAMERA_CAMERACONTROL_ROLL 0x00000003 +#define GFCAMERA_CAMERACONTROL_ZOOM 0x00000004 +#define GFCAMERA_CAMERACONTROL_EXPOSURE 0x00000005 +#define GFCAMERA_CAMERACONTROL_IRIS 0x00000006 +#define GFCAMERA_CAMERACONTROL_FOCUS 0x00000007 +#define GFCAMERA_CAMERACONTROL_FLASH 0x00000008 +#define GFCAMERA_VIDEOPROCAMP_BRIGHTNESS 0x00000009 +#define GFCAMERA_VIDEOPROCAMP_CONTRAST 0x0000000a +#define GFCAMERA_VIDEOPROCAMP_HUE 0x0000000b +#define GFCAMERA_VIDEOPROCAMP_SATURATION 0x0000000c +#define GFCAMERA_VIDEOPROCAMP_SHARPNESS 0x0000000d +#define GFCAMERA_VIDEOPROCAMP_GAMMA 0x0000000e +#define GFCAMERA_VIDEOPROCAMP_COLORENABLE 0x0000000f +#define GFCAMERA_VIDEOPROCAMP_WHITEBALANCE 0x00000010 +#define GFCAMERA_VIDEOPROCAMP_BACKLIGHT_COMPENSATION 0x00000011 +#define GFCAMERA_VIDEOPROCAMP_GAIN 0x00000012 + +#endif + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDef.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDef.h new file mode 100755 index 00000000..c7a9df55 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDef.h @@ -0,0 +1,254 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFDef.h + * GFSDK Definition header file + */ + +#ifndef __GFDEF_H__ +#define __GFDEF_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "GFDefScr.h" + +/* Register field manipulation using xxx_RANGE macros defined in hardware + * header files. + */ +#define GF_LOWBIT(x) (0?x) +#define GF_HIGHBIT(x) (1?x) +#define GF_SIZE(x) (GF_HIGHBIT(x)-GF_LOWBIT(x)+1) +#define GF_SHIFT(x) ((0?x)%32) +#define GF_MASK(x) (0xFFFFFFFFUL>>(31-((1?x)%32)+((0?x)%32))) +#define GF_BITS(val, x) (((val) & GF_MASK(x))<> GF_SHIFT(d##_##r##_0_##f##_RANGE))& GF_MASK(d##_##r##_0_##f##_RANGE)) + +#define GF_FLD_SET_DRF_NUM(d,r,f,n,v) ((v & ~GF_SHIFTMASK(d##_##r##_0_##f##_RANGE)) | GF_DRF_NUM(d,r,f,n)) +#define GF_FLD_SET_DRF_DEF(d,r,f,c,v) (((v) & ~GF_SHIFTMASK(d##_##r##_0_##f##_RANGE)) | GF_DRF_DEF(d,r,f,c)) + +#define GF_RESETVAL(d,r) (d##_##r##_0_RESET_VAL) + +#define OP_DRF_DEF(o,f,c) ((o##_##f##_##c) << GF_SHIFT(o##_##f##_RANGE)) +#define OP_DRF_NUM(o,f,n) (((n)& GF_MASK(o##_##f##_RANGE))<< GF_SHIFT(o##_##f##_RANGE)) +#define OP_DRF_VAL(o,f,v) (((v)>> GF_SHIFT(o##_##f##_RANGE))& GF_MASK(o##_##f##_RANGE)) + +#define OP_FLD_SET_DRF_NUM(o,f,n,v) ((v & ~GF_SHIFTMASK(o##_##f##_RANGE)) | GF_DRF_NUM(o,f,n)) +#define OP_FLD_SET_DRF_DEF(o,f,c,v) (((v) & ~GF_SHIFTMASK(o##_##f##_RANGE)) | GF_DRF_DEF(o,f,c)) + +/* Default Return Codes */ +/* - All errors has MSB set, indicate a negative val. */ + +/** Macro to test if an error code of type GF_RETTYPE signals failure. + @param code (GF_RETTYPE) Error code + @return Evaluates to \a true on failure, \a false on success. +*/ +#define ISGFERROR(code) ((GF_RETTYPE)(code) < GF_SUCCESS) + +/** Macro to test if an error code of type GF_RETTYPE signals success. + @param code (GF_RETTYPE) Error code + @return Evaluates to \a true on success, \a false on failure. +*/ +#define ISGFSUCCESS(code) ((GF_RETTYPE)(code) >= GF_SUCCESS) + +/** Common error code: Generic error. */ +#define GF_ERROR 0x80000000L +/** Common error code: Success (not an error). */ +#define GF_SUCCESS 0x00000000L +/** Common error code: Busy (not an error). */ +#define GF_ERROR_BUSY 0x80000001L +/** Common error code: Out of memory. This can be CPU heap memory, or GPU memory. */ +#define GF_ERROR_OUT_MEMORY 0x80000003L +/** Common error code: Bad parameter. */ +#define GF_ERROR_BAD_PARAMETER 0x80000005L + + +#define GF_COMPONENT_ERROR_SHIFT 24 +/** Macro to reverse bits of the 7 bit component ID. + See GF_RETTYPE for explanation. +*/ +#define GF_COMPONENT_REVERSE(c) ((((c)&64)>>6)|(((c)&32)>>4)|(((c)&16)>>2)|((c)&8)|(((c)&4)<<2)|(((c)&2)<<4)|(((c)&1)<<6)) + +#define GX_ERROR (GF_COMPONENT_REVERSE(GF_GXAPI)< + +/** Utility macro */ +#define CHECK_STATUS_CLEANUP(f) \ + do { \ + if(ISGFERROR( ( status = (f) ) )) \ + goto Cleanup; \ + } while(0) + + + +#if !defined(NV_MODS) + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * READ THIS FIRST: + * + * None of these funtions should be called directly by an application. The + * macros below should be used instead. + */ + +/** Diag context structure */ +typedef struct _GFDIAGCONTEXT +{ + NvU32 processID; + NvU32 threadID; +} GFDIAGCONTEXT, *PGFDIAGCONTEXT; + + +/** Public exposed DIAG API functions in the table */ +typedef struct _GFDIAGTABLE +{ + /** + @see GF_DIAG_INITIALIZE + */ + GF_RETTYPE ( *DiagInitialize)( GFDiagHandle DiagHandle, int argc, char **argv ); + + /** + @see GF_DIAG_GET_VERSION + */ + GF_RETTYPE ( *DiagGetVersion)( GFDiagHandle DiagHandle, char *versionStr, int bufferLen ); + + /** + @see GF_DIAG_SET_RENDER_SURFACE + */ + GF_RETTYPE ( *DiagSetRenderSurface)( GFDiagHandle DiagHandle, PGFRMSURFACE surface ); + + /** + @see GF_DIAG_SET_IDLE_CHIP_CALLBACK + */ + GF_RETTYPE ( *DiagSetIdleChipCallback)( GFDiagHandle DiagHandle, + GF_RETTYPE (*pIdleCallback)(void *idleCallbackData), void *data ); + + /** + @see GF_DIAG_FRAME_DONE + */ + GF_RETTYPE ( *DiagFrameDone)( GFDiagHandle DiagHandle ); + + /** + @see GF_DIAG_CLEANUP + */ + GF_RETTYPE ( *DiagCleanup)( GFDiagHandle DiagHandle ); + + /** + @see GF_DIAG_RUN_TEST + */ + GF_RETTYPE (* DiagRunTest)( GFDiagHandle DiagHandle, char *testName, + const char *pCmdLine, NvU8 flag, GFDiagHandle *pDiagChildHandle ); + + /** + @see GF_DIAG_WAIT_FOR_TEST + */ + GF_RETTYPE (* DiagWaitForTest)( GFDiagHandle DiagHandle ); + + /** + @see GF_DIAG_PRINT + */ + GF_RETTYPE (* DiagPrint)( GFDiagHandle DiagHandle, const char *msg ); + + /** + @see GF_DIAG_GET_CONTEXT + */ + GF_RETTYPE (* DiagGetContext)( GFDiagHandle DiagHandle, GFDIAGCONTEXT *pContext ); +} GFDIAGTABLE, *PGFDIAGTABLE; + +/* +***************************************************************************** +* MACROS - Apps should use these to communicate with GFDiag +***************************************************************************** +*/ + +// Function documentation goes here to bypass #ifdef problems + +/** @name Functions +@{*/ + +/** @def GF_DIAG_MAIN + Replace your standard definition of "int main" with with this macro + for use with GFDiag. + + @param unused1 (int) Unused -- obsolete argument, to be removed + @param unused2 (char**) Unused -- obsolete argument, to be removed + @param testName (char*) Name of the test + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_INITIALIZE + Control things like storing vs checking, HW vs SW crcs via this function. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param argc (int) Argument count + @param argv (char**) Argument data + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Will read in the stored CRCs if applicable. +*/ + +/** @def GF_DIAG_GET_VERSION + Query the GFDiag version. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param str (char*) Pointer to a buffer that will be filled with the GFDiag version + @param len (int) Length of the buffer, versionStr + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The application allocates a buffer and passes it + (along with its length) to GFDiag. +*/ + +/** @def GF_DIAG_SET_IDLE_CHIP_CALLBACK +Allow the test to idle the chip in its own way. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param callbackFn (GF_RETTYPE (void *idleCallbackData)) Function pointer to call on idle + @param callbackData (void*) Data to pass to pIdleCallback when it is called + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_SET_RENDER_SURFACE + Tell GFDiag what surface we want to CRC etc. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param surface (#PGFRMSURFACE) Surface we want to CRC + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_FRAME_DONE + Announce the completion of a frame. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFDiag has the option to: + + Calculate a CRC on the primary surface. This function calls the callback + function set by GFDiagSetIdleChipCallback (or a default if no idle chip + callback is supplied) to idle the chip before calculating CRCs + + In "storing mode" this will store the CRC in some DB that gets written + to file later. + + In "checking mode" this checks the CRC against the one we read in from file. +*/ + +/** @def GF_DIAG_CLEANUP + Perform any necessary cleanup operations before the test exits and write + CRCs to file if applicable. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_PRINT + Prints to GFDiag. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param x (const char*) Message to print + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_RUN_TEST +Starts a test executing. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param testName (char*) Name of the test to execute + @param pCmdLine (const char*) The command line to execute the test + @param flag (NvU8) This is an option specifying how the test should be run. May contain one of: GF_DIAG_RUN_NEW_PROCESS, GF_DIAG_RUN_NEW_THREAD or GF_DIAG_RUN_NORMAL + @param pDiagChildHandle (#GFDiagHandle) This is a pointer to a GFDiagHandle that will be filled in with the handle of the child process + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_WAIT_FOR_TEST + Waits for test to complete, return value will be result of test. + + @param DiagHandle (#GFDiagHandle) Handle to Diag of test to run (probably the handle placed in pDiagChildHandle from GF_DAIG_RUN_TEST) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see GF_DIAG_RUN_TEST +*/ + +/** @def GF_DIAG_GET_CONTEXT +Gets context from GFDiag. + + @param DiagHandle (#GFDiagHandle) Handle to Diag + @param pContext (#GFDIAGCONTEXT) Points to a structure that will be filled with the current context + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ + +/** @def GF_DIAG_PRINTF + Format prints a message. + + @param x (bracketed printf string) Message to print +*/ + +/*@}*/ + +/* Run flags */ + +/** Test is run in same thread */ +#define GF_DIAG_RUN_NORMAL 1 +#define GF_DIAG_RUN_NEW_THREAD 2 +#define GF_DIAG_RUN_NEW_PROCESS 4 + + +/** @def GF_DIAG_CRC_STATUS + Helper macro to check the status of a call to GF_DIAG_FRAME_DONE + and increment a fail count if the status was a failure. + + eg: + @code GF_DIAG_CRC_STATUS(GF_DIAG_FRAME_DONE("DxTest"), GF_Diag_CrcFailCount); + @endcode + + @param status The status of a call to GF_DIAG_FRAME_DONE + @param gf_diag_crcFailCount The var containing the current failure count + + @see GF_DIAG_FRAME_DONE +*/ +#define GF_DIAG_CRC_STATUS(status, gf_diag_crcFailCount) + +#ifdef GF_DIAG_ENABLED + +/* + * See doxygen comments above for info on the following macros + */ +#define GF_DIAG_MAIN(unused1, unused2, testName) \ + int TestMain(int argc, char *argv[], GFDiagHandle handle) + +#define GF_DIAG_INITIALIZE(handle, argc, argv) \ + ((PGFDIAGTABLE)handle)->DiagInitialize((handle), (argc), (argv)) + +#define GF_DIAG_GET_VERSION(handle, str, len) \ + ((PGFDIAGTABLE)handle)->DiagGetVersion((handle), (str), (len)) + +#define GF_DIAG_SET_IDLE_CHIP_CALLBACK(handle, callbackFn, callbackData) \ + ((PGFDIAGTABLE)handle)->DiagSetIdleChipCallback(handle, callbackFn, callbackData) + +#define GF_DIAG_SET_RENDER_SURFACE(handle, surface) \ + ((PGFDIAGTABLE)handle)->DiagSetRenderSurface((handle), (surface)) + +#define GF_DIAG_FRAME_DONE(handle) \ + ((PGFDIAGTABLE)handle)->DiagFrameDone((handle)) + +#define GF_DIAG_CLEANUP(handle) \ + ((PGFDIAGTABLE)handle)->DiagCleanup((handle)) + +#define GF_DIAG_PRINT(handle, x) \ + ((PGFDIAGTABLE)handle)->DiagPrint(handle, x) + +#define GF_DIAG_RUN_TEST(handle, testName, pCmdLine, flag, pDiagChildHandle) \ + ((PGFDIAGTABLE)handle)->DiagRunTest(handle, testName, pCmdLine, flag, pDiagChildHandle) + +#define GF_DIAG_WAIT_FOR_TEST(handle) \ + ((PGFDIAGTABLE)handle)->DiagWaitForTest(handle) + +#define GF_DIAG_GET_CONTEXT(handle, pContext) \ + ((PGFDIAGTABLE)handle)->DiagGetContext(handle, pContext) + + +static void +GFDiagPrintf( GFDiagHandle handle, const char *fmt, ... ) +{ + char buf[1024]; + va_list list; + + va_start(list, fmt); + + GFSprintfVAL(buf, fmt, list); + + GF_DIAG_PRINT(handle, buf); + + va_end(list); +} + +#define GF_DIAG_PRINTF(x) GFDiagPrintf x + +#else + +/* + * Do this exactly like nvplat...so this will have an OS specific + * implementation in the final GFDiag.h + */ +#if NVOS_IS_LINUX || NVOS_IS_WINDOWS +#define GF_DIAG_MAIN(unused1, unused2, testName) \ + int TestMain(int argc, char *argv[]) +#define GF_DIAG_MAIN_DEFAULT_1ARG(unused1, unused2, testName, arg1) \ + int TestMain(int argc, char *argv[]) +#define GF_DIAG_MAIN_DEFAULT_2ARGS(unused1, unused2, testName, arg1, arg2) \ + int TestMain(int argc, char *argv[]) +#define GF_DIAG_MAIN_DEFAULT_3ARGS(unused1, unused2, testName, arg1, arg2, arg3) \ + int TestMain(int argc, char *argv[]) +#else +#define GF_DIAG_MAIN(unused1, unused2, testName) \ + int argc = 1; \ + char *argv[] = { #testName }; \ + int main() +#define GF_DIAG_MAIN_DEFAULT_1ARG(unused1, unused2, testName, arg1) \ + int argc = 2; \ + char *argv[] = { #testName, arg1 }; \ + int main() +#define GF_DIAG_MAIN_DEFAULT_2ARGS(unused1, unused2, testName, arg1, arg2) \ + int argc = 3; \ + char *argv[] = { #testName, arg1, arg2 }; \ + int main() +#define GF_DIAG_MAIN_DEFAULT_3ARGS(unused1, unused2, testName, arg1, arg2, arg3) \ + int argc = 4; \ + char *argv[] = { #testName, arg1, arg2, arg3 }; \ + int main() +#endif + +#define GF_DIAG_INITIALIZE(testName, argc, argv) GF_SUCCESS +#define GF_DIAG_CLEANUP(testName) GF_SUCCESS + +/* These should be removed once all the Apps & MODS are updated */ +#define GF_DIAG_GET_VERSION(testName, str, len) GF_SUCCESS +#define GF_DIAG_SET_IDLE_CHIP_CALLBACK(testName, callbackFn, callbackData) GF_SUCCESS +#define GF_DIAG_SET_RENDER_SURFACE(testName, surface) GF_SUCCESS +#define GF_DIAG_FRAME_DONE(testName) GF_SUCCESS +#define GF_DIAG_PRINT(handle, x) GF_SUCCESS +#define GF_DIAG_RUN_TEST(handle, testName, pCmdLine, flag, pDiagChildHandle) GF_SUCCESS +#define GF_DIAG_WAIT_FOR_TEST(handle) GF_SUCCESS +#define GF_DIAG_GET_CONTEXT(handle, pContext) GF_SUCCESS + +#define GF_DIAG_PRINTF(x) GFPrintf x + +#endif /* GF_DIAG_ENABLED */ + +#ifdef __cplusplus +} +#endif + +/* NV_MODS */ +#else + +/* GFDiag is always enabled in NV_MODS builds */ +#define GF_DIAG_ENABLED 1 + +#ifndef INCLUDED_GFMODS_H +#include "../GFMods/src/GFMods.h" +#endif + +#endif /* NV_MODS */ + +#define CHECK_STATUS_MSG(f,TEXT) \ + do { \ + if(ISGFERROR( ( status = (f) ) )) \ + { \ + GF_DIAG_PRINTF((TEXT)); \ + } \ + } while(0) + + +#define CHECK_STATUS_CLEANUP_MSG(f , TEXT) \ + do { \ + if(ISGFERROR( ( status = (f) ) )) \ + { \ + GF_DIAG_PRINTF(TEXT); \ + goto Cleanup; \ + } \ + } while(0) + +#define CHECK_STATUS_AND_DISPLAY_CLEANUP_MSG(f , TEXT) \ + do { \ + if(ISGFERROR( ( status = (f) ) )) \ + { \ + GF_DIAG_PRINTF((TEXT,f)); \ + goto Cleanup; \ + } \ + } while(0) +#endif /* __GFDIAG_H__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDispCmdData.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDispCmdData.h new file mode 100755 index 00000000..5106900b --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDispCmdData.h @@ -0,0 +1,1740 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#if !defined __GFDISPCMDDATA_H__ +#define __GFDISPCMDDATA_H__ + +// Display Signal Options 0 + +#define GF_DEFAULT_TABLE 0x01 // Display Default Table Support +#define GF_DXAPI_SUPPORT 0x02 // DxAPI Support +#define GF_FMARK_SUPPORT 0x04 // FMARK Supported by panel + +#define GFSDXAPI_PROC0 0x80000000 // PROC0 in Display DxAPI table in Script +#define GFSDXAPI_PROC1 0x80000001 // PROC1 in Display DxAPI table in Script +#define GFSDXAPI_PROC2 0x80000002 // PROC2 in Display DxAPI table in Script +#define GFSDXAPI_PROC3 0x80000003 // PROC3 in Display DxAPI table in Script +#define GFSDXAPI_PROC4 0x80000004 // PROC4 in Display DxAPI table in Script +#define GFSDXAPI_PROC5 0x80000005 // PROC5 in Display DxAPI table in Script +#define GFSDXAPI_PROC6 0x80000006 // PROC6 in Display DxAPI table in Script +#define GFSDXAPI_PROC7 0x80000007 // PROC7 in Display DxAPI table in Script +#define GFSDXAPI_PROC8 0x80000008 // PROC8 in Display DxAPI table in Script +#define GFSDXAPI_PROC9 0x80000009 // PROC9 in Display DxAPI table in Script +#define GFSDXAPI_PROC10 0x8000000A // PROC10 in Display DxAPI table in Script +#define GFSDXAPI_PROC11 0x8000000B // PROC11 in Display DxAPI table in Script +#define GFSDXAPI_PROC12 0x8000000C // PROC12 in Display DxAPI table in Script +#define GFSDXAPI_PROC13 0x8000000D // PROC13 in Display DxAPI table in Script +#define GFSDXAPI_PROC14 0x8000000E // PROC14 in Display DxAPI table in Script +#define GFSDXAPI_PROC15 0x8000000F // PROC14 in Display DxAPI table in Script +#define GFSDXAPI_PROC16 0x80000010 // PROC16 in Display DxAPI table in Script +#define GFSDXAPI_PROC17 0x80000011 // PROC17 in Display DxAPI table in Script +#define GFSDXAPI_PROC18 0x80000012 // PROC18 in Display DxAPI table in Script +#define GFSDXAPI_PROC19 0x80000013 // PROC19 in Display DxAPI table in Script +#define GFSDXAPI_PROC20 0x80000014 // PROC20 in Display DxAPI table in Script +#define GFSDXAPI_PROC21 0x80000015 // PROC21 in Display DxAPI table in Script +#define GFSDXAPI_PROC22 0x80000016 // PROC22 in Display DxAPI table in Script +#define GFSDXAPI_PROC23 0x80000017 // PROC23 in Display DxAPI table in Script +#define GFSDXAPI_PROC24 0x80000018 // PROC24 in Display DxAPI table in Script +#define GFSDXAPI_PROC25 0x80000019 // PROC25 in Display DxAPI table in Script +#define GFSDXAPI_PROC26 0x8000001A // PROC26 in Display DxAPI table in Script +#define GFSDXAPI_PROC27 0x8000001B // PROC27 in Display DxAPI table in Script +#define GFSDXAPI_PROC28 0x8000001C // PROC28 in Display DxAPI table in Script +#define GFSDXAPI_PROC29 0x8000001D // PROC29 in Display DxAPI table in Script +#define GFSDXAPI_PROC30 0x8000001E // PROC30 in Display DxAPI table in Script +#define GFSDXAPI_PROC31 0x8000001F // PROC31 in Display DxAPI table in Script +#define GFSDXAPI_PROC_END 0x8000FFFF // PROC End in Display DxAPI table in Script + +#define OFFSET_DISP_SIGNAL_OPTIONS0 0x00000101 + +#define GFSCMD_H_PULSE0 0x00088101 +#define GFSCMD_H_PULSE1 0x000A8101 +#define GFSCMD_H_PULSE2 0x000C8101 +#define GFSCMD_V_PULSE0 0x00108101 +#define GFSCMD_V_PULSE1 0x00128101 +#define GFSCMD_V_PULSE2 0x00138101 +#define GFSCMD_V_PULSE3 0x00148101 +#define GFSCMD_M0 0x00188101 +#define GFSCMD_M1 0x001A8101 + +#define GF_H_PULSE0_DISABLE 0x00000000 +#define GF_H_PULSE0_ENABLE 0x00000100 +#define GF_H_PULSE1_DISABLE 0x00000000 +#define GF_H_PULSE1_ENABLE 0x00000400 +#define GF_H_PULSE2_DISABLE 0x00000000 +#define GF_H_PULSE2_ENABLE 0x00001000 +#define GF_V_PULSE0_DISABLE 0x00000000 +#define GF_V_PULSE0_ENABLE 0x00010000 +#define GF_V_PULSE1_DISABLE 0x00000000 +#define GF_V_PULSE1_ENABLE 0x00040000 +#define GF_V_PULSE2_DISABLE 0x00000000 +#define GF_V_PULSE2_ENABLE 0x00080000 +#define GF_V_PULSE3_DISABLE 0x00000000 +#define GF_V_PULSE3_ENABLE 0x00100000 +#define GF_M0_DISABLE 0x00000000 +#define GF_M0_ENABLE 0x01000000 +#define GF_M1_DISABLE 0x00000000 +#define GF_M1_ENABLE 0x02000000 + + +// Display Signal Options 1 + +#define OFFSET_DISP_SIGNAL_OPTIONS1 0x00000102 +#define GFSCMD_DI 0x00108102 +#define GFSCMD_PP 0x00128102 + +#define GF_DI_DISABLE 0x00000000 +#define GF_DI_ENABLE 0x00010000 +#define GF_PP_DISABLE 0x00000000 +#define GF_PP_ENABLE 0x00040000 + +#define OFFSET_H_PULSE0_CONTROL 0x0000010c + +#define GFSCMD_H_PULSE0_MODE 0x0003810c +#define GFSCMD_H_PULSE0_POLARITY 0x0004810c +#define GFSCMD_H_PULSE0_V_QUAL 0x0006810c +#define GFSCMD_H_PULSE0_LAST 0x0008810c + +#define GF_H_PULSE0_MODE_NORMAL 0x00000000 +#define GF_H_PULSE0_MODE_ONE_CLOCK 0x00000008 +#define GF_H_PULSE0_POLARITY_HIGH 0x00000000 +#define GF_H_PULSE0_POLARITY_LOW 0x00000010 +#define GF_H_PULSE0_V_QUAL_ALWAYS 0x00000000 +#define GF_H_PULSE0_V_QUAL_VACTIVE 0x00000080 +#define GF_H_PULSE0_V_QUAL_VACTIVE1 0x000000A0 +#define GF_H_PULSE0_LAST_START_A 0x00000000 +#define GF_H_PULSE0_LAST_END_A 0x00000100 +#define GF_H_PULSE0_LAST_START_B 0x00000200 +#define GF_H_PULSE0_LAST_END_B 0x00000300 +#define GF_H_PULSE0_LAST_START_C 0x00000400 +#define GF_H_PULSE0_LAST_END_C 0x00000500 +#define GF_H_PULSE0_LAST_START_D 0x00000600 +#define GF_H_PULSE0_LAST_END_D 0x00000700 + +#define OFFSET_H_PULSE0_POSITION_A 0x0000010d +#define GFSCMD_H_PULSE0_POSITION_A 0x0000810d + +#define OFFSET_H_PULSE1_CONTROL 0x00000111 + +#define GFSCMD_H_PULSE1_MODE 0x00038111 +#define GFSCMD_H_PULSE1_POLARITY 0x00048111 +#define GFSCMD_H_PULSE1_V_QUAL 0x00068111 +#define GFSCMD_H_PULSE1_LAST 0x00088111 + +#define GF_H_PULSE1_MODE_NORMAL 0x00000000 +#define GF_H_PULSE1_MODE_ONE_CLOCK 0x00000008 +#define GF_H_PULSE1_POLARITY_HIGH 0x00000000 +#define GF_H_PULSE1_POLARITY_LOW 0x00000010 +#define GF_H_PULSE1_V_QUAL_ALWAYS 0x00000000 +#define GF_H_PULSE1_V_QUAL_VACTIVE 0x00000080 +#define GF_H_PULSE1_V_QUAL_VACTIVE1 0x000000A0 +#define GF_H_PULSE1_LAST_START_A 0x00000000 +#define GF_H_PULSE1_LAST_END_A 0x00000100 +#define GF_H_PULSE1_LAST_START_B 0x00000200 +#define GF_H_PULSE1_LAST_END_B 0x00000300 +#define GF_H_PULSE1_LAST_START_C 0x00000400 +#define GF_H_PULSE1_LAST_END_C 0x00000500 +#define GF_H_PULSE1_LAST_START_D 0x00000600 +#define GF_H_PULSE1_LAST_END_D 0x00000700 + +#define OFFSET_H_PULSE1_POSITION_A 0x00000112 +#define GFSCMD_H_PULSE1_POSITION_A 0x00008112 + +#define OFFSET_H_PULSE2_CONTROL 0x00000116 +#define GFSCMD_H_PULSE2_MODE 0x00038116 +#define GFSCMD_H_PULSE2_POLARITY 0x00048116 +#define GFSCMD_H_PULSE2_V_QUAL 0x00068116 +#define GFSCMD_H_PULSE2_LAST 0x00088116 + +#define GF_H_PULSE2_MODE_NORMAL 0x00000000 +#define GF_H_PULSE2_MODE_ONE_CLOCK 0x00000008 +#define GF_H_PULSE2_POLARITY_HIGH 0x00000000 +#define GF_H_PULSE2_POLARITY_LOW 0x00000010 +#define GF_H_PULSE2_V_QUAL_ALWAYS 0x00000000 +#define GF_H_PULSE2_V_QUAL_VACTIVE 0x00000080 +#define GF_H_PULSE2_V_QUAL_VACTIVE1 0x000000A0 +#define GF_H_PULSE2_LAST_START_A 0x00000000 +#define GF_H_PULSE2_LAST_END_A 0x00000100 +#define GF_H_PULSE2_LAST_START_B 0x00000200 +#define GF_H_PULSE2_LAST_END_B 0x00000300 +#define GF_H_PULSE2_LAST_START_C 0x00000400 +#define GF_H_PULSE2_LAST_END_C 0x00000500 +#define GF_H_PULSE2_LAST_START_D 0x00000600 +#define GF_H_PULSE2_LAST_END_D 0x00000700 + +#define OFFSET_H_PULSE2_POSITION_A 0x00000117 +#define GFSCMD_H_PULSE2_POSITION_A 0x00008117 + +#define GFSCMD_V_PULSE0_POLARITY 0x0004811b +#define GFSCMD_V_PULSE0_DELAY_CNTRL 0x0006811b +#define GFSCMD_V_PULSE0_LAST 0x0008811b + +#define GF_V_PULSE0_POLARITY_HIGH 0x00000000 +#define GF_V_PULSE0_POLARITY_LOW 0x00000010 +#define GF_V_PULSE0_NODELAY 0x00000000 +#define GF_V_PULSE0_DELAY 0x00000040 +#define GF_V_PULSE0_DELAY1 0x00000080 +#define GF_V_PULSE0_LAST_START_A 0x00000000 +#define GF_V_PULSE0_LAST_END_A 0x00000100 +#define GF_V_PULSE0_LAST_START_B 0x00000200 +#define GF_V_PULSE0_LAST_END_B 0x00000300 +#define GF_V_PULSE0_LAST_START_C 0x00000400 +#define GF_V_PULSE0_LAST_END_C 0x00000500 + +#define OFFSET_V_PULSE0_POSITION_A 0x0000011c +#define GFSCMD_V_PULSE0_POSITION_A 0x0000811c + +#define GF_V_PULSE0_START_A 0x00000000 +#define GF_V_PULSE0_END_A 0x00010000 + +#define GFSCMD_V_PULSE1_POLARITY 0x0004811f +#define GFSCMD_V_PULSE1_DELAY_CNTRL 0x0006811f +#define GFSCMD_V_PULSE1_LAST 0x0008811f + +#define GF_V_PULSE1_POLARITY_HIGH 0x00000000 +#define GF_V_PULSE1_POLARITY_LOW 0x00000010 +#define GF_V_PULSE1_NODELAY 0x00000000 +#define GF_V_PULSE1_DELAY1 0x00000040 +#define GF_V_PULSE1_DELAY2 0x00000080 +#define GF_V_PULSE1_LAST_START_A 0x00000000 +#define GF_V_PULSE1_LAST_END_A 0x00000100 +#define GF_V_PULSE1_LAST_START_B 0x00000200 +#define GF_V_PULSE1_LAST_END_B 0x00000300 +#define GF_V_PULSE1_LAST_START_C 0x00000400 +#define GF_V_PULSE1_LAST_END_C 0x00000500 + +#define OFFSET_V_PULSE1_POSITION_A 0x00000120 +#define GFSCMD_V_PULSE1_POSITION_A 0x00008120 + +#define OFFSET_M0_CONTROL 0x00000127 +#define GFSCMD_M0_CLOCK_SELECT 0x00008127 +#define GFSCMD_M0_PHASE_CONTROL 0x00048127 +#define GFSCMD_M0_PHASE_RESET 0x00068127 +#define GFSCMD_M0_POLARITY 0x00078127 +#define GFSCMD_M0_PERIOD 0x00088127 +#define GFSCMD_M0_H_POSITION 0x00108127 + +#define GF_M0_CLOCK_SELECT_PCLK 0x00000000 +#define GF_M0_CLOCK_SELECT_LCLK 0x00000002 +#define GF_M0_CLOCK_SELECT_FCLK 0x00000003 +#define GF_M0_PHASE_CONTROL_FREE_RUN 0x00000000 +#define GF_M0_PHASE_CONTROL_VACTIVE_RESTART 0x00000020 +#define GF_M0_PHASE_CONTROL_FRAME_INVERT 0x00000030 +#define GF_M0_PHASE_RESET_NOT_RESET 0x00000000 +#define GF_M0_PHASE_RESET_RESET 0x00000040 +#define GF_M0_POLARITY_HIGH 0x00000000 +#define GF_M0_POLARITY_LOW 0x00000080 +#define GF_M0_PERIOD_VAL 0x00000100 +#define GF_M0_H_POSITION_VAL 0x00010000 + +#define OFFSET_M1_CONTROL 0x00000128 +#define GFSCMD_M1_CLOCK_SELECT 0x00008128 +#define GFSCMD_M1_PHASE_CONTROL 0x00048128 +#define GFSCMD_M1_PHASE_RESET 0x00068128 +#define GFSCMD_M1_POLARITY 0x00078128 +#define GFSCMD_M1_PERIOD 0x00088128 +#define GFSCMD_M1_H_POSITION 0x00108128 + +#define GF_M1_CLOCK_SELECT_PCLK 0x00000000 +#define GF_M1_CLOCK_SELECT_LCLK 0x00000002 +#define GF_M1_CLOCK_SELECT_FCLK 0x00000003 +#define GF_M1_PHASE_CONTROL_FREE_RUN 0x00000000 +#define GF_M1_PHASE_CONTROL_VACTIVE_RESTART 0x00000020 +#define GF_M1_PHASE_CONTROL_FRAME_INVERT 0x00000030 +#define GF_M1_PHASE_RESET_NOT_RESET 0x00000000 +#define GF_M1_PHASE_RESET_RESET 0x00000040 +#define GF_M1_POLARITY_HIGH 0x00000000 +#define GF_M1_POLARITY_LOW 0x00000080 +#define GF_M1_PERIOD_VAL 0x00000100 +#define GF_M1_H_POSITION_VAL 0x00010000 + +#define GF_DISP_CLOCK_CONTROL_0 0x0000012f + +#define GFSCMD_SHIFT_CLK_DIVIDER 0x0000812f +#define GFSCMD_PIXEL_CLK_DIVIDER 0x0008812f + +//#define GF_SHCLKD_1_256_VAL 0x00000000 +#define GF_PCD1 0x00000000 +#define GF_PCD1H 0x00000100 +#define GF_PCD2 0x00000200 +#define GF_PCD3 0x00000300 +#define GF_PCD4 0x00000400 +#define GF_PCD6 0x00000500 +#define GF_PCD8 0x00000600 +#define GF_PCD9 0x00000700 +#define GF_PCD12 0x00000800 +#define GF_PCD16 0x00000900 +#define GF_PCD13 0x00000a00 +#define GF_PCD18 0x00000b00 +#define GF_PCD24 0x00000c00 + +#define OFFSET_DISP_INTERFACE_CONTROL 0x00000130 +#define GFSCMD_DISP_DATA_FORMAT 0x00008130 + +#define GFSCMD_DISP_DATA_ALIGNMENT 0x00088130 +#define GFSCMD_DISP_DATA_ORDER 0x00098130 + +#define GF_DF1P1C_PRLL 0x00000000 +#define GF_DF1P2C24B_PRLL 0x00000001 +#define GF_DF1P2C18B_PRLL 0x00000002 +#define GF_DF1P2C16B_PRLL 0x00000003 +#define GF_DF1CNL_SRL 0x00000004 +#define GF_DF2CNL_SRL 0x00000005 +#define GF_DF3CNL_SRL 0x00000006 +#define GF_DF_SPI 0x00000007 +#define GF_MSB 0x00000000 +#define GF_LSB 0x00000100 +#define GF_RED_BLUE 0x00000000 +#define GF_BLUE_RED 0x00000200 + +#define OFFSET_DISP_COLOR_CONTROL 0x00000131 +#define GFSCMD_BASE_COLOR_SIZE 0x00008131 +#define GFSCMD_DITHER_CONTROL 0x00088131 +#define GFSCMD_ORD_DITHER_ROTATION 0x000C8131 +#define GFSCMD_DISP_COLOR_SWAP 0x00108131 +#define GFSCMD_BLANK_COLOR 0x00118131 +#define GFSCMD_NON_BASE_COLOR 0x00128131 +#define GFSCMD_LCD_MD0 0x00188131 + +#define GF_BASE666 0x00000000 +#define GF_BASE111 0x00000001 +#define GF_BASE222 0x00000002 +#define GF_BASE333 0x00000003 +#define GF_BASE444 0x00000004 +#define GF_BASE555 0x00000005 +#define GF_BASE565 0x00000006 +#define GF_BASE332 0x00000007 +#define GF_BASE888 0x00000008 +#define GF_DISABLE 0x00000000 +#define GF_ORDERED 0x00000200 +#define GF_ERRDIFF 0x00000300 +#define GF_ORD_DITHER_ROTATION_VAL 0x00000000 +#define GF_SWAP_RGB 0x00000000 +#define GF_SWAP_BGR 0x00010000 +#define GF_BLANK_ZERO 0x00000000 +#define GF_BLANK_ONES 0x00020000 +#define GF_NON_BASE_ZERO 0x00000000 +#define GF_NON_BASE_ONES 0x00040000 +#define GF_LCD_MD0_LOW 0x00000000 +#define GF_LCD_MD0_HIGH 0x01000000 + + +#define OFFSET_SHIFT_CLOCK_OPTIONS 0x00000132 + +#define GFSCMD_SC0_H_QUALIFIER 0x00008132 +#define GFSCMD_SC0_V_QUALIFIER 0x00038132 +#define GFSCMD_SC0_CLK_DIVIDER 0x00068132 +#define GFSCMD_SC1_H_QUALIFIER 0x00108132 +#define GFSCMD_SC1_V_QUALIFIER 0x00138132 +#define GFSCMD_SC1_CLK_DIVIDER 0x00158132 + +#define GF_SC0_H_DISABLE 0x00000000 +#define GF_SC0_H_NO_HQUAL 0x00000001 +#define GF_SC0_H_HACTIVE 0x00000002 +#define GF_SC0_H_EXT_HACTIVE 0x00000003 +#define GF_SC0_H_HPULSE0 0x00000004 +#define GF_SC0_H_EXT_HPULSE0 0x00000005 +#define GF_SC0_V_NO_VQUAL 0x00000000 +#define GF_SC0_V_RESERVED 0x00000008 +#define GF_SC0_V_VACTIVE 0x00000010 +#define GF_SC0_V_EXT_VACTIVE 0x00000018 +#define GF_SC0_V_VPULSE0 0x00000020 +#define GF_SC0_V_EXT_VPULSE0 0x00000028 +#define GF_SC0_DIV1 0x00000000 +#define GF_SC0_DIV2 0x00000040 +#define GF_SC0_DIV4 0x00000080 + +#define GF_SC1_H_DISABLE 0x00000000 +#define GF_SC1_H_NO_HQUAL 0x00010000 +#define GF_SC1_H_HACTIVE 0x00020000 +#define GF_SC1_H_EXT_HACTIVE 0x00030000 +#define GF_SC1_H_HPULSE1 0x00040000 +#define GF_SC1_H_EXT_HPULSE1 0x00050000 +#define GF_SC1_V_NO_VQUAL 0x00000000 +#define GF_SC1_V_RESERVED 0x00080000 +#define GF_SC1_V_VACTIVE 0x00100000 +#define GF_SC1_V_EXT_VACTIVE 0x00180000 +#define GF_SC1_V_VPULSE1 0x00200000 +#define GF_SC1_V_EXT_VPULSE1 0x00280000 +#define GF_SC1_DIV1 0x00000000 +#define GF_SC1_DIV2 0x00400000 +#define GF_SC1_DIV4 0x00800000 + +#define OFFSET_DATA_ENABLE_OPTIONS 0x00000133 + +#define GFSCMD_DE_SELECT_ACTIVE 0x00008133 +#define GFSCMD_DE_CONTROL 0x00038133 + +#define GF_DE_ACTIVE_ALL_LINES 0x00000000 +#define GF_DE_ACTIVE_NOBLANK 0x00000001 +#define GF_DE_ONECLK 0x00000000 +#define GF_DE_NORMAL 0x00000004 +#define GF_DE_ONE_CLK_PRECD_ACTIVE 0x00000008 +#define GF_DE_ONE_PIXEL_CLK_EARLY 0x0000000C + + +#define OFFSET_SERIAL_INTERFACE_OPTIONS 0x00000134 +#define GFSCMD_SDT_STP_MODE 0x00008134 +#define GFSCMD_SDT_STP_DURATION 0x00028134 +#define GFSCMD_STH_DURATION 0x00068134 +#define GFSCMD_STP_CONTRO 0x00078134 + +#define GF_SDT_STP_DISABLE 0x00000000 +#define GF_SDT_STP_RESERVED 0x00000001 +#define GF_SDT_STP_ENABLE_DUP 0x00000002 +#define GF_SDT_STP_ENABLE 0x00000003 +#define GF_SDT_STP_DURATION_VAL 0x00000000 +#define GF_ONE_CLOCK 0x00000000 +#define GF_TWO_CLOCK 0x00000040 +#define GF_STP_NORMAL 0x00000000 +#define GF_STP_EXTENDED 0x00000080 + + +#define OFFSET_LCD_LSPI_OPTIONS 0x00000135 +#define GFSCMD_LCD_SPI_CS_MAIN 0x00008135 +#define GFSCMD_LCD_SPI_DC 0x00018135 +#define GFSCMD_SPI_CS_CONTROL_LCD_IS_SPI 0x00028135 +#define GFSCMD_LCD_SPI_DIRECTION_LSB2MSB 0x00048135 + +#define GF_CS_MAIN 0x00000000 +#define GF_CS_SUB 0x00000001 +#define GF_LDC_LOW 0x00000000 +#define GF_LDC_HIGH 0x00000002 +#define GF_LCD_IS_SPI 0x00000000 +#define GF_LCD_SPI 0x00000004 +#define GF_IS_SPI 0x00000008 +#define GF_FORCED 0x0000000C +#define GF_MSB2LSB 0x00000000 +#define GF_LSB2MSB 0x00000010 + + +#define OFFSET_SIGNAL_RAISE 0x00000005 +#define GFSCMD_SIGNAL_RAISE_VECTOR 0x00008005 +#define GFSCMD_SIGNAL_RAISE_SELECT 0x00088005 +#define GFSCMD_SIGNAL_RAISE_CHANNEL_ID 0x00108005 + +#define GF_RAISE_VECTOR_VAL 0x00000000 +#define GF_RAISE_NONE 0x00000000 +#define GF_RAISE_FRAME_END 0x00000100 +#define GF_RAISE_VBLANK 0x00000200 +#define GF_RAISE_VPULSE3 0x00000300 +#define GF_RAISE_CHANNEL_ID_VAL 0x00000000 + + +#define OFFSET_SIGNAL_REFCOUNT 0x00000006 +#define GFSCMD_SIGNAL_REFCOUNT_VECTOR 0x00008006 +#define GFSCMD_SIGNAL_REFCOUNT_SELECT 0x00108006 + +#define GF_REFCOUNT_VECTOR_VAL 0x00000000 +#define GF_REFCOUNT_NONE 0x00000000 +#define GF_REFCOUNT_FRAME_END 0x00010000 + + + +// Display Power Control + +#define OFFSET_DISPLAY_POWER_CONTROL 0x00000009 +#define GFSCMD_PW0_CONTROL 0x00008009 +#define GFSCMD_PW1_CONTROL 0x00028009 +#define GFSCMD_PW2_CONTROL 0x00048009 +#define GFSCMD_PW3_CONTROL 0x00068009 +#define GFSCMD_PW4_CONTROL 0x00088009 +#define GFSCMD_PM0_CONTROL 0x00108009 +#define GFSCMD_PM1_CONTROL 0x00128009 +#define GFSCMD_SPI_CONTROL 0x00188009 +#define GFSCMD_HSPI_CONTROL 0x00198009 + +#define GF_PW0_DISABLE 0x00000000 +#define GF_PW0_ENABLE 0x00000001 +#define GF_PW1_DISABLE 0x00000000 +#define GF_PW1_ENABLE 0x00000004 +#define GF_PW2_DISABLE 0x00000000 +#define GF_PW2_ENABLE 0x00000010 +#define GF_PW3_DISABLE 0x00000000 +#define GF_PW3_ENABLE 0x00000040 +#define GF_PW4_DISABLE 0x00000000 +#define GF_PW4_ENABLE 0x00010000 +#define GF_PM0_DISABLE 0x00000000 +#define GF_PM0_ENABLE 0x00040000 +#define GF_PM1_DISABLE 0x00000000 +#define GF_PM1_ENABLE 0x00400000 +#define GF_SPI_DISABLE 0x00000000 +#define GF_SPI_ENABLE 0x01000000 +#define GF_HSPI_DISABLE 0x00000000 +#define GF_HSPI_ENABLE 0x02000000 + +// Pin Output Enable registers + +#define OFFSET_PIN_OUTPUT_ENABLE0 0x00000802 +#define GFSCMD_LD0_PIN_OUTPUT 0x00008802 +#define GFSCMD_LD1_PIN_OUTPUT 0x00028802 +#define GFSCMD_LD2_PIN_OUTPUT 0x00048802 +#define GFSCMD_LD3_PIN_OUTPUT 0x00068802 +#define GFSCMD_LD4_PIN_OUTPUT 0x00088802 +#define GFSCMD_LD5_PIN_OUTPUT 0x000a8802 +#define GFSCMD_LD6_PIN_OUTPUT 0x000c8802 +#define GFSCMD_LD7_PIN_OUTPUT 0x000e8802 +#define GFSCMD_LD8_PIN_OUTPUT 0x00108802 +#define GFSCMD_LD9_PIN_OUTPUT 0x00128802 +#define GFSCMD_LD10_PIN_OUTPUT 0x00148802 +#define GFSCMD_LD11_PIN_OUTPUT 0x00168802 +#define GFSCMD_LD12_PIN_OUTPUT 0x00188802 +#define GFSCMD_LD13_PIN_OUTPUT 0x001a8802 +#define GFSCMD_LD14_PIN_OUTPUT 0x001c8802 +#define GFSCMD_LD15_PIN_OUTPUT 0x001e8802 +#define GFSCMD_LD0_LD15_PIN_OUTPUT 0x00208802 + + +#define GF_LD0_OUTPUT_ENABLE 0x00000000 +#define GF_LD0_OUTPUT_DISABLE 0x00000001 +#define GF_LD1_OUTPUT_ENABLE 0x00000000 +#define GF_LD1_OUTPUT_DISABLE 0x00000004 +#define GF_LD2_OUTPUT_ENABLE 0x00000000 +#define GF_LD2_OUTPUT_DISABLE 0x00000010 +#define GF_LD3_OUTPUT_ENABLE 0x00000000 +#define GF_LD3_OUTPUT_DISABLE 0x00000040 +#define GF_LD4_OUTPUT_ENABLE 0x00000000 +#define GF_LD4_OUTPUT_DISABLE 0x00000100 +#define GF_LD5_OUTPUT_ENABLE 0x00000000 +#define GF_LD5_OUTPUT_DISABLE 0x00000400 +#define GF_LD6_OUTPUT_ENABLE 0x00000000 +#define GF_LD6_OUTPUT_DISABLE 0x00001000 +#define GF_LD7_OUTPUT_ENABLE 0x00000000 +#define GF_LD7_OUTPUT_DISABLE 0x00004000 +#define GF_LD8_OUTPUT_ENABLE 0x00000000 +#define GF_LD8_OUTPUT_DISABLE 0x00010000 +#define GF_LD9_OUTPUT_ENABLE 0x00000000 +#define GF_LD9_OUTPUT_DISABLE 0x00040000 +#define GF_LD10_OUTPUT_ENABLE 0x00000000 +#define GF_LD10_OUTPUT_DISABLE 0x00100000 +#define GF_LD11_OUTPUT_ENABLE 0x00000000 +#define GF_LD11_OUTPUT_DISABLE 0x00400000 +#define GF_LD12_OUTPUT_ENABLE 0x00000000 +#define GF_LD12_OUTPUT_DISABLE 0x01000000 +#define GF_LD13_OUTPUT_ENABLE 0x00000000 +#define GF_LD13_OUTPUT_DISABLE 0x04000000 +#define GF_LD14_OUTPUT_ENABLE 0x00000000 +#define GF_LD14_OUTPUT_DISABLE 0x10000000 +#define GF_LD15_OUTPUT_ENABLE 0x00000000 +#define GF_LD15_OUTPUT_DISABLE 0x40000000 +#define GF_LD0_LD15_OUTPUT_ENABLE 0x00000000 +#define GF_LD0_LD15_OUTPUT_DISABLE 0x55555555 + + +#define OFFSET_PIN_OUTPUT_ENABLE1 0x00000803 +#define GFSCMD_LD16_PIN_OUTPUT 0x00008803 +#define GFSCMD_LD17_PIN_OUTPUT 0x00028803 +#define GFSCMD_LPW0_PIN_OUTPUT 0x00108803 +#define GFSCMD_LPW1_PIN_OUTPUT 0x00128803 +#define GFSCMD_LPW2_PIN_OUTPUT 0x00148803 +#define GFSCMD_LSC0_PIN_OUTPUT 0x00188803 +#define GFSCMD_LSC1_PIN_OUTPUT 0x001a8803 +#define GFSCMD_LVS_PIN_OUTPUT 0x001c8803 +#define GFSCMD_LHS_PIN_OUTPUT 0x001e8803 +#define GFSCMD_LD16_LD17_PIN_OUTPUT 0x00208803 + +#define GF_LD16_OUTPUT_ENABLE 0x00000000 +#define GF_LD16_OUTPUT_DISABLE 0x00000001 +#define GF_LD17_OUTPUT_ENABLE 0x00000000 +#define GF_LD17_OUTPUT_DISABLE 0x00000004 +#define GF_LPW0_OUTPUT_ENABLE 0x00000000 +#define GF_LPW0_OUTPUT_DISABLE 0x00010000 +#define GF_LPW1_OUTPUT_ENABLE 0x00000000 +#define GF_LPW1_OUTPUT_DISABLE 0x00040000 +#define GF_LPW2_OUTPUT_ENABLE 0x00000000 +#define GF_LPW2_OUTPUT_DISABLE 0x00100000 +#define GF_LSC0_OUTPUT_ENABLE 0x00000000 +#define GF_LSC0_OUTPUT_DISABLE 0x01000000 +#define GF_LSC1_OUTPUT_ENABLE 0x00000000 +#define GF_LSC1_OUTPUT_DISABLE 0x04000000 +#define GF_LVS_OUTPUT_ENABLE 0x00000000 +#define GF_LVS_OUTPUT_DISABLE 0x10000000 +#define GF_LHS_OUTPUT_ENABLE 0x00000000 +#define GF_LHS_OUTPUT_DISABLE 0x40000000 +#define GF_LD16_LD17_OUTPUT_ENABLE 0x00000000 +#define GF_LD16_LD17_OUTPUT_DISABLE 0x00000005 + + +#define DC_PIN_OUTPUT_ENABLE2 0x00000804 +#define GFSCMD_LHP0_PIN_OUTPUT 0x00008804 +#define GFSCMD_LHP1_PIN_OUTPUT 0x00028804 +#define GFSCMD_LHP2_PIN_OUTPUT 0x00048804 +#define GFSCMD_LVP0_PIN_OUTPUT 0x00088804 +#define GFSCMD_LVP1_PIN_OUTPUT 0x000A8804 +#define GFSCMD_LM0_PIN_OUTPUT 0x00108804 +#define GFSCMD_LM1_PIN_OUTPUT 0x00128804 +#define GFSCMD_LDI_PIN_OUTPUT 0x00148804 +#define GFSCMD_LPP_PIN_OUTPUT 0x00168804 + +#define GF_LHP0_OUTPUT_ENABLE 0x00000000 +#define GF_LHP0_OUTPUT_DISABLE 0x00000001 +#define GF_LHP1_OUTPUT_ENABLE 0x00000000 +#define GF_LHP1_OUTPUT_DISABLE 0x00000004 +#define GF_LHP2_OUTPUT_ENABLE 0x00000000 +#define GF_LHP2_OUTPUT_DISABLE 0x00000010 +#define GF_LVP0_OUTPUT_ENABLE 0x00000000 +#define GF_LVP0_OUTPUT_DISABLE 0x00000100 +#define GF_LVP1_OUTPUT_ENABLE 0x00000000 +#define GF_LVP1_OUTPUT_DISABLE 0x00000404 +#define GF_LM0_OUTPUT_ENABLE 0x00000000 +#define GF_LM0_OUTPUT_DISABLE 0x00010000 +#define GF_LM1_OUTPUT_ENABLE 0x00000000 +#define GF_LM1_OUTPUT_DISABLE 0x00040000 +#define GF_LDI_OUTPUT_ENABLE 0x00000000 +#define GF_LDI_OUTPUT_DISABLE 0x00100000 +#define GF_LPP_OUTPUT_ENABLE 0x00000000 +#define GF_LPP_OUTPUT_DISABLE 0x00400000 + +#define OFFSET_OUTPUT_ENABLE3 0x00000805 +#define GFSCMD_LSCK_PIN_OUTPUT 0x00008805 +#define GFSCMD_LSDA_PIN_OUTPUT 0x00028805 +#define GFSCMD_LCSN_PIN_OUTPUT 0x00048805 +#define GFSCMD_LDC_PIN_OUTPUT 0x00068805 +#define GFSCMD_LSPI_PIN_OUTPUT 0x00088805 + +#define GF_LSCK_OUTPUT_ENABLE 0x00000000 +#define GF_LSCK_OUTPUT_DISABLE 0x00000001 +#define GF_LSDA_OUTPUT_ENABLE 0x00000000 +#define GF_LSDA_OUTPUT_DISABLE 0x00000004 +#define GF_LCSN_OUTPUT_ENABLE 0x00000000 +#define GF_LCSN_OUTPUT_DISABLE 0x00000010 +#define GF_LDC_OUTPUT_ENABLE 0x00000000 +#define GF_LDC_OUTPUT_DISABLE 0x00000040 +#define GF_LSPI_OUTPUT_ENABLE 0x00000000 +#define GF_LSPI_OUTPUT_DISABLE 0x00000100 + + +// Pin Output Polarity registers + +#define OFFSET_PIN_OUTPUT_POLARITY0 0x00000806 +#define GFSCMD_LD0_PIN_POLARITY 0x00008806 +#define GFSCMD_LD1_PIN_POLARITY 0x00028806 +#define GFSCMD_LD2_PIN_POLARITY 0x00048806 +#define GFSCMD_LD3_PIN_POLARITY 0x00068806 +#define GFSCMD_LD4_PIN_POLARITY 0x00088806 +#define GFSCMD_LD5_PIN_POLARITY 0x000a8806 +#define GFSCMD_LD6_PIN_POLARITY 0x000c8806 +#define GFSCMD_LD7_PIN_POLARITY 0x000e8806 +#define GFSCMD_LD8_PIN_POLARITY 0x00108806 +#define GFSCMD_LD9_PIN_POLARITY 0x00128806 +#define GFSCMD_LD10_PIN_POLARITY 0x00148806 +#define GFSCMD_LD11_PIN_POLARITY 0x00168806 +#define GFSCMD_LD12_PIN_POLARITY 0x00188806 +#define GFSCMD_LD13_PIN_POLARITY 0x001a8806 +#define GFSCMD_LD14_PIN_POLARITY 0x001c8806 +#define GFSCMD_LD15_PIN_POLARITY 0x001e8806 +#define GFSCMD_LD0_LD15_PIN_POLARITY 0x00208806 + + +#define GF_LD0_POLARITY_HIGH 0x00000000 +#define GF_LD0_POLARITY_LOW 0x00000001 +#define GF_LD1_POLARITY_HIGH 0x00000000 +#define GF_LD1_POLARITY_LOW 0x00000004 +#define GF_LD2_POLARITY_HIGH 0x00000000 +#define GF_LD2_POLARITY_LOW 0x00000010 +#define GF_LD3_POLARITY_HIGH 0x00000000 +#define GF_LD3_POLARITY_LOW 0x00000040 +#define GF_LD4_POLARITY_HIGH 0x00000000 +#define GF_LD4_POLARITY_LOW 0x00000100 +#define GF_LD5_POLARITY_HIGH 0x00000000 +#define GF_LD5_POLARITY_LOW 0x00000400 +#define GF_LD6_POLARITY_HIGH 0x00000000 +#define GF_LD6_POLARITY_LOW 0x00001000 +#define GF_LD7_POLARITY_HIGH 0x00000000 +#define GF_LD7_POLARITY_LOW 0x00004000 +#define GF_LD8_POLARITY_HIGH 0x00000000 +#define GF_LD8_POLARITY_LOW 0x00010000 +#define GF_LD9_POLARITY_HIGH 0x00000000 +#define GF_LD9_POLARITY_LOW 0x00040000 +#define GF_LD10_POLARITY_HIGH 0x00000000 +#define GF_LD10_POLARITY_LOW 0x00100000 +#define GF_LD11_POLARITY_HIGH 0x00000000 +#define GF_LD11_POLARITY_LOW 0x00400000 +#define GF_LD12_POLARITY_HIGH 0x00000000 +#define GF_LD12_POLARITY_LOW 0x01000000 +#define GF_LD13_POLARITY_HIGH 0x00000000 +#define GF_LD13_POLARITY_LOW 0x04000000 +#define GF_LD14_POLARITY_HIGH 0x00000000 +#define GF_LD14_POLARITY_LOW 0x10000000 +#define GF_LD15_POLARITY_HIGH 0x00000000 +#define GF_LD15_POLARITY_LOW 0x40000000 +#define GF_LD0_LD15_POLARITY_HIGH 0x00000000 +#define GF_LD0_LD15_POLARITY_LOW 0x55555555 + +#define OFFSET_PIN_OUTPUT_POLARITY1 0x00000807 +#define GFSCMD_LD16_PIN_POLARITY 0x00008807 +#define GFSCMD_LD17_PIN_POLARITY 0x00028807 +#define GFSCMD_LPW0_PIN_POLARITY 0x00108807 +#define GFSCMD_LPW1_PIN_POLARITY 0x00128807 +#define GFSCMD_LPW2_PIN_POLARITY 0x00148807 +#define GFSCMD_LSC0_PIN_POLARITY 0x00188807 +#define GFSCMD_LSC1_PIN_POLARITY 0x001a8807 +#define GFSCMD_LVS_PIN_POLARITY 0x001c8807 +#define GFSCMD_LHS_PIN_POLARITY 0x001e8807 +#define GFSCMD_LD16_LD17_PIN_POLARITY 0x00208807 + +#define GF_LD16_POLARITY_HIGH 0x00000000 +#define GF_LD16_POLARITY_LOW 0x00000001 +#define GF_LD17_POLARITY_HIGH 0x00000000 +#define GF_LD17_POLARITY_LOW 0x00000004 +#define GF_LPW0_POLARITY_HIGH 0x00000000 +#define GF_LPW0_POLARITY_LOW 0x00010000 +#define GF_LPW1_POLARITY_HIGH 0x00000000 +#define GF_LPW1_POLARITY_LOW 0x00040000 +#define GF_LPW2_POLARITY_HIGH 0x00000000 +#define GF_LPW2_POLARITY_LOW 0x00100000 +#define GF_LSC0_POLARITY_HIGH 0x00000000 +#define GF_LSC0_POLARITY_LOW 0x01000000 +#define GF_LSC1_POLARITY_HIGH 0x00000000 +#define GF_LSC1_POLARITY_LOW 0x04000000 +#define GF_LVS_POLARITY_HIGH 0x00000000 +#define GF_LVS_POLARITY_LOW 0x10000000 +#define GF_LHS_POLARITY_HIGH 0x00000000 +#define GF_LHS_POLARITY_LOW 0x40000000 +#define GF_LD16_LD17_POLARITY_HIGH 0x00000000 +#define GF_LD16_LD17_POLARITY_LOW 0x00000005 + +#define DC_PIN_OUTPUT_POLARITY2 0x00000808 +#define GFSCMD_LHP0_PIN_POLARITY 0x00008808 +#define GFSCMD_LHP1_PIN_POLARITY 0x00028808 +#define GFSCMD_LHP2_PIN_POLARITY 0x00048808 +#define GFSCMD_LVP0_PIN_POLARITY 0x00088808 +#define GFSCMD_LVP1_PIN_POLARITY 0x000A8808 +#define GFSCMD_LM0_PIN_POLARITY 0x00108808 +#define GFSCMD_LM1_PIN_POLARITY 0x00128808 +#define GFSCMD_LDI_PIN_POLARITY 0x00148808 +#define GFSCMD_LPP_PIN_POLARITY 0x00168808 + +#define GF_LHP0_POLARITY_HIGH 0x00000000 +#define GF_LHP0_POLARITY_LOW 0x00000001 +#define GF_LHP1_POLARITY_HIGH 0x00000000 +#define GF_LHP1_POLARITY_LOW 0x00000004 +#define GF_LHP2_POLARITY_HIGH 0x00000000 +#define GF_LHP2_POLARITY_LOW 0x00000010 +#define GF_LVP0_POLARITY_HIGH 0x00000000 +#define GF_LVP0_POLARITY_LOW 0x00000100 +#define GF_LVP1_POLARITY_HIGH 0x00000000 +#define GF_LVP1_POLARITY_LOW 0x00000404 +#define GF_LM0_POLARITY_HIGH 0x00000000 +#define GF_LM0_POLARITY_LOW 0x00010000 +#define GF_LM1_POLARITY_HIGH 0x00000000 +#define GF_LM1_POLARITY_LOW 0x00040000 +#define GF_LDI_POLARITY_HIGH 0x00000000 +#define GF_LDI_POLARITY_LOW 0x00100000 +#define GF_LPP_POLARITY_HIGH 0x00000000 +#define GF_LPP_POLARITY_LOW 0x00400000 + +#define OFFSET_OUTPUT_POLARITY3 0x00000809 +#define GFSCMD_LSCK_PIN_POLARITY 0x00008809 +#define GFSCMD_LSDA_PIN_POLARITY 0x00028809 +#define GFSCMD_LCSN_PIN_POLARITY 0x00048809 +#define GFSCMD_LDC_PIN_POLARITY 0x00068809 +#define GFSCMD_LSPI_PIN_POLARITY 0x00088809 + +#define GF_LSCK_POLARITY_HIGH 0x00000000 +#define GF_LSCK_POLARITY_LOW 0x00000001 +#define GF_LSDA_POLARITY_HIGH 0x00000000 +#define GF_LSDA_POLARITY_LOW 0x00000004 +#define GF_LCSN_POLARITY_HIGH 0x00000000 +#define GF_LCSN_POLARITY_LOW 0x00000010 +#define GF_LDC_POLARITY_HIGH 0x00000000 +#define GF_LDC_POLARITY_LOW 0x00000040 +#define GF_LSPI_POLARITY_HIGH 0x00000000 +#define GF_LSPI_POLARITY_LOW 0x00000100 + +// Pin Output data registers + +#define OFFSET_PIN_OUTPUT_DATA0 0x0000080a +#define GFSCMD_LD0_PIN_OUTPUT_DATA 0x0000880a +#define GFSCMD_LD1_PIN_OUTPUT_DATA 0x0002880a +#define GFSCMD_LD2_PIN_OUTPUT_DATA 0x0004880a +#define GFSCMD_LD3_PIN_OUTPUT_DATA 0x0006880a +#define GFSCMD_LD4_PIN_OUTPUT_DATA 0x0008880a +#define GFSCMD_LD5_PIN_OUTPUT_DATA 0x000a880a +#define GFSCMD_LD6_PIN_OUTPUT_DATA 0x000c880a +#define GFSCMD_LD7_PIN_OUTPUT_DATA 0x000e880a +#define GFSCMD_LD8_PIN_OUTPUT_DATA 0x0010880a +#define GFSCMD_LD9_PIN_OUTPUT_DATA 0x0012880a +#define GFSCMD_LD10_PIN_OUTPUT_DATA 0x0014880a +#define GFSCMD_LD11_PIN_OUTPUT_DATA 0x0016880a +#define GFSCMD_LD12_PIN_OUTPUT_DATA 0x0018880a +#define GFSCMD_LD13_PIN_OUTPUT_DATA 0x001a880a +#define GFSCMD_LD14_PIN_OUTPUT_DATA 0x001c880a +#define GFSCMD_LD15_PIN_OUTPUT_DATA 0x001e880a +#define GFSCMD_LD0_LD15_PIN_OUTPUT_DATA 0x0020880a + + +#define GF_LD0_DATA_LOW 0x00000002 +#define GF_LD0_DATA_HIGH 0x00000003 +#define GF_LD1_DATA_LOW 0x00000008 +#define GF_LD1_DATA_HIGH 0x0000000c +#define GF_LD2_DATA_LOW 0x00000020 +#define GF_LD2_DATA_HIGH 0x00000030 +#define GF_LD3_DATA_LOW 0x00000080 +#define GF_LD3_DATA_HIGH 0x000000c0 +#define GF_LD4_DATA_LOW 0x00000200 +#define GF_LD4_DATA_HIGH 0x00000300 +#define GF_LD5_DATA_LOW 0x00000800 +#define GF_LD5_DATA_HIGH 0x00000c00 +#define GF_LD6_DATA_LOW 0x00002000 +#define GF_LD6_DATA_HIGH 0x00003000 +#define GF_LD7_DATA_LOW 0x00008000 +#define GF_LD7_DATA_HIGH 0x0000c000 +#define GF_LD8_DATA_LOW 0x00020000 +#define GF_LD8_DATA_HIGH 0x00030000 +#define GF_LD9_DATA_LOW 0x00080000 +#define GF_LD9_DATA_HIGH 0x000c0000 +#define GF_LD10_DATA_LOW 0x00200000 +#define GF_LD10_DATA_HIGH 0x00300000 +#define GF_LD11_DATA_LOW 0x00800000 +#define GF_LD11_DATA_HIGH 0x00c00000 +#define GF_LD12_DATA_LOW 0x02000000 +#define GF_LD12_DATA_HIGH 0x03000000 +#define GF_LD13_DATA_LOW 0x08000000 +#define GF_LD13_DATA_HIGH 0x0c000000 +#define GF_LD14_DATA_LOW 0x20000000 +#define GF_LD14_DATA_HIGH 0x30000000 +#define GF_LD15_DATA_LOW 0x80000000 +#define GF_LD15_DATA_HIGH 0xc0000000 +#define GF_LD0_LD15_DATA_LOW 0xaaaaaaaa +#define GF_LD0_LD15_DATA_HIGH 0xffffffff + +#define OFFSET_PIN_OUTPUT_DATA1 0x0000080b +#define GFSCMD_LD16_PIN_OUTPUT_DATA 0x0000880b +#define GFSCMD_LD17_PIN_OUTPUT_DATA 0x0002880b +#define GFSCMD_LPW0_PIN_OUTPUT_DATA 0x0010880b +#define GFSCMD_LPW1_PIN_OUTPUT_DATA 0x0012880b +#define GFSCMD_LPW2_PIN_OUTPUT_DATA 0x0014880b +#define GFSCMD_LSC0_PIN_OUTPUT_DATA 0x0018880b +#define GFSCMD_LSC1_PIN_OUTPUT_DATA 0x001a880b +#define GFSCMD_LVS_PIN_OUTPUT_DATA 0x001c880b +#define GFSCMD_LHS_PIN_OUTPUT_DATA 0x001e880b +#define GFSCMD_LD16_LD17_PIN_OUTPUT_DATA 0x0020880b + +#define GF_LD16_DATA_LOW 0x00000002 +#define GF_LD16_DATA_HIGH 0x00000003 +#define GF_LD17_DATA_LOW 0x00000008 +#define GF_LD17_DATA_HIGH 0x0000000c +#define GF_LPW0_DATA_LOW 0x00020000 +#define GF_LPW0_DATA_HIGH 0x00030000 +#define GF_LPW1_DATA_LOW 0x00080000 +#define GF_LPW1_DATA_HIGH 0x000c0000 +#define GF_LPW2_DATA_LOW 0x00200000 +#define GF_LPW2_DATA_HIGH 0x00300000 +#define GF_LSC0_DATA_LOW 0x02000000 +#define GF_LSC0_DATA_HIGH 0x03000000 +#define GF_LSC1_DATA_LOW 0x08000000 +#define GF_LSC1_DATA_HIGH 0x0c000000 +#define GF_LVS_DATA_LOW 0x20000000 +#define GF_LVS_DATA_HIGH 0x30000000 +#define GF_LHS_DATA_LOW 0x80000000 +#define GF_LHS_DATA_HIGH 0xc0000000 +#define GF_LD16_LD17_DATA_LOW 0x0000000a +#define GF_LD16_LD17_DATA_HIGH 0x0000000f + + +#define OFFSET_PIN_OUTPUT_DATA2 0x0000080c +#define GFSCMD_LHP0_PIN_OUTPUT_DATA 0x0000880c +#define GFSCMD_LHP1_PIN_OUTPUT_DATA 0x0002880c +#define GFSCMD_LHP2_PIN_OUTPUT_DATA 0x0004880c +#define GFSCMD_LVP0_PIN_OUTPUT_DATA 0x0008880c +#define GFSCMD_LVP1_PIN_OUTPUT_DATA 0x000A880c +#define GFSCMD_LM0_PIN_OUTPUT_DATA 0x0010880c +#define GFSCMD_LM1_PIN_OUTPUT_DATA 0x0012880c +#define GFSCMD_LDI_PIN_OUTPUT_DATA 0x0014880c +#define GFSCMD_LPP_PIN_OUTPUT_DATA 0x0016880c + +#define GF_LHP0_DATA_LOW 0x00000002 +#define GF_LHP0_DATA_HIGH 0x00000003 +#define GF_LHP1_DATA_LOW 0x00000008 +#define GF_LHP1_DATA_HIGH 0x0000000c +#define GF_LHP2_DATA_LOW 0x00000020 +#define GF_LHP2_DATA_HIGH 0x00000030 +#define GF_LVP0_DATA_LOW 0x00000200 +#define GF_LVP0_DATA_HIGH 0x00000300 +#define GF_LVP1_DATA_LOW 0x00000800 +#define GF_LVP1_DATA_HIGH 0x00000c00 +#define GF_LM0_DATA_LOW 0x00020000 +#define GF_LM0_DATA_HIGH 0x00030000 +#define GF_LM1_DATA_LOW 0x00080000 +#define GF_LM1_DATA_HIGH 0x000c0000 +#define GF_LDI_DATA_LOW 0x00200000 +#define GF_LDI_DATA_HIGH 0x00300000 +#define GF_LPP_DATA_LOW 0x00800000 +#define GF_LPP_DATA_HIGH 0x00c00000 + +#define OFFSET_OUTPUT_DATA3 0x0000080d +#define GFSCMD_LSCK_PIN_OUTPUT_DATA 0x0000880d +#define GFSCMD_LSDA_PIN_OUTPUT_DATA 0x0002880d +#define GFSCMD_LCSN_PIN_OUTPUT_DATA 0x0004880d +#define GFSCMD_LDC_PIN_OUTPUT_DATA 0x0006880d +#define GFSCMD_LSPI_PIN_OUTPUT_DATA 0x0008880d + +#define GF_LSCK_DATA_LOW 0x00000002 +#define GF_LSCK_DATA_HIGH 0x00000003 +#define GF_LSDA_DATA_LOW 0x00000008 +#define GF_LSDA_DATA_HIGH 0x0000000c +#define GF_LCSN_DATA_LOW 0x00000020 +#define GF_LCSN_DATA_HIGH 0x00000030 +#define GF_LDC_DATA_LOW 0x00000080 +#define GF_LDC_DATA_HIGH 0x000000c0 +#define GF_LSPI_DATA_LOW 0x00000200 +#define GF_LSPI_DATA_HIGH 0x00000300 + +// Pin Input Enable + +#define GFSCMD_LSPI_PIN_INPUT 0x00088811 +#define GF_LSPI_INPUT_ENABLE 0x00000000 +#define GF_LSPI_INPUT_DISABLE 0x00000100 + +#define GFSCMD_LDC_PIN_INPUT 0x00088411 +#define GF_LDC_INPUT_ENABLE 0x00000000 +#define GF_LDC_INPUT_DISABLE 0x00000040 + +#define GFSCMD_LPP_PIN_INPUT 0x00168811 +#define GF_LPP_INPUT_ENABLE 0x00000000 +#define GF_LPP_INPUT_DISABLE 0x00400000 + +// Pin Output Select + +#define DC_PIN_OUTPUT_SELECT0 0x00000814 +#define GFSCMD_LD0_OUTPUT_SELECT 0x00008814 +#define GFSCMD_LD1_OUTPUT_SELECT 0x00048814 +#define GFSCMD_LD2_OUTPUT_SELECT 0x00088814 +#define GFSCMD_LD3_OUTPUT_SELECT 0x000C8814 +#define GFSCMD_LD4_OUTPUT_SELECT 0x00108814 +#define GFSCMD_LD5_OUTPUT_SELECT 0x00148814 +#define GFSCMD_LD6_OUTPUT_SELECT 0x00188814 +#define GFSCMD_LD7_OUTPUT_SELECT 0x001C8814 +#define GFSCMD_LD0_LD7_OUTPUT_SELECT 0x00208814 + +#define GF_LD0_PIN_FOR_LD0 0 +#define GF_LD0_PIN_FOR_LD0_OUT 1 +#define GF_LD0_PIN_FOR_SC_ 4 +#define GF_LD1_PIN_FOR_LD1 0 +#define GF_LD1_PIN_FOR_LD1_OUT 1 +#define GF_LD1_PIN_FOR_SC 4 +#define GF_LD2_PIN_FOR_LD2 0 +#define GF_LD2_PIN_FOR_LD2_OUT 1 +#define GF_LD2_PIN_FOR_SD0_ 4 +#define GF_LD3_PIN_FOR_LD3 0 +#define GF_LD3_PIN_FOR_LD3_OUT 1 +#define GF_LD3_PIN_FOR_SD0 4 +#define GF_LD4_PIN_FOR_LD4 0 +#define GF_LD4_PIN_FOR_LD4_OUT 1 +#define GF_LD4_PIN_FOR_SD1_ 4 +#define GF_LD5_PIN_FOR_LD5 0 +#define GF_LD5_PIN_FOR_LD5_OUT 1 +#define GF_LD5_PIN_FOR_SD1 4 +#define GF_LD6_PIN_FOR_LD6 0 +#define GF_LD6_PIN_FOR_LD6_OUT 1 +#define GF_LD6_PIN_FOR_STH 4 +#define GF_LD7_PIN_FOR_LD7 0 +#define GF_LD7_PIN_FOR_LD7_OUT 1 +#define GF_LD7_PIN_FOR_SDT 4 +#define GF_LD0_LD7_PIN_FOR_LD0_LD7 0x00000000 +#define GF_LD0_LD7_PIN_FOR_LD0_LD7_OUT 0x11111111 +#define GF_LD0_LD7_PIN_FOR_LPD0_LPD7_OUT 0x22222222 + +#define DC_PIN_OUTPUT_SELECT1 0x00000815 +#define GFSCMD_LD8_OUTPUT_SELECT 0x00008815 +#define GFSCMD_LD9_OUTPUT_SELECT 0x00048815 +#define GFSCMD_LD10_OUTPUT_SELECT 0x00088815 +#define GFSCMD_LD11_OUTPUT_SELECT 0x000C8815 +#define GFSCMD_LD12_OUTPUT_SELECT 0x00108815 +#define GFSCMD_LD13_OUTPUT_SELECT 0x00148815 +#define GFSCMD_LD14_OUTPUT_SELECT 0x00188815 +#define GFSCMD_LD15_OUTPUT_SELECT 0x001C8815 +#define GFSCMD_LD8_LD15_OUTPUT_SELECT 0x00208815 + +#define GF_LD8_PIN_FOR_LD8 0 +#define GF_LD8_PIN_FOR_LD8_OUT 1 +#define GF_LD8_PIN_FOR_LPD8_OUT 2 +#define GF_LD8_PIN_FOR_STP 4 +#define GF_LD9_PIN_FOR_LD9 0 +#define GF_LD9_PIN_FOR_LD9_OUT 1 +#define GF_LD9_PIN_FOR_LPD9_OUT 2 +#define GF_LD9_PIN_FOR_SD2_ 4 +#define GF_LD10_PIN_FOR_LD10 0 +#define GF_LD10_PIN_FOR_LD10_OUT 1 +#define GF_LD10_PIN_FOR_SD2 4 +#define GF_LD11_PIN_FOR_LD11 0 +#define GF_LD11_PIN_FOR_LD11_OUT 1 +#define GF_LD12_PIN_FOR_LD12 0 +#define GF_LD12_PIN_FOR_LD12_OUT 1 +#define GF_LD13_PIN_FOR_LD13 0 +#define GF_LD13_PIN_FOR_LD13_OUT 1 +#define GF_LD14_PIN_FOR_LD14 0 +#define GF_LD14_PIN_FOR_LD14_OUT 1 +#define GF_LD15_PIN_FOR_LD15 0 +#define GF_LD15_PIN_FOR_LD15_OUT 1 +#define GF_LD8_LD15_PIN_FOR_LD8_LD15 0x00000000 +#define GF_LD8_LD15_PIN_FOR_LD8_LD15_OUT 0x11111111 +#define GF_LD8_LD15_PIN_FOR_LPD8_LPD15_OUT 0x22222222 + +#define DC_PIN_OUTPUT_SELECT2 0x00000816 +#define GFSCMD_LD16_OUTPUT_SELECT 0x00008816 +#define GFSCMD_LD17_OUTPUT_SELECT 0x00048816 + +#define GF_LD16_PIN_FOR_LD16 0 +#define GF_LD16_PIN_FOR_LD16_OUT 1 +#define GF_LD17_PIN_FOR_LD17 0 +#define GF_LD17_PIN_FOR_LD17_OUT 1 + +#define OFFSET_PIN_OUTPUT_SELECT3 0x00000817 +#define GFSCMD_LPW0_OUTPUT_SELECT 0x00008817 +#define GFSCMD_LPW1_OUTPUT_SELECT 0x00048817 +#define GFSCMD_LPW2_OUTPUT_SELECT 0x00088817 +#define GFSCMD_LSC0_OUTPUT_SELECT 0x00108817 +#define GFSCMD_LSC1_OUTPUT_SELECT 0x00148817 +#define GFSCMD_LVS_OUTPUT_SELECT 0x00188817 +#define GFSCMD_LHS_OUTPUT_SELECT 0x001c8817 + +#define GF_LPW0_PIN_FOR_PW0 0 +#define GF_LPW0_PIN_FOR_PW0_OUT 1 +#define GF_LPW0_PIN_FOR_PW1 2 +#define GF_LPW0_PIN_FOR_PM0 3 +#define GF_LPW0_PIN_FOR_PW2 4 +#define GF_LPW1_PIN_FOR_PW1 0 +#define GF_LPW1_PIN_FOR_PW1_OUT 1 +#define GF_LPW1_PIN_FOR_PW2 2 +#define GF_LPW1_PIN_FOR_PM1 3 +#define GF_LPW1_PIN_FOR_PW3 4 +#define GF_LPW2_PIN_FOR_PW2 0 +#define GF_LPW2_PIN_FOR_PW2_OUT 1 +#define GF_LPW2_PIN_FOR_PW3 2 +#define GF_LPW2_PIN_FOR_PM0 3 +#define GF_LPW2_PIN_FOR_PW4 4 +#define GF_LSC0_PIN_FOR_LSC0 0 +#define GF_LSC0_PIN_FOR_LSC0_OUT 1 +#define GF_LSC1_PIN_FOR_LSC1 0 +#define GF_LSC1_PIN_FOR_LSC1_OUT 1 +#define GF_LSC1_PIN_FOR_LSC1_DE 2 +#define GF_LVS_PIN_FOR_VSYNC 0 +#define GF_LVS_PIN_FOR_LVS_OUT 1 +#define GF_LVS_PIN_FOR_PM1 3 +#define GF_LHS_PIN_FOR_HSYNC 0 +#define GF_LHS_PIN_FOR_LHS_OUT 1 +#define GF_LHS_PIN_FOR_PM0 3 + +#define OFSSET_PIN_OUTPUT_SELECT4 0x00000818 +#define GFSCMD_LHP0_OUTPUT_SELECT 0x00008818 +#define GFSCMD_LHP1_OUTPUT_SELECT 0x00048818 +#define GFSCMD_LHP2_OUTPUT_SELECT 0x00088818 +#define GFSCMD_LVP0_OUTPUT_SELECT 0x00108818 +#define GFSCMD_LVP1_OUTPUT_SELECT 0x00148818 + +#define GF_LHP0_PIN_FOR_LHP0 0 +#define GF_LHP0_PIN_FOR_LHP0_OUT 1 +#define GF_LHP0_PIN_FOR_LD21 2 +#define GF_LHP0_PIN_FOR_PM0 3 +#define GF_LHP1_PIN_FOR_LHP1 0 +#define GF_LHP1_PIN_FOR_LHP1_OUT 1 +#define GF_LHP1_PIN_FOR_LD18 2 +#define GF_LHP1_PIN_FOR_PM1 3 +#define GF_LHP2_PIN_FOR_LHP2 0 +#define GF_LHP2_PIN_FOR_LHP2_OUT 1 +#define GF_LHP2_PIN_FOR_LD19 2 +#define GF_LHP2_PIN_FOR_PM0 3 +#define GF_LHP2_PIN_FOR_LVP2 4 +#define GF_LVP0_PIN_FOR_LVP0 0 +#define GF_LVP0_PIN_FOR_LVP0_OUT 1 +#define GF_LVP0_PIN_FOR_PM0 3 +#define GF_LVP1_PIN_FOR_LVP1 0 +#define GF_LVP1_PIN_FOR_LVP1_OUT 1 +#define GF_LVP1_PIN_FOR_LD20 2 +#define GF_LVP1_PIN_FOR_PM1 3 +#define GF_LVP1_PIN_FOR_PW4 4 + +#define OFFSET_PIN_OUTPUT_SELECT5 0x00000819 +#define GFSCMD_LM0_OUTPUT_SELECT 0x00008819 +#define GFSCMD_LM1_OUTPUT_SELECT 0x00048819 +#define GFSCMD_LDI_OUTPUT_SELECT 0x00088819 +#define GFSCMD_LPP_OUTPUT_SELECT 0x000c8819 + +#define GF_LM0_PIN_FOR_LM0 0 +#define GF_LM0_PIN_FOR_LM0_OUT 1 +#define GF_LM0_PIN_FOR_SCS 2 +#define GF_LM0_PIN_FOR_PM0 3 +#define GF_LM0_PIN_FOR_LVP2 4 +#define GF_LM1_PIN_FOR_M1 0 +#define GF_LM1_PIN_FOR_LM1_OUT 1 +#define GF_LM1_PIN_FOR_LD21 2 +#define GF_LM1_PIN_FOR_PM1 3 +#define GF_LM1_PIN_FOR_LVP3 4 +#define GF_LDI_PIN_FOR_DI 0 +#define GF_LDI_PIN_FOR_LDI_OUT 1 +#define GF_LDI_PIN_FOR_LD22 2 +#define GF_LDI_PIN_FOR_PM0 3 +#define GF_LDI_PIN_FOR_SCS 4 +#define GF_LPP_PIN_FOR_PP 0 +#define GF_LPP_PIN_FOR_LPP_OUT 1 +#define GF_LPP_PIN_FOR_LD23 2 +#define GF_LPP_PIN_FOR_PM1 3 +#define GF_LPP_PIN_FOR_LVP3 4 + +#define OFFSET_PIN_OUTPUT_SELECT6 0x0000081a +#define GFSCMD_LSCK_OUTPUT_SELECT 0x0000881a +#define GFSCMD_LSDA_OUTPUT_SELECT 0x0004881a +#define GFSCMD_LCSN_OUTPUT_SELECT 0x0008881a +#define GFSCMD_LDC_OUTPUT_SELECT 0x000c881a +#define GFSCMD_LSPI_OUTPUT_SELECT 0x0010881a + +#define GF_LSCK_PIN_FOR_SCK 0 +#define GF_LSCK_PIN_FOR_LSCK_OUT 1 +#define GF_LSCK_PIN_FOR_PM0 3 +#define GF_LSDA_PIN_FOR_SDA 0 +#define GF_LSDA_PIN_FOR_LSDA_OUT 1 +#define GF_LSDA_PIN_FOR_SCS 2 +#define GF_LSDA_PIN_FOR_PM1 3 +#define GF_LCS_PIN_FOR_MCS 0 +#define GF_LCS_PIN_FOR_LCS_OUT 1 +#define GF_LCS_PIN_FOR_PM0 3 +#define GF_LDC_PIN_FOR_SDC 0 +#define GF_LDC_PIN_FOR_LDC_OUT 1 +#define GF_LDC_PIN_FOR_LD22 2 +#define GF_LDC_PIN_FOR_PM1 3 +#define GF_LSPI_PIN_FOR_SPI 0 +#define GF_LSPI_PIN_FOR_LSPI_OUT 1 +#define GF_LSPI_PIN_FOR_DE 2 +#define GF_LSPI_PIN_FOR_PM0 3 +#define GF_LSPI_PIN_FOR_PCLK 4 + + +//#define OFFSET_PIN_MISC_CONTROL 0x0000081b +//#define DISP_CLOCK_OUTPUT_MASK +//#define DISP_CLOCK_OUTPUT_SHIFT +//#define DISP_CLOCK_OUTPUT_DISABLE +//#define DISP_CLOCK_OUTPUT_ENABLE + +#define OFFSET_PM0_CONTROL 0x0000081c +#define GFSCMD_PM0_CLOCK_SELECT 0x0000881c +#define GFSCMD_PM0_CLOCK_DIVIDER 0x0004881c +#define GFSCMD_PM0_PERIOD 0x0012881c + +#define GF_PM0_SHIFT_CLOCK 0x00000000 +#define GF_PM0_PIXEL_CLOCK 0x00000001 +#define GF_PM0_LINE_CLOCK 0x00000002 +#define GF_PM0_FRAME_CLOCK 0x00000003 +#define GF_PM0_CLOCK_DIVIDER_VAL 0x00000010 +#define GF_PM0_PERIOD_VAL 0x00040000 + +#define OFFSET_PM0_DUTY_CYCLE 0x0000081d +#define GFSCMD_PM0_DUTY_CYCLE 0x0000881d + +#define GF_PM0_DUTY_CYCLE_VAL 0x00000000 + +#define OFFSET_PM1_CONTROL 0x0000081e +#define GFSCMD_PM1_CLOCK_SELECT 0x0000881e +#define GFSCMD_PM1_CLOCK_DIVIDER 0x0004881e +#define GFSCMD_PM1_PERIOD 0x0012881e + +#define GF_PM1_SHIFT_CLOCK 0x00000000 +#define GF_PM1_PIXEL_CLOCK 0x00000001 +#define GF_PM1_LINE_CLOCK 0x00000002 +#define GF_PM1_FRAME_CLOCK 0x00000003 +#define GF_PM1_CLOCK_DIVIDER_VAL 0x00000010 +#define GF_PM1_PERIOD_VAL 0x00040000 + +#define OFFSET_PM1_DUTY_CYCLE 0x0000081f +#define GFSCMD_PM1_DUTY_CYCLE 0x0000881f + +#define GF_PM1_DUTY_CYCLE_VAL 0x00000000 + +//////////////////////// +#define OFFSET_SPI_CONTROL 0x00000820 +#define GFSCMD_SPI_SERIAL_CLK_CONTROL 0x00008820 +#define GFSCMD_SPI_DATA_DIRECTION 0x00038820 +#define GFSCMD_SPI_BITS_PER_CYCLE 0x00048820 +#define GFSCMD_SPI_CLK_DIVIDER_1_32 0x00108820 +#define GFSCMD_SPI_STATUS 0x00188820 + +#define GF_SPI_1SCLK_CS_RISING_EDGE_ACTV 0x00000000 +#define GF_SPI_2SCLK_CS_RISING_EDGE_ACTV 0x00000001 +#define GF_SPI_1SCLK_CS_FALLING_EDGE_ACTV 0x00000002 +#define GF_SPI_2SCLK_CS_FALLING_EDGE_ACTV 0x00000003 +#define GF_SPI_MSB2LSB 0x00000000 +#define GF_SPI_LSB2MSB 0x00000008 +#define GF_SPI8 0x00000000 +#define GF_SPI8DC 0x00000010 +#define GF_SPI12 0x00000020 +#define GF_SPI16 0x00000030 +#define GF_SPI16DC 0x00000040 +#define GF_START_BYTE_PLUS_SPI16 0x00000050 +#define GF_SPI18 0x00000060 +#define GF_SPI24 0x00000070 +//#define GF_SPI_CLK_DIVIDER_1_32_VAL +#define GF_SPI_STATUS_DISABLE 0x00000000 +#define GF_STATUS_ENABLE_HOST_SPI 0x01000000 +#define GF_STATUS_ENABLE_HOST_IS_SPI 0x02000000 +#define GF_STATUS_ENABLE_ALL_SPI_CYCL 0x03000000 + +//#define OFFSET_HSPI_START_BYTE 0x00000821 +#define GFSCMD_HSPI_DATA_START_BYTE 0x00008821 +#define GFSCMD_HSPI_START_BYTE 0x00008821 +//#define GFSCMD_HSPI_COMMAND_START_BYTE 0x00088821 + +//#define OFFSET_HSPI_WRITE_DATA_CD 0x00000822 +#define GFSCMD_HSPI_WRITE_DATA_A 0x00008822 +#define GFSCMD_HSPI_WRITE_DATA_B 0x00088822 +#define GFSCMD_HSPI_WRITE_DATA_AB 0x00208822 + +//#define OFFSET_HSPI_WRITE_DATA_CD 0x00000823 +#define GFSCMD_HSPI_WRITE_DATA_C 0x00008823 +#define GFSCMD_HSPI_WRITE_DATA_D 0x00088823 +#define GFSCMD_HSPI_WRITE_DATA_CD 0x00208823 + +#define GF_HSPI_CMD_CYCLE1 0 +#define GF_HSPI_CMD_CYCLE2 0 +#define GF_HSPI_CMD_CYCLE3 0 +#define GF_HSPI_CMD_CYCLE4 0 + +#define GF_HSPI_DATA_CYCLE1 1 +#define GF_HSPI_DATA_CYCLE2 2 +#define GF_HSPI_DATA_CYCLE3 4 +#define GF_HSPI_DATA_CYCLE4 8 + +#define GF_HSPI_MAIN_CS_CYCLE1 1 +#define GF_HSPI_MAIN_CS_CYCLE2 2 +#define GF_HSPI_MAIN_CS_CYCLE3 4 +#define GF_HSPI_MAIN_CS_CYCLE4 8 + +#define GF_HSPI_SUB_CS_CYCLE1 1 +#define GF_HSPI_SUB_CS_CYCLE2 2 +#define GF_HSPI_SUB_CS_CYCLE3 4 +#define GF_HSPI_SUB_CS_CYCLE4 8 + +////////////////////////// + +#if 0 +// LCD SPI interface signals + +#define DC_P_LCD_SPI_OPTIONS 0x00000135 +#define GF_LCD_SPI_CS 0x00008135 +#define GF_LCD_SPI_DC 0x00018135 +#define GF_SPI_CS_CONTROL 0x00028135 +#define GF_LCD_SPI_DIRECTION 0x00048135 + +#define GF_LCD_SPI_CS_MAIN 0x00000000 +#define GF_LCD_SPI_CS_SUB 0x00000001 +#define GF_LCD_SPI_DC_LOW 0x00000000 +#define GF_LCD_SPI_DC_HIGH 0x00000002 +#define GF_SPI_CS_CONTROL_LCD_IS_SPI 0x00000000 +#define GF_SPI_CS_CONTROL_LCD_SPI 0x00000004 +#define GF_SPI_CS_CONTROL_IS_SPI 0x00000008 +#define GF_SPI_CS_CONTROL_FORCED 0x0000000C +#define GF_LCD_SPI_DIRECTION_MSB2LSB 0x00000000 +#define GF_LCD_SPI_DIRECTION_LSB2MSB 0x00000010 +#endif + +// Class: Initialization Sequence (IS) + +#define OFSSET_P_INIT_SEQ_CONTROL 0x00000141 +#define GFSCMD_SEND_INIT_SEQUENCE 0x00008141 +#define GFSCMD_INIT_SEQUENCE_MODE_PLCD 0x00018141 +#define GFSCMD_INIT_SEQ_DC_SIGNAL_NODC 0x00048141 +#define GFSCMD_INIT_SEQ_DC_CONTROL 0x00078141 +#define GFSCMD_FRAME_INIT_SEQ_CYCLES 0x00088141 + +#define GF_SEND_INIT_SEQUENCE_DISABLE 0x00000000 +#define GF_SEND_INIT_SEQUENCE_ENABLE 0x00000001 +#define GF_INIT_SEQUENCE_MODE_PLCD_INIT 0x00000000 +#define GF_INIT_SEQUENCE_MODE_SPI_INIT 0x00000002 +#define GF_INIT_SEQ_SIGNAL_NODC 0x00000000 +#define GF_INIT_SEQ_SIGNAL_VSYNC 0x00000010 +#define GF_INIT_SEQ_SIGNAL_VPULSE0 0x00000020 +#define GF_INIT_SEQ_SIGNAL_VPULSE1 0x00000030 +#define GF_INIT_SEQ_SIGNAL_VPULSE2 0x00000040 +#define GF_INIT_SEQ_SIGNAL_VPULSE3 0x00000050 +#define GF_INIT_SEQ_CONTROL 0x00000080 + +//#define GF_FRAME_INIT_SEQ_CYCLES 0x00000100 + + +// SPI Init Sequence Write Data bits 31-0 +#define DC_P_SPI_INIT_SEQ_DATA_A 0x00000142 +#define GFSCMD_SPI_INIT_SEQ_DATA_A 0x00008142 + +// SPI Init Sequence Write Data bits 63-32 +#define DC_P_SPI_INIT_SEQ_DATA_B 0x00000143 +#define GFSCMD_SPI_INIT_SEQ_DATA_B 0x00008143 + +// SPI Init Sequence Write Data bits 95-64 +#define DC_P_SPI_INIT_SEQ_DATA_C 0x00000144 +#define GFSCMD_SPI_INIT_SEQ_DATA_C 0x00008144 + +// SPI Init Sequence Write Data bits 127-96 +#define DC_P_SPI_INIT_SEQ_DATA_D 0x00000145 +#define GFSCMD_SPI_INIT_SEQ_DATA_D 0x00008145 + +#define OFFSET_DISPLAY_COMMAND 0x00000003 +#define GFSCMD_DISPLAY_CTRL_MODE 0x00058003 + +#define GF_CTRL_MODE_STOP 0x00000000 +#define GF_CTRL_MODE_C_DISPLAY 0x00000020 +#define GF_CTRL_MODE_NC_DISPLAY 0x00000040 +#define GF_CTRL_MODE_NOCHANGE 0x000000C0 + + +/* Other Commands */ + +#define GF_NO_DATA 0x00000000 +#define GFSCMD_LVDD_ON 0x01020000 +#define GFSCMD_LVDD_OFF 0x01020001 + +#define GFSCMD_RESET_LHP2 0x0104880c +#define GFSCMD_RESET_LVP0 0x0108880c +#define GFSCMD_MS_DELAY 0x01005A5A +#define GFSCMD_WAIT_VBLANK 0x01005555 +#define GFSCMD_END_OF_TABLE 0x0100ffff +#define GFSCMD_I2C_A_PAL_PLL2_CLK 0x0100F000 + +#define GFSDEFAULT_CMD 0x10000000 // Default settings +#define GFSDEFAULT_BACKLIGHT0 0x10000001 +#define GF_ON_LPW2 0x00000000 +#define GF_ON_LPW0 0x00000001 + +#define GFSDEFAULT_BACKLIGHT1 0x10000002 +#define GF_ON_LM1 0x00000000 +#define GF_ON_LPW1 0x00000001 + +#define GFPDRV_CMD 0x20000000 +#define GFHOST_CMD 0x40000000 +#define GFSCMD_PANEL_PKT_HEADER_START 0x40000000 + +#define GF_DLY_AFTR_DATA_SENT_MASK 0x00002000 +#define GF_A_2MS_DLY_AFTR_DATA_SENT 0x00000000 +#define GF_A_NO_DLY_AFTR_DATA_SENT 0x00002000 + +#define GF_RAISE_WAIT_AFTR_DATA_SENT_MASK 0x00001000 +#define GF_A_RAISE_WAIT_AFTR_DATA_SENT 0x00001000 + +#define GF_DATA_BURST_MASK 0x000000ff +#define GF_A_DATA_BURST0 0x00000000 +#define GF_A_DATA_BURST1 0x00000001 +#define GF_A_DATA_BURST2 0x00000002 +#define GF_A_DATA_BURST3 0x00000003 +#define GF_A_DATA_BURST4 0x00000004 +#define GF_A_DATA_BURST5 0x00000005 +#define GF_A_DATA_BURST6 0x00000006 +#define GF_A_DATA_BURST7 0x00000007 +#define GF_A_DATA_BURST8 0x00000008 + +#define GF_CS_MASK 0x000f0000 +#define GF_A_MCS_ACTVH 0x00010000 +#define GF_A_MCS_ACTVL 0x00020000 +#define GF_A_SCS_ACTVH 0x00030000 +#define GF_A_SCS_ACTVL 0x00040000 + +#define GF_RS_DC_MASK 0x00f00000 +#define GF_A_RS_DC_IXH_DATAL 0x00100000 +#define GF_A_RS_DC_IXL_DATAL 0x00200000 +#define GF_A_RS_DC_IXL_DATAH 0x00300000 +#define GF_A_RS_DC_IXH_DATAH 0x00400000 + +#define GF_IFACE_MASK 0x00008f00 +#define GF_A_IFACE_PRLL 0x00008000 + +#define GF_A_IFACE_PRLL_8 0x00008100 +#define GF_A_IFACE_PRLL_9 0x00008200 +#define GF_A_IFACE_PRLL_16 0x00008300 +#define GF_A_IFACE_PRLL_18 0x00008400 +#define GF_A_IFACE_SPI_8 0x00000100 +#define GF_A_IFACE_SPI_8DC 0x00000200 +#define GF_A_IFACE_SPI_12 0x00000300 +#define GF_A_IFACE_SPI_16 0x00000400 +#define GF_A_IFACE_SPI_16DC 0x00000500 +#define GF_A_IFACE_SPI_16_START8 0x00000600 +#define GF_A_IFACE_SPI_18 0x00000700 +#define GF_A_IFACE_SPI_24 0x00000800 +#define GF_A_IF_LSB_ALINED 0x00004000 +#define GF_A_IF_MSB_ALINED 0x00000000 +#define GF_IF_ALINED_MASK 0x00004000 + +#define GF_CLK_PER_PIXEL_MASK 0x3f000000 +#define GF_A_1CLK_PIXEL 0x01000000 +#define GF_A_2CLK_PIXEL 0x02000000 +#define GF_A_3CLK_PIXEL 0x03000000 +#define GF_A_4CLK_PIXEL 0x04000000 +#define GF_A_24CLK_PIXEL 0x18000000 + +// Parellel +#define GF_A_DATA_VLD_MASK 0xC0000000 +#define GF_A_DATA_VLD_CLK_RISE 0x40000000 +#define GF_A_DATA_VLD_CLK_FALL 0x80000000 + +// Serial + +#define GF_SPI_SCLK_CS_EDGE_ACTV_MASK 0xC0000000 +#define GF_A_SPI_1SCLK_CS_RISING_EDGE_ACTV 0x40000000 +#define GF_A_SPI_2SCLK_CS_RISING_EDGE_ACTV 0x00000000 +#define GF_A_SPI_1SCLK_CS_FALLING_EDGE_ACTV 0xC0000000 +#define GF_A_SPI_2SCLK_CS_FALLING_EDGE_ACTV 0x80000000 + +#define GF_A_SPI_CS_ACTVH 0x00010000 +#define GF_A_SPI_CS_ACTVL 0x00020000 + +#define GF_SPI_RS_DC_MASK 0x00f00000 +#define GF_A_SPI_RS_DC_IXH_DATAL 0x00100000 +#define GF_A_SPI_RS_DC_IXL_DATAL 0x00200000 +#define GF_A_SPI_RS_DC_IXL_DATAH 0x00300000 +#define GF_A_SPI_RS_DC_IXH_DATAH 0x00400000 + + +#define GF_B_ 0x00000000 +#define GF_C_ 0x00000000 + +#define GF_SPI_DATA_START_BYTE 0x00000000 +#define GF_SPI_CMD_START_BYTE 0x00000000 +#define GF_PANEL_DRV_CMD_DATA ~0x0000ffff +#define GFSCMD_PANEL_PKT_HEADER_END 0x40008000 + +#define GFPERIODIC_CMD 0x4000C000 +#define GFSCMD_PERIODIC_PKT_HEADER_START 0x4000C000 +#define GFSCMD_PERIODIC_PKT_HEADER_SIZE 0x0000000A + +#define GF_IS_PERDC_MSB9_LSB9_SWAP_MASK 0x00800000 +#define GF_IS_PERDC_MSB9_LSB9_SWAP 0x00800000 + +#define GF_IS_PERDC_PARLL_CYCLE_MASK 0x0000000f +#define GF_IS_PERDC_PARLL_CYCLE0 0x00000000 +#define GF_IS_PERDC_PARLL_CYCLE1 0x00000001 +#define GF_IS_PERDC_PARLL_CYCLE2 0x00000002 +#define GF_IS_PERDC_PARLL_CYCLE3 0x00000003 +#define GF_IS_PERDC_PARLL_CYCLE4 0x00000004 +#define GF_IS_PERDC_PARLL_CYCLE5 0x00000005 +#define GF_IS_PERDC_PARLL_CYCLE6 0x00000006 +#define GF_IS_PERDC_PARLL_CYCLE7 0x00000007 +#define GF_IS_PERDC_PARLL_CYCLE8 0x00000008 +#define GF_IS_PERDC_PARLL_CYCLE9 0x00000009 +#define GF_IS_PERDC_PARLL_CYCLE10 0x0000000A +#define GF_IS_PERDC_PARLL_CYCLE11 0x0000000B +#define GF_IS_PERDC_PARLL_CYCLE12 0x0000000C + +#define GF_IS_PERDC_PARLL_IF_MASK 0xf0000000 +#define GF_IS_PERDC_PARLL_IF_8 0x00000000 +#define GF_IS_PERDC_PARLL_IF_9 0x10000000 +#define GF_IS_PERDC_PARLL_IF_18 0x20000000 +#define GF_IS_PERDC_PARLL_IF_16 0x30000000 + +#define GF_IS_PERDC_PARLL_MAX_DATA_MASK 0x0000ff00 +#define GF_IS_PERDC_PARLL_MAX_DATA_IF_8 0x00005900 +#define GF_IS_PERDC_PARLL_MAX_DATA_IF_9 0x00005900 +#define GF_IS_PERDC_PARLL_MAX_DATA_IF_16 0x00006B00 +#define GF_IS_PERDC_PARLL_MAX_DATA_IF_18 0x00006B00 + +#define GFIS_PRLL_EN_RS_DC_C 0 +#define GFIS_PRLL_EN_RS_DC_D 0 + +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_1_D (1 << (108-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_2_D (1 << (111-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_3_D (1 << (114-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_4_D (1 << (117-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_5_D (1 << (120-96)) +#define GFIS_PRLL_ENBLE_LSC0_18_CYCLE_6_D (1 << (123-96)) + +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_1_D (1 << (109-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_2_D (1 << (112-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_3_D (1 << (115-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_4_D (1 << (118-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_5_D (1 << (121-96)) +#define GFIS_PRLL_ENBLE_LSC1_18_CYCLE_6_D (1 << (124-96)) + +#define GFIS_PRLL_RS_CD_18_CYCLE_1_H_D (1 << (110-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_1_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_2_H_D (1 << (113-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_2_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_3_H_D (1 << (116-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_3_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_4_H_D (1 << (119-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_4_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_5_H_D (1 << (122-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_5_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_18_CYCLE_6_H_D (1 << (125-96)) +#define GFIS_PRLL_RS_CD_18_CYCLE_6_L_D 0x00000000 + +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_1_C (1 << (90-64)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_2_C (1 << (93-64)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_3_D (1 << (96-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_4_D (1 << (99-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_5_D (1 << (102-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_6_D (1 << (105-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_7_D (1 << (108-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_8_D (1 << (111-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_9_D (1 << (114-96)) +#define GFIS_PRLL_ENBLE_LSC0_9_CYCLE_10_D (1 << (117-96)) + +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_1_C (1 << (91-64)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_2_C (1 << (94-64)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_3_D (1 << (97-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_4_D (1 << (100-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_5_D (1 << (103-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_6_D (1 << (106-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_7_D (1 << (109-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_8_D (1 << (112-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_9_D (1 << (115-96)) +#define GFIS_PRLL_ENBLE_LSC1_9_CYCLE_10_D (1 << (118-96)) + +#define GFIS_PRLL_RS_CD_9_CYCLE_1_H_C (1 << (92-64)) +#define GFIS_PRLL_RS_CD_9_CYCLE_1_L_C 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_2_H_C (1 << (95-64)) +#define GFIS_PRLL_RS_CD_9_CYCLE_2_L_C 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_3_H_D (1 << (98-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_3_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_4_H_D (1 << (101-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_4_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_5_H_D (1 << (104-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_5_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_6_H_D (1 << (107-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_6_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_7_H_D (1 << (110-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_7_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_8_H_D (1 << (113-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_8_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_9_H_D (1 << (116-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_9_L_D 0x00000000 +#define GFIS_PRLL_RS_CD_9_CYCLE_10_H_D (1 << (119-96)) +#define GFIS_PRLL_RS_CD_9_CYCLE_10_L_D 0x00000000 + +// Serial + +#define GF_IS_PERDC_SERIAL_CYCLE_MASK 0x0000000f +#define GF_IS_PERDC_SERIAL_CYCLE0 0x00000000 +#define GF_IS_PERDC_SERIAL_CYCLE1 0x00000001 +#define GF_IS_PERDC_SERIAL_CYCLE2 0x00000002 +#define GF_IS_PERDC_SERIAL_CYCLE3 0x00000003 +#define GF_IS_PERDC_SERIAL_CYCLE4 0x00000004 +#define GF_IS_PERDC_SERIAL_CYCLE5 0x00000005 +#define GF_IS_PERDC_SERIAL_CYCLE6 0x00000006 +#define GF_IS_PERDC_SERIAL_CYCLE7 0x00000007 +#define GF_IS_PERDC_SERIAL_CYCLE8 0x00000008 +#define GF_IS_PERDC_SERIAL_CYCLE9 0x00000009 +#define GF_IS_PERDC_SERIAL_CYCLE10 0x0000000A +#define GF_IS_PERDC_SERIAL_CYCLE11 0x0000000B +#define GF_IS_PERDC_SERIAL_CYCLE12 0x0000000C + +#define GF_IS_PERDC_SERIAL_IF_MASK 0xf0000000 +#define GF_IS_PERDC_SERIAL_IF_8 0x80000000 +#define GF_IS_PERDC_SERIAL_IF_9 0x90000000 +#define GF_IS_PERDC_SERIAL_IF_12 0xA0000000 +#define GF_IS_PERDC_SERIAL_IF_16 0xB0000000 +#define GF_IS_PERDC_SERIAL_IF_18 0xC0000000 +#define GF_IS_PERDC_SERIAL_IF_24 0xD0000000 + +#define GF_IS_PERDC_SERIAL_MAX_DATA_MASK 0x0000ff00 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_8 0x00005900 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_9 0x00005900 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_12 0x00006A00 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_16 0x00006B00 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_18 0x00006C00 +#define GF_IS_PERDC_SERIAL_MAX_DATA_IF_24 0x00006D00 + +#define GFIS_SERIAL_EN_RS_DC_C 0 +#define GFIS_SERIAL_EN_RS_DC_D 0 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_24_CYCLE_1_D (1 << (96-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_24_CYCLE_2_D (1 << (98-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_24_CYCLE_3_D (1 << (100-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_24_CYCLE_4_D (1 << (102-96)) + +#define GFIS_SERIAL_RS_CD_24_CYCLE_1_H_D (1 << (97-96)) +#define GFIS_SERIAL_RS_CD_24_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_24_CYCLE_2_H_D (1 << (99-96)) +#define GFIS_SERIAL_RS_CD_24_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_24_CYCLE_3_H_D (1 << (101-96)) +#define GFIS_SERIAL_RS_CD_24_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_24_CYCLE_4_H_D (1 << (103-96)) +#define GFIS_SERIAL_RS_CD_24_CYCLE_4_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_1_D (1 << (108-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_2_D (1 << (110-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_3_D (1 << (112-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_4_D (1 << (114-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_5_D (1 << (116-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_18_CYCLE_6_D (1 << (118-96)) + +#define GFIS_SERIAL_RS_CD_18_CYCLE_1_H_D (1 << (109-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_2_H_D (1 << (111-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_3_H_D (1 << (113-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_4_H_D (1 << (115-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_5_H_D (1 << (117-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_18_CYCLE_6_H_D (1 << (119-96)) +#define GFIS_SERIAL_RS_CD_18_CYCLE_6_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_1_D (1 << (112-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_2_D (1 << (114-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_3_D (1 << (116-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_4_D (1 << (118-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_5_D (1 << (120-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_6_D (1 << (122-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_7_D (1 << (124-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_16_CYCLE_7_D (1 << (124-96)) + +#define GFIS_SERIAL_RS_CD_16_CYCLE_1_H_D (1 << (113-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_2_H_D (1 << (115-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_3_H_D (1 << (117-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_4_H_D (1 << (119-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_5_H_D (1 << (121-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_6_H_D (1 << (123-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_6_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_16_CYCLE_7_H_D (1 << (125-96)) +#define GFIS_SERIAL_RS_CD_16_CYCLE_7_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_1_D (1 << (109-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_2_D (1 << (111-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_3_D (1 << (113-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_4_D (1 << (115-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_5_D (1 << (117-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_6_D (1 << (119-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_7_D (1 << (121-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_8_D (1 << (123-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_12_CYCLE_9_D (1 << (125-96)) + +#define GFIS_SERIAL_RS_CD_12_CYCLE_1_H_D (1 << (110-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_2_H_D (1 << (112-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_3_H_D (1 << (114-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_4_H_D (1 << (116-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_5_H_D (1 << (118-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_6_H_D (1 << (120-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_6_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_7_H_D (1 << (122-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_7_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_8_H_D (1 << (124-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_8_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_12_CYCLE_9_H_D (1 << (126-96)) +#define GFIS_SERIAL_RS_CD_12_CYCLE_9_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_1_D (1 << (99-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_2_D (1 << (101-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_3_D (1 << (103-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_4_D (1 << (105-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_5_D (1 << (107-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_6_D (1 << (109-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_7_D (1 << (111-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_8_D (1 << (113-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_9_D (1 << (115-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_9_CYCLE_10_D (1 << (117-96)) + +#define GFIS_SERIAL_RS_CD_9_CYCLE_1_H_D (1 << (100-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_2_H_D (1 << (102-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_3_H_D (1 << (104-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_4_H_D (1 << (106-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_5_H_D (1 << (108-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_6_H_D (1 << (110-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_6_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_7_H_D (1 << (112-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_7_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_8_H_D (1 << (114-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_8_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_9_H_D (1 << (116-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_9_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_9_CYCLE_10_H_D (1 << (118-96)) +#define GFIS_SERIAL_RS_CD_9_CYCLE_10_L_D 0x00000000 + +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_1_D (1 << (96-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_2_D (1 << (98-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_3_D (1 << (100-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_4_D (1 << (102-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_5_D (1 << (104-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_6_D (1 << (106-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_7_D (1 << (108-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_8_D (1 << (110-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_9_D (1 << (112-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_10_D (1 << (114-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_11_D (1 << (116-96)) +#define GFIS_SERIAL_ENBLE_LMSCS_LSSCS_8_CYCLE_12_D (1 << (118-96)) + +#define GFIS_SERIAL_RS_CD_8_CYCLE_1_H_D (1 << (97-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_1_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_2_H_D (1 << (99-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_2_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_3_H_D (1 << (101-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_3_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_4_H_D (1 << (103-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_4_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_5_H_D (1 << (105-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_5_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_6_H_D (1 << (107-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_6_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_7_H_D (1 << (109-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_7_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_8_H_D (1 << (111-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_8_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_9_H_D (1 << (113-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_9_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_10_H_D (1 << (115-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_10_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_11_H_D (1 << (117-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_11_L_D 0x00000000 +#define GFIS_SERIAL_RS_CD_8_CYCLE_12_H_D (1 << (119-96)) +#define GFIS_SERIAL_RS_CD_8_CYCLE_12_L_D 0x00000000 + +#define GFSCMD_PERIODIC_PKT_HEADER_END 0x4000E000 + +#define GFSCMD_I2C_PKT_HEADER_START 0x4000A000 + +#define GF_I2C_DATA_BURST_MASK 0x000000ff +#define GF_I2C_A_DATA_BURST0 0x00000000 +#define GF_I2C_A_DATA_BURST1 0x00000001 +#define GF_I2C_A_DATA_BURST2 0x00000002 +#define GF_I2C_A_DATA_BURST3 0x00000003 +#define GF_I2C_A_DATA_BURST4 0x00000004 +#define GF_I2C_A_DATA_BURST5 0x00000005 +#define GF_I2C_A_DATA_BURST6 0x00000006 +#define GF_I2C_A_DATA_BURST7 0x00000007 +#define GF_I2C_A_DATA_BURST8 0x00000008 + +#define GF_HW_SW_I2C_MASK 0x00000300 +#define GF_HW_I2C 0x00000000 +#define GF_SW_I2C 0x00000100 +#define GF_I2C_B_WRITE_ID 0x00000000 +#define GF_I2C_C_READ_ID 0x00000000 +#define GFSCMD_I2C_PKT_HEADER_END 0x4000B000 + + +//SDIO GPIOs + +#define GFSCMD_GPIO_SD_INIT 0x00008f00 //One time Init SD GPIO +#define GF_NO_DATA 0x00000000 + +#define GFSCMD_GPIO_SD_PIN_SDGP0 0x00008f01 +#define GFSCMD_GPIO_SD_PIN_SDGP1 0x00018f01 +#define GFSCMD_GPIO_SD_PIN_CMD 0x00028f02 +#define GFSCMD_GPIO_SD_PIN_CLK 0x00038f02 +#define GFSCMD_GPIO_SD_PIN_DATA0 0x00048f00 +#define GFSCMD_GPIO_SD_PIN_DATA1 0x00048f01 +#define GFSCMD_GPIO_SD_PIN_DATA2 0x00048f02 +#define GFSCMD_GPIO_SD_PIN_DATA3 0x00048f03 + +#define GF_GPIO_PIN_OUTPUT_ENABLE 0x00000000 +#define GF_GPIO_PIN_INPUT_ENABLE 0x00000001 +#define GF_GPIO_PIN_DISABLE 0x00000002 +#define GF_GPIO_PIN_HIGH 0x00000003 +#define GF_GPIO_PIN_LOW 0x00000004 + +#endif //__GFDISPCMDDATA_H__ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDx.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDx.h new file mode 100755 index 00000000..cca38e76 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFDx.h @@ -0,0 +1,1847 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFDx.h + GFSDK Display Initialization API header file. + */ + +#ifndef GF_DX_H +#define GF_DX_H + +#include "GFDispCmdData.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupDx DxAPI Display Initialization API +
        +
      • @ref pageDxAppNotes +
          +
        • @ref pageDxAppNotes1 +
        +
      +*/ +/*@{*/ + +/** GFDxAPI color info to be used during programming GFDxErase*/ +#define GFDX_COLOR_RED 0xF800F800 +#define GFDX_COLOR_GREEN 0x07E007E0 +#define GFDX_COLOR_BLUE 0x001F001F + + + +/** GFDxAPI error code: Function not supported. */ +#define GFDX_ERROR_NO_SUPPORT (GFDX_ERROR | 2) +/** GFDxAPI error code: Invalid attribute ID for GFDxSetAttribute() / GFDxGetAttribute(). */ +#define GFDX_ERROR_INVALID_ATTRIBUTE (GFDX_ERROR | 6) + +/** + This struct is used by GFDxGetProperty(). + * */ +typedef struct _GFDXPROPERTY +{ + /** standard GF property, following info is available as cap */ + GFPROPERTY Prop; + /** Not supported */ + NvU16 LcdWidth; + /** Not supported */ + NvU16 LcdHeight; + /** Not supported */ + NvU16 LcdIndex; + /** Not supported */ + char LcdName[18]; + /** Not supported */ + NvU16 SubLcdWidth; + /** Not supported */ + NvU16 SubLcdHeight; + /** Not supported */ + NvU16 SubLcdIndex; + /** Not supported */ + char SubLcdName[18]; + +} GFDXPROPERTY, *PGFDXPROPERTY; + +#define DC_P_A_BLEND_2WIN_B DC_P_B_BLEND_2WIN_A +#define DC_P_A_BLEND_2WIN_C DC_P_B_BLEND_2WIN_C + +#define DC_P_C_BLEND_2WIN_A DC_P_B_BLEND_2WIN_A +#define DC_P_C_BLEND_2WIN_B DC_P_B_BLEND_2WIN_C + +//#define DC_P_B_BLEND_2WIN_B DC_P_B_BLEND_2WIN_C +#define P_B_CKEY_ENABLE_2WIN_B_CKEY0 P_B_CKEY_ENABLE_2WIN_C_CKEY0 +#define P_B_CKEY_ENABLE_2WIN_B_CKEY1 P_B_CKEY_ENABLE_2WIN_C_CKEY1 +#define P_B_BLEND_CONTROL_2WIN_B_MASK P_B_BLEND_CONTROL_2WIN_C_MASK +#define P_B_BLEND_CONTROL_2WIN_B_ALPHA_WEIGHT P_B_BLEND_CONTROL_2WIN_C_ALPHA_WEIGHT +#define P_B_BLEND_CONTROL_2WIN_B_DEPENDENT_WEIGHT P_B_BLEND_CONTROL_2WIN_C_DEPENDENT_WEIGHT +#define P_B_BLEND_WEIGHT0_2WIN_B_MASK P_B_BLEND_WEIGHT0_2WIN_C_MASK +#define P_B_BLEND_WEIGHT0_2WIN_B_SHIFT P_B_BLEND_WEIGHT0_2WIN_C_SHIFT +#define P_B_BLEND_WEIGHT1_2WIN_B_MASK P_B_BLEND_WEIGHT1_2WIN_C_MASK +#define P_B_BLEND_WEIGHT1_2WIN_B_SHIFT P_B_BLEND_WEIGHT1_2WIN_C_SHIFT + +//#define DC_P_B_BLEND_3WIN_AB DC_P_B_BLEND_3WIN_AC +#define DC_P_A_BLEND_3WIN_BC DC_P_B_BLEND_3WIN_AC +#define P_B_CKEY_ENABLE_3WIN_AB_CKEY0 P_B_CKEY_ENABLE_3WIN_AC_CKEY0 +#define P_B_CKEY_ENABLE_3WIN_AB_CKEY1 P_B_CKEY_ENABLE_3WIN_AC_CKEY1 +#define P_B_BLEND_CONTROL_3WIN_AB_MASK P_B_BLEND_CONTROL_3WIN_AC_MASK +#define P_B_BLEND_CONTROL_3WIN_AB_ALPHA_WEIGHT P_B_BLEND_CONTROL_3WIN_AC_ALPHA_WEIGHT +#define P_B_BLEND_CONTROL_3WIN_AB_DEPENDENT_WEIGHT P_B_BLEND_CONTROL_3WIN_AC_DEPENDENT_WEIGHT +#define P_B_BLEND_WEIGHT0_3WIN_AB_MASK P_B_BLEND_WEIGHT0_3WIN_AC_MASK +#define P_B_BLEND_WEIGHT0_3WIN_AB_SHIFT P_B_BLEND_WEIGHT0_3WIN_AC_SHIFT +#define P_B_BLEND_WEIGHT1_3WIN_AB_MASK P_B_BLEND_WEIGHT1_3WIN_AC_MASK +#define P_B_BLEND_WEIGHT1_3WIN_AB_SHIFT P_B_BLEND_WEIGHT1_3WIN_AC_SHIFT + +//#define DC_P_B_BLEND_3WIN_BC DC_P_B_BLEND_3WIN_AC +#define DC_P_C_BLEND_3WIN_AB DC_P_B_BLEND_3WIN_AC +#define P_B_CKEY_ENABLE_3WIN_BC_CKEY0 P_B_CKEY_ENABLE_3WIN_AC_CKEY0 +#define P_B_CKEY_ENABLE_3WIN_BC_CKEY1 P_B_CKEY_ENABLE_3WIN_AC_CKEY1 +#define P_B_BLEND_CONTROL_3WIN_BC_MASK P_B_BLEND_CONTROL_3WIN_AC_MASK +#define P_B_BLEND_CONTROL_3WIN_BC_ALPHA_WEIGHT P_B_BLEND_CONTROL_3WIN_AC_ALPHA_WEIGHT +#define P_B_BLEND_CONTROL_3WIN_BC_DEPENDENT_WEIGHT P_B_BLEND_CONTROL_3WIN_AC_DEPENDENT_WEIGHT +#define P_B_BLEND_WEIGHT0_3WIN_BC_MASK P_B_BLEND_WEIGHT0_3WIN_AC_MASK +#define P_B_BLEND_WEIGHT0_3WIN_BC_SHIFT P_B_BLEND_WEIGHT0_3WIN_AC_SHIFT +#define P_B_BLEND_WEIGHT1_3WIN_BC_MASK P_B_BLEND_WEIGHT1_3WIN_AC_MASK +#define P_B_BLEND_WEIGHT1_3WIN_BC_SHIFT P_B_BLEND_WEIGHT1_3WIN_AC_SHIFT + +/** + Definition of attribute ids for Set/GetAttributes() + */ +typedef enum _GFDXATTRIBUTES + { + /** Width of the LCD fixed (240 for a 240x320 panel) */ + GFDX_ATTR_LCDWIDTH, + /** Height of the LCD fixed (320 for a 240x320 panel) */ + GFDX_ATTR_LCDHEIGHT, + /** NVIDIA panel index, This function overwrites environment panel Index setting */ + GFDX_ATTR_LCDTYPE, + /** Name of the panel (upto 16 chars,"PHILIPS_LP7123A") */ + GFDX_ATTR_LCDNAME, + /** Width of the display area usually same as LCDWIDTH, + Parameters: W[15:0] */ + GFDX_ATTR_WIDTH, + /** Height of the display area, can be less if emulating smaller size, + Parameters: H[15:0] */ + GFDX_ATTR_HEIGHT, + /** set/gets width height together to avoid artifacts, + Parameters: W[15:0], H[31:16] */ + GFDX_ATTR_WH_WA, + /** set/gets x, y start position of window A, + Parameters: X[15:0], Y[31:16] */ + GFDX_ATTR_XY_POS_WA, + /** Color Depth Bits per pixel: 1,2,4,8,12,15(RGB555),16(RGB565), 32(ARGB888), + GFDX_COLOR_DEPTH_YCbCr422, + GFDX_COLOR_DEPTH_YUV422, + GFDX_COLOR_DEPTH_YCbCr420P, + GFDX_COLOR_DEPTH_YUV420P, + GFDX_COLOR_DEPTH_YUV422P, + GFDX_COLOR_DEPTH_YCbCr422P, + GFDX_COLOR_DEPTH_YCbCr422R, + GFDX_COLOR_DEPTH_YUV422R, + GFDX_COLOR_DEPTH_YCbCr422RA, + GFDX_COLOR_DEPTH_YUV422RA, + */ + GFDX_ATTR_BPP_WA, + /** On/Off Horizontal & Vertical Pixel Doubling for window A, + Parameters: GFDXA_PIX_DBL_H, GFDXA_PIX_DBL_V or 0-Disable */ + GFDX_ATTR_PIXEL_DBL_WA, + /** Start Address for Window A Buffer 0 */ + GFDX_ATTR_ADDR_WA_B0, + /** Start Address for Window A Buffer 1 */ + GFDX_ATTR_ADDR_WA_B1, + /** Stride for Window A Buffer 0 */ + GFDX_ATTR_STRIDE_WA_B0, + /** Stride for Window A Buffer 1 */ + GFDX_ATTR_STRIDE_WA_B1, + /** Enable/Disable Windows A, Parameters: 1-Enable 0-Disable */ + GFDX_ATTR_ENABLE_WA, + /** Enable/Disable Buf0, Buf1, VI, GE Double Buffer (see def), + Parameters: GFDXA_DB_BUF0, GFDXA_DB_BUF1, GFDXA_DB_GE, GFDXA_DB_VI, + GFDXA_DB_EPP, GFDXA_DB_MPEGE, GFDXA_DB_HOST + */ + GFDX_ATTR_DBL_BUF_WA, + /** Sets/Gets GC Rotate bits for window A, for internal use only */ + GFDX_ATTR_ROTATE_BIT_WA, + /** Set/Get H Direction Increment/Decrement for window A, for internal use only */ + GFDX_ATTR_H_DIRECTION_WA, + /** Set/Get V Direction Increment/Decrement for window A, for internal use only */ + GFDX_ATTR_V_DIRECTION_WA, + /** Enable/Disable Palette for WinA */ + GFDX_ATTR_PALETTE_EN_WA, + /** Set/Get Palette 666 R[31-24], G[23-16], B[15-8], Index[7-0] WinA */ + GFDX_ATTR_PALETTE_WA, + /** Set/Get Palette 888 R[31-24], G[23-16], B[15-8], Index[7-0] WinA */ + GFDX_ATTR_PALETTE888_WA, + /** Enable/Disable DV WinA , + Parameters: GFDX_ATTR_DV_ENABLE, GFDX_ATTR_DV_DISABLE + */ + GFDX_ATTR_DV_CONTROL_EN_WA, + /** Set/Get DV Control R[26-24], G[18-16], B[10-8] WinA */ + GFDX_ATTR_DV_CONTROL_WA, + /** Color Key0 Lower range for overlay, there are two sets of color keys KEY0 & KEY1, + Parameters: R[23-16],G[15-8],B[7-0], Each KEY has Lower and Upper range */ + GFDX_ATTR_COLOR_KEY0_LOWER_RANGE, + /** Color Key0 Upper range for overlay, there are two sets of color keys KEY0 & KEY1, + Parameters: R[23-16],G[15-8],B[7-0], Each KEY has Lower and Upper range */ + GFDX_ATTR_COLOR_KEY0_UPPER_RANGE, + /** Color Key1 Lower range for overlay, there are two sets of color keys KEY0 & KEY1, + Parameters: R[23-16],G[15-8],B[7-0], Each KEY has Lower and Upper range */ + GFDX_ATTR_COLOR_KEY1_LOWER_RANGE, + /** Color Key1 Upper range for overlay, there are two sets of color keys KEY0 & KEY1, + Parameters: R[23-16],G[15-8],B[7-0], Each KEY has Lower and Upper range */ + GFDX_ATTR_COLOR_KEY1_UPPER_RANGE, + /** Color Key enbled but pixel color is not in range, + Parameters: GFDXA_BLEND_CONTROL_NOKEY_ALPHA_WEIGHT else 0 for Fix Weight */ + GFDX_ATTR_COLOR_NOKEY_WA, + /** Weight0 for Color Key not match area, + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT0_WA, + /** Weight1 for Color Key not match area, + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT1_WA, + /** Color Key0 Enble/Disable for WinA, + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE or GFDXA_BLEND_COLOR_KEY0_DISABLE */ + GFDX_ATTR_COLOR_KEY0_1WIN_WA, + /** Color Key1 Enble/Disable for WinA, + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE or GFDXA_BLEND_COLOR_KEY1_DISABLE */ + GFDX_ATTR_COLOR_KEY1_1WIN_WA, + /** Blend Control for WinA where does not Overlap with other Window, + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or 0 for Fix Weight */ + GFDX_ATTR_COLOR_1WIN_WA, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0, + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT0_WA, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1, + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT1_WA, + /** Color Key0 Enble/Disable for WinA, Overlap with WinB, + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY01 + else 2WIN_A_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY1 + else 2WIN_A_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_B_WA, + /** Color Key1 Enble/Disable for WinA, Overlap with WinB, + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY01 + else 2WIN_A_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY0 + else 2WIN_A_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_B_WA, + /** Blend Control for WinA area that overlap with WinB only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_B_WA, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_B_WEIGHT0_WA, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_B_WEIGHT1_WA, + /** Color Key0 Enble/Disable for WinA, Overlap with WinC + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY01 + else 2WIN_A_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY1 + else 2WIN_A_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_C_WA, + /** Color Key1 Enble/Disable for WinA, Overlap with WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY01 + else 2WIN_A_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_A_CKEY1 enbled then ENABLE_2WIN_A_CKEY0 + else 2WIN_A_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_C_WA, + /** Blend Control for WinA area that overlap with WinC only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_C_WA, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_C_WEIGHT0_WA, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_C_WEIGHT1_WA, + /** Color Key0 Enble/Disable for WinA, Overlap with WinA & WinC Only + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 3WIN_AC_CKEY1 enbled then ENABLE_3WIN_AC_CKEY01 + else 3WIN_AC_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 3WIN_AC_CKEY1 enbled then ENABLE_3WIN_AC_CKEY1 + else 3WIN_AC_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_3WIN_BC_WA, + /** Color Key1 Enble/Disable for WinA, Overlap with WinA & WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 3WIN_AC_CKEY1 enbled then ENABLE_3WIN_AC_CKEY01 + else 3WIN_AC_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 3WIN_AC_CKEY1 enbled then ENABLE_3WIN_AC_CKEY0 + else 3WIN_AC_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_3WIN_BC_WA, + /** Blend Control for WinA area that overlap with WinA & WinC only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_3WIN_BC_WA, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_3WIN_BC_WEIGHT0_WA, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_3WIN_BC_WEIGHT1_WA, + /** set/gets width height together to avoid artifacts */ + GFDX_ATTR_WH_WB, + /** set/gets source width height together to avoid artifacts, + Parameters: W[15:0], H[31:16] */ + GFDX_ATTR_SRC_WH_WB, + /** set/gets x, y start position of window B, + Parameters: X[15:0], Y[31:16] */ + GFDX_ATTR_XY_POS_WB, + /** Color Depth Bits per pixel: 1,2,4,8,12,15(RGB555),16(RGB565), 32(ARGB888), + GFDX_COLOR_DEPTH_YCbCr422, + GFDX_COLOR_DEPTH_YUV422, + GFDX_COLOR_DEPTH_YCbCr420P, + GFDX_COLOR_DEPTH_YUV420P, + GFDX_COLOR_DEPTH_YUV422P, + GFDX_COLOR_DEPTH_YCbCr422P, + GFDX_COLOR_DEPTH_YCbCr422R, + GFDX_COLOR_DEPTH_YUV422R, + GFDX_COLOR_DEPTH_YCbCr422RA, + GFDX_COLOR_DEPTH_YUV422RA, + */ + GFDX_ATTR_BPP_WB, + /** On/Off Horizontal & Vertical Pixel Doubling for Window B, + Parameters: GFDXA_PIX_DBL_H, GFDXA_PIX_DBL_V or 0-Disable */ + GFDX_ATTR_PIXEL_DBL_WB, + /** Upscales/Downscales window */ + GFDX_ATTR_SCALE_WB, + /** Start Address for Window B Buffer 0 */ + GFDX_ATTR_ADDR_WB_B0, + /** U Start Address for Window B Buffer 0 */ + GFDX_ATTR_ADDR_U_WB_B0, + /** V Start Address for Window B Buffer 0 */ + GFDX_ATTR_ADDR_V_WB_B0, + /** Stride for Window B Buffer 0 */ + GFDX_ATTR_STRIDE_WB_B0, + /** UV Stride for Window B Buffer 0 */ + GFDX_ATTR_STRIDE_UV_WB_B0, + /** Start Address for Window B Buffer 1 */ + GFDX_ATTR_ADDR_WB_B1, + /** U Start Address for Window B Buffer 1 */ + GFDX_ATTR_ADDR_U_WB_B1, + /** V Start Address for Window B Buffer 1 */ + GFDX_ATTR_ADDR_V_WB_B1, + /** Stride for Window B Buffer 1 */ + GFDX_ATTR_STRIDE_WB_B1, + /** UV Stride for Window B Buffer 1 */ + GFDX_ATTR_STRIDE_UV_WB_B1, + /** Enable/Disable Windows B, Parameters: 1-Enable 0-Disable */ + GFDX_ATTR_ENABLE_WB, + /** Enable/Disable Buf0, Buf1, VI, GE Double Buffer (see def), + Parameters: GFDXA_DB_BUF0, GFDXA_DB_BUF1, GFDXA_DB_GE, GFDXA_DB_VI, + GFDXA_DB_EPP, GFDXA_DB_MPEGE, GFDXA_DB_HOST + */ + GFDX_ATTR_DBL_BUF_WB, + /** Sets/Gets GC Rotate bits for window B, for internal use only */ + GFDX_ATTR_ROTATE_BIT_WB, + /** Set/Get H Direction Increment/Decrement for window B, for internal use only */ + GFDX_ATTR_H_DIRECTION_WB, + /** Set/Get V Direction Increment/Decrement for window B, for internal use only */ + GFDX_ATTR_V_DIRECTION_WB, + /** Enable/Disable Palette for WinB */ + GFDX_ATTR_PALETTE_EN_WB, + /** Set/Get Palette 666 R[31-24], G[23-16], B[15-8], Index[7-0] WinB */ + GFDX_ATTR_PALETTE_WB, + /** Set/Get Palette 888 R[31-24], G[23-16], B[15-8], Index[7-0] WinB */ + GFDX_ATTR_PALETTE888_WB, + /** Enable/Disable DV WinB , + Parameters: GFDX_ATTR_DV_ENABLE, GFDX_ATTR_DV_DISABLE + */ + GFDX_ATTR_DV_CONTROL_EN_WB, + /** Set/Get DV Control R[26-24], G[18-16], B[10-8] WinB */ + GFDX_ATTR_DV_CONTROL_WB, + /** Color Key enbled but pixel color is not in range + Parameters: GFDXA_BLEND_CONTROL_NOKEY_ALPHA_WEIGHT else 0 for Fix Weight */ + GFDX_ATTR_COLOR_NOKEY_WB, + /** Weight0 for Color Key not match area + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT0_WB, + /** Weight1 for Color Key not match area + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT1_WB, + /** Color Key0 Enble/Disable for WinB + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE or GFDXA_BLEND_COLOR_KEY0_DISABLE */ + GFDX_ATTR_COLOR_KEY0_1WIN_WB, + /** Color Key1 Enble/Disable for WinB + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE or GFDXA_BLEND_COLOR_KEY1_DISABLE */ + GFDX_ATTR_COLOR_KEY1_1WIN_WB, + /** Blend Control for WinB where does not Overlap with other Window + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or 0 for Fix Weight */ + GFDX_ATTR_COLOR_1WIN_WB, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT0_WB, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT1_WB, + /** Color Key0 Enble/Disable for WinB, Overlap with WinA + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY01 + else 2WIN_B_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY1 + else 2WIN_B_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_A_WB, + /** Color Key1 Enble/Disable for WinB, Overlap with WinA + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY01 + else 2WIN_B_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY0 + else 2WIN_B_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_A_WB, + /** Blend Control for WinB where does not Overlap with other Window + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_A_WB, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_A_WEIGHT0_WB, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_A_WEIGHT1_WB, + /** Color Key0 Enble/Disable for WinB, Overlap with WinC + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY01 + else 2WIN_B_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY1 + else 2WIN_B_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_C_WB, + /** Color Key1 Enble/Disable for WinB, Overlap with WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY01 + else 2WIN_B_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_B_CKEY1 enbled then ENABLE_2WIN_B_CKEY0 + else 2WIN_B_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_C_WB, + /** Blend Control for WinB area that overlap with WinC only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_C_WB, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_C_WEIGHT0_WB, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_C_WEIGHT1_WB, + /** Color Key0 Enble/Disable for WinB, Overlap with WinA & WinC Only + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 3WIN_BC_CKEY1 enbled then ENABLE_3WIN_BC_CKEY01 + else 3WIN_BC_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 3WIN_BC_CKEY1 enbled then ENABLE_3WIN_BC_CKEY1 + else 3WIN_BC_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_3WIN_AC_WB, + /** Color Key1 Enble/Disable for WinB, Overlap with WinA & WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 3WIN_BC_CKEY1 enbled then ENABLE_3WIN_BC_CKEY01 + else 3WIN_BC_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 3WIN_BC_CKEY1 enbled then ENABLE_3WIN_BC_CKEY0 + else 3WIN_BC_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_3WIN_AC_WB, + /** Blend Control for WinB area that overlap with WinA & WinC only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_3WIN_AC_WB, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_3WIN_AC_WEIGHT0_WB, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_3WIN_AC_WEIGHT1_WB, + + /** set/gets width height together to avoid artifacts */ + GFDX_ATTR_WH_WC, + /** set/gets source width height together to avoid artifacts, + Parameters: W[15:0], H[31:16] */ + GFDX_ATTR_SRC_WH_WC, + /** set/gets x, y start position of window C, + Parameters: X[15:0], Y[31:16] */ + GFDX_ATTR_XY_POS_WC, + /** Color Depth Bits per pixel: 1,2,4,8,12,15(RGB555),16(RGB565), 32(ARGB888), + GFDX_COLOR_DEPTH_YCbCr422, + GFDX_COLOR_DEPTH_YUV422, + GFDX_COLOR_DEPTH_YCbCr420P, + GFDX_COLOR_DEPTH_YUV420P, + GFDX_COLOR_DEPTH_YUV422P, + GFDX_COLOR_DEPTH_YCbCr422P, + GFDX_COLOR_DEPTH_YCbCr422R, + GFDX_COLOR_DEPTH_YUV422R, + GFDX_COLOR_DEPTH_YCbCr422RA, + GFDX_COLOR_DEPTH_YUV422RA, + */ + GFDX_ATTR_BPP_WC, + /** Set Trigger for encode window, 0- Disable, 1- Enable, 2-single Shot*/ + GFDX_ATTR_TRIGGER_WENC, + /** On/Off Horizontal & Vertical Pixel Doubling for Window C, + Parameters: GFDXA_PIX_DBL_H, GFDXA_PIX_DBL_V or 0-Disable */ + GFDX_ATTR_PIXEL_DBL_WC, + /** Upscales/Downscales window */ + GFDX_ATTR_SCALE_WC, + /** Start Address for window C Buffer 0 */ + GFDX_ATTR_ADDR_WC_B0, + /** U Start Address for window C Buffer 0 */ + GFDX_ATTR_ADDR_U_WC_B0, + /** V Start Address for window C Buffer 0 */ + GFDX_ATTR_ADDR_V_WC_B0, + /** Stride for window C Buffer 0 */ + GFDX_ATTR_STRIDE_WC_B0, + /** UV Stride for window C Buffer 0 */ + GFDX_ATTR_STRIDE_UV_WC_B0, + /** Start Address for window C Buffer 1 */ + GFDX_ATTR_ADDR_WC_B1, + /** U Start Address for window C Buffer 1 */ + GFDX_ATTR_ADDR_U_WC_B1, + /** V Start Address for window C Buffer 1 */ + GFDX_ATTR_ADDR_V_WC_B1, + /** Stride for window C Buffer 1 */ + GFDX_ATTR_STRIDE_WC_B1, + /** UV Stride for window C Buffer 1 */ + GFDX_ATTR_STRIDE_UV_WC_B1, + /** Enable/Disable Windows C, Parameters: 1-Enable 0-Disable */ + GFDX_ATTR_ENABLE_WC, + /** Enable/Disable Buf0, Buf1, VI, GE Double Buffer (see def), + Parameters: GFDXA_DB_BUF0, GFDXA_DB_BUF1, GFDXA_DB_GE, GFDXA_DB_VI, + GFDXA_DB_EPP, GFDXA_DB_MPEGE, GFDXA_DB_HOST + */ + GFDX_ATTR_DBL_BUF_WC, + /** Sets/Gets GC Rotate bits for window C, for internal use only */ + GFDX_ATTR_ROTATE_BIT_WC, + /** Set/Get H Direction Increment/Decrement for window C, for internal use only */ + GFDX_ATTR_H_DIRECTION_WC, + /** Set/Get V Direction Increment/Decrement for window C, for internal use only */ + GFDX_ATTR_V_DIRECTION_WC, + /** Enable/Disable Palette for WinC */ + GFDX_ATTR_PALETTE_EN_WC, + /** Set/Get Palette 666 R[31-24], G[23-16], B[15-8], Index[7-0] WinC */ + GFDX_ATTR_PALETTE_WC, + /** Set/Get Palette 888 R[31-24], G[23-16], B[15-8], Index[7-0] WinC */ + GFDX_ATTR_PALETTE888_WC, + /** Enable/Disable DV WinC, + Parameters: GFDX_ATTR_DV_ENABLE, GFDX_ATTR_DV_DISABLE + */ + GFDX_ATTR_DV_CONTROL_EN_WC, + /** Set/Get DV Control R[26-24], G[18-16], B[10-8] WinA */ + GFDX_ATTR_DV_CONTROL_WC, + /** Color Key enbled but pixel color is not in range + Parameters: GFDXA_BLEND_CONTROL_NOKEY_ALPHA_WEIGHT else 0 for Fix Weight */ + GFDX_ATTR_COLOR_NOKEY_WC, + /** Weight0 for Color Key not match area + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT0_WC, + /** Weight1 for Color Key not match area + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_NOKEY_WEIGHT1_WC, + /** Color Key0 Enble/Disable for WinC + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE or GFDXA_BLEND_COLOR_KEY0_DISABLE */ + GFDX_ATTR_COLOR_KEY0_1WIN_WC, + /** Color Key1 Enble/Disable for WinC + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE or GFDXA_BLEND_COLOR_KEY1_DISABLE */ + GFDX_ATTR_COLOR_KEY1_1WIN_WC, + /** Blend Control for WinC where does not Overlap with other Window + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or 0 for Fix Weight */ + GFDX_ATTR_COLOR_1WIN_WC, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT0_WC, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_1WIN_WEIGHT1_WC, + /** Color Key0 Enble/Disable for WinC, Overlap with WinA + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY01 + else 2WIN_C_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY1 + else 2WIN_C_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_A_WC, + /** Color Key1 Enble/Disable for WinC, Overlap with WinA + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY01 + else 2WIN_C_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY0 + else 2WIN_C_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_A_WC, + /** Blend Control for WinC area that overlap with WinA only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_A_WC, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_A_WEIGHT0_WC, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_A_WEIGHT1_WC, + /** Color Key0 Enble/Disable for WinC, Overlap with WinB + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY01 + else 2WIN_C_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY1 + else 2WIN_C_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_2WIN_B_WC, + /** Color Key1 Enble/Disable for WinC, Overlap with WinB + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY01 + else 2WIN_C_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 2WIN_C_CKEY1 enbled then ENABLE_2WIN_C_CKEY0 + else 2WIN_C_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_2WIN_B_WC, + /** Blend Control for WinC area that overlap with WinB only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_2WIN_B_WC, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_2WIN_B_WEIGHT0_WC, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_2WIN_B_WEIGHT1_WC, + /** Color Key0 Enble/Disable for WinC, Overlap with WinA & WinB Only + Parameters: GFDXA_BLEND_COLOR_KEY0_ENABLE (if 3WIN_AB_CKEY1 enbled then ENABLE_3WIN_AB_CKEY01 + else 3WIN_AB_CKEY0) + GFDXA_BLEND_COLOR_KEY0_DISABLE (if 3WIN_AB_CKEY1 enbled then ENABLE_3WIN_AB_CKEY1 + else 3WIN_AB_NOKEY) + */ + GFDX_ATTR_COLOR_KEY0_3WIN_AB_WC, + /** Color Key1 Enble/Disable for WinC, Overlap with WinA & WinB + Parameters: GFDXA_BLEND_COLOR_KEY1_ENABLE (if 3WIN_AB_CKEY1 enbled then ENABLE_3WIN_AB_CKEY01 + else 3WIN_AB_CKEY1) + GFDXA_BLEND_COLOR_KEY1_DISABLE (if 3WIN_AB_CKEY1 enbled then ENABLE_3WIN_AB_CKEY0 + else 3WIN_AB_NOKEY) + */ + GFDX_ATTR_COLOR_KEY1_3WIN_AB_WC, + /** Blend Control for WinC area that overlap with WinA & WinB only + Parameters: GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT or GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT + or 0 for FIX WEIGHT + */ + GFDX_ATTR_COLOR_3WIN_AB_WC, + /** Win Blend Weight0 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 0 uses Weight0 + Parameters: Weight0 value[7:0], if 1-bit Alpha Weight0 value = 0 */ + GFDX_ATTR_COLOR_3WIN_AB_WEIGHT0_WC, + /** Win Blend Weight1 for CKey disabled or CKey enabled w key match area or 1-bit Alpha, Alpha 1 uses Weight1 + Parameters: Weight1 value[7:0], if 1-bit Alpha Weight1 value = 1 */ + GFDX_ATTR_COLOR_3WIN_AB_WEIGHT1_WC, + /** GC Color Key for overlay, Not supported */ + GFDX_ATTR_COLOR_KEY, + /** GC Color Key Mask for overlay, Not supported */ + GFDX_ATTR_COLOR_KEY_MASK, + /** Set overlap type (see def), Not supported */ + GFDX_ATTR_OVERLAP_TYPE, + /** Gets VDisplay End for GE Start Window programming, Not supported */ + GFDX_ATTR_V_DISPLAY_END, + /** Gets range for clock divider L=0:H=15 */ + GFDX_ATTR_PWM0_CLK_RANGE, + /** Gets range for duty cycle L=0:H=255 */ + GFDX_ATTR_PWM0_DTY_RANGE, + /** Controls Backlight0 clock divider for PWM0 Bits[5:0] */ + GFDX_ATTR_PWM0_CLOCK, + /** Controls Backlight0 duty cycle for PWM0 Bits[7:0] */ + GFDX_ATTR_PWM0_DUTYCY, + /** Gets range for clock divider L=0:H=15 */ + GFDX_ATTR_PWM1_CLK_RANGE, + /** Gets range for duty cycle L=0:H=255 */ + GFDX_ATTR_PWM1_DTY_RANGE, + /** Controls Backlight1 clock divider for PWM1 Bits[5:0] */ + GFDX_ATTR_PWM1_CLOCK, + /** Controls Backlight1 duty cycle for PWM1 Bits[7:0] */ + GFDX_ATTR_PWM1_DUTYCY, + /** LCD Type 0-Main Lcd, 1-Sub Lcd */ + GFDX_ATTR_DISP_TYPE, + /** SW register 1 for program usage */ + GFDX_ATTR_SW_REG_1, + /** SW register 2 for program usage */ + GFDX_ATTR_SW_REG_2, + /** set/gets width height of screen encode window, + Parameters: W[15:0], H[31:16] */ + GFDX_ATTR_WH_WENC, + /** set/gets x, y start position of screen encode window, + Parameters: X[15:0], Y[31:16] */ + GFDX_ATTR_XY_POS_WENC, + /** Enable/Disable screen encode window. Parameters: 1-Enable 0-Disable. + * Please note that this sets the encode rate to its maximum value of + * 1.000 so if you plan to change it after enabling, + * use attribute GFDX_ATTR_WENC_RATE. */ + GFDX_ATTR_ENABLE_WENC, + /** Get Device ID & Rev, Not supported */ + GFDX_ATTR_DEVICE_INFO, + /** Enable CRC, Set Wait 1 or 2 VSync + Parameters: GFDXA_CRC_WAIT_VSYNC1, GFDXA_CRC_WAIT_VSYNC2, GFDXA_CRC_DISABLE + */ + GFDX_ATTR_CRC_ENABLE, + /** Get Check Sum */ + GFDX_ATTR_CRC_CHECK_SUM, + /** Not supported, Not supported */ + GFDX_ATTR_HC_SHAPE, + /** load Hardware Cursor Image, Not supported */ + GFDX_ATTR_HC_SHAPE_EXT, + /** set cursor hot spot, Not supported */ + GFDX_ATTR_HC_HOTSPOT, + /** set foreground and background color, Not supported */ + GFDX_ATTR_HC_COLOR, + /** Set Hardware Cursor new Position, Not supported */ + GFDX_ATTR_HC_POSITION, + /** Enable, Disable Hardware Cursor, Not supported */ + GFDX_ATTR_HC_SHOW, + /** free internal buffer, Not supported */ + GFDX_ATTR_HC_RELEASE, + /** Set Start or Stop Frame + Parameters: GFDX_MAIN_START, GFDX_MAIN_STOP, GFDX_SUB_START, GFDX_SUB_STOP + */ + GFDX_ATTR_STOP_START, + /** Set Start or Stop Frame + Parameters: GFDX_MAIN_ONE_FRAME, GFDX_SUB_ONE_FRAME + */ + GFDX_ATTR_SEND_ONE_FRAME, + /** Set No change */ + GFDX_ATTR_NOCHANGE, + /** Get Pre Init LCD Resolution Bit[0-15] Width, Bit[16-31] Height*/ + GFDX_ATTR_PRE_INIT_LCD_RES, + /** NVIDIA panel index internal to API use */ + GFDX_ATTR_INTERNAL_LCDTYPE, + /** Setting this attribute will bypass any hardware writes in DxAPI which go through + * the GFDX_CHANNEL_xx macros. The runtime environment GFSDK_DXINIT_BYPASS uses + * this attribue to disable hardware writes during DxSetDisplay(). + * Parameters: GFDX_SET_WRITE_SHADOW or GFDX_CLR_WRITE_SHADOW + */ + GFDX_ATTR_WRITE_SHADOW_ONLY, + /** Backlight0 ON GPIO LPW2 Low */ + GFDX_ATTR_BACKLIGHT0_ON, + /** Backlight1 ON GPIO LM1 Low */ + GFDX_ATTR_BACKLIGHT1_ON, + /** Backlight0 OFF GPIO LPW2 High */ + GFDX_ATTR_BACKLIGHT0_OFF, + /** Backlight1 OFF GPIO LM1 High*/ + GFDX_ATTR_BACKLIGHT1_OFF, + /** configure BACKLIGHT0 as GPIO on LPW2*/ + GFDX_ATTR_BACKLIGHT0_CONFIGURE_GPIO, + /** configure BACKLIGHT1 as GPIO on LM1*/ + GFDX_ATTR_BACKLIGHT1_CONFIGURE_GPIO, + /** configure BACKLIGHT0 as PWM on LPW2*/ + GFDX_ATTR_BACKLIGHT0_CONFIGURE_PWM, + /** configure BACKLIGHT1 as PWM on LM1 */ + GFDX_ATTR_BACKLIGHT1_CONFIGURE_PWM, + + /** Set Stop Frame Options, + Parameters: GFDX_MAIN_STOP_POLARITY_HIGH, GFDX_MAIN_STOP_POLARITY_LOW, GFDX_SUB_STOP_POLARITY_HIGH + GFDX_SUB_STOP_POLARITY_LOW, GFDX_MAIN_STOP_INPUT_PIN_ENABLE, GFDX_MAIN_STOP_INPUT_PIN_DISABLE, + GFDX_SUB_STOP_INPUT_PIN_ENABLE, GFDX_SUB_STOP_INPUT_PIN_DISABLE, GFDX_STOP_WINDOW_A_NC_ENABLE, + GFDX_STOP_WINDOW_A_NC_DISABLE, GFDX_STOP_WINDOW_B_NC_ENABLE, GFDX_STOP_WINDOW_B_NC_DISABLE, + GFDX_STOP_WINDOW_B_NC_ENABLE, GFDX_STOP_WINDOW_B_NC_DISABLE + */ + GFDX_ATTR_STOP_FRAME_OPTIONS, + /** Set Non Continuos Display */ + GFDX_ATTR_NC_DISPLAY, + /** Horizontal and Vertical Filter Support Window B + Parameters: GFDX_H_FILTER_ENABLE, GFDX_H_FILTER_DISABLE, GFDX_V_FILTER_ENABLE, GFDX_V_FILTER_DISABLE + */ + GFDX_ATTR_H_V_FILTER_WB, + /** Horizontal and Vertical Filter Support Window C + Parameters: GFDX_H_FILTER_ENABLE, GFDX_H_FILTER_DISABLE, GFDX_V_FILTER_ENABLE, GFDX_V_FILTER_DISABLE + */ + GFDX_ATTR_H_V_FILTER_WC, + + /** Get Supported Display Script Options + Parameters: GFDX_DEFAULT_TABLE, GFDX_DXAPI_SUPPORT, GFDX_FMARK_SUPPORT + */ + GFDX_ATTR_DISPLAY_SCRIPT_OPTIONS, + /** Rate of window decode output frames when sending continuously. + * please note that the rate is overwritten with the maximum value (i.e. 1.000 + * which is represented by a fixed point fraction 16.16) if you use attribute + * GFDX_ATTR_ENABLE_WENC, so you need to overwrite with this attribute. + * Parameters: any number between 0x0 and 0x10000 (i.e. 0.0 an 1.000) + */ + GFDX_ATTR_WENC_RATE + +} GFDXATTRIBUTES; + +// Stop Frame Options +#define GFDX_MAIN_STOP_POLARITY_HIGH 0x00000001 +#define GFDX_MAIN_STOP_POLARITY_LOW 0x80000001 +#define GFDX_MAIN_STOP_INPUT_PIN_ENABLE 0x00000002 +#define GFDX_MAIN_STOP_INPUT_PIN_DISABLE 0x80000002 + +#define GFDX_SUB_STOP_POLARITY_HIGH 0x00000004 +#define GFDX_SUB_STOP_POLARITY_LOW 0x80000004 +#define GFDX_SUB_STOP_INPUT_PIN_ENABLE 0x00000006 +#define GFDX_SUB_STOP_INPUT_PIN_DISABLE 0x80000006 + +#define GFDX_STOP_WINDOW_A_NC_ENABLE 0x00000010 +#define GFDX_STOP_WINDOW_A_NC_DISABLE 0x80000010 +#define GFDX_STOP_WINDOW_B_NC_ENABLE 0x00000011 +#define GFDX_STOP_WINDOW_B_NC_DISABLE 0x80000011 +#define GFDX_STOP_WINDOW_C_NC_ENABLE 0x00000012 +#define GFDX_STOP_WINDOW_C_NC_DISABLE 0x80000012 + +// Horizontal and Vertical Filter Support Window B & C + +#define GFDX_H_FILTER_ENABLE 0x00000100 +#define GFDX_H_FILTER_DISABLE 0x80000100 +#define GFDX_V_FILTER_ENABLE 0x00004000 +#define GFDX_V_FILTER_DISABLE 0x80004000 +#define GFDX_V_FILTER_OPTIMIZE_ENABLE 0x00010000 +#define GFDX_V_FILTER_OPTIMIZE_DISABLE 0x80010000 + +// Display Script Options + +#define GFDX_DEFAULT_TABLE 0x00000001 +#define GFDX_DXAPI_SUPPORT 0x00000002 +#define GFDX_FMARK_SUPPORT 0x00000004 + + +/** Attribute value for GFDX_ATTR_WRITE_SHADOW_ONLY. + * Setting this attribute will disable all channel hardware writes in DxAPI. + * The runtime environment GFSDK_DXINIT_BYPASS uses this attribue to disable + * hardware writes in DxSetDisplay(). + */ +#define GFDX_SET_WRITE_SHADOW 0x00000001 +/** Attribute value for GFDX_ATTR_WRITE_SHADOW_ONLY. + * This attribute is used to clear the effect of #GFDX_SET_WRITE_SHADOW. + * It must be used explicitly to re-enable hardware writes in DxAPI. + */ +#define GFDX_CLR_WRITE_SHADOW 0x80000001 + + + +#define GFDX_COLOR_DEPTH_YCbCr422 (16UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV422 (17UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YCbCr420P (18UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV420P (19UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YCbCr422P (20UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV422P (21UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YCbCr422R (22UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV422R (23UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YCbCr422RA (24UL | 0x80000000) +#define GFDX_COLOR_DEPTH_YUV422RA (25UL | 0x80000000) + +#define GFDX_SWAP_MASK 0x000f0000 +#define GFDX_NO_SWAP 0x00000000 +#define GFDX_BYTE_SWAP 0x00010000 +#define GFDX_ORDER_SWAP 0x00020000 +#define GFDX_WORD_SWAP 0x00030000 + +#define GFDX_COLOR_DEPTH_YUV422_YVYU (17UL | 0x80000000 | GFDX_NO_SWAP) +#define GFDX_COLOR_DEPTH_YUV422_VYUY (17UL | 0x80000000 | GFDX_BYTE_SWAP) +#define GFDX_COLOR_DEPTH_YUV422_UYVY (17UL | 0x80000000 | GFDX_ORDER_SWAP) +#define GFDX_COLOR_DEPTH_YUV422_YUYV (17UL | 0x80000000 | GFDX_WORD_SWAP) + +#define GFDX_COLOR_DEPTH_YCbCr422_YVYU (16UL | 0x80000000 | GFDX_NO_SWAP) +#define GFDX_COLOR_DEPTH_YCbCr422_VYUY (16UL | 0x80000000 | GFDX_BYTE_SWAP) +#define GFDX_COLOR_DEPTH_YCbCr422_UYVY (16UL | 0x80000000 | GFDX_ORDER_SWAP) +#define GFDX_COLOR_DEPTH_YCbCr422_YUYV (16UL | 0x80000000 | GFDX_WORD_SWAP) + + +// Horizontal Filter Coefficients + +#define GF_H_P00C0 0x0 +#define GF_H_P00C1 (0x0 << 3 ) +#define GF_H_P00C2 (0x80 << 8 ) +#define GF_H_P00C3 (0x0 << 16) +#define GF_H_P00C4 (0x0 << 24) +#define GF_H_P00C5 (0x0 << 29) +#define GF_H_P00CX GF_H_P00C0|GF_H_P00C1|GF_H_P00C2|GF_H_P00C3|GF_H_P00C4|GF_H_P00C5 + +#define GF_H_P01C0 0x1 +#define GF_H_P01C1 (0x1c << 3 ) +#define GF_H_P01C2 (0x7c << 8 ) +#define GF_H_P01C3 (0x8 << 16) +#define GF_H_P01C4 (0x1e << 24) +#define GF_H_P01C5 (0x1 << 29) +#define GF_H_P01CX GF_H_P01C0|GF_H_P01C1|GF_H_P01C2|GF_H_P01C3|GF_H_P01C4|GF_H_P01C5 + +#define GF_H_P02C0 0x1 +#define GF_H_P02C1 (0x18 << 3 ) +#define GF_H_P02C2 (0x7a << 8 ) +#define GF_H_P02C3 (0x11 << 16) +#define GF_H_P02C4 (0x1b << 24) +#define GF_H_P02C5 (0x1 << 29) +#define GF_H_P02CX GF_H_P02C0|GF_H_P02C1|GF_H_P02C2|GF_H_P02C3|GF_H_P02C4|GF_H_P02C5 + +#define GF_H_P03C0 0x2 +#define GF_H_P03C1 (0x15 << 3 ) +#define GF_H_P03C2 (0x73 << 8 ) +#define GF_H_P03C3 (0x1b << 16) +#define GF_H_P03C4 (0x19 << 24) +#define GF_H_P03C5 (0x2 << 29) +#define GF_H_P03CX GF_H_P03C0|GF_H_P03C1|GF_H_P03C2|GF_H_P03C3|GF_H_P03C4|GF_H_P03C5 + +#define GF_H_P04C0 0x2 +#define GF_H_P04C1 (0x13 << 3 ) +#define GF_H_P04C2 (0x6d << 8 ) +#define GF_H_P04C3 (0x25 << 16) +#define GF_H_P04C4 (0x17 << 24) +#define GF_H_P04C5 (0x2 << 29) +#define GF_H_P04CX GF_H_P04C0|GF_H_P04C1|GF_H_P04C2|GF_H_P04C3|GF_H_P04C4|GF_H_P04C5 + +#define GF_H_P05C0 0x3 +#define GF_H_P05C1 (0x11 << 3 ) +#define GF_H_P05C2 (0x66 << 8 ) +#define GF_H_P05C3 (0x2f << 16) +#define GF_H_P05C4 (0x15 << 24) +#define GF_H_P05C5 (0x2 << 29) +#define GF_H_P05CX GF_H_P05C0|GF_H_P05C1|GF_H_P05C2|GF_H_P05C3|GF_H_P05C4|GF_H_P05C5 + +#define GF_H_P06C0 0x3 +#define GF_H_P06C1 (0x11 << 3 ) +#define GF_H_P06C2 (0x5e << 8 ) +#define GF_H_P06C3 (0x38 << 16) +#define GF_H_P06C4 (0x13 << 24) +#define GF_H_P06C5 (0x3 << 29) +#define GF_H_P06CX GF_H_P06C0|GF_H_P06C1|GF_H_P06C2|GF_H_P06C3|GF_H_P06C4|GF_H_P06C5 + +#define GF_H_P07C0 0x3 +#define GF_H_P07C1 (0x10 << 3 ) +#define GF_H_P07C2 (0x55 << 8 ) +#define GF_H_P07C3 (0x43 << 16) +#define GF_H_P07C4 (0x12 << 24) +#define GF_H_P07C5 (0x3 << 29) +#define GF_H_P07CX GF_H_P07C0|GF_H_P07C1|GF_H_P07C2|GF_H_P07C3|GF_H_P07C4|GF_H_P07C5 + +#define GF_H_P08C0 0x3 +#define GF_H_P08C1 (0x11 << 3 ) +#define GF_H_P08C2 (0x4c << 8 ) +#define GF_H_P08C3 (0x4c << 16) +#define GF_H_P08C4 (0x11 << 24) +#define GF_H_P08C5 (0x3 << 29) +#define GF_H_P08CX GF_H_P08C0|GF_H_P08C1|GF_H_P08C2|GF_H_P08C3|GF_H_P08C4|GF_H_P08C5 + +#define GF_H_P09C0 0x3 +#define GF_H_P09C1 (0x12 << 3 ) +#define GF_H_P09C2 (0x43 << 8 ) +#define GF_H_P09C3 (0x55 << 16) +#define GF_H_P09C4 (0x10 << 24) +#define GF_H_P09C5 (0x3 << 29) +#define GF_H_P09CX GF_H_P09C0|GF_H_P09C1|GF_H_P09C2|GF_H_P09C3|GF_H_P09C4|GF_H_P09C5 + +#define GF_H_P0AC0 0x3 +#define GF_H_P0AC1 (0x13 << 3 ) +#define GF_H_P0AC2 (0x38 << 8 ) +#define GF_H_P0AC3 (0x5e << 16) +#define GF_H_P0AC4 (0x11 << 24) +#define GF_H_P0AC5 (0x3 << 29) +#define GF_H_P0ACX GF_H_P0AC0|GF_H_P0AC1|GF_H_P0AC2|GF_H_P0AC3|GF_H_P0AC4|GF_H_P0AC5 + +#define GF_H_P0BC0 0x2 +#define GF_H_P0BC1 (0x15 << 3 ) +#define GF_H_P0BC2 (0x2f << 8 ) +#define GF_H_P0BC3 (0x66 << 16) +#define GF_H_P0BC4 (0x11 << 24) +#define GF_H_P0BC5 (0x3 << 29) +#define GF_H_P0BCX GF_H_P0BC0|GF_H_P0BC1|GF_H_P0BC2|GF_H_P0BC3|GF_H_P0BC4|GF_H_P0BC5 + +#define GF_H_P0CC0 0x2 +#define GF_H_P0CC1 (0x17 << 3 ) +#define GF_H_P0CC2 (0x25 << 8 ) +#define GF_H_P0CC3 (0x6d << 16) +#define GF_H_P0CC4 (0x13 << 24) +#define GF_H_P0CC5 (0x2 << 29) +#define GF_H_P0CCX GF_H_P0CC0|GF_H_P0CC1|GF_H_P0CC2|GF_H_P0CC3|GF_H_P0CC4|GF_H_P0CC5 + +#define GF_H_P0DC0 0x2 +#define GF_H_P0DC1 (0x19 << 3 ) +#define GF_H_P0DC2 (0x1b << 8 ) +#define GF_H_P0DC3 (0x73 << 16) +#define GF_H_P0DC4 (0x15 << 24) +#define GF_H_P0DC5 (0x2 << 29) +#define GF_H_P0DCX GF_H_P0DC0|GF_H_P0DC1|GF_H_P0DC2|GF_H_P0DC3|GF_H_P0DC4|GF_H_P0DC5 + +#define GF_H_P0EC0 0x1 +#define GF_H_P0EC1 (0x1b << 3 ) +#define GF_H_P0EC2 (0x11 << 8 ) +#define GF_H_P0EC3 (0x7a << 16) +#define GF_H_P0EC4 (0x18 << 24) +#define GF_H_P0EC5 (0x1 << 29) +#define GF_H_P0ECX GF_H_P0EC0|GF_H_P0EC1|GF_H_P0EC2|GF_H_P0EC3|GF_H_P0EC4|GF_H_P0EC5 + +#define GF_H_P0FC0 0x1 +#define GF_H_P0FC1 (0x1e << 3 ) +#define GF_H_P0FC2 (0x8 << 8 ) +#define GF_H_P0FC3 (0x7c << 16) +#define GF_H_P0FC4 (0x1c << 24) +#define GF_H_P0FC5 (0x1 << 29) +#define GF_H_P0FCX GF_H_P0FC0|GF_H_P0FC1|GF_H_P0FC2|GF_H_P0FC3|GF_H_P0FC4|GF_H_P0FC5 + +// Vertical Filter Coefficients +#define GF_V_P00C0 0x80 +#define GF_V_P01C0 0x78 +#define GF_V_P02C0 0x70 +#define GF_V_P03C0 0x68 +#define GF_V_P04C0 0x60 +#define GF_V_P05C0 0x58 +#define GF_V_P06C0 0x50 +#define GF_V_P07C0 0x48 +#define GF_V_P08C0 0x40 +#define GF_V_P09C0 0x38 +#define GF_V_P0AC0 0x30 +#define GF_V_P0BC0 0x28 +#define GF_V_P0CC0 0x20 +#define GF_V_P0DC0 0x18 +#define GF_V_P0EC0 0x10 +#define GF_V_P0FC0 0x8 + +/** Hardware Cursor definition */ +typedef struct _HC_COLOR +{ + NvU32 foreground; + NvU32 background; +} HC_COLOR, *PHC_COLOR; + +typedef struct _HC_POSITION +{ + NvU32 x; + NvU32 y; +} HC_POSITION, *PHC_POSITION; + +typedef struct _HC_HOTSPOT +{ + NvU32 x; + NvU32 y; +} HC_HOTSPOT, *PHC_HOTSPOT; + +enum +{ + CD64X64, + CD32X32 +}; + +typedef struct _HC_MASK +{ + NvU32 *data; + NvU32 size; + NvU32 dimension; +} HC_MASK, *PHC_MASK; + +typedef struct _DisplayTimingEntry +{ + /** Horizontal Ref. Need not to be changed, set 0 for default setting */ + NvU16 usHRef; + /** Vertical Ref. Need not to be changed, set 0 for default setting */ + NvU16 usVRef; + /** Horizontal Sync Width, set 0 for default setting */ + NvU16 usHSyncWidth; + /** Vertical Sync Width, set 0 for default setting */ + NvU16 usVSyncWidth; + /** Horizontal Back Porch, set 0 for default setting */ + NvU16 usHBackPorch; + /** Vertical Back Porch, set 0 for default setting */ + NvU16 usVBackPorch; + /** Horizontal Active, Set same as Window Width */ + NvU16 usHActive; + /** Vertical Active, Set same as Window Height */ + NvU16 usVActive; + /** Horizontal Total, set 0 for default setting */ + NvU16 usHTotal; + /** Vertical Total, set 0 for default setting */ + NvU16 usVTotal; + /** Window Width */ + NvU16 usPanelVX; + /** Window Height */ + NvU16 usPanelVY; + /** Window Start X Position */ + NvU16 usPosX; + /** Window Start Y Position */ + NvU16 usPosY; + /** Window Sel 0-WinA (GFDX_DISPTMG_SEL_WINA), 1-WinB (GFDX_DISPTMG_SEL_WINB) */ + NvU16 SelWin; + NvU16 Reserved1; + NvU16 Reserved2; + NvU16 Reserved3; +} DISPLAYTIMINGENTRY, *PDISPLAYTIMINGENTRY; + +// Display Timing + +#define GFDX_DISPTMG_SEL_WINA 0 +#define GFDX_DISPTMG_SEL_WINB 1 + +/** redefine some of the constants for compatibility */ +#define GFDX_ATTR_WIDTH_HEIGHT GFDX_ATTR_WH_WA +#define GFDX_ATTR_XY_POSITION GFDX_ATTR_XY_POS_WA +#define GFDX_ATTR_BPP GFDX_ATTR_BPP_WA +#define GFDX_ATTR_PIXEL_DOUBLE GFDX_ATTR_PIXEL_DBL_WA +#define GFDX_ATTR_STARTADDR GFDX_ATTR_ADDR_WA_B0 +#define GFDX_ATTR_STRIDE GFDX_ATTR_STRIDE_WA_B0 + +/** definition of GFDX_ATTR_PIXEL_DOUBLE */ +#define GFDXA_PIX_DBL_H 0x01 /* Horizontal pixel doubling on */ +#define GFDXA_PIX_DBL_V 0x02 /* Vertical pixel doubling on */ + +/** definition of GFDX_ATTR_DOUBLE_BUF control (0,2,1,3 is same as hw) */ +#define GFDXA_DB_BUF0 0x00 /* GC display buffer address is from buf0 */ +#define GFDXA_DB_BUF1 0x02 /* GC display buffer address is from buf1 */ +#define GFDXA_DB_HOST 0x06 /* GC display buffer address is from Host */ +#define GFDXA_DB_GE 0x01 /* GC display buffer address is from GE */ +#define GFDXA_DB_VI 0x03 /* GC display buffer address is from VI */ +#define GFDXA_DB_EPP 0x04 +#define GFDXA_DB_MPEGE 0x05 + +/** definition of GFDX_ATTR_ROTATE_BIT_W? */ +#define GFDXA_ROTATE_BITS_0 0x00000000 // no rotation, x+,y+,startAddr = 0 +#define GFDXA_ROTATE_BITS_90 0x00000500 // +90 (anti-clock), x-, y+, start= stride-3 (TL) +#define GFDXA_ROTATE_BITS_180 0x00000300 // +180(anti-clock), x-, y-, start= height*stride-3 (BR) +#define GFDXA_ROTATE_BITS_270 0x00000600 // +270(anti-clock), x+, y-, start= (height-1)*stride (BL) + +/** definition of Color Key and Alpha Blending*/ +#define GFDXA_BLEND_CONTROL_NOKEY_ALPHA_WEIGHT 0x00000001 + +#define GFDXA_BLEND_COLOR_KEY0_ENABLE 0x00000001 +#define GFDXA_BLEND_COLOR_KEY1_ENABLE 0x00000002 +#define GFDXA_BLEND_COLOR_KEY0_DISABLE 0x00000000 +#define GFDXA_BLEND_COLOR_KEY1_DISABLE 0x00000000 +#define GFDXA_BLEND_CONTROL_nWIN_ALPHA_WEIGHT 0x00000004 +#define GFDXA_BLEND_CONTROL_nWIN_DEPENDENT_WEIGHT 0x00000008 + +/** Disable CRC capture. */ +#define GFDXA_CRC_DISABLE 0x00000000 +/** Wait for 1 VSYNC and capture CRC for one frame. */ +#define GFDXA_CRC_WAIT_VSYNC1 0x00000001 +/** Wait for 2 VSYNC and capture CRC for one frame. */ +#define GFDXA_CRC_WAIT_VSYNC2 0x00000003 + +/** Set Direction for Rotation*/ +#define GFDX_ATTR_H_DIRECTION_DECREMENT 0x00000001 +#define GFDX_ATTR_H_DIRECTION_INCREMENT 0x00000000 +#define GFDX_ATTR_V_DIRECTION_DECREMENT 0x00000004 +#define GFDX_ATTR_V_DIRECTION_INCREMENT 0x00000000 + +/** definition of Palette Enable/Disable*/ +#define GFDX_ATTR_PALETTE_ENABLE 0x00010000 +#define GFDX_ATTR_PALETTE_DISABLE 0x00000000 +#define GFDX_ATTR_DV_ENABLE 0x00100000 +#define GFDX_ATTR_DV_DISABLE 0x00000000 + +#define GFDX_ATTR_WENC_DISABLE 0x00000000 +#define GFDX_ATTR_WENC_ENABLE 0x00000001 +#define GFDX_ATTR_WENC_TRIG_DISABLE 0x00000000 +#define GFDX_ATTR_WENC_TRIG_ENABLE 0x00000001 +#define GFDX_ATTR_WENC_TRIG_ONE_SHOT 0x00000002 + +/** Read CRC Check Sum */ +#define GFDXA_CRC_READ_CHECK_SUM 0x00000001 + +/** + Sub-LCD support + */ +#define LCD_MAIN 0 +#define LCD_SUB 1 +#define MAX_LCD 2 + +/** + Start-Stop Frame support + */ +#define GFDX_MAIN_START 0x00000001 +#define GFDX_MAIN_STOP 0x00000002 +#define GFDX_SUB_START 0x00000003 +#define GFDX_SUB_STOP 0x00000004 +#define GFDX_MAIN_ONE_FRAME 0x00000001 +#define GFDX_SUB_ONE_FRAME 0x00000002 + +#define GF_DISPLAY_NORMAL 0x00000000 +#define GF_DISPLAY_PARTIAL 0x00000001 + +#ifdef PROJECT_SEC_G1 +#define GF_DISPLAY_NTSC_V570 0x00000002 +#define GF_DISPLAY_NTSC_V490 0x00000003 +#define GF_DISPLAY_NTSC_V700 0x00000004 +#define GF_DISPLAY_PAL 0x00000005 +#endif + +/** + DxEnableDisplay support + */ +#define GF_PANEL_DRV_ONOFF 0x00000100 +#define GF_PANEL_DRV_SLP_WKUP 0x00000200 + +/** + Clock selections, profile and options + */ +#define GFDX_OSC 0x00000001 +#define GFDX_ROSC 0x00000002 +#define GFDX_PLL1 0x00000003 +#define GFDX_PLL_QUERY 0x80000000 +#define GFDX_POWER 0x00010000 +#define GFDX_PERFORMANCE 0x00020000 + +/** + Option for GFDxVSync: Waits until vertical blank (default). + */ +#define GFDX_VSYNC_WAIT 0x0000 +/** + Option for GFDxVSync: Checks and immediately returns vertical blank status. + Returns GF_SUCCESS if in vertical blank, else returns GF_ERROR. + */ +#define GFDX_VSYNC_CHECK 0x0001 +/** + Option for GFDxVSync: Puts Wait token in the command FIFO and the CPU returns + immediately. Uses FRAME_END interrupt bit. + */ +#define GFDX_VSYNC_HW_WAIT 0x0002 +/** + Option for GFDxVSync: Raise and wait in the command fifo for VBLANK. + */ +#define GFDX_VBLANK_HW_WAIT 0x0003 +/** + Option for GFDxVSync: Raise and wait in the command fifo for VPULSE3. + */ +#define GFDX_VPULSE3_HW_WAIT 0x0004 + +/** Dx Hardware has multiple windows (some registers are replicated per + window - the window must be exlicitly selected to write to the correct + register in the window). Use this enum to select which window + to write to for APIs that support this - window selection is mostly + done through the attribute name, eg: _WA, _WB, etc. + */ +typedef enum _GFDXWINDOWSELECT +{ + DX_WINDOW_SELECT_NONE = 0, + DX_WINDOW_SELECT_NORMAL = 1, /* all windows */ + DX_WINDOW_SELECT_A = 2, + DX_WINDOW_SELECT_B = 4, + DX_WINDOW_SELECT_C = 8 +} GFDXWINDOWSELECT; + +/** Color Space Conversion coefficients. Use GFDxSetCSCCoeff() and + GFDxGetCSCCoeff() to write/read the coefficients to/from hardware. + */ +typedef struct _GFDXCSCCOEFF +{ + NvU32 YOF; + NvU32 KYRGB; + NvU32 KUR; + NvU32 KVR; + NvU32 KUG; + NvU32 KVG; + NvU32 KUB; + NvU32 KVB; +} GFDXCSCCOEF; + +typedef struct _DXSCRIPTCMD +{ + NvU32 ScriptCmdType; /** Script Command */ + NvU32 DataBurstCount; /** Burst count 0-255, not Valid for GFSCMD */ + NvU32 PanelDriverCmd; /** Valid Only if ScriptCmdType = GFPDRV_CMD */ + NvU32 *PanelIndexData; /** Data pointer */ + NvU32 GFData; /** Valid only if ScriptCmdType is GFSCMD */ + NvU32 reserved1; +} DXSCRIPTCMD, *PDXSCRIPTCMD; + +typedef struct _GFLCDTABLE { + /** For usage see GFDxSetDisplay()*/ + GF_RETTYPE (* DxSetDisplay)(GFDxHandle DxHandle, int lcdSel, NvU32 ulStartAddr, + NvU32 ulStride, unsigned bpp); + /** For usage see GFDxEnableDisplay()*/ + GF_RETTYPE (* DxEnableDisplay)(GFDxHandle DxHandle, int lcdSel, unsigned bOn); + /** For usage see GFDxSetAttribute()*/ + GF_RETTYPE (* DxSetAttribute)(GFDxHandle DxHandle, int lcdSel, unsigned aid, NvU32 attr); + /** For usage see GFDxGetAttribute()*/ + GF_RETTYPE (* DxGetAttribute)(GFDxHandle DxHandle, int lcdSel, unsigned aid, NvU32 *attr); + /** For usage see GFDxSetAttributeWithCS()*/ + GF_RETTYPE (* DxSetAttributeWithCS)(GFDxHandle DxHandle, int lcdSel, unsigned aid, NvU32 attr); + /** For usage see GFDxGetAttributeWithCS()*/ + GF_RETTYPE (* DxGetAttributeWithCS)(GFDxHandle DxHandle, int lcdSel, unsigned aid, NvU32 *attr); + /** For usage see GFDxRotate()*/ + GF_RETTYPE (* DxRotate)(GFDxHandle DxHandle, int lcdSel, unsigned nRotate, NvU32 ulStartAddr); + /** For usage see GFDxErase()*/ + GF_RETTYPE (* DxErase)(GFDxHandle DxHandle, int lcdSel, NvU32 ulStartAddr, NvU32 color); + /** For usage see GFDxSwitchLCD()*/ + GF_RETTYPE (* DxSwitchLCD)(GFDxHandle DxHandle, int lcdSel, int Option); + /** LCD Configurations */ + void * pLcdConfig; + /** For usage see GFDxScriptCmd()*/ + GF_RETTYPE (* DxScriptCmd)(GFDxHandle DxHandle, int lcdSel, PDXSCRIPTCMD pDxScriptCmd, NvU32 Option); + /** For usage see GFDxScriptCmdWithCS()*/ + GF_RETTYPE (* DxScriptCmdWithCS)(GFDxHandle DxHandle, int lcdSel, PDXSCRIPTCMD pDxScriptCmd, NvU32 Option); + /** For usage see GFDxDisplayTiming()*/ + GF_RETTYPE (* DxDisplayTiming)(GFDxHandle DxHandle, int lcdSel, PDISPLAYTIMINGENTRY pDxTiming, NvU32 Option); + /** For usage see GFDxDisplayTimingWithCS()*/ + GF_RETTYPE (* DxDisplayTimingWithCS)(GFDxHandle DxHandle, int lcdSel, PDISPLAYTIMINGENTRY pDxTiming, NvU32 Option); + /** For usage see GFDxSetDisplayEx()*/ + GF_RETTYPE (* DxSetDisplayEx)(GFDxHandle DxHandle, int lcdSel, NvU32 ulStartAddr, + NvU32 ulStride, unsigned bpp, unsigned bOn); +} GFLCDTABLE; + +/* Publicly exposed DX API function table */ +typedef struct _GFDXTABLE +{ + /** For usage see GFDxGetProperty()*/ + GF_RETTYPE (* DxGetProperty)(GFDxHandle DxHandle, PGFDXPROPERTY pDxProp); + /** For usage see GFDxVSync()*/ + GF_RETTYPE (* DxVSync)(GFDxHandle DxHandle, NvU16 option); + /** For usage see GFDxSetDisplayWithCS()*/ + GF_RETTYPE (* DxSetDisplayWithCS)(GFDxHandle DxHandle, int lcdSel, + NvU32 ulStartAddr, NvU32 ulStride, unsigned bpp); + /** For usage see GFDxEnableDisplayWithCS()*/ + GF_RETTYPE (* DxEnableDisplayWithCS)(GFDxHandle DxHandle, int lcdSel, + unsigned bOn); +// Removed to make the WinCE dll binary compatible with SC4 dll. +// GF_RETTYPE (* DxHSync)(GFDxHandle DxHandle, NvU16 option); + + /** For per LCD functions. ()*/ + GFLCDTABLE Lcd[MAX_LCD]; + /** For usage see GFDxEraseWithCS()*/ + GF_RETTYPE (* DxEraseWithCS)(GFDxHandle DxHandle, int lcdSel, + NvU32 ulStartAddr, NvU32 color); + /** For usage see GFDxSetCSCCoeff()*/ + GF_RETTYPE (* DxSetCSCCoeff)( GFDxHandle DxHandle, GFDXWINDOWSELECT window, + GFDXCSCCOEF *coef ); + /** For usage see GFDxGetCSCCoeff()*/ + GF_RETTYPE (* DxGetCSCCoeff)( GFDxHandle DxHandle, GFDXWINDOWSELECT window, + GFDXCSCCOEF *coef ); + /** For usage see GFDxVSyncWithCS()*/ + GF_RETTYPE (* DxVSyncWithCS)(GFDxHandle DxHandle, NvU16 option); + /** For usage see GFDxSetCSCCoeffWithCS()*/ + GF_RETTYPE (* DxSetCSCCoeffWithCS)( GFDxHandle DxHandle, GFDXWINDOWSELECT window, + GFDXCSCCOEF *coef ); + /** For usage see GFDxGetCSCCoeffWithCS()*/ + GF_RETTYPE (* DxGetCSCCoeffWithCS)( GFDxHandle DxHandle, GFDXWINDOWSELECT window, + GFDXCSCCOEF *coef ); + /** For usage see GFDxSetDisplayExWithCS()*/ + GF_RETTYPE (* DxSetDisplayExWithCS)(GFDxHandle DxHandle, int lcdSel, + NvU32 ulStartAddr, NvU32 ulStride, unsigned bpp, unsigned bOn); +} GFDXTABLE, *PGFDXTABLE; + +/** Filter coefficients */ +typedef struct GFDxHorizontalFilter_t +{ + NvU32 filter[16]; +} GFDxHorizontalFilter; + +typedef struct GFDxVerticalFilter_t +{ + NvU32 filter[16]; +} GFDxVerticalFilter; + +/** + Typesafe function for opening Dx component. + This function is implicitly called by the resource manager (GFRm) in response + to an application’s call to GFRmComponentGet() for the GFDxAPI + component. It is not supposed to be called by an application. It is included + here only for the purpose of GFDxAPI source code customization. + + @param hrm (GFRmHandle) Handle to Rm component. + @param phDx (GFDxHandle *) Handle to Dx component. + @param state (GF_STATE_TYPE) + @param hCh (GFRmChHandle) Handle to Channel. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +GF_RETTYPE GFDxOpen(GFRmHandle hRm, GFDxHandle *phDx, + GF_STATE_TYPE state, GFRmChHandle hCh); + +/** + Typesafe function for closing Dx component. + This function is implicitly called by the resource manager (GFRm) in response + to an application’s call to GFRmComponentGet() for the GFDxAPI + component. It is included here only for the purpose of GFDxAPI source code + customization. + + @param phDx (GFDxHandle *) Handle to Dx component. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + * +*/ +void GFDxClose(GFDxHandle *phDx); + +/** + This funtion returns the fixed properties of the display hardware. + + @param DxHandle (GFDxHandle) Handle to Dx Component + @param pDxProp (PGFDXPROPERTY) See #GFDXPROPERTY + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxGetProperty( handle, pDxProp ) \ + ((PGFDXTABLE)handle)->DxGetProperty( handle, pDxProp ) + +/** + This functions waits for a vertical sync and returns to the caller. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param option (NvU16) Search for Option for GFDxVSync for more info. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxVSync(handle, option) \ + ((PGFDXTABLE)handle)->DxVSync( handle, option ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxVSync(). + */ +#define GFDxVSyncWithCS(handle, option) \ + ((PGFDXTABLE)handle)->DxVSyncWithCS( handle, option ) + +/** + IMPORTANT NOTE: This function is not available. + */ +#define GFDxHSync(handle, option) \ + ((PGFDXTABLE)handle)->DxHSync( handle, option ) + +/** + This function initializes the main LCD or sub-LCD display. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param Handle (DxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param ulStartAddr (NvU32) display start address for main or sub-LCD (should be set to 0). + GFDxSetAttribute() should be called to set the display start + address for the main LCD or sub-LCD. + @param ulStride (NvU32) Default stride if 0; otherwise use the passed value. + GFDxSetAttribute() should be called to set the display stride + for the main LCD or sub-LCD. + @param bpp (unsigned) Default should be 16 bits/pixel for main LCD or sub-LCD. + GFDxSetAttribute() should be called to set the display bpp for + the main LCD or sub-LCD. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSetDisplay( handle, lcdSel, ulStartAddr, ulStride, bpp ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSetDisplay( handle, lcdSel, ulStartAddr, ulStride, bpp ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxSetDisplay(). + */ +#define GFDxSetDisplayWithCS( handle, lcdSel, ulStartAddr, ulStride, bpp ) \ + ((PGFDXTABLE)handle)->DxSetDisplayWithCS( handle, lcdSel, ulStartAddr, \ + ulStride, bpp ) + +/** + This function initializes the main LCD or sub-LCD display. + IMPORTANT NOTE: This function extends GFDxSetDisplay() function by adding an option to enable/disable + the LCD display. + + @param Handle (DxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param ulStartAddr (NvU32) display start address for main or sub-LCD (should be set to 0). + GFDxSetAttribute() should be called to set the display start + address for the main LCD or sub-LCD. + @param ulStride (NvU32) Default stride if 0; otherwise use the passed value. + GFDxSetAttribute() should be called to set the display stride + for the main LCD or sub-LCD. + @param bpp (unsigned) Default should be 16 bits/pixel for main LCD or sub-LCD. + GFDxSetAttribute() should be called to set the display bpp for + the main LCD or sub-LCD. + @param bOn (unsigned) 1 to Enable Display, + 0 to disable Display. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSetDisplayEx( handle, lcdSel, ulStartAddr, ulStride, bpp, bOn ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSetDisplayEx( handle, lcdSel, ulStartAddr, ulStride, bpp, bOn ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxSetDisplayEx(). + */ +#define GFDxSetDisplayExWithCS( handle, lcdSel, ulStartAddr, ulStride, bpp, bOn ) \ + ((PGFDXTABLE)handle)->DxSetDisplayExWithCS( handle, lcdSel, ulStartAddr, \ + ulStride, bpp, On) + +/** + This function enables/disables LCD display with proper power sequencing. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param Handle (DxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param bOn (unsigned) Bit0: 1 to Enable Display, + 0 to disable Display. + Also Option for Panel Driver On/Off + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxEnableDisplay( handle, lcdSel, bOn ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxEnableDisplay( handle, lcdSel, bOn ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxEnableDisplay(). + */ +#define GFDxEnableDisplayWithCS( handle, lcdSel, bOn ) \ + ((PGFDXTABLE)handle)->DxEnableDisplayWithCS( handle, lcdSel, bOn ) + +/** + GFDxSetAttribute() sets the display attributes for a main panel or + subpanel. All the GFDxAPI attributes should be set after the + GFDxSetDisplay() + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param aid (unsigned) Attribute IDs. See #GFDXATTRIBUTES Enumeration Type + @param attr (NvU32) Attribute value for main LCD or sub-LCD. Should be + written with attribute ID in aid. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSetAttribute( handle, lcdSel, aid, attr) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSetAttribute( handle, lcdSel, aid, attr ) + +/** + Execute script command from DxApiTable. Send cmd/data to panel. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param ScriptCmdType (PDXSCRIPTCMD) Script Command + @param Option (NvU32) Reserved, not used. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxScriptCmd( handle, lcdSel, pDxScriptCmd, Option) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxScriptCmd( handle, lcdSel, pDxScriptCmd, Option ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxScriptCmd(). + */ +#define GFDxScriptCmdWithCS( handle, lcdSel, pDxScriptCmd, Option) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxScriptCmdWithCS( handle, lcdSel, pDxScriptCmd, Option ) + +/** Sets the timing registers. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param pDxTiming (PDISPLAYTIMINGENTRY) See #PDISPLAYTIMINGENTRY. + @param Option (NvU32) GF_DISPLAY_PARTIAL or GF_DISPLAY_NORMAL. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxDisplayTiming( handle, lcdSel, pDxTiming, Option) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxDisplayTiming( handle, lcdSel, pDxTiming, Option ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxDisplayTiming(). + */ +#define GFDxDisplayTimingWithCS( handle, lcdSel, pDxTiming, Option) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxDisplayTimingWithCS( handle, lcdSel, pDxTiming, Option ) + +/** + This function returns the bit depth, the destination stride, the start address, + the associated surface of the display buffer, or the graphics command + execution control. The location of the returned attribute value is pointed to by + attr. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param aid (unsigned) Attribute ID. see #GFDXATTRIBUTES. + @param attr (NvU32 *) pointer to attribute value. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxGetAttribute( handle, lcdSel, aid, pAttr) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxGetAttribute( handle, lcdSel, aid, pAttr ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxSetAttribute(). + */ +#define GFDxSetAttributeWithCS( handle, lcdSel, aid, attr) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSetAttributeWithCS( handle, lcdSel, aid, attr ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxGetAttribute(). + */ +#define GFDxGetAttributeWithCS( handle, lcdSel, aid, pAttr) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxGetAttributeWithCS( handle, lcdSel, aid, pAttr ) + +/** + IMPORTANT NOTE: this function is not available. + */ +#define GFDxRotate( handle, lcdSel, nRotate, ulStartAddr ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxRotate( handle, lcdSel, nRotate, ulStartAddr ) + +/** + This function clears the main or subdisplay screen with the given color. It also + clears the display buffer of the main or subpanel window. Window A buffer 0 + is used as a display buffer. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param ulStartAddr (NvU32) Start Address. (The offset in bytes of the + display frame buffer.) + @param color (NvU32) Clear screen with this color. The 32-bit value + has a 16-bit color duplicated in the upper and + lower parts. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxErase( handle, lcdSel, ulStartAddr, color ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxErase( handle, lcdSel, ulStartAddr, color ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxErase(). + */ +#define GFDxEraseWithCS( handle, lcdSel, ulStartAddr, color ) \ + ((PGFDXTABLE)handle)->DxEraseWithCS( handle, lcdSel, ulStartAddr, color ) + +/** + This function enables swithcing between the main LCD and sub-LCD. + IMPORTANT NOTE: This function has critical sections and is thread-safe. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param lcdSel (int) 0 for LCD_MAIN. + 1 for LCD_SUB. + @param Option (NvU32) 0 for switch (Must be set to 0) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSwitchLCD( handle, lcdSel, Option ) \ + ((PGFDXTABLE)handle)->Lcd[lcdSel].DxSwitchLCD( handle, lcdSel, Option ) + +/** + This function sets the hardware Color Space Conversion (CSC) Coefficients. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param window (GFDXWINDOWSELECT) Controller window. see #GFDXWINDOWSELECT. + @param coef (GFDXCSCCOEF *) CSC coefficients. see #GFDXCSCCOEF. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxSetCSCCoeff( handle, window, coef ) \ + ((PGFDXTABLE)handle)->DxSetCSCCoeff( handle, window, coef ) + +/** + This function gets the hardware Color Space Conversion (CSC) Coefficients. + IMPORTANT NOTE: This function is now identical to the WithCS version + of it (i.e. it has Critical Sections and is multi-thread safe) as the + WithCS version is being phased out. + + @param DxHandle (GFDxHandle) Handle to Dx Component. + @param window (GFDXWINDOWSELECT) Controller window. see #GFDXWINDOWSELECT. + @param coef (GFDXCSCCOEF *) CSC coefficients. see #GFDXCSCCOEF. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + */ +#define GFDxGetCSCCoeff( handle, window, coef ) \ + ((PGFDXTABLE)handle)->DxGetCSCCoeff( handle, window, coef ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxSetCSCCoeff(). + */ +#define GFDxSetCSCCoeffWithCS( handle, window, coef ) \ + ((PGFDXTABLE)handle)->DxSetCSCCoeffWithCS( handle, window, coef ) + +/** + IMPORTANT NOTE: This function is being phased out. The critical + section functionality now exists in GFDxGetCSCCoeff(). + */ +#define GFDxGetCSCCoeffWithCS( handle, window, coef ) \ + ((PGFDXTABLE)handle)->DxGetCSCCoeffWithCS( handle, window, coef ) +/*@}*/ + +/** GFDxSetDefaultPanelMode - sets the default mode for multi-mode panels. + + @param handle A handle to a Dx instance + @param mode The panel mode + + Some panels support multiple modes. To support mode switching, the + default panel mode must be known. + */ +GF_RETTYPE +GFDxSetDefaultPanelMode( GFDxHandle handle, NvU32 mode ); + +/** GFDxSwitchPanelMode - switch from the current mode to a new mode. + + @param handle A handle to a Dx instance + @param mode The panel mode + + This switches from the current mode to a new mode. This calls a display + script with the name "SwitchMode__to_" where x is the current mode + and y is the new mode. + */ +GF_RETTYPE +GFDxSwitchPanelMode( GFDxHandle handle, NvU32 mode ); + +/** GFDxSPIRegEnable - enable register reads and writes over SPI. + + @param handle A handle to a Dx instance + @param enable Either enable or disable register read/writes. + + Enabling SPI register reads/writes may change the pin mapping which + may prevent the rest of the display api from behaving properly (pixel + data may no longer output to the panel). Disabling will restore + the pin mapping. + */ +void +GFDxSpiRegEnable( GFDxHandle handle, NvBool enable ); + +/** GFDxSPIRegWrite - write a 16 bit register over SPI. + + @param handle A handle to a Dx instance + @param address The address to write + @param data The data to write + */ +GF_RETTYPE +GFDxSpiRegWrite( GFDxHandle handle, NvU16 address, NvU16 data ); + +/** GFDxSPIRegRead - read a 16 bit register over SPI. + + @param handle A handle to a Dx instance + @param address The address to read from + @param data The data to read (out param) + */ +GF_RETTYPE +GFDxSpiRegRead( GFDxHandle handle, NvU16 address, NvU16 *data ); + +/** GFDxSpiPixelInit - send init sequence to the panel and setup the pixel + write hardware. + + @param handle A handle to a Dx instance + @param seq_data_a The first 32 bits of init data + @param seq_data_b The second 32 bits of init data + @param seq_data_c The third 32 bits of init data + @param seq_data_d The fourth 32 bits of init data + + Note that this only support SPI16 mode, msb2lsb data ordering. + + Some panels may need the init sequence before every frame, in which + case, this should always be called before GFDxSpiPixelWrite(). + */ +GF_RETTYPE +GFDxSpiPixelInit( GFDxHandle handle, NvU32 seq_data_a, + NvU32 seq_data_b, NvU32 seq_data_c, NvU32 seq_data_d ); + +/** GFDxSpiPixelWrite - writes the given pixel to the panel over SPI. + + @param handle A handle to a Dx instance + @param pixel The pixels to write + */ +GF_RETTYPE +GFDxSpiPixelWrite( GFDxHandle handle, NvUPtr pixels ); + +/** GFDxSpiScript - send commands to the spi hardware via an in-memory script. + + @param handle A handle to a Dx instance + @param script The script to execute + */ +GF_RETTYPE +GFDxSpiScript( GFDxHandle handle, NvU32 *script ); + +/** GFDxSetPixelClock - sets the pixel clock divider in half step increments. + + @param handle A handle to the Dx instance + @param divider The pixel clock divider (actually shift clock - pixel clock + will be the same as shift clock) + + Note: the divider is in half step increments: 1 = 1, 2 = 1.5, 3 = 2, etc. + */ +GF_RETTYPE +GFDxSetPixelClock( GFDxHandle handle, NvU32 divider ); + +/** GFDxGetPixelClock - gets the current shift clock divider value. + + @param handle A handle to the Dx instance + @param divider The pixel clock divider (actually shift clock - pixel clock + will be the same as shift clock) + + */ +GF_RETTYPE +GFDxGetPixelClock( GFDxHandle handle, NvU32 *divider ); + +/** GFDxSetFilter - sets the window filtering coefficients. + + @param handle A handle to the Dx instance + @param window The target window for the new coefficients + @param hfilter The horizontal filtering coefficients + @param vfilter The vertical filtering coefficients + + Window A does NOT support filtering. + Window C only supports horizontal filtering (the vfilter param must be + null) + Window B supports both h and v filtering + + Passing null to both h and v filter will disabling filtering. + + DX_WINDOW_SELECT_NONE and DX_WINDOW_SELECT_NORMAL should not be used. + */ +GF_RETTYPE +GFDxSetFilter( GFDxHandle handle, GFDXWINDOWSELECT window, + GFDxHorizontalFilter *hfilter, GFDxVerticalFilter *vfilter ); + +#ifdef PROJECT_SEC_G1 +/** GFDxSetFilter - sets the clock and timing to support focus TV encoder. + + @param handle A handle to the Dx instance + @param option The Normal/NTSC/PAL mode to set + */ +GF_RETTYPE +GFDxSetMode( GFDxHandle handle, NvU32 option ); +#endif + +#ifdef __cplusplus +} +#endif + +/** @page pageDxAppNotes DxAPI Application Notes + + @section pageDxAppNotes1 Todo + +*/ + +#endif /* GF_DX_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFEPP.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFEPP.h new file mode 100755 index 00000000..36d28219 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFEPP.h @@ -0,0 +1,89 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFEPP.h + GFSDK EPP API +*/ + +#ifndef __GFEPP_H__ +#define __GFEPP_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupEPP EPPAPI EPP API +*/ +/*@{*/ + +typedef struct _GFEPPBUFFERINFO +{ + NvU32 flag; + PGFRECT pSrcRect; + void *pLine; + NvU32 alphaValue; + NvU32 numofSurfs; + PGFRMSURFACE *ppSurf; +} GFEPPBUFFERINFO, *PEPPBUFFERINFO; + + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFEPPOpen(GFRmHandle hRm, GFEPPHandle *phEPP, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFEPPClose(GFEPPHandle *phEPP); + +GF_RETTYPE GFEPPSetBuffers(GFEPPHandle EPPHandle, PEPPBUFFERINFO pBuf); +GF_RETTYPE GFEPPRaiseBuffer(GFEPPHandle EPPHandle, NvU32, NvU32* pCmdS, NvU32* pIndex); +GF_RETTYPE GFEPPRaiseFrame(GFEPPHandle EPPHandle, NvU32, NvU32* pCmdS, NvU32* pIndex); + + +#define EPPBUFFERINFO_FLAG_SRC_VI 0x00000001 + //incoming video from VI +#define EPPBUFFERINFO_FLAG_SRC_SB 0x00000002 + //incoming video from SB +#define EPPBUFFERINFO_FLAG_SRC_GC 0x00000003 + //incoming video from display +#define EPPBUFFERINFO_FLAG_SRC_MASK 0x0000000F + +#define EPPBUFFERINFO_FLAG_SRC_VI_YUV444 0x00000010 + //incoming video from VI +#define EPPBUFFERINFO_FLAG_SRC_VI_BAYER 0x00000020 + //incoming video from VI, Raw Bayer data +#define EPPBUFFERINFO_FLAG_SRC_VI_RGB 0x00000030 + //incoming video from VI, Raw RGB data +#define EPPBUFFERINFO_FLAG_SRC_VI_MASK 0x000000F0 + +#define EPPBUFFERINFO_FLAG_PRE_PROC 0x00000100 + //pre process filter enable +#define EPPBUFFERINFO_FLAG_AVERAGE 0x00000200 + //enable average for 420 planar or 444 to 422 conversion. +#define EPPBUFFERINFO_FLAG_C_SIGN 0x00000400 + //chroma sign +#define EPPBUFFERINFO_FLAG_DMA 0x00000800 + //enable DMA +#define EPPBUFFERINFO_FLAG_DUP 0x00001000 + //duplicate +#define EPPBUFFERINFO_FLAG_H_DIRECTION 0x00002000 +#define EPPBUFFERINFO_FLAG_V_DIRECTION 0x00004000 +#define EPPBUFFERINFO_FLAG_XY_SWAP 0x00008000 + +#define EPPBUFFERINFO_FLAG_SRC_SB_YUV 0x00010000 +#define EPPBUFFERINFO_FLAG_SRC_SB_RGB 0x00020000 +#define EPPBUFFERINFO_FLAG_SRC_SB_MASK 0x000F0000 + + //BE CAREFUL WITH THE STRIDE PROGRAMMING! + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif // _GFEPP_H_ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFFDev.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFFDev.h new file mode 100755 index 00000000..6826085b --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFFDev.h @@ -0,0 +1,321 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFFDev.h + GFSDK File Device API header file. +*/ + +#ifndef __GFFDEV_H__ +#define __GFFDEV_H__ + +#include "nvtypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupFDev FDevAPI File Device API +
        +
      • @ref pageFDevAppNotes +
          +
        • @ref pageFDevAppNotes1 +
        +
      +*/ +/*@{*/ + +/** FDev capability flag. + @see GFFDevMount() + */ +#define GFFDEV_CAP_STANDARD 0x00010000 /**< Standard C Library */ + +/** FDev capability flag. + @see GFFDevMount() + */ +#define GFFDEV_CAP_DEVICE_SD 0x00000001 /**< SD Device Supported */ + +/** FDev capability flag. + @see GFFDevMount() + */ +#define GFFDEV_CAP_FAT 0x00020000 /**< Fat FileSystem */ + +/** FDev capability flag. + @see GFFDevMount() + */ +#define GFFDEV_CAP_DEVICE_MASK 0x00000FFF + +/** FDev capability flag - default on the selected OS. + Linux, Windows -> Standard, else -> SD + @see GFFDevMount() + */ +#if !NVOS_IS_WINDOWS && !NVOS_IS_LINUX +#define GFFDEV_CAP_DEFAULT_FOR_OS GFFDEV_CAP_DEVICE_SD +#else +#define GFFDEV_CAP_DEFAULT_FOR_OS GFFDEV_CAP_STANDARD +#endif + +/** Parameter enum for GFFDevSeekFile. + @see GFFDevSeekFile + */ +typedef enum +{ + GFFDEV_SEEK_SET = 0, /**< Set fileHandle relative to beginning of file */ + GFFDEV_SEEK_CUR, /**< Set fileHandle relative to specified offset location */ + GFFDEV_SEEK_END /**< Set fileHandle relative to end of file */ +} GFFDEVSEEKTYPE; + +/** Public File Info structure. + Matches Microsoft's struct _finddata_t . + + @see FDevFindFirstFile() + @see FDevFindNextFile() + */ +typedef struct _GFFDEVFILEINFO +{ + unsigned attrib; + NvU32 time_create; /**< -1 for FAT file systems */ + NvU32 time_access; /**< -1 for FAT file systems */ + NvU32 time_write; + NvU32 size; + char name[260]; +} GFFDEVFILEINFO, *PGFFDEVFILEINFO; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFFDevOpen(GFRmHandle hRm, GFFDevHandle *phFDev, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFFDevClose(GFFDevHandle *phFDev); + +/** @name Functions +@{*/ + +/** Mounts a filesystem. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param capType (NvU32) capability type + + The filesystem pointed to by #FDevHandle will be mounted based on + the #capType. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevMount(GFFDevHandle FDevHandle, NvU32 capType); + +/** Unmounts a mounted filesystem. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error +*/ +GF_RETTYPE GFFDevUnmount(GFFDevHandle FDevHandle); + +/** Opens a file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (const char *) name of the file + @param fileSpec (const char *) read/write/etc flags + @param pFileHandle (#GFFDevFileHandle) Pointer to the handle of the opened file - + will be filled in by #GFFDevOpenFile() + + Opens a file on the mounted filesystem with #fileName. Open flags, + given by #fileSpec, are the same as libc's fopen. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevOpenFile(GFFDevHandle FDevhandle, + const char *fileName, + const char *fileSpec, + GFFDevFileHandle *pFileHandle); + +/** Closes an open file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param pFileHandle (#GFFDevFileHandle *) Pointer to the open file + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevCloseFile(GFFDevHandle FDevhandle, + GFFDevFileHandle *pFileHandle); + +/** Reads data from a file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileHandle (#GFFDevFileHandle) Handle to the open file + @param pReadBuf (void *) Buffer for file bytes + @param pCount (NvU32 *) Pointer to number of bytes to read, will be + written to the actual number of bytes read. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevReadFile(GFFDevHandle FDevhandle, + GFFDevFileHandle fileHandle, + void * pReadBuf, + NvU32 *pCount); + +/** Writes data to an open file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileHandle (#GFFDevFileHandle) Handle to open file + @param pWriteBuf (void *) pointer to bytes to write to the file + @param pCount (NvU32 *) pointer to number of bytes to write, will + be written to actual number of bytes written. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevWriteFile(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle, + void * pWriteBuf, + NvU32 *pCount ); + +/** Sets the file read/write position. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileHandle (#GFFDevFileHandle) Handle to open file + @param offset (NvS32) offset to be used with #where + @param where (#GFFDEVSEEKTYPE) file offset base + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevSeekFile(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle, + NvS32 offset, + GFFDEVSEEKTYPE where); + +/** Gets the current file position. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileHandle (#GFFDevFileHandle) Handle to open file + @param pOffset (NvU32 *) pointer to offset, will be filled in + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevTellFile(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle, + NvU32 *pOffset); + +/** Gets the file size. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (#GFFDevFileHandle) Handle of open file + @param pSize (NvU32 *) pointer to file size, will be filled in. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevGetFileSize(GFFDevHandle FDevHandle, + const char *fileName, + NvU32 *pSize); + +/** Renames a file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param oldFileName (const char *) name of existing file + @param newFileName (const char *) name to which to rename the file + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevRenameFile(GFFDevHandle FDevHandle, + const char *oldFileName, + const char *newFileName); + +/** Removes a file from the filesystem + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (#GFFDevFileHandle) Handle of open file + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevDeleteFile(GFFDevHandle FDevHandle, + const char *fileName); + +/** Gets the first file in a directory. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param dirName (const char *) Name of the directory to enumerate + @param pFileInfo (#GFFDEVFILEINFO *) pointer to the file info for the + first file + @param pDirHandle (#GFFDevDirHandle *) pointer to the handle to the directory + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevFindFirstFile(GFFDevHandle FDevHandle, + const char *dirName, + GFFDEVFILEINFO *pFileInfo, + GFFDevDirHandle *pDirHandle); + +/** Gets the next file in the directory. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param pFileInfo (#GFFDEVFILEINFO *) pointer ot the info for the next file + @param pDirHandle (#GFFDevDirHandle *) pointer to the directory handle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevFindNextFile(GFFDevHandle FDevHandle, + GFFDEVFILEINFO *pFileInfo, + GFFDevDirHandle *pDirHandle); + +/** Closes the directory. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param pDirHandle (#GFFDevDirHandle *) pointer to the directory handle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevFindCloseFile(GFFDevHandle FDevHandle, + GFFDevDirHandle *pdirHandle); + +/** Flushes all buffered data to the file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (#GFFDevFileHandle) Handle of open file + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevFlushFile(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle); + +/** Gets the filesystem blocks for the file. + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param fileName (#GFFDevFileHandle) Handle of open file + @param size (NvU32) size of the file + @param ppBlockList (#PGFBLOCKLIST *) block list to be allocated + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevBlockListAlloc(GFFDevHandle FDevHandle, + GFFDevFileHandle fileHandle, + NvU32 size, + PGFBLOCKLIST *ppBlockList ); + +/** Gets the FDev API properties + @param FDevHandle (#GFFDevHandle) Handle to FDev API + @param pBlockList (#PGFBLOCKLIST) Block list to deallocate + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Error + */ +GF_RETTYPE GFFDevBlockListFree(GFFDevHandle FDevHandle, + PGFBLOCKLIST pBlockList ); + +/*@}*/ +/*@}*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/** @page pageFDevAppNotes FDevAPI Application Notes + + @section pageFDevAppNotes1 Todo + +*/ + +#endif /* __GFFDEV_H__ */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFGx.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFGx.h new file mode 100755 index 00000000..5a974df4 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFGx.h @@ -0,0 +1,1927 @@ +/* + * Copyright (c) 2005 - 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software and related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ +/** @file GFGx.h + GFSDK Graphics API header file. +*/ + +#ifndef __GFGx_H__ +#define __GFGx_H__ + +#include "GFRm.h" + +/* GFGxAPI error codes */ +#include "GFGxError.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +/** @addtogroup groupGx GxAPI Graphics API +*/ + /*
        +
      • @ref pageGxAppNotes +
          +
        • @ref pageGxAppNotes1 +
        +
      + */ + +/*@{*/ + +/**** GX CAPABILITIES DEFINITIONS ****/ + +/** GFGxAPI capability definition : bitblt support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_BLT 0x00000001UL // BitBlt +/** GFGxAPI capability definition : linedraw support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_LINE 0x00000002UL // Line draw +/** GFGxAPI capability definition : clipping support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_CLIP 0x00000004UL // Clipping +/** GFGxAPI capability definition : stretchblt support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_STRETCHBLT 0x00000008UL // StretchBlt +/** GFGxAPI capability definition : alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHABLENDING 0x00000010UL // Alpha blending +/** GFGxAPI capability definition : alphablending and transparency support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_COLOR_CMP 0x00000020UL // Alpha blending + +/* NEW CAPABILITY FLAGS */ + +/** GFGxAPI capability definition : fast rotation support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_FAST_ROTATION 0x00000040UL // Fast Rotation + +/** GFGxAPI capability definition : inside clipping support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_CLIPPING_INSIDE 0x00000100UL // Inside Clipping +/** GFGxAPI capability definition : fadeblt support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_FADE_BLT 0x00000200UL // Fade Blt + +/** GFGxAPI capability definition : color pattern support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_COLOR_PATTERN 0x00001000UL // Color Pattern +/** GFGxAPI capability definition : color pattern transparency support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_CLR_PAT_TRANSPARENT 0x00002000UL // Color Pattern Transparency +/** GFGxAPI capability definition : alphablending and fading support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_AND_FADING 0x00004000UL // ALpha Blending & fading +/** GFGxAPI capability definition : 1BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_1BPP 0x00008000UL // Planar 1 BPP Alpha +/** GFGxAPI capability definition : 2BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_2BPP 0x00010000UL // Planar 2 BPP Alpha +/** GFGxAPI capability definition : 4BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_4BPP 0x00020000UL // Planar 4 BPP Alpha +/** GFGxAPI capability definition : 8BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_8BPP 0x00040000UL // Planar 8 BPP Alpha +/** GFGxAPI capability definition : SRC4DST4BPP alpha plane support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_SRC4DST4 0x00080000UL // Planar 44 BPP Alpha + // 8 bpp plane, src * 4 + dst*4 +/** GFGxAPI capability definition : 32BPP to 16BPP alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_PLANAR_32BLEND16 0x00200000UL // 32 bits source blending +/** GFGxAPI capability definition : src 1555 alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_SRC1555 0x00400000UL // Src alpha 1555 +/** GFGxAPI capability definition : src 4444 alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_SRC4444 0x00800000UL // Src alpha 4444 +/** GFGxAPI capability definition : src fixed alphablending support. + @see GFGxGetProperty() +*/ +#define GFGX_CAP_ALPHA_FIXED 0x01000000UL // Fixed alpha + +/**** CLIPPING FLAGS ****/ + +/* disable clipping */ +/** GFGxAPI CLIPPING flags : disable clipping. + @see GFGxSetClip() +*/ +#define GFGX_SETCLIP_DISABLE 0x00000000UL + +/* enable clipping */ +/** GFGxAPI CLIPPING flags : enable clipping. + @see GFGxSetClip() +*/ +#define GFGX_SETCLIP_ENABLE 0x00000001UL + +/* set clipping rectangle */ +/** GFGxAPI CLIPPING flags : set clipping rectangle. + @see GFGxSetClip() +*/ +#define GFGX_SETCLIP_SETRECT 0x00000002UL + +/* set inside clipping - default is outside clipping*/ +/** GFGxAPI CLIPPING flags : set inside clipping, default is outside. + @see GFGxSetClip() +*/ +#define GFGX_SETCLIP_INSIDE 0x00000004UL + + +/**** LINE DRAW FLAGS ****/ + +/* don't draw last pixel */ +/** GFGxAPI LINE DRAW flags : do not draw last pixel. + @see GFGxLine() +*/ +#define GFGX_LINE_NOT_DRAW_LAST_PIXEL 0x00000001UL + +/**** BITBLT - SOURCE FLAGS ****/ + +/* source is screen */ +/** GFGxAPI BITBLT Source flags : source comes from video mem. + @see GFGxBlt() +*/ +#define GFGX_BLT_SRC_VIDEO 0x00000000UL + +/* color source in system memory */ +/** GFGxAPI BITBLT Source flags : colour source comes from system mem. + @see GFGxBlt() +*/ +#define GFGX_BLT_SRC_SYSMEM_COLOR 0x00000001UL + +/* mono source in system memory */ +/** GFGxAPI BITBLT Source flags : mono source comes from system mem. + @see GFGxBlt() +*/ +#define GFGX_BLT_SRC_SYSMEM_MONO 0x00000002UL + +/* source is solid color */ +/** GFGxAPI BITBLT Source flags : source is solid (unique color). + @see GFGxBlt() +*/ +#define GFGX_BLT_SRC_SOLID 0x00000004UL + + +/**** BITBLT - PATTERN FLAGS ****/ + +/* pattern is mono */ +/** GFGxAPI BITBLT Pattern flags : pattern is mono. + @see GFGxBlt() +*/ +#define GFGX_BLT_PAT_MONO 0x00000008UL + +/* pattern is color */ +/** GFGxAPI BITBLT Pattern flags : pattern is color. + @see GFGxBlt() +*/ +#define GFGX_BLT_PAT_COLOR 0x00000010UL + +/* pattern is solid color */ +/** GFGxAPI BITBLT Pattern flags : pattern is solid (unique color). + @see GFGxBlt() +*/ +#define GFGX_BLT_PAT_SOLID 0x00000020UL + +/* pattern is cached */ +/** GFGxAPI BITBLT Pattern flags : pattern is cached in video mem. + The pattern ID for the cached pattern is returned in the pPatID + field in GFGXBLTPARAM sruct. User needs to make sure that a valid + pointer is passed in pPatID. + @see GFGxBlt() +*/ +#define GFGX_BLT_PAT_CACHE 0x00000040UL + + +/**** BITBLT - MODE FLAGS ****/ +/**** Linear / XY Mode / Surface Flag ****/ + +/* XY Mode Blt */ +/** GFGxAPI BITBLT Mode flags : X/Y mode is used. + @see GFGxBlt() +*/ +#define GFGX_BLT_MODE_XY 0x00000000UL + +/* Linear Mode Blt */ +/** GFGxAPI BITBLT Mode flags : linear mode is used. + @see GFGxBlt() +*/ +#define GFGX_BLT_MODE_LINEAR 0x00000080UL + +/* Surface to Surface blt */ +/** GFGxAPI BITBLT Mode flags : surface to surface mode is used. + @see GFGxBlt() +*/ +#define GFGX_BLT_SURFACE 0x00000100UL + + +/**** BITBLT - CLIPPING FLAGS ****/ + +/* enable clipping */ +/** GFGxAPI BITBLT Clipping flags : enable clipping. + @see GFGxBlt() +*/ +#define GFGX_BLT_CLIP 0x00000200UL + +/**** BITBLT - SOURCE TRANSPARENCY FLAGS ****/ + +/* color source transparent blt (if source pixel matches colorCompare, +do not overwrite) */ +/** GFGxAPI BITBLT Source Transparency flags : enable color source transparency + (if source pixel matches colorCompare, do not overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_SRC_COLOR 0x00000400UL + +/* color source inverse transparent blt (if source pixel matches +colorCompare, overwrite) */ +/** GFGxAPI BITBLT Source Transparency flags : enable color source inverse + transparency (if source pixel matches colorCompare, overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_SRC_COLOR_INV 0x08000000UL + + +/* mono source transparent blt (if source bit is 0, no +overwrite on corresponding destination location) */ +/** GFGxAPI BITBLT Source Transparency flags : enable mono source transparency + (if source bit is 0, no overwrite on corresponding destination location). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_SRC_MONO 0x00000800UL + +/* mono source inverted transparent blt (if source bit +is 1, no overwrite on corresponding destination location) */ +/** GFGxAPI BITBLT Source Transparency flags : enable mono source inverse + transparency (if source bit is 1, no overwrite on corresponding destination + location). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_SRC_MONO_INV 0x00001000UL + + +/**** BITBLT - DESTINATION TRANSPARENCY FLAGS ****/ + +/* destination transparent blt (if destination pixel matches colorCompare, +overwrite) */ +/** GFGxAPI BITBLT Destination Transparency flags : enable destination + transparency (if destination pixel matches colorCompare, overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_DST 0x00002000UL + +/* destination transparent inverse blt (if destination pixel matches +colorCompare, donot overwrite) */ +/** GFGxAPI BITBLT Destination Transparency flags : enable destination inverse + transparency (if destination pixel matches colorCompare, do not overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_DST_INV 0x10000000UL + +/**** BITBLT - PATTERN TRANSPARENCY FLAGS ****/ + +/* Mono pattern transparent Blt */ +/** GFGxAPI BITBLT Pattern Transparency flags : enable mono pattern transparency + (if pattern bit is 0, no overwrite on corresponding destination location). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_PAT_MONO 0x00004000UL + +/* Mono pattern inverted transparent Blt */ +/** GFGxAPI BITBLT Pattern Transparency flags : enable mono pattern inverse + transparency (if pattern bit is 1, no overwrite on corresponding destination + location). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_PAT_MONO_INV 0x00008000UL + +/* Color pattern transparency Blt */ +/** GFGxAPI BITBLT Pattern Transparency flags : enable color pattern transparency + (if pattern pixel matches colorCompare, do not overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_PAT_COLOR 0x00010000UL + +/* Color pattern transparency Blt */ +/** GFGxAPI BITBLT Pattern Transparency flags : enable color pattern inverse + transparency (if pattern pixel matches colorCompare, overwrite). + @see GFGxBlt() +*/ +#define GFGX_BLT_TRANSPARENT_PAT_COLOR_INV 0x20000000UL + +/**** Fade Blt ****/ +/** GFGxAPI BITBLT flags : enable fade blt. + @see GFGxBlt() +*/ +#define GFGX_BLT_FADE_BLT 0x00020000UL + +/* Enable alpha blending */ +/** GFGxAPI BITBLT flags : enable alphablending. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_BLENDING 0x00080000UL + + + +/**** ALPHABLENDING FLAGS ****/ + +/* Fixed alpha operation */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is fixed value. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_FIXED ( 0x00200000UL) + +/* Inverse Fixed alpha */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse fixed value. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_FIXED_INV (0x00400000UL) + +/* Source alpha ARGB1555 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB1555. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_SRC_1555_T (0x00800000UL) + +/* Inverse Source alpha ARGB1555 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB1555. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_SRC_1555_T_INV (0x01000000UL) + +/* Source alpha ARGB4444 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB4444. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_SRC_4444 (0x02000000UL) + +/* Inverse Source ARGB4444 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB4444. + @see GFGxBlt() +*/ +#define GFGX_BLT_ALPHA_SRC_4444_INV (0x04000000UL) + +/* new flags */ + +/** GFGxAPI BITBLT Alphablending mask. + @see GFGxBlt() +*/ +#define GFGXEX1_MASK 0x3FFFFFFF + +/* Fixed alpha operation */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is fixed value. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_FIXED (0x40000000 | 0x00000001UL) + +/* Inverse Fixed alpha */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse fixed value. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_FIXED_INV (0x40000000 | 0x00000002UL) + +/* Source alpha ARGB1555 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB1555. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_1555_T (0x40000000 | 0x00000004UL) + +/* Inverse Source alpha ARGB1555 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB1555. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_1555_T_INV (0x40000000 | 0x00000008UL) + +/* Source alpha ARGB4444 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB4444. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_4444 (0x40000000 | 0x00000010UL) + +/* Inverse Source ARGB4444 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB4444. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_4444_INV (0x40000000 | 0x00000020UL) + +/* Source alpha ARGB8888 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is source ARGB8888. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_8888 (0x40000000 | 0x00000040UL) + +/* Inverse source alpha ARGB8888 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse source ARGB8888. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_SRC_8888_INV (0x40000000 | 0x00000080UL) + +/* Destination alpha ARGB8888 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is destination ARGB8888. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_DST_8888 (0x40000000 | 0x00000100UL) + +/* Inverse Destination alpha 8888 */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse destination ARGB8888. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_ALPHA_DST_8888_INV (0x40000000 | 0x00000200UL) + +/* Planar 1BPP alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 1BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_1BPP (0x40000000 | 0x00000400UL ) + +/* Planar 1BPP Inv alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 1BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_1BPP_INV (0x40000000 | 0x00000800UL) + +/* Planar 2BPP alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 2BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_2BPP (0x40000000 | 0x00001000UL) + +/* Planar 2BPP Inv alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 2BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_2BPP_INV (0x40000000 | 0x00002000UL) + +/* Planar 4BPP alpha Blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 4BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_4BPP (0x40000000 | 0x00004000UL) + +/* Planar 4BPP Inv alpha Blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 4BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_4BPP_INV (0x40000000 | 0x00008000UL) + +/* Planar 8BPP alpha Blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 8BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_8BPP (0x40000000 | 0x00010000UL) + +/* Planar 8Bpp Inv alpha Blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 8BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_8BPP_INV (0x40000000 | 0x00020000UL) + +/* Planar 44BPP alpha blending */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is SRC4DST4BPP planar. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_44BPP (0x40000000 | 0x00040000UL) + +/* Planar 32 bpp src blending 16 bpp dst */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is 32BPP src to 16BPP dst. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_32BPP16 (0x40000000 | 0x00080000UL) + +/*Planar Inv 32 bpp src blending 16 bpp dst */ +/** GFGxAPI BITBLT Alphablending flags : alpha mode is inverse 32BPP src to + 16BPP dst. + @see GFGxBlt() +*/ +#define GFGXEX1_BLT_PLANAR_32BPP16_INV (0x40000000 | 0x00100000UL) + +/* Alpha planar is already in video mem, no need to transfer it from sys mem */ +#define GFGXEX1_BLT_PLANAR_NOTRANSFER (0x40000000 | 0x00200000UL) + +/**** FAST ROTATION FLAGS ****/ +/** GFGxAPI BITBLT Fast Rotation mask. + @see GFGxFastRotate() +*/ +#define GFGXEX2_MASK 0x3FFFFFFF + +/* Fast Rotation Modes */ + +/* Square (in place rotation) */ +/** GFGxAPI BITBLT Fast Rotation flags : dst is same than src. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_SQUARE (0x80000000 | 0x00000001UL) + +/* Source to Destination Rotation ( 2 buffers) */ +/** GFGxAPI BITBLT Fast Rotation flags : dst is different than src. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_SRC_DST_COPY (0x80000000 | 0x00000002UL) + +/* Disable Fast Rotation */ +/** GFGxAPI BITBLT Fast Rotation flags : disable fast rotation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_DISABLE (0x80000000 | 0x00000004UL) + +/* Fast Rotation Types */ + +/* Flip-X */ +/** GFGxAPI BITBLT Fast Rotation flags : FLIP-X transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_FLIP_X (0x80000000 | 0x00000008UL) + +/* Flip-Y */ +/** GFGxAPI BITBLT Fast Rotation flags : FLIP-Y transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_FLIP_Y (0x80000000 | 0x00000010UL) + +/* Trans-LR */ +/** GFGxAPI BITBLT Fast Rotation flags : TRANSPOSE LEFT-RIGHT transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_TRANS_LR (0x80000000 | 0x00000020UL) + +/* Trans-RL */ +/** GFGxAPI BITBLT Fast Rotation flags : TRANSPOSE RIGHT-LEFT transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_TRANS_RL (0x80000000 | 0x00000040UL) + +/* 90 deg Rotation */ +/** GFGxAPI BITBLT Fast Rotation flags : 90° rotation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_ROT_90 (0x80000000 | 0x00000080UL) + +/* 180 deg Rotation */ +/** GFGxAPI BITBLT Fast Rotation flags : 180° rotation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_ROT_180 (0x80000000 | 0x00000100UL) + +/* 270 deg Rotation */ +/** GFGxAPI BITBLT Fast Rotation flags : 270° rotation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_ROT_270 (0x80000000 | 0x00000200UL) + +/* Identity */ +/** GFGxAPI BITBLT Fast Rotation flags : identity transformation. + @see GFGxFastRotate() +*/ +#define GFGXEX2_FAST_ROTATE_IDENTITY (0x80000000 | 0x00000400UL) + + +/** GFGXAPI STRETCHBLT flag in GFGXBLTPARAM struct + This flag waits for the StretchBlt engine to be idle. + If enabled it will block the CPU thread until the StretchBlt is done. + It is effective only for GFGxStretchBlt(). + For other api's it is ignored. + @see GFGxBlt() +*/ +#define GFGX_STRETCHBLT_WAITFOR_FINISH 0x00100000UL + + +/* + * Definition of attribute ids for Set/GetAttributes() + */ + +/** GFGxAPI attributes definition. + @see GFGxGetAttribute(), GFGxSetAttribute() +*/ +typedef enum _GFGXATTRIBUTES + { + /** Current bits per pixel. */ + GFGX_ATTR_BPP, + /** Frame buffer line width in bytes. */ + GFGX_ATTR_STRIDE, + /** Ptr to start address of the display frame buffer. */ + GFGX_ATTR_ADDR_PTR, + /** Start address offset. */ + GFGX_ATTR_ADDR, + /** Surface for GFGxAPI operations. */ + GFGX_ATTR_SURFACE, + /** Palette RGB888. */ + GFGX_ATTR_PALETTE_RGB888 +} GFGXATTRIBUTES; + +/* Blt parameter struct */ +/** GFGxAPI BLT parameter structure. + @see GFGxBlt() +*/ +typedef struct _GFGXBLTPARAM +{ + /** Destination x in pixels (relative to left). */ + NvS16 dx; + /** Destination y in scan lines (relative to top). */ + NvS16 dy; + /** Width of the source rectangle in pixels. */ + NvS16 w; + /** Height of the source rectangle in pixels. */ + NvS16 h; + /** Source x in pixels (relative to left). */ + NvS16 sx; + /** Source y in scan lines (relative to top). */ + NvS16 sy; + /** Width of the source rectangle in pixels (for Stretch Blt only). */ + NvS16 sw; + /** Height of the source rectangle in scan lines (for Stretch Blt only). */ + NvS16 sh; + /** Color depth */ + NvU16 bpp; + /** Number of bytes per scanline for bitmap. */ + NvS16 stride; + /** Foreground color (used if pixel data is 1 on 1BPP source bitmap). */ + NvU32 fgColor; + /** Background color (used if pixel data is 0 on 1BPP source bitmap). */ + NvU32 bgColor; + /** Pointer to source bitmap. */ + NvU8 *pBits; + /** Pattern offset in x direction. */ + NvS16 px; + /** Pattern offset in y direction. */ + NvS16 py; + /** Pattern foreground color (used if pixel data is 1 on 1BPP pattern bitmap).*/ + NvU32 patFgColor; + /** Pattern background color (used if pixel data is 0 on 1BPP pattern bitmap).*/ + NvU32 patBgColor; + /** Pattern color key for transparent blt.*/ + NvU32 patColorCmp; + /** Pointer to pattern bitmap. */ + NvU8 *pPatBits; + /** Number of bytes per scanline for pattern. */ + NvU32 patStride; + /** Width of pattern. */ + NvU32 patW; + /** Height of pattern. */ + NvU32 patH; + + /** pointer to Pattern ID when GFGX_BLT_PAT_CACHE flag is set. */ + /** GFGxBlt() will return the patID in this field */ + NvU32 *pPatID; + + // Miscellaneous parameters + /** Color key for transparent blt. */ + NvU32 colorCompare; + /** Main flags setting. */ + NvU32 flags; + /** Raster operation code (ROP3). */ + NvU16 rop3; + + // Surface parameters + /** Pointer to dst surface pointer. */ + PGFRMSURFACE *ppDestSurf; + /** Pointer to src surface pointer. */ + PGFRMSURFACE *ppSrcSurf; + /** Source start address. */ + NvU32 srcStartAddr; + /** Destination start address. */ + NvU32 dstStartAddr; + /** Number of bytes per scanline for destination. */ + NvS16 dstStride; + + // alpha blending parameters + /** Alpha value for GFGX_BLT_ALPHA_FIXED or alphaFg for GFGX_BLT_ALPHA_SRC_1555_T. */ + NvU16 alpha; + /** Background alpha for GFGX_BLT_ALPHA_SRC_1555_T. */ + NvU16 alphaBg; + /** Pointer to alpha plane. */ + NvU8 *pAlphaplane; + + // Fading parameters + /** Fading coefficient. */ + NvU32 fadeCoeff; + /** Fading offset. */ + NvU32 fadeOffset; + + /** Alphablending flag. */ + NvU32 flagex1; + + /** Fast rotation flag. */ + NvU32 flagex2; + +} GFGXBLTPARAM; + + +/** @name Functions +@{*/ + +/** This function returns version and capabilities of API and hardware. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pGxProp (PGFPROPERTY) Pointer to property structure to be filled in + + @retval #GF_SUCCESS pGxProp filled in successfully + @retval #GF_ERROR Some error occured + + The #GFPROPERTY structure passed with parameter pGxProp will be + filled in on successfull return. + + The GFPROPERTY::Capability field will hold a combination of flagbits + indicating capabilities specific to the GFGxAPI : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFGX_CAP_BLT BitBlt supported.
      #GFGX_CAP_LINE Line Draw supported.
      #GFGX_CAP_CLIP Clipping supported.
      #GFGX_CAP_STRETCHBLTStretchblt supported.
      #GFGX_CAP_ALPHABLENDING Alphablending supported.
      #GFGX_CAP_ALPHA_COLOR_CMPAlphablending and transparency supported.
      #GFGX_CAP_FAST_ROTATION Fast rotation supported.
      #GFGX_CAP_CLIPPING_INSIDE Inside clipping supported.
      #GFGX_CAP_FADE_BLT Fadeblt supported.
      #GFGX_CAP_COLOR_PATTERN Color pattern supported.
      #GFGX_CAP_CLR_PAT_TRANSPARENTColor pattern transparency supported.
      #GFGX_CAP_ALPHA_AND_FADING Alphablending and fading supported.
      #GFGX_CAP_ALPHA_PLANAR_1BPP 1BPP alpha planar supported.
      #GFGX_CAP_ALPHA_PLANAR_2BPP 2BPP alpha plane supported.
      #GFGX_CAP_ALPHA_PLANAR_4BPP 4BPP alpha plane supported.
      #GFGX_CAP_ALPHA_PLANAR_8BPP 8BPP alpha plane supported.
      #GFGX_CAP_ALPHA_PLANAR_SRC4DST4SRC4DST4BPP alpha plane supported.
      #GFGX_CAP_ALPHA_PLANAR_32BLEND16 32BPP to 16BPP alphablending supported.
      #GFGX_CAP_ALPHA_SRC1555Src 1555 alphablending supported.
      #GFGX_CAP_ALPHA_SRC4444 Src 4444 alphablending supported.
      #GFGX_CAP_ALPHA_FIXED Src fixed alphablending supported.
      + + It is recommended, but not mandatory, that you call this function to query + for the GFGxAPI version and capabilities before proceeding to call any of + the other GFGxAPI functions. + + @see GFPROPERTY +*/ +GF_RETTYPE GFGxGetProperty(GFGxHandle GxHandle, + PGFPROPERTY pGxProp); +/** This function fills a rectangle in video memory with the specified solid color. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param x,y (NvS16) left-top corner of the rectangle (x in pixels, y in scan lines) + @param w,h (NvS16) width & height of the rectangle (w in pixels, h in scan lines) + @param color (NvU32) color to be filled (8BPP index, or 16BPP-32BPP TrueColor) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxFillRectEx() +*/ +GF_RETTYPE GFGxFillRect(GFGxHandle GxHandle, + NvS16 x, NvS16 y, + NvS16 w, NvS16 h, + NvU32 color); +/** This function is commonly used in scrolling an image in video memory. It copies + a rectangular image in the video memory to another location in the same video + memory. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle (dx in pixels, dy in scan lines) + @param w,h (NvS16) width & height of rectangles (w in pixels, h in scan lines) + @param sx,sy (NvS16) left-top corner of source rectangle (sx in pixels, sy in scan lines) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFGxCopyRect() checks for the destruction of the copied image in video memory + caused by overlapping source and destination locations. + + Also, if the destination for the rectangle exceeds the limit of the video memory, + wrapping is done in hardware and no error code is returned. + + + @see GFGxCopyRectEx(), GFGxCopyRectDirect() +*/ +GF_RETTYPE GFGxCopyRect(GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy); + +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap is specified in monochrome (1BPP) pixels. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle (dx in pixels, dy in scan lines) + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle (sx in pixels, sy in scan lines) + @param fgColor (NvU16) color applied to source data bit 1 (The color depth should be same as the frame buffer) + @param bgColor (NvU16) color applied to source data bit 0 (The color depth should be same as the frame buffer) + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to monochome (1bpp) bitmap + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransMonoBitmap() +*/ +GF_RETTYPE GFGxCopyMonoBitmap( GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvU32 fgColor, NvU32 bgColor, + NvS16 srcStride, + NvU8 *pMonoBits); +/** This function copies the bitmap from video memory to system memory. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle (dx in pixels, dy in scan lines) + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle (sx in pixels, sy in scan lines) + @param dstStride (NvS16) destination stride in bytes + @param pDstAddr (NvU8*) pointer to destination buffer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFGxReadBlt( GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvS16 dstStride, + NvU8 *pDstStartAddr); +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap is specified in monochrome (1BPP) pixels and can be transparent. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param color (NvU16) color applied to non-transparent source data bit + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to monochome (1bpp) bitmap + @param selectTrans (NvS16) transparency select: 0 or 1 + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function is similar to GFGxCopyMonoBitmap() except for the selectTrans parameter. + This parameter indicates whether bit data equal to 0 or 1 is going to be transparent. + This function could be used for drawing a transparent text string or character. + + + @see GFGxCopyMonoBitmap() +*/ +GF_RETTYPE GFGxCopyTransMonoBitmap( GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvU32 color, + NvS16 srcStride, + NvU8 *pMonoBits, + NvS16 selectTrans ); +/** This function is used to blit/blend a given source rectangle to/with the given + destination location in the video memory. + + Overlap rectangles are handled properly. Source and destination rectangles must + have same size. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pBltParam (#GFGXBLTPARAM*) refer to structure definition + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + This routine is more generic. It supports System Memory to Video Memory Blts and + Video to Video Memory Blts involving Source and Pattern data.The Source and Pattern + data can be either Color or Monochrome(1 Bpp). Monochrome Blts are supported by performing + a Monochrome to Color Expansion. + + Tiling mode is also supported for Mono Patttern Blts. The size of the pattern in this case + should be 16x16. Tiling is not supported for Color Patterns. + + The following features can also be enabled during Blts : + + - Color Source and Mono Source Transparency + - Destination Transparency, + - Color Pattern and Mono Pattern Transparency + - Alphablending ( Both Planar and Source Alpha) + - Fading + - Microsoft Windows compatible ROP3 + - Clipping + + GFGxBlt() supports both raster operations and alpha blending operations.The two types + of operations are mutually exclusive. + + Please refer to the supported GFGxBlt() flags starting with GFGX_BLT_* and GFGXEX1_BLT_*. + + + @see GFGxCopyRect(), GFGxCopyRectDirect(), GFGxBltSurface(), GFGxCopyMonoBitmap(), + GFGxCopyTransMonoBitmap(), GFGxCopyColorBitmap() +*/ +GF_RETTYPE GFGxBlt( GFGxHandle GxHandle, + const GFGXBLTPARAM *pBltParam ); + +/** + This function performs a surface-to-surface blit. The color depth of the source + surface must match that of the destination. Also, the width and height of the + source must be the same as the destination's width and height. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param ppDestSurf (#PGFRMSURFACE*) pointer to destination surface pointer + @param ppSrcSurf (#PGFRMSURFACE) pointer so source surface pointer + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param rop3 (NvU16) raster operation code + @param srcStartAddr (NvU32) start address relative to the source surface + @param dstStartAddr (NvU32) start address relative to the destination surface + @param flags (NvU32) Transparent blit flag. See Below + @param colorCompare (NvU32) color key for transparent blit. If there is no transparent blit, colorCompare = 0 + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Transparent blit flag is one of the following: + - GFGX_BLT_TRANSPARENT_SRC_COLOR + - GFGX_BLT_TRANSPARENT_SRC_MONO + - GFGX_BLT_TRANSPARENT_SRC_MONO_INV + - GFGX_BLT_TRANSPARENT_DST + - GFGX_BLT_TRANSPARENT_PAT_COLOR + - GFGX_BLT_TRANSPARENT_PAT_COLOR_INV + - GFGX_BLT_TRANSPARENT_PAT_MONO + - GFGX_BLT_TRANSPARENT_PAT_MONO_INV + Refer to GFGX_BLT_X flag definitions for further information. If no transparent blit, flag = 0 + + Alphablending is not supported. + + + @see GFGxCopyRect(), GFGxCopyRectDirect(), GFGxBltSurface(), GFGxCopyMonoBitmap(), + GFGxCopyTransMonoBitmap(), GFGxCopyColorBitmap() +*/ +GF_RETTYPE GFGxBltSurface( GFGxHandle GxHandle, PGFRMSURFACE *ppDestSurf, + PGFRMSURFACE *ppSrcSurf, + NvS16 w, NvS16 h, NvU16 rop3, + NvU32 srcStartAddr, NvU32 dstStartAddr, + NvU32 flags, NvU32 colorCompare); + +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap's color depth must match the destination's video memory's color depth. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyMonoBitmap() +*/ +GF_RETTYPE GFGxCopyColorBitmap( GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits ); + +/** This function draws a line from a point x1, y1 to another point x2, y2 with a specified color + and ROP2 code. GFGxSetClip() should be called before calling GFGxLine(). If clipping is needed, + it is assumed that clipping is enabled and clipping rectangle was set by GFGxSetClip(). If + clipping is not set, the line wraps if it is too long, and no error code is returned. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param x1,y1 (NvU16) (x,y) destination point coords (in pixels, scan lines) + @param x2,y2 (NvU16) (x,y) source point coords in (pixels, scan lines) + @param rop2 (NvU16) ROP2 code + @param color (NvU16) color key for transparent blt or pattern color + @param flags (NvU16) refer to GFGX_LINE_X flag definitions + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Set flags to GFGX_LINE_NOT_DRAW_LAST_PIXEL if the last pixel is not to be + drawn. + +*/ +GF_RETTYPE GFGxLine( GFGxHandle GxHandle, + NvU16 x1, NvU16 y1, NvU16 x2, NvU16 y2, + NvU16 rop2, NvU32 color, NvU16 flags ); + +/** This function enables or disables clipping and also sets the clipping rectangle for subsequent + blit and line drawing functions. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pClipRect (#PGFRECT) pointer to the clipping rectangle + @param clipFlag (NvU32) See below + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Set clipFlag to one of the following: + - GFGX_SETCLIP_DISABLE + - GFGX_SETCLIP_ENABLE + - GFGX_SETCLIP_SETRECT + Refer to GFGX_SETCLIP_X flag definitions + + Clipping Sample Code + // Initialize clipping and rectangle parameters. + clipRect.top = 10; + clipRect.left = 10; + clipRect.right = 60; + clipRect.bottom = 60; + // Set the clipping rectangle and enable clipping. + GFGxSetClip( GxHandle, &clipRect, (GFGX_SETCLIP_SETRECT| + GFGX_SETCLIP_ENABLE) ); + // Call drawing function: Rectangle Fill, Pattern Fill, etc. + GFGXFillRect( GxHandle, 20, 20, 30, 30, 0x07E0 ); + // Disable clipping. + GFGxSetClip( GxHandle, NULL, GFGX_SETCLIP_DISABLE ); + + +*/ +GF_RETTYPE GFGxSetClip( GFGxHandle GxHandle, + PGFRECT pClipRect, NvU32 clipFlag); + +/** This function ensures synchronization between 2D operations and others modules operations. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param timeout (NvU32) obsolete parameter + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + When several modules share the same channel (like 3D,2D), it may be necessary to + synchronize the command flow with the 2D module execution. Putting a GFGxNotBusy() + call after a 2D operation ensures that commands which follow the 2D command are + executed after full completion of the 2D command. + + As opposed to GFGxWaitNotBusy(), this function doesn't block the CPU thread. + Graphics engine may not be idle when returning from the function. Control returns + to the CPU right after a wait command is placed in the graphics engine command FIFO. + The GoForce hardware begins executing the commands following the engine idle + command only after the graphics engine becomes idle. + + + @see GFGxWaitNotBusy() +*/ +GF_RETTYPE GFGxNotBusy( GFGxHandle GxHandle, + NvU32 timeout ); +/** This function sets the new value into the palette entry at index location. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param palVal (NvU32) New palette entry value + @param index (NvU16) Index of the palette entry + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The index value ranges from [0..255] inclusively. Parameter palVal is in RGB format, + where bits [0-7] represent the red value, bits [8-15] the green value, and bits [16-23] + the blue value. + + When this function is called, the physical palette entry is modified permanently. + + This function is used only for the 8-bits per-pixel mode and does not apply to the RGB 16 and + 32-bits mode. + + + @see GFGxGetPal(), GFGxSetPalRange(), GFGxGetPalRange() +*/ +GF_RETTYPE GFGxSetPal(GFGxHandle GxHandle, + NvU32 palVal, NvU16 index); + +/** This function sets the a range of new values pointed by pPalRange into the palette entries + starting at startIndex location and ending at endIndex inclusively. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pPalRange (NvU32*) Pointer to a range of palette entry values + @param startIndex (NvU16) Starting index of palette entries + @param endIndex (NvU16) Ending index of palette entries + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The index value ranges from [0..255] inclusively. Each palette entry value is in RGB format, + where bits [0-7] represent the red value, bits [8-15] the green value, and bits [16-23] + the blue value. + + When this function is called, the physical palette entry is modified permanently. + + This function is used only for the 8-bits per-pixel mode and does not apply to the RGB 16 and + 32-bits mode. + + + @see GFGxGetPal(), GFGxSetPalRange(), GFGxGetPalRange() +*/ +GF_RETTYPE GFGxSetPalRange(GFGxHandle GxHandle, + NvU32 * palRange, + NvU16 startIndex, NvU16 endIndex); + +/** This function returns the palette entry value at index location. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pPalVal (NvU32*) pointer to palette entry value + @param index (NvU16) index of the palette entry + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The index value ranges from [0..255] inclusively. The returned palette entry value is stored + in the location pointed to by pPalVal. + + This function is used only for the 8-bits per-pixel mode and does not apply to the RGB 16 and + 32-bits mode. + + + @see GFGxSetPal(), GFGxSetPalRange(), GFGxGetPalRange() +*/ +GF_RETTYPE GFGxGetPal(GFGxHandle GxHandle, + NvU32 * pPalVal, + NvU16 index); +/** This function returns the palette entry values starting from location startIndex to endIndex + inclusively. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pPalArray (NvU32*) Pointer to a range of palette entry values + @param startIndex (NvU16) Starting index of palette entries + @param endIndex (NvU16) Ending index of palette entries + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The index value ranges from [0..255] inclusively. The returned values are stored into + variables pointed to by pPalArray. + + This function is used only for the 8-bits per-pixel mode and does not apply to the RGB 16 and + 32-bits mode. + + + @see GFGxSetPal(), GFGxGetPal(), GFGxSetPalRange() +*/ + +GF_RETTYPE GFGxGetPalRange(GFGxHandle GxHandle, + NvU32 * pPalArray, + NvU16 startIndex, NvU16 endIndex); +/** This function transfers a color bitmap of exact full screen size from system memory to video memory. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pBltParam (#GFGXBLTPARAM*) refere to structure definition + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxBlt() +*/ + +GF_RETTYPE GFGxBltFullScreen(GFGxHandle GxHandle, + const GFGXBLTPARAM *pBltParam); +/** This function copies a rectangular image in the video memory to another location in the same video + memory without taking care of overlapping cases. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of rectangles + @param sx,sy (NvS16) left-top corner of source rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This is a special case of GxCopyRect(). It does not check on destructions of copied image + on video memory due to overlapping source and destination locations. + + + @see GFGxCopyRectEx(), GFGxCopyRect() +*/ +GF_RETTYPE GFGxCopyRectDirect(GFGxHandle GxHandle, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy); +/** This function copies a source bitmap from system memory to the video memory with + certain restrictions. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param bitmapPtr (NvU32*) Pointer to color bitmap + @param size_in_bytes (NvU16) Total bytes to transfer + @param rect (#GFRECT) Destination rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This is a special case of GxCopyColorBitmap(). Conditions below must be verified : + - The source bitmap pointer, pColorBits, has to be a 32-bit (DWORD) aligned address. + - The size of each line of the source bitmap must be 64-bits (8 bytes, QWORD) aligned. + - There must not be any skipping bytes between lines. + - Total bitmap size has to be smaller than or equal to 2K (2048) bytes. + - The source bitmap's color depth MUST match the destination video memory's color depth. + + + @see GxCopyColorBitmap() +*/ +GF_RETTYPE GFGxCopyPackedColorBitmap(GFGxHandle GxHandle, + NvU32 *pColorBits, + NvU16 bitmapSize, + GFRECT rect); +/** This function sets a given attribute. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param aid (NvU32) Attribute id, such as width, height etc + @param attr (NvU32) Attribute value + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Attribute id can be one of the following : + + + + + + + + + + + + + +
      #GFGX_ATTR_BPP Current bits per pixel.
      #GFGX_ATTR_STRIDE Frame buffer line width in bytes.
      #GFGX_ATTR_ADDR_PTR Ptr to start address of the display frame buffer.
      #GFGX_ATTR_ADDRStart address offset.
      #GFGX_ATTR_SURFACE Surface for GFGxAPI operations.
      #GFGX_ATTR_PALETTE_RGB888 Palette RGB888.
      + + + @see GFGxGetAttribute() +*/ + +GF_RETTYPE GFGxSetAttribute(GFGxHandle GxHandle, + NvU32 aid,NvU32 attr); +/** This function gets an attribute. Certain attributes are fixed. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param aid (NvU32) attribute id, such as width, height etc + @param attr (NvU32*) pointer to returned attribute value + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Attribute id can be one of the following : + + + + + + + + + + + + + + +
      #GFGX_ATTR_BPP Current bits per pixel.
      #GFGX_ATTR_STRIDE Frame buffer line width in bytes.
      #GFGX_ATTR_ADDR_PTR Ptr to start address of the display frame buffer.
      #GFGX_ATTR_ADDRStart address offset.
      #GFGX_ATTR_SURFACE Surface for GFGxAPI operations.
      #GFGX_ATTR_PALETTE_RGB888 Palette RGB888.
      + + @see GFGxSetAttribute() +*/ +GF_RETTYPE GFGxGetAttribute(GFGxHandle GxHandle, + NvU32 aid, NvU32 *attr); +/** This function checks whether the graphics engine is busy or idle. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param timeout (NvU32) obsolete parameter + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The function will wait until the graphics engine is idle. For example, if you want + to write to the frame buffer but the graphics engine is busy the function can be used + to wait until it is idle. + + As opposed to GFGxNotBusy(), this function blocks the CPU thread while waiting for + the graphics engine to become idle. + + + @see GFGxNotBusy() +*/ +GF_RETTYPE GFGxWaitNotBusy( GFGxHandle GxHandle, + NvU32 timeout ); +/** This function is used to stretch or shrink an image, which can be in system memory or video memory. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pBltParam (#GFGXBLTPARAM*) refere to structure definition + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The function has these limitations : + - supports 16 and 32BPP color depths, + + @see GFGxBlt() +*/ + +GF_RETTYPE GFGxStretchBlt( GFGxHandle GxHandle, + const GFGXBLTPARAM *pBltParam ); +/*******************************New API's based on enhancing old API's****************************/ + +/** This function fills a rectangle in the video memory with the specified solid color. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param x,y (NvS16) left-top corner of the rectangle + @param w,h (NvS16) width & height of the rectangle + @param color (NvU32) color to be filled (8BPP index, or 16BPP-32BPP TrueColor) + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxFillRect() +*/ + /* Old API's with enhancement */ +GF_RETTYPE GFGxFillRectEx(GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 x, NvS16 y, + NvS16 w, NvS16 h, + NvU32 color); +/** This function copies a rectangular image in the video memory to another location in the same + video memory. It is commonly used in scrolling an image in video memory. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of rectangles + @param sx,sy (NvS16) left-top corner of source rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFGxCopyRectEx() checks for the destruction of the copied image in video memory + caused by overlapping source and destination locations. Also, if the destination + for the rectangle exceeds the limit of the video memory, wrapping is done in hardware + and no error code is returned. + + + @see GFGxCopyRect(), GFGxCopyRectDirect() +*/ +GF_RETTYPE GFGxCopyRectEx(GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy); +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap is specified in monochrome (1BPP) pixels. + Video memory location is specified by the surface parameter. + + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param fgColor (NvU16) color applied to source data bit 1 + @param bgColor (NvU16) color applied to source data bit 0 + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to monochome (1bpp) bitmap + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransMonoBitmap() +*/ +GF_RETTYPE GFGxCopyMonoBitmapEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvU32 fgColor, NvU32 bgColor, + NvS16 srcStride, + NvU8 *pMonoBits); +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap is specified in monochrome (1BPP) pixels and can be transparent. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param color (NvU16) color applied to non-transparent source data bit + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to monochome (1bpp) bitmap + @param selectTrans (NvS16) transparency select: 0 or 1 + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function is similar to GFGxCopyMonoBitmapEx() except for the selectTrans + parameter. This parameter indicates whether bit data equal to 0 or 1 is going to be + transparent. + + This function could be used for drawing a transparent text string or character. + + + @see GFGxCopyMonoBitmapEx() +*/ +GF_RETTYPE GFGxCopyTransMonoBitmapEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvU32 color, + NvS16 srcStride, + NvU8 *pMonoBits, + NvS16 selectTrans); + +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap's color depth must match the destination's video memory's color depth. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyMonoBitmap() +*/ +GF_RETTYPE GFGxCopyColorBitmapEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits + ); + +/** This function draws a line from a point x1, y1 to another point x2, y2 with a specified color + and ROP2 code. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param x1,y1 (NvU16) (x,y) destination point coords + @param x2,y2 (NvU16) (x,y) source point coords + @param rop2 (NvU16) ROP2 code + @param color (NvU16) color key for transparent blt or pattern color + @param flags (NvU16) refere to GFGX_LINE_X flag definitions + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxLine() +*/ +GF_RETTYPE GFGxLineEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvU16 x1, NvU16 y1, + NvU16 x2, NvU16 y2, + NvU16 rop2, NvU32 color, + NvU16 flags); + +GF_RETTYPE GFGxBltFullScreenEx(GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + const GFGXBLTPARAM *pBltParam); +/** This function copies a rectangular image in the video memory to another location in the same video + memory without taking care of overlapping cases. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of rectangles + @param sx,sy (NvS16) left-top corner of source rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This is a special case of GxCopyRect(). It does not check on destructions + of copied image on video memory due to overlapping source and destination locations. + + + @see GFGxCopyRectEx(), GFGxCopyRect(), GFGxCopyRectDirect() +*/ +GF_RETTYPE GFGxCopyRectDirectEx(GFGxHandle GxHandle, + PGFRMSURFACE pSurfNvS16, + NvS16 dx, NvS16 dy, + NvS16 w, NvS16 h, + NvS16 sx, NvS16 sy); + +/** This function copies a source bitmap from system memory to the video memory with + certain restrictions. + Video memory location is specified by the surface parameter. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pSurf (#PGFRMSURFACE) pointer to destination surface + @param pColorBits (NvU32*) pointer to color bitmap + @param bitmapSize (NvU16) total bytes to transfer + @param rect (#GFRECT) destination rectangle + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This is a special case of GxCopyColorBitmap(). Conditions below must be verified : + - The source bitmap pointer, pColorBits, has to be a 32-bit (DWORD) aligned address. + - The size of each line of the source bitmap must be 64-bits (8 bytes, QWORD) aligned. + - There must not be any skipping bytes between lines. + - Total bitmap size has to be smaller than or equal to 2K (2048) bytes. + - The source bitmap's color depth MUST match the destination video memory's color depth. + + + @see GxCopyColorBitmap(), GFGxCopyPackedColorBitmap() +*/ +GF_RETTYPE GFGxCopyPackedColorBitmapEx( GFGxHandle GxHandle, + PGFRMSURFACE pSurf, + NvU32 *pColorBits, + NvU16 bitmapSize, + GFRECT rect +/** This function performs a surface-to-surface blit. The color depth of the source + surface must match that of the destination. Also, the width and height of the + source must be the same as the destination's width and height. + Alphablending parameters can be specified. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param ppDestSurf (#PGFRMSURFACE*)pointer to destination surface pointer + @param ppSrcSurf (#PGFRMSURFACE) pointer so source surface pointer + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param rop3 (NvU16) raster operation code + @param srcStartAddr (NvU32) start address relative to the source surface + @param dstStartAddr (NvU32) start address relative to the destination surface + @param flags (NvU32) refer to GFGX_BLT_X flag definitions + @param flagex1 (NvU32) refer to alphablending flag definitions GFGXEX1_BLT_X + @param colorCompare (NvU32) color key for transparent blit + @param alpha (NvU16) alpha value for GFGX_BLT_ALPHA_FIXED or alphaFg + @param alphaBg (NvU16) background alpha + + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyRect(), GFGxCopyRectDirect(), GFGxBltSurface(), GFGxCopyMonoBitmap(), + GFGxCopyTransMonoBitmap(), GFGxCopyColorBitmap() +*/ ); +GF_RETTYPE GFGxBltSurfaceEx( GFGxHandle GxHandle, PGFRMSURFACE *ppDestSurf, + PGFRMSURFACE *ppSrcSurf, + NvS16 w, NvS16 h, NvU16 rop3, + NvU32 srcStartAddr, NvU32 dstStartAddr, + NvU32 flags, NvU32 flagex1, NvU32 colorCompare, + NvU16 alpha, NvU16 alphaBg); + + /* New API's based on new features */ + +/*******************************New API's based on New Features***********************************/ + +/** This function is used to transform a given source rectangle to the given destination + location in the video memory. + + Rotation takes place in counterclockwise direction. + + Destination rectangle can be same than source rectangle or different.

      + Both source and destination must be in video memory. + + Common input data requirements : + + - the data buffer must be aligned on all edges (top, bottom, left, right), which also implies + that stride is
      multiple of 16 bytes, + - the base address of both source and destination must be aligned at a 128-bit word aligned, + - in GFGX_BLT_SURFACE mode, source and destination must be same format : GF_SURFACE_RGB8,
      + GF_SURFACE_RGB565, GF_SURFACE_ARGB8888, or GF_SURFACE_YUV420, + - GFGX_BLT_MODE_LINEAR and X/Y modes are also supported for GF_SURFACE_RGB8,
      GF_SURFACE_RGB565 + and GF_SURFACE_ARGB8888, + - width and height must be multiple of 16 pixels in 8bpp mode, 8 in 16bpp and 4 in 32bpp for
      + GF_SURFACE_RGB8, GF_SURFACE_RGB565 and GF_SURFACE_ARGB8888 surfaces, + - in GFGXEX2_FAST_ROTATE_SQUARE mode, width should be equal to height for 90, 270,
      + TRANS_LR and TRANS_RL modes. Also the destination surface should be same as source + surface. + + Specific GF_SURFACE_YUV420 input data requirements : + + - only GFGX_BLT_SURFACE mode is supported, with no offsets defined for both source and +
      destination (dstStartAddr = srcStartAddr = 0). + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param pBltParam (#GFGXBLTPARAM*) refere to structure definition + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + This function can be used the same way than GFGxBlt, adding flagex2 information. + + The following transformations are supported : + + + + + + + + + + + + + + + + + +
      #GFGXEX2_FAST_ROTATE_FLIP_X FLIP-X.
      #GFGXEX2_FAST_ROTATE_FLIP_Y FLIP-Y.
      #GFGXEX2_FAST_ROTATE_TRANS_LR TRANSPOSE LEFT-RIGHT.
      #GFGXEX2_FAST_ROTATE_TRANS_RLTRANSPOSE RIGHT-LEFT.
      #GFGXEX2_FAST_ROTATE_ROT_90 90° rotation.
      #GFGXEX2_FAST_ROTATE_ROT_180180° rotation.
      #GFGXEX2_FAST_ROTATE_ROT_270 270° rotation.
      + + + @see GFGxBlt() +*/ +GF_RETTYPE GFGxFastRotate(GFGxHandle GxHandle, + const GFGXBLTPARAM *pBltParam); +/** This function copies a source bitmap from system memory to the video memory. + The source bitmap's color depth must match the destination's video memory's color depth. + Source transparency is supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + @param pSrcColorKey (NvU32*) pointer to source color key. If NULL no transparency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyMonoBitmap(), GFGxCopyColorBitmap() +*/ +GF_RETTYPE GFGxCopyTransColorBitmap(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits, + NvU32 *pSrcColorKey); +/** This function copies a source bitmap from system memory to the video memory with a mono + pattern buffer combination. + The source bitmap's color depth must match the destination's video memory's color depth. + Source and mono pattern transparencies are supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + @param pSrcColorKey (NvU32*) pointer to source color key. If NULL no transparency. + @param rop3 (NvU8) raster operation code + @param pPatBuffer (NvU8*) pointer to pattern buffer + @param patFgColor (NvU32) pattern foreground color + @param patBgColor (NvU32) pattern background color + @param patW, patH (NvU32) width & height of pattern buffer + @param patStride (NvU32) pattern stride in bytes + @param pSelectPatTrans (NvU16*) pointer to pattern color key. If NULL no transparency. + + Depending of pattern size, replicated mode is used or not. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransColorBitmap(), GFGxCopyColorBitmap() +*/ +GF_RETTYPE GFGxCopyTransColorBitmapWithMonoPattern(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits, + NvU32 *pSrcColorKey, + NvU8 rop3, + NvU8 *pPatBuffer, + NvU32 patFgColor, + NvU32 patBgColor, + NvU32 patW, + NvU32 patH, + NvU32 patStride, + NvU16 *pSelectPatTrans); +/** This function copies a source bitmap from system memory to the video memory with a colour + pattern buffer combination. + The source bitmap and pattern's color depth must match the destination's video memory's color depth. + Source and color pattern transparencies are supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcStride (NvS16) source stride in bytes, must be pixel size aligned + @param pColorBits (NvU8*) pointer to color bitmap + @param pSrcColorKey (NvU32*) pointer to source color key. If NULL no transparency. + @param rop3 (NvU8) raster operation code + @param pPatBuffer (NvU8*) pointer to pattern buffer + @param patW, patH (NvU32) width & height of pattern buffer + @param patStride (NvU32) pattern stride in bytes + @param pPatColorKey (NvU32*) pointer to pattern color key. If NULL no transparency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransColorBitmap(), GFGxCopyColorBitmap(), GFGxCopyTransColorBitmapWithMonoPattern() +*/ +GF_RETTYPE GFGxCopyTransColorBitmapWithColorPattern(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvS16 srcStride, + NvU8 *pColorBits, + NvU32 *pSrcColorKey, + NvU8 rop3, + NvU8 *pPatBuffer, + NvU32 patW, + NvU32 patH, + NvU32 patStride, + NvU32 *pPatColorKey); +/** This function copies a source bitmap from system memory to the video memory with a mono + pattern buffer combination. + The source bitmap and pattern are mono (1BPP). + Mono source and mono pattern transparencies are supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcFgColor (NvU32) source foreground color + @param srcBgColor (NvU32) source background color + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to source bitmap + @param pSelectSrcTrans (NvU16*) pointer to source color key. If NULL no transparency. + @param rop3 (NvU8) raster operation code + @param pPatBuffer (NvU8*) pointer to pattern buffer + @param patFgColor (NvU32) pattern foreground color + @param patBgColor (NvU32) pattern background color + @param patW, patH (NvU32) width & height of pattern buffer + @param patStride (NvU32) pattern stride in bytes + @param pSelectPatTrans (NvU16*) pointer to pattern color key. If NULL no transparency. + + Depending of pattern size, replicated mode is used or not. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransColorBitmap(), GFGxCopyTransMonoBitmap() +*/ +GF_RETTYPE GFGxCopyTransMonoBitmapWithMonoPattern(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvU32 srcFgColor, + NvU32 srcBgColor, + NvS16 srcStride, + NvU8 *pMonoBits, + NvU16 *pSelectSrcTrans, + NvU8 rop3, + NvU8 *pPatBuffer, + NvU32 patFgColor, + NvU32 patBgColor, + NvU32 patW, + NvU32 patH, + NvU32 patStride, + NvU16 *pSelectPatTrans); +/** This function copies a source bitmap from system memory to the video memory with a color + pattern buffer combination. + The source bitmap is mono (1BPP). + Mono source and color pattern transparencies are supported. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + @param dx,dy (NvS16) left-top corner of destination rectangle + @param w,h (NvS16) width & height of the rectangle in pixels and scan lines + @param sx,sy (NvS16) left-top corner of source rectangle + @param srcFgColor (NvU32) source foreground color + @param srcBgColor (NvU32) source background color + @param srcStride (NvS16) source stride in bytes + @param pMonoBits (NvU8*) pointer to source bitmap + @param pSelectSrcTrans (NvU16*) pointer to source color key. If NULL no transparency. + @param rop3 (NvU8) raster operation code + @param pPatBuffer (NvU8*) pointer to pattern buffer + @param patW, patH (NvU32) width & height of pattern buffer + @param patStride (NvU32) pattern stride in bytes + @param pPatColorKey (NvU32*) pointer to pattern color key. If NULL no transparency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + @see GFGxCopyTransMonoBitmap(), GFGxCopyTransMonoBitmapWithMonoPattern() +*/ +GF_RETTYPE GFGxCopyTransMonoBitmapWithColorPattern(GFGxHandle GxHandle, + NvS16 dx, + NvS16 dy, + NvS16 w, + NvS16 h, + NvS16 sx, + NvS16 sy, + NvU32 srcFgColor, + NvU32 srcBgColor, + NvS16 srcStride, + NvU8 *pMonoBits, + NvU16 *pSelectSrcTrans, + NvU8 rop3, + NvU8 *pPatBuffer, + NvU32 patW, + NvU32 patH, + NvU32 patStride, + NvU32 *pPatColorKey); + +/** This function purges the graphics cache used to store pattern buffers when + GFGX_BLT_PAT_CACHE is used. + + @param GxHandle (#GFGxHandle) Handle to GFGxAPI + + @retval #GF_SUCCESS Success + @retval #GFGX_ERROR_NULL_PARAMETER Invalid GxHandle + + @see GFGxBlt() +*/ +GF_RETTYPE GFGxCachePurge(GFGxHandle GxHandle); + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFGxOpen(GFRmHandle hRm, GFGxHandle *phGx, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFGxClose(GFGxHandle *phGx); + +/*@}*/ +/*@}*/ + +#ifdef __cplusplus +} +#endif + +/** @page pageGxAppNotes GxAPI Application Notes + + @section pageGxAppNotes1 Todo + +*/ + +#endif // _GFGx_H_ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFGxError.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFGxError.h new file mode 100755 index 00000000..64e84624 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFGxError.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFGxError.h + * GFSDK Gx Graphics API header file. + */ + +#ifndef __GFGXERROR_H__ +#define __GFGXERROR_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** GFGxAPI error code: Bad parameter. */ +#define GFGX_ERROR_ILLEGAL_PARAMETER (GFGX_ERROR | 0x00000001L) +#define GFGX_ERROR_NULL_SURFACE (GFGX_ERROR | 0x00000002L) +/** GFGxAPI error code: Color depth not supported. */ +#define GFGX_ERROR_COLORDEPTH_NOT_SUPPORTED (GFGX_ERROR | 0x00000003L) +#define GFGX_ERROR_ILLEGAL_ALPHA_MODE (GFGX_ERROR | 0x00000004L) +#define GFGX_ERROR_ILLEGAL_ROTATION_FLAG (GFGX_ERROR | 0x00000005L) +#define GFGX_ERROR_GETTING_COMPONENT (GFGX_ERROR | 0x00000006L) +#define GFGX_ERROR_NO_PRIMARY_SURFACE (GFGX_ERROR | 0x00000007L) +#define GFGX_ERROR_NO_COLORCONVERT_SUPPORT (GFGX_ERROR | 0x00000008L) +#define GFGX_ERROR_NULL_PARAMETER (GFGX_ERROR | 0x00000009L) +/** GFGxAPI error code: Function not supported. */ +#define GFGX_ERROR_NOT_SUPPORTED (GFGX_ERROR | 0x0000000AL) + + + +#ifdef __cplusplus +} +#endif + +#endif // __GFGXERROR_H__ + + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFI2C.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFI2C.h new file mode 100755 index 00000000..458a21c0 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFI2C.h @@ -0,0 +1,314 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFI2C.h + GFSDK I2C API header file. +*/ + +#ifndef __I2C_H__ +#define __I2C_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @addtogroup groupI2C I2CAPI I2C API +*/ +/*@{*/ + +/** GFI2C Error code: Function was passed an illegal parameter. */ +#define GFI2C_ERROR_ILLEGAL_PARAMETER (GFI2C_ERROR | 0x00000001L) +/** GFI2C Error code: I2C slave device did not respond with ack signal. */ +#define GFI2C_ERROR_ACKNOWLEDGE_FAILURE (GFI2C_ERROR | 0x00000002L) +/** GFI2C Error code: Polling routine generated a timeout error. */ +#define GFI2C_ERROR_TIMEOUT_ERROR (GFI2C_ERROR | 0x00000003L) + +/** Enum specifies attribute ids for GFI2CSetAttribute() + @see GFI2CSetAttribute() +*/ +typedef enum _GFI2CATTRIBUTES +{ + GFI2C_ATTR_PULLUP, /**< Set internal I2C pullups, see GFI2C_ATTR_PULLUP_FLAGS. */ + GFI2C_ATTR_SW, /**< Set to use GPIO for SW I2C */ + GFI2C_ATTR_HW, /**< Set to use HW I2C (default) */ + GFI2C_ATTR_TIMING, /**< I2C timing mode, valid for GFI2C_ATTR_HW mode only, see GFI2C_TIMING */ + GFI2C_ATTR_RESPTIMEOUT /**< Set I2C Ack response timeout in ms */ + +} GFI2CATTRIBUTES; + +/** Flag bits for for GFI2C_ATTR_PULLUP attribute. + + Usage example: +
      +    attr = (SP_SCL_PULLUP_DISABLE | SP_SDA_PULLUP_DISABLE)
      +    GFI2CSetAttribute(I2CHandle, GFI2C_ATTR_PULLUP, attr)
      +    
      + + @see GFI2CSetAttribute(), GFI2CATTRIBUTES +*/ +typedef enum _GFI2C_ATTR_PULLUP_FLAGS +{ + SDA_PULLDOWN_DISABLE = 0, //!< Flag to disable I2C data pull down + SDA_PULLDOWN_ENABLE = 1, //!< Flag to enable I2C data pull down + SDA_PULLUP_DISABLE = 0, //!< Flag to disable I2C data pull up + SDA_PULLUP_ENABLE = 1, //!< Flag to enable I2C data pull up + SCL_PULLDOWN_DISABLE = 0, //!< Flag to disable I2C clock pull down + SCL_PULLDOWN_ENABLE = 1, //!< Flag to enable I2C clock pull down + SCL_PULLUP_DISABLE = 0, //!< Flag to disable I2C data pull up + SCL_PULLUP_ENABLE = 0, //!< Flag to enable I2C clock pull up + SCL_DEFAULT = 0, //!< Flag sets I2C clock back to default + SDA_DEFAULT = 0 //!< Flag sets I2C data back to default + +} GFI2C_ATTR_PULLUP_FLAGS; + +/** Timing modes for GFI2C_ATTR_TIMING attribute. + + The timing mode has effect for I2C HW mode (GFI2C_ATTR_HW) only. + + It affects the programming of IC_IC_CONFIG_0/THDCTL and + IC_TCOMMAND_0/SPEED_CTL registers. +*/ +typedef enum _GFI2C_TIMING +{ + /** Standard timing (default). + IC_TCOMMAND_0, SPEED_CTL is programmed to STD_MODE (standard timing). + */ + GFI2C_TIMING_STANDARD = 0, + + /** Fast mode with 2 clocks extended hold time. + IC_TCOMMAND_0, SPEED_CTL is programmed to FAST_MODE. + IC_IC_CONFIG_0, THDCTL is programmed to b'10 (add 2 clocks to hold time). + */ + GFI2C_TIMING_FASTADD2CLK + +} GFI2C_TIMING; + +typedef struct _GFI2CTABLE +{ + GF_RETTYPE (* I2CWrite)( GFI2CHandle I2CHandle, + NvU32 slaveAddr, + NvU8 *pDataBytes, + NvU32 len, + NvU32 delayInMSec ); + + GF_RETTYPE (* I2CRead)( GFI2CHandle I2CHandle, + NvU32 slaveAddr, + NvU8 *pDataBytes, + NvU32 len, + NvU32 delayInMSec ); + + GF_RETTYPE (* I2CRestartRead)( GFI2CHandle I2CHandle, + NvU32 slaveAddr, + NvU32 index, + NvU8 *pDataBytes, + NvU32 len, + NvU32 delayInMSec ); + + GF_RETTYPE (* I2CScan)( GFI2CHandle I2CHandle, + NvU16 slaveAddr ); + + GF_RETTYPE (* I2CPowerSwitch)( GFI2CHandle I2CHandle, NvU8 status); + + GF_RETTYPE (* I2CGetProperty)( GFI2CHandle I2CHandle, + PGFPROPERTY pI2CProp ); + + GF_RETTYPE (* I2CSetAttribute)(GFI2CHandle I2CHandle, NvU32 aid, NvU32 attr); + GF_RETTYPE (* I2CSetClock)( GFI2CHandle I2CHandle, NvU32 selectclock); + GF_RETTYPE (* I2CWritePrepare)( GFI2CHandle I2CHandle, + NvU32 slaveAddr, + NvU32 *pData, + NvU32 len, + NvU32 *pBuffer, + NvU32 *bufferSize); + GF_RETTYPE (* I2CRestartWrite)( GFI2CHandle I2CHandle, + NvU32 slaveAddr1, + NvU8 *pIndexBytes, + NvU32 lenIndex, + NvU32 slaveAddr2, + NvU8 *pDataBytes, + NvU32 lenData, + NvU32 delayInMSec ); + +} GFI2CTABLE, *PGFI2CTABLE; + +/** Open GFI2C component. + @param hRm RM handle + @param phI2C Returns I2C component handle on success + @param state Channel allocation mode + @param hCh Channel to use, or NULL to allocate new +*/ +GF_RETTYPE GFI2COpen(GFRmHandle hRm, GFI2CHandle *phI2C, GF_STATE_TYPE state, GFRmChHandle hCh); + +/** Close GFi@c component. + @param phI2C I2C component handle, will be reset to NULL. Can be NULL. +*/ +void GFI2CClose(GFI2CHandle *phI2C); + +/** This routine writes out len bytes of data during one I2C transfer. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + @param pDataBytes (NvU8) Pointer to data bytes to be written + @param len (NvU32) Number of bytes of data to be written + @param delayInMSec (NvU32) Optional delay inserted after transfer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CWrite(I2CHandle, slaveAddr, pDataBytes, len, delayInMSec) \ + ((PGFI2CTABLE)I2CHandle)->I2CWrite(I2CHandle, slaveAddr, pDataBytes, len, delayInMSec) + +/** This routine reads len bytes of data during one I2C transfer. A typical I2C slave + device requires its address already be set by a preceding GFI2CWrite() function. + These functions should be executed together with no other activity in between. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + @param pDataBytes (NvU8) Pointer to data bytes read from device + @param len (NvU32) Number of bytes of data to be read + @param delayInMSec (NvU32) Optional delay inserted after transfer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CRead(I2CHandle, slaveAddr, pDataBytes, len, delayInMSec) \ + ((PGFI2CTABLE)I2CHandle)->I2CRead(I2CHandle, slaveAddr, pDataBytes, len, delayInMSec) + +/** This function reads in len or fewer bytes of data from an I2C slave device. It differs + from the GFI2CRead() function in that it does so with a combination of an I2C write and + read. There is an I2C write of the slave address and index byte then followed by a START + condition. There is no STOP condition in-between the write and read transactions. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + @param index (NvU32) 2nd byte index of slave device register + @param pDataBytes (NvU8) Pointer to data bytes read from device + @param len (NvU32) Number of bytes of data to be read + @param delayInMSec (NvU32) Optional delay inserted after transfer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CRestartRead(I2CHandle, slaveAddr, index, pDataBytes, len, delayInMSec) \ + ((PGFI2CTABLE)I2CHandle)->I2CRestartRead(I2CHandle, slaveAddr, index, pDataBytes, len, delayInMSec) + +/** This routine writes out a I2C slave address and checks for an ACK. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CScan(I2CHandle, slaveAddr) \ + ((PGFI2CTABLE)I2CHandle)->I2CScan(I2CHandle, slaveAddr) + +/** This function has been replaced by camera scripting. Camera power is now + controlled by a function in the camera scripts. +*/ +#define GFI2CPowerSwitch(I2CHandle, status) \ + ((PGFI2CTABLE)I2CHandle)->I2CPowerSwitch(I2CHandle, status) + +/** This routine sets various I2C attributes. The aid parameter passes an + enumeration GFI2CATTRIBUTES that selects the attribute operation. Each + attribute has a set of defined values passed in the parameter attr, that + it will operate on. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param aid (NvU32) attribute flag + @param attr (NvU32) attribute data value + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see GFI2CATTRIBUTES + +*/ +#define GFI2CSetAttribute( I2CHandle, aid, attr) \ + ((PGFI2CTABLE)I2CHandle)->I2CSetAttribute(I2CHandle, aid, attr ) + +/** This routine sets the I2C clock output on the SCL pin. The parameter + selectclock specifies the new I2C clock in kilohertz. The default + is 100. If selectclock = 0, then the default will be set. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param selectclock (NvU32) new clock value in kHz. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CSetClock(I2CHandle, selectclock) \ + ((PGFI2CTABLE)I2CHandle)->I2CSetClock(I2CHandle, selectclock) + +/** This routine Provide properties about I2C. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param pProp (GFPROPERTY) pointer to GFPROPERTY struct. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +#define GFI2CGetProperty(I2CHandle, pProp) \ + ((PGFI2CTABLE)I2CHandle)->I2CGetProperty(I2CHandle, pProp) + +/** This function prepares a buffer that contains the command sequence for an + I2C write. This may concatenated onto another command sequence and written + to the channel as a combination of two transactions. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr (NvU32) I2C address of slave device + @param pData (NvU8) Pointer to data bytes to be written + @param len (NvU32) Number of bytes of data to be read + @param pBuffer (NvU8) Pointer to command sequence for I2C write + @param bufferSize (NvU32) Number of commands returned + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CWritePrepare(I2CHandle, slaveAddr, pData, len, pBuffer, bufferSize) \ + ((PGFI2CTABLE)I2CHandle)->I2CWritePrepare(I2CHandle, slaveAddr, pData, len, pBuffer, bufferSize) + +/** This function writes lenData bytes of data to an I2C slave device. It differs + from the GFI2CWrite() function in that it does so with a combination of two I2C writes + There is an I2C write of the slave address and index bytes then followed by a START + condition. There is no STOP condition in-between the write and write transactions. + + @param I2CHandle (#GFI2CHandle) Handle to I2CAPI + @param slaveAddr1 (NvU32) I2C address of 1st slave device + @param pDataIndex (NvU8) Pointer to index data to be written to the 1st device + @param lenIndex (NvU32) index data length + @param slaveAddr2 (NvU32) I2C address of 2nd slave device + @param pDataBytes (NvU8) Pointer to data bytes written to 2nd device + @param lenData (NvU32) Number of bytes of data to be read + @param delayInMSec (NvU32) Optional delay inserted after transfer + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +#define GFI2CRestartWrite(I2CHandle, slaveAddr1, pIndexBytes, lenIndex, \ + slaveAddr2, pDataBytes, lenData, delayInMSec) \ + ((PGFI2CTABLE)I2CHandle)->I2CRestartWrite(I2CHandle, slaveAddr1, pIndexBytes, lenIndex, \ + slaveAddr2, pDataBytes, lenData, delayInMSec) + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* __I2C_H__ */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFI2S.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFI2S.h new file mode 100755 index 00000000..bbfd876e --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFI2S.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* +* File: GFi2s.h +* I2S header file. +*/ + + +#ifndef __I2S_H__ +#define __I2S_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFI2SOpen(GFRmHandle hRm, GFI2SHandle *phI2S, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFI2SClose(GFI2SHandle *phI2S); + +GF_RETTYPE GFI2SSetTransmitBuffer(GFI2SHandle I2SHandle, + NvU32 startAddr, + NvU32 sizeBytes, + NvU32 numBuffers); + +GF_RETTYPE GFI2SSetTransmitState(GFI2SHandle I2SHandle, + NvU32 state); + +GF_RETTYPE GFI2SSetReceiveBuffer(GFI2SHandle I2SHandle, + NvU32 startAddr, + NvU32 sizeBytes, + NvU32 numBuffers); + +GF_RETTYPE GFI2SSetReceiveState(GFI2SHandle I2SHandle, + NvU32 state); + +#ifdef __cplusplus +} +#endif + +#endif /* __I2S_H__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFINTx.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFINTx.h new file mode 100755 index 00000000..2b45eb76 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFINTx.h @@ -0,0 +1,114 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFINTx.h + GFSDK Interrupt API header file. +*/ + +#ifndef __GFINTx_H__ +#define __GFINTx_H__ + +#include "GFRmOEM.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupINTx INTxAPI Interrupt API +*/ +/*@{*/ + +#define GF_INTR_START 0 +#define GF_INTR_END 15 + +/* Embedded memory controller interrupt */ +#define GF_EMC_INTR (15) + +/* MC interrupt. */ +#define GF_MC_INTR (14) + +/* SD interrupt. */ +#define GF_SD_INTR (13) + +/* I2C interrupt. */ +#define GF_IC_INTR (12) + +/* I2s interrupt. */ +#define GF_I2S_INTR (11) + +/* Display interrupt. */ +#define GF_DISPLAY_INTR (10) + +/* 3d interrupt. */ +#define GF_GR3D_INTR (9) + +/* 2d interrupt. */ +#define GF_GR2D_INTR (8) + +/* DSP interrupt. */ +#define GF_DSP_INTR (7) + +/* ISP interrupt. */ +#define GF_ISP_INTR (6) + +/* SDGP1 input falling edge interrupt. */ +#define GF_EPP_INTR (5) + +/* VI interrupt. */ +#define GF_VI_INTR (4) + +/* JPEG Encoder interrupt. */ +#define GF_JPEGE_INTR (3) + +/* Mpeg Encoder interrupt. */ +#define GF_ME_INTR (2) + +/* Graphics MPD interrupt. */ +#define GF_GRMPD_INTR (1) + +/* Host interface interrupt. */ +#define GF_HOST_INTR (0) + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFINTxOpen(GFRmHandle hRm, GFINTxHandle *phINTx, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFINTxClose(GFINTxHandle *phINTx); + +/* ### Helper Macros ### */ +GF_RETTYPE GFINTxGetProperty(GFINTxHandle INTxHandle, + PGFPROPERTY pINTxProp); + + +GF_RETTYPE GFINTxDisable(GFINTxHandle INTxHandle, + NvU32 idInt); + +GF_RETTYPE GFINTxEnable(GFINTxHandle INTxHandle, + NvU32 idInt); + +/** Wait for system level interrupt request. + @param handle Handle to INTx API + @param idInt System level interrupt ID + @param timeout Timeout in miliseconds, or 0 to wait endlessly + @retval GF_SUCCESS Interrupt request received + @retval GF_WAIT_TIME_OUT Timeout without interrupt request received +*/ +GF_RETTYPE GFINTxWaitForIRQ(GFINTxHandle INTxHandle, + NvU32 idInt, + NvU32 timeout); + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif // __GFINTx_H__ +/* End of file. */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFIsp.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFIsp.h new file mode 100755 index 00000000..b3c7e512 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFIsp.h @@ -0,0 +1,1654 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFIsp.h + GFSDK Image Signal Processing API header file. +*/ + +#ifndef _GF_ISP__ +#define _GF_ISP__ + +//#define DVS_DEVELOPMENT + +#include "GFCamera.h" +#include "GFVx.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupIsp IspAPI Image Signal Processing API + + As image resolution increases (three megapixels and up), image signal + processing inside the imager module becomes complex and costly, and the + required bandwidth to transfer processed data to the GPU increases. + + One solution to this problem is to incorporate image signal processing (ISP1) + capabilities inside the GPU, and let the imager send raw Bayer Pattern Data + from the CMOS or CCD sensor to the GPU. This reduces bandwidth as ISP + programming is easier and much faster compared to having the ISP unit + inside the imager. + + The ISP pipeline consists of various stages of image processing operations to + enhance the image so that its digital representation is as close to the natural + look as possible. The ISP pipeline consists of the following stages: + - Optical Black Compensation (OB) + - De-Knee Linearization + - Lens Shading Compensation + - White Balance Gain Adjustment (M1, M2, M3 statistics gathering) + - Bad Pixel Compensation + - Noise Reduction + - Demosaicing + - Edge Enhancement (M4 statistics gathering) + - Color Noise Reduction + - Color Correction + - Gamma Correction + - RGB to YUV conversion + + Besides these pipeline stages, the ISP module also provides a statistics + collection mechanism that can be applied to multiple regions of the image. + Image statistics information can be used to compute Auto Exposure (AE), + Auto White Balance (AWB) and Auto Focus (AF). + + The GFISPAPI sets up parameters for each pipeline functional block. If + needed, the user can also choose to bypass each individual functional block. + Once all blocks are set up, image data flows through them automatically. + + Figure 1, "Block Diagram of the ISP Interface," shows the ISP with + respect to other input blocks such as video input (VI) and the encoder + preprocessor (EPP). + + @image html ISPFigure1.bmp + + Figure 2, "Internal ISP Data Flow," shows the data flow inside the + ISP. + + @image html ISPFigure2.bmp + +*/ +/*@{*/ + +/** @defgroup groupIspCapability ISP Capability Flags + These flags represent the various capabilities of the ISP. + @see GFISPPROPERTY +*/ +/*@{*/ + +/** IspAPI property flag: Bayer format input supported. + @see GFISPGetProperty() +*/ +#define GFISP_CAP_FORMAT_BAYER 0x00000001 + +/** IspAPI property flag: Stacked format input supported. + @see GFISPGetProperty() +*/ +#define GFISP_CAP_FORMAT_STACKED 0x00000002 + +/** IspAPI property flag: Three optical black regions supported. + @see GFISPGetProperty(), GFISPOBCONTROL +*/ +#define GFISP_CAP_THREE_OB_REGIONS 0x00000004 + +/** IspAPI property flag: Four optical black regions supported. + @see GFISPGetProperty(), GFISPOBCONTROL +*/ +#define GFISP_CAP_FOUR_OB_REGIONS 0x00000008 + +/** IspAPI property flag: Frame-based optical black supported. + @see GFISPGetProperty(), GFISPOBCONTROL +*/ +#define GFISP_CAP_FRAME_OB 0x00000010 + +/** IspAPI property flag: Line-based optical black supported. + @see GFISPGetProperty(), GFISPOBCONTROL +*/ +#define GFISP_CAP_LINE_OB 0x00000020 + +/** IspAPI property flag: Column-based optical black supported. + @see GFISPGetProperty() +*/ +#define GFISP_CAP_COLUMN_OB 0x00000040 + +/** IspAPI property flag: Deknee (input linearization) supported. + @see GFISPGetProperty(), GFISPDEKNEECONTROL +*/ +#define GFISP_CAP_DE_KNEE 0x00000100 + +/** IspAPI property flag: Lens shading supported. + @see GFISPGetProperty(), GFISPLENSSHADING +*/ +#define GFISP_CAP_LENSSHADING 0x00000200 + +/** IspAPI property flag: White balance supported. + @see GFISPGetProperty(), GFISPWBCONTROL +*/ +#define GFISP_CAP_WB 0x00000400 + +/** IspAPI property flag: Demosaic supported. + @see GFISPGetProperty(), GFISPDEMOSAICCONTROL +*/ +#define GFISP_CAP_DEMOSIAC 0x00000800 + +/** IspAPI property flag: Edge enhancement supported. + @see GFISPGetProperty(), GFISPEDGEENHANCECONTROL +*/ +#define GFISP_CAP_EDGEENHANCE 0x00001000 + +/** IspAPI property flag: Bad pixel concealment supported. + @see GFISPGetProperty(), GFISPBADPIXELCONTROL +*/ +#define GFISP_CAP_BADPIXEL 0x00002000 + +/** IspAPI property flag: Noise reduction supported. + @see GFISPGetProperty(), GFISPNOISECONTROL1 +*/ +#define GFISP_CAP_NOISEREDUCTION1 0x00004000 + +/** IspAPI property flag: Color noise reduction supported. + @see GFISPGetProperty(), GFISPNOISECONTROL2 +*/ +#define GFISP_CAP_NOISEREDUCTION2 0x00008000 + +/** IspAPI property flag: Color correction supported. + @see GFISPGetProperty(), GFISPCOLORCORRECTION +*/ +#define GFISP_CAP_COLORCORRECTION 0x00100000 + +/** IspAPI property flag: Gamma correction supported. + @see GFISPGetProperty(), GFISPGAMMACONTROL +*/ +#define GFISP_CAP_GAMMACORRECTION 0x00200000 + +/** IspAPI property flag: YUV conversion supported. + @see GFISPGetProperty(), GFISPYUVCONVERSION +*/ +#define GFISP_CAP_YUVCONVERSION 0x00400000 + +/** IspAPI property flag: M1 window statistics supported. + @see GFISPGetProperty(), GFISPM1WINDOW +*/ +#define GFISP_CAP_M1 0x01000000 + +/** IspAPI property flag: M2 window statistics supported. + @see GFISPGetProperty(), GFISPM2WINDOW +*/ +#define GFISP_CAP_M2 0x02000000 + +/** IspAPI property flag: M3 window statistics supported. + @see GFISPGetProperty(), GFISPM3WINDOW +*/ +#define GFISP_CAP_M3 0x04000000 + +/** IspAPI property flag: M4 window statistics supported. + @see GFISPGetProperty(), GFISPM4WINDOW +*/ +#define GFISP_CAP_M4 0x08000000 + +/** IspAPI property flag: Negative effect supported. + @see GFISPGetProperty() +*/ +#define GFISP_CAP_NEGATIVEEFFECT 0x80000000 +/*@}*/ + +//#define MANUAL_ENABLE_WAIT_FOR_OUTPUT_END 1 + +/** Struct for ISP version and capabilities. + @see GFISPGetProperty +*/ +typedef struct _GFISPPROPERTY +{ + NvU32 size; /**< Actual size of GFISPPROPERTY data structure. */ + NvU32 version; /**< Version of GFISPAPI. */ + + NvU32 cap; /**< Combination of @ref groupIspCapability. Each bit corresponds to one ISP capability. */ + NvU32 maxWidth, /**< Maximum supported image width. */ + maxHeight; /**< Maximum image height. */ + NvU32 supportedScriptVersion; /**< Version of script supported by ISP API. Incorrect script version may cause some API calls to fail. */ +} GFISPPROPERTY, *PGFISPPROPERTY; + + +/** Definition of attribute ids for GFISPGetAttribute() and GFISPSetAttribute(). +*/ +typedef enum _GFISPATTRIBUTES { + GFISP_ATTR_ENABLE_ISP, /**< The master switch of ISP. 1 = Enable ISP processing, 0 = Disable */ + GFISP_ATTR_ENABLE_OB, /**< The master switch for optical black. 1 = Enable OB, 0 = Disable */ + GFISP_ATTR_ENABLE_SENSOR_MANUAL_OB, /**< The master switch for SENSOR Manual optical black. 1 = Enable OB, 0 = Disable */ + GFISP_ATTR_ENABLE_SENSOR_AUTO_OB, /**< The master switch for SENSOR Auto optical black. 1 = Enable OB, 0 = Disable */ + GFISP_ATTR_ENABLE_FOB, /**< Switch for frame based optical black. 1 = Enable frame based optical black, 0 = Disable */ + GFISP_ATTR_ENABLE_FOB_SELFRESET, /**< Switch for self-reset for frame based optical black. 1 = Enable (reset every frame), 0 = Disable */ + GFISP_ATTR_ENABLE_FOB_TEMPORAL, /**< Switch for temporal filtering for frame based optical black. 1 = Enable temporal filtering, 0 = Disable */ + GFISP_ATTR_ENABLE_LOB, /**< Switch for line based optical black. 1 = Enable line based OB, 0 = Disable */ + GFISP_ATTR_ENABLE_DEKNEE, /**< Switch for deknee. 1 = Enable deknee, 0 = Disable */ + GFISP_ATTR_ENABLE_LENS_SHADING, /**< Switch for lens shading correction. 1 = Enable lens shading correction, 0 = Disable */ + GFISP_ATTR_ENABLE_WB, /**< The master switch for white balance. 1 = Enable white balance, 0 = Disable */ + GFISP_ATTR_ENABLE_AWB, /**< Switch for built-in automatic white balance. 1 = Automatic/dynamic (real-time) white balance, 0 = Preprogrammed mode white balance */ + GFISP_ATTR_AWB_HOLD, /**< Switch to pause automatic white balance. Only effective when GFISP_ATTR_ENABLE_AWB=1. 1 = Start applying current AWB gain value to all future frames, 0 = Restore normal AWB mode */ + GFISP_ATTR_ENABLE_DEMOSAIC, /**< Switch for demosaic processing. 1 = Enable demosaic processing, 0 = Disable */ + GFISP_ATTR_ENABLE_EDGE_ENHANCE, /**< Switch for edge enhancement. 1 = Enable edge enhancement, 0 = Disable */ + GFISP_ATTR_ENABLE_NOISE_CONTROL1, /**< Switch for noise control 1. Noise control method 1 is built in the demosaic unit. 1 = Enable noise control 1, 0 = Disable */ + GFISP_ATTR_ENABLE_BAD_PIXEL, /**< Switch for bad pixel concealment. 1 = Enable bad pixel detection and concealment, 0 = Disable */ + GFISP_ATTR_ENABLE_COLOR_CORRECTION, /**< Switch for color correction. 1 = Enable color correction, 0 = Disable */ + GFISP_ATTR_ENABLE_NOISE_CONTROL2, /**< Switch for noise control 2. Noise control method 2 is built in the color correction unit. 1 = Enable noise control 2, 0 = Disable */ + GFISP_ATTR_ENABLE_GAMMA_CORRECTION, /**< Switch for gamma correction. 1 = Enable gamma correction, 0 = Disable */ + GFISP_ATTR_ENABLE_YUV_CONVERSION, /**< Switch for RGB to YUV conversion. 1 = Enable RGB-YUV conversion, 0 = Disable */ + GFISP_ATTR_ENABLE_NEGATIVE_EFFECT, /**< Switch for negative effect. 1 = Negate whole output image, 0 = Normal image */ + GFISP_ATTR_ENABLE_M2, /**< Switch for M2 statistics. 1 = Enable M2 statistics gathering, 0 = Disable */ + GFISP_ATTR_ENABLE_M3, /**< Switch for M3 statistics. 1 = Enable M3 statistics gathering, 0 = Disable */ + GFISP_ATTR_ENABLE_M4, /**< Switch for M4 statistics. 1 = Enable M4 statistics gathering, 0 = Disable */ + GFISP_ATTR_ENABLE_STATS_RAISE, /**< Switch for statistics raise. 1 = Generate raise vector when statistics gathering is complete, 0 = Disable */ + GFISP_ATTR_ENABLE_STATS_INT, /**< Switch for statistics interrupt. 1 = Generate interrupt when statistics gathering is complete, 0 = Disable */ + GFISP_ATTR_STATS_LINE_END, /**< The line at which statistics gathering is complete. When the line counter reaches STATS_LINE_END, the raise vector and/or interrupt are generated (if enabled). */ +#ifdef MANUAL_ENABLE_WAIT_FOR_OUTPUT_END + GFISP_ATTR_ENABLE_WAIT_FOR_OUTPUT_END, /**< Temporary used to enable wait for OUTPUT_END. 1 = Wait for output end, 0 = Disable */ +#endif + /* Special effects */ + GFISP_ATTR_ENABLE_EMBOSS, /**< Switch for emboss special effect. 1 = Enable emboss special effect, 0 = Disable */ + GFISP_ATTR_ENABLE_SOLARIZE, /**< Switch for solarize special effect. 1 = Enable solarize special effect, 0 = Disable */ + GFISP_ATTR_ENABLE_SEPIA, /**< Switch for sepia special effect. 1 = Enable sepia special effect, 0 = Disable */ + GFISP_ATTR_ENABLE_MONOCHROME, /**< Switch for monochrome special effect. 1 = Enable monochrome special effect, 0 = Disable */ + /* Video settings */ + GFISP_ATTR_CONTRAST, /**< Contrast control. Acts as offset for Y data. Range is [0, 128]. */ + GFISP_ATTR_BRIGHTNESS, /**< Brightness control. Modifies slope of Y data. Range is [0, 256]. */ + GFISP_ATTR_HUE, /**< Hue control. Modifies slope of UV data. Range is [0, 128]. */ + GFISP_ATTR_SATURATION_U, /**< Hue control. Modifies slope of UV data. Range is [0, 256]. */ + GFISP_ATTR_SATURATION_V, /**< Hue control. Modifies slope of UV data. Range is [0, 256]. */ + /* Software 3A control */ + GFISP_ATTR_ENABLE_3A_AE, /**< Switch for software auto exposure. 1 = Enable auto exposure and disable sensor exposure, 0 = Disable */ + GFISP_ATTR_ENABLE_3A_AWB, /**< Switch for software auto white balance. 1 = Enable auto white balance and disable sensor exposure, 0 = Disable */ + GFISP_ATTR_ENABLE_3A_AF, /**< Switch for software auto focus. 1 = Enable auto focus and disable sensor auto focus, 0 = Disable */ + + GFISP_ATTR_ENABLE_SENSOR_AE, /**< Switch for sensor auto exposure. 1 = Enable sensor auto exposure and disable software expoture, 0 = Disable */ + GFISP_ATTR_ENABLE_SENSOR_AWB, /**< Switch for sensor auto white balance. 1 = Enable sensor auto white balance and disable software white balance, 0 = Disable */ + GFISP_ATTR_ENABLE_SENSOR_AF, /**< Switch for sensor auto focus. 1 = Enable sensor auto focus and disable software auto focus, 0 = Disable */ + GFISP_ATTR_ENABLE_AUTO_CC_VIVIDITY /**< Flag for auto vividity. 1 = Enable auto vividity, 0 = Disable auto vividity*/ +} GFISPATTRIBUTES; + + +/** Definition of parameter ids and data structures for #GFISPGetParameter and #GFISPSetParameter. +*/ +typedef enum _GFISPPARAMETERS { + GFISP_PARA_TIMING, /**< Get/Set timing parameters. @see GFISPIMGTIMING */ + GFISP_PARA_M1WINDOW, /**< Get/Set M1 statistics parameters. @see GFISPM1WINDOW */ + GFISP_PARA_M2WINDOW, /**< Get/Set M2 statistics parameters. @see GFISPM2WINDOW */ + GFISP_PARA_M3WINDOW, /**< Get/Set M3 statistics parameters. @see GFISPM3WINDOW */ + GFISP_PARA_M4WINDOW, /**< Get/Set M4 statistics parameters. @see GFISPM4WINDOW */ + GFISP_PARA_OB, /**< Get/Set optical black parameters. @see GFISPOBCONTROL */ + GFISP_PARA_DEKNEE, /**< Get/Set deknee parameters. @see GFISPDEKNEECONTROL */ + GFISP_PARA_LENSSHADING, /**< Get/Set lens shading parameters. @see GFISPLENSSHADING */ + GFISP_PARA_WB, /**< Get/Set white balance parameters. @see GFISPWBCONTROL */ + GFISP_PARA_DEMOSAIC, /**< Get/Set demosaic parameters. @see GFISPDEMOSAICCONTROL */ + GFISP_PARA_EDGEENHANCE, /**< Get/Set edge enhancement parameters. @see GFISPEDGEENHANCECONTROL */ + GFISP_PARA_NOISECONTROL1, /**< Get/Set noise control 1 parameters. @see GFISPNOISECONTROL1 */ + GFISP_PARA_NOISECONTROL2, /**< Get/Set noise control 2 parameters. @see GFISPNOISECONTROL2 */ + GFISP_PARA_BADPIXEL, /**< Get/Set bad pixel parameters. @see GFISPBADPIXELCONTROL */ + GFISP_PARA_COLORCORRECT, /**< Get/Set color correction parameters. @see GFISPCOLORCORRECTION */ + GFISP_PARA_GAMMACORRECT, /**< Get/Set gamma correction parameters. @see GFISPGAMMACONTROL */ + GFISP_PARA_YUVCONVERT, /**< Get/Set YUV conversion parameters. @see GFISPYUVCONVERSION */ + GFISP_PARA_SETMODE, /**< Get/Set ISP mode as specified in script. @see GFISPSETMODE */ + GFISP_PARA_3A_AE, /**< Get/Set 3A AE parameters. @see GFISP3AAE */ + GFISP_PARA_3A_AWB, /**< Get/Set 3A AWB parameters. @see GFISP3AAWB */ + GFISP_PARA_3A_AF , /**< Get/Set 3A AF parameters. @see GFISP3AAF */ + GFISP_PARA_3A_PREV_MODE_AWB, + GFISP_PARA_3A_AWB_SAT_Y_LIMITS, + GFISP_PARA_3A_FRAME_RATE_LOW_LIMIT, + GFISP_PARA_3A_FRAME_RATE_HIGH_LIMIT, + GFISP_PARA_3A_FRAME_RATE_CHOICE, + GFISP_PARA_ISO_SENSITIVITY, /**< Get/Set ISO Sensitivity for 3AAE. */ + GFISP_PARA_REDUCE_GAIN_COMPRESS_GAMMA, /**< Reduce/Restore sensor gain and compensate gain change through Gamma curve Compression/Restoration. + To be used only with SetParameter fn. @see GFISPGAINGAMMACTRL */ + GFISP_PARA_IMAGE_STABILIZATION, /**< Set Image Stabilization. 1 = Enable Image Stabilization, 0 = Disable */ + GFISP_PARA_EXPOSURE_CONTROL, /**< Get/Set exposure control parameters. @see GFISPEXPOSURECONTROL */ + GFISP_PARA_EXPOSURE, /**< Get/Set exposure manually. @see GFISPMANUALEXPOSURE */ + GFISP_ISP_SENSOR_CAPABILITY, /**< ISP 3A Capability >*/ + GFISP_PARA_SENSOR_REGISTER /**< SENSOR Register Read wrtie parameter>*/ + +} GFISPPARAMETERS; + +/** Number of fractional bits of fixed point parameters. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_FIXEDPOINTPARAMETER_FBITS 8 +/** Total number of bits of fixed point parameters. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_FIXEDPOINTPARAMETER_BITS 16 +/** Macro to convert floating point to fixed point. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_CONVERT_FLOAT_TO_FIXED_SIGNED(x) ((NvS16)(x * (2 << GFISP_FIXEDPOINTPARAMETER_FBITS))) +/** Macro to convert floating point to fixed point. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_CONVERT_FLOAT_TO_FIXED_UNSIGNED(x) ((NvU16)(x * (2 << GFISP_FIXEDPOINTPARAMETER_FBITS))) +/** Macro to convert fixed point to floating point. + All fixed point parameters are in u8.8 format or 2's complement + s7.8 format regardless of internal precision to simplify the + interface and keep it consistent across chip revisions. + Generic macros have been provided to convert to and + from floating point format on systems that support it. For + actual range and precision of individual parameters, see the + description of that parameter. +*/ +#define GFISP_CONVERT_FIXED_TO_FLOAT(x) (((float)x) / (2 << GFISP_FIXEDPOINTPARAMETER_FBITS)) + + +/** Enum for which pixel of the R, G, G, B pattern the active frame starts on. + @see GFISPIMGTIMING +*/ +typedef enum +{ + GFISP_RGGB = 0, + GFISP_GRBG = 1, + GFISP_GBRG = 2, + GFISP_BGGR = 3 +} GFISP_BAYERPATTERN_SEL; + +/** Timing Generator Control. + + Whole timing frame consists of scanned part and idle parts (void periods in between lines + and frames). Overall scanned image frame is specified by H_SCAN_SIZE and V_SCAN_SIZE which + includes H and V blank periods. Line and pixel counters are set to 1 at transitions of active + edge of V and H sync input pulses. Note that coordinate in the whole frame starts with + (1,1) instead of (0,0). + + In horizotal direction, H sync active edge indicates start of scan line and it initiates + pixel count from 1 to H_SCAN_SIZE (end of line). After H_SCAN_SIZE pixels are received, + the ISP module goes into void period, in which it waits for next arrival of H sync active + edge. In practice, H blank period is composed of inactive period during H_SCAN SIZE and the + void period in between end of line and start next line. + + Same applies to vertical direction. + + Active part (non-blanking part) consists of "optical black" lines at top and bottom of the + image frame and left and right of image line, and active lines with active pixels in the + middle. + + @see GFISPGetParameter, GFISPSetParameter +*/ +typedef struct _GFISPIMGTIMING +{ + NvU16 hScanSize, /**< Number of pixel clock periods per scan line (including H blanking). */ + vScanSize; /**< Number of line periods per scan frame (including V blanking). */ + NvU8 hSyncEdge, /**< Active edge selection for horizontal sync. 0 = positive transition, 1 = negative transition. */ + vSyncEdge; /**< Active edge selection for vertical sync. 0 = positive transition, 1 = negative transition. */ + GFISP_BAYERPATTERN_SEL bayerSel; /**< Bayer timing format. Specifies which pixel of the R, G, G, B pattern the active frame starts on. */ + + GFRECT ActiveRect; /**< Active image area. */ + GFRECT OutputRect; /**< Output image area. */ +} GFISPIMGTIMING, *PGFISPIMGTIMING; + + +/** Enum for the number of samples to take across the M1 statistics window. + @see GFISPM1WINDOW +*/ +typedef enum +{ + GFISP_M1SAMPLE32 = 0, + GFISP_M1SAMPLE64 = 1 +} GFISP_M1_SAMPLE_SEL; + +/** M1 statistics window control. + + The GFISPAPI provides four methods that programmers can use to gather + statistics on pixel values. Based on the values, the programmer can take + appropriate compensating action as needed. The four methods are M1 + Window, M2 Window, M3 Window, and M4 Window. + + This structure describes the M1 Window method, which measures average/ + peak pixel values inside the specified area. It returns eight values—four + values (RGGB) represent average pixels, and four values represent peak + pixels. The measurement result can be used for white balance, either + automatically by AWB or manually by the programmer. + + Refer to the function #GFISPReadMWindowValues() for reading the + measured values. + + @see GFISPGetParameter, GFISPSetParameter, GFISPReadMWindowValues +*/ +typedef struct _GFISPM1WINDOW +{ + GFRECT M1WindowRect; /**< M1 Window size/position. */ + GFISP_M1_SAMPLE_SEL horzSampSel, /**< Horizontal sample density. */ + vertSampSel; /**< Vertical sample density. */ + NvU16 PeakMax; /**< Maximum limit of peak detection. */ + NvU16 TemporalFilterStrength; /**< Selects temporal filter coefficients. Valid range is [0-7]. Value 0 effectively turns off temporal filter. */ +} GFISPM1WINDOW, *PGFISPM1WINDOW; + + +/** M2 statistics window control. + + The GFISPAPI provides four methods that programmers can use to gather + statistics on pixel values. Based on the values, the programmer can take + appropriate compensating action as needed. The four methods are M1 + Window, M2 Window, M3 Window, and M4 Window. + + This structure describes the M2 Window method for gathering statistics on + pixel values. The M2 Window method measures the number of pixels at + specified ranges inside a specified area. A histogram with four bins is + generated. + + Refer to the function #GFISPReadMWindowValues() for reading the + measured values. + + @see GFISPGetParameter, GFISPSetParameter, GFISPReadMWindowValues, GFISP_ATTR_ENABLE_M2 +*/ +typedef struct _GFISPM2WINDOW +{ + GFRECT M2WindowRect; /**< M2 Window size/pos. */ + NvU16 HistBinL1, /**< Cut point of 1st bin. */ + HistBinL2, /**< Cut point of 2nd bin. */ + HistBinL3; /**< Cut point of 3rd bin. */ + NvU16 reserved; +} GFISPM2WINDOW, *PGFISPM2WINDOW; + + +/** M3 statistics window control. + + The GFISPAPI provides four methods that programmers can use to gather + statistics on pixel values. Based on the values, the programmer can take + appropriate compensating action as needed. The four methods are M1 + Window, M2 Window, M3 Window, and M4 Window. + + This structure describes the M3 Window method for gathering statistics on + pixel values, The M3 Window method generates a group of pixel samples + from the specified area. Each sub-window generates one 32-bit value. + + The horizontal interval of M3 sub-windows is derived from M3 window + line width divided by M3 window horizontal count, rounded down. + + The vertical interval of M3 sub-windows is derived from M3 window + frame height divided by M3 window vertical count, rounded down. + + Refer to the function #GFISPReadMWindowValues() for reading the + measured values. + + @see GFISPGetParameter, GFISPSetParameter, GFISPReadMWindowValues, GFISP_ATTR_ENABLE_M3 +*/ +typedef struct _GFISPM3WINDOW +{ + GFRECT M3WindowRect; /**< M3 Window size/pos. */ + NvU8 SubWindowCountH, /**< Number of sub-windows in horizontal direction. Can be {16,32,64}. */ + SubWindowCountV; /**< Number of sub-windows in vertical direction. Can be {16,32,64}. */ + NvU16 SubWindowWidth, /**< Width of sub-windows. Can be {2,4,8,16,32}. */ + SubWindowHeight; /**< Height of sub-windows. Can be {2,4,8,16,32}. */ + NvU16 reserved; +} GFISPM3WINDOW, *PGFISPM3WINDOW; + + +/** M4 statistics window control. + + The GFISPAPI provides four methods that programmers can use to gather + statistics on pixel values. Based on the values, the programmer can take + appropriate compensating action as needed. The four methods are M1 + Window, M2 Window, M3 Window, and M4 Window. + + This structure describes the M4 Window method for gathering statistics on + pixel values. The M4 Window method takes statistical measurements for + auto-focus control. It generates two values for each sub-window. One value + represents the high frequency factor inside the sub-window. The other value + represents sub-window luminance. + + There are {1, 2, 3, 4, 6, 9} sub-windows in {1,2,3}x{1,2,3} configurations. + + SC15 implementation has the following constraints + * SubWindowintervalH >= SubWindowWidth + * SubWindowintervalV >= SubWindowHeight + + Refer to the function #GFISPReadMWindowValues() for reading the + measured values. + + @see GFISPGetParameter, GFISPSetParameter, GFISPReadMWindowValues, GFISP_ATTR_ENABLE_M4 +*/ +typedef struct _GFISPM4WINDOW +{ + NvU32 Left, /**< Specifies left of first M4 sub-window. */ + Top; /**< Specifies top of first M4 sub-window. */ + NvU8 SubWindowCountH, /**< Specifies the number of sub-windows in the horizontal direction. Can be {1,2,3}. */ + SubWindowCountV; /**< Specifies the number of sub-windows in the vertical direction. Can be {1,2,3}. */ + NvU16 SubWindowWidth, /**< Specifies the width of each sub-window. */ + SubWindowHeight; /**< Specifies the height of each sub-window. */ + NvU16 SubWindowIntervalH, /**< Specifies the horizontal interval of sub-windows. */ + SubWindowIntervalV; /**< Specifies the vertical interval of sub-windows. */ + NvU8 CoreLimit; /**< Top limit of noise coring for M4 statistics gathering. Valid range is [0-63]. */ + NvU8 reserved; +} GFISPM4WINDOW, *PGFISPM4WINDOW; + + +/** Enum for the Optical Black Mode. + @see GFISPOBCONTROL +*/ +typedef enum +{ + OB_MODE_FRAME = 0, + OB_MODE_AVG_FRAME_LINE = 1, + OB_MODE_LINE = 2 +} GFISP_OB_MODE_SEL; + + +/** Optical black control. + + The very first ISP operation to be applied to the input pixel signal is to + establish "black" level. This anchors signal activities to a black reference level, + or "zero" level. + + There are two methods of accomplishing optical blacking. One method is + performed on each frame and is called Frame-based Optical Blacking (FOB). + The other method is performed on each scan line and is called Line-based + Optical Blacking (LOB). + + Under FOB, optical black level can be established in one of two ways--by + setting it manually, or more commonly by letting the ISP measure it + automatically. In the automatic method the user can specify black regions + which surround the active imaging area. The pixel levels from these regions + are used to determine the input signal level of reference black, which is + mapped to "zero" level in the subsequent pixel processing. + + LOB is applied to each scan line and is used to detect and compensate for + fluctuations in the imager input signal level of reference black. + + The user can choose to use either FOB, or LOB, or both. + + Four optical black regions are defined through 16 coordinates. + + If ISP's OB capability is GFISP_CAP_THREE_OB_REGIONS, then: + - Only six of the 16 OB coordinates are used: + - OBTopRegionStartV, OBTopRegionHeight, + - OBLeftRegionStartH, OBLeftRegionWidth, + - OBBottomRegionStartV, OBBottomRegionHeight + - Right OB region is not supported. + - Top region width is assumed equal to input width. + - Left region height is assumed equal to input height. + - Bottom region width is assumed equal to input width. + - Bottom region is only used if GFISP_ATTR_ENABLE_FOB_SELFRESET is disabled. + + If ISP's OB capability is GFISP_CAP_FOUR_OB_REGIONS, then all sixteen + OB coordinates are used. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_FOB, GFISP_ATTR_ENABLE_FOB_SELFRESET, GFISP_ATTR_ENABLE_FOB_TEMPORAL, GFISP_ATTR_ENABLE_MANUALOB, GFISP_ATTR_ENABLE_LOB +*/ +typedef struct _GFISPOBCONTROL +{ + NvU32 OBTopRegionStartV, OBTopRegionHeight, OBTopRegionStartH, OBTopRegionWidth; + NvU32 OBBottomRegionStartV, OBBottomRegionHeight, OBBottomRegionStartH, OBBottomRegionWidth; + NvU32 OBLeftRegionStartV, OBLeftRegionHeight, OBLeftRegionStartH, OBLeftRegionWidth; + NvU32 OBRightRegionStartV, OBRightRegionHeight, OBRightRegionStartH, OBRightRegionWidth; + + NvU8 FOBCoef; /**< Filter coefficient of FOB acquisition. Valid range is [0-15]. */ + NvU8 TOBCoef; /**< Temporal filter coefficient of FOB temporal filter. Valid range is [0-15]. */ + + NvU8 LOBWidth; /**< Width used for LOB. Valid values are {2, 4, 8}. */ + + NvU8 FOBAdjust; /**< Manual adjustment applied to the black level. Valid range is [0, 63]. */ + GFISP_OB_MODE_SEL OBMode; /**< Optical black mode vales {frame, avg of frame + line, line } */ +} GFISPOBCONTROL, *PGFISPOBCONTROL; + + +/** This structure describes one approximated linear segment for deknee. + @see GFISPDEKNEECONTROL +*/ +typedef struct _GFISPDEKNEEENTRY +{ + NvU16 start; /**< Start of a range. */ + NvU16 slope; /**< Slope of the linear. Unsigned fixed point format. Valid range is [0, 3 63/64] with precision of 1/64. */ +} GFISPDEKNEEENTRY, *PGFISPDEKNEEENTRY; + +/** Deknee control. + + Imagers tend to show some degree of non-linearity in their light-to-electric + transfer characteristics. Deknee unit attempts to improve the linearity. + + NVIDIA ISP implements Deknee as a piece-wise linear approximation of up + to 16 segments. + + This structure describes the start and slope values for the Deknee look-up + table. The caller may choose to divide the table into 4, 8, or 16 linear segments + (4, 8, or 16 entries in the table). + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_DEKNEE +*/ +typedef struct _GFISPDEKNEECONTROL +{ + NvU32 nEntries; /**< Number of entries in the pEntry table. Valid values are {4,8,16}. */ + GFISPDEKNEEENTRY *pEntries; /**< Deknee entry table. */ +} GFISPDEKNEECONTROL, *PGFISPDEKNEECONTROL; + + +/** Lens shading compensation control. + + An optical lens in front of the imager tends to introduce shading and + unevenness in the strength of incident light. It is strongest at the center and + diminishes as the distance from the center increases. Actual shading + characteristics vary depending on the choice of optics. + + This structure describes a method for compensating for this shading by + applying varying levels of gain to the pixel signal in the reverse function of + the shading. + + The GFISPAPI implements this as a second degree quadratic equation for + each color component at H and V: + + F = 1 + X * (Coef1 + Coef2 *X) + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_LENS_SHADING +*/ +typedef struct _GFISPLENSHADING +{ + NvU16 hCenter, /**< Horizontal center point of camera lens. */ + vCenter; /**< Vertical center point of camera lens. */ + + NvU16 rHorzCoef1, /**< First order coefficient for Horizontal Red. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + rHorzCoef2; /**< Second order coefficient for Horizontal Red. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 rVertCoef1, /**< First order coefficient for Vertical Red. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + rVertCoef2; /**< Second order coefficient for Vertical Red. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 gHorzCoef1, /**< First order coefficient for Horizontal Green. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + gHorzCoef2; /**< Second order coefficient for Horizontal Green. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 gVertCoef1, /**< First order coefficient for Vertical Green. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + gVertCoef2; /**< Second order coefficient for Vertical Green. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 bHorzCoef1, /**< First order coefficient for Horizontal Blue. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + bHorzCoef2; /**< Second order coefficient for Horizontal Blue. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + NvU16 bVertCoef1, /**< First order coefficient for Vertical Blue. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ + bVertCoef2; /**< Second order coefficient for Vertical Blue. Unsigned fixed point format. Valid range is [0, 7 63/64] with precision of 1/64. */ +} GFISPLENSSHADING, *PGFISPLENSSHADING; + + + +/** White balance control. + + White Values + + RGB component signal levels are balanced to render white objects as white. + This is a normalization step of electronic signal of RGB color primaries. + Depending on the "color temperature" of the white reference, the relative + strength of RGB tri-stimulus values vary. In the electric signal, ER/EG/EB + corresponding to the RGB tri-stimulus values are normalized so that white (of + 100% strength) is represented by ER = EG = EB = 1. The original image in front + of the imager is reproduced only when a display device does precise reverse + conversion, which is a purely ideal case. Otherwise, the original image is + rendered in different shades of colors depending on the reference white for + which the display device is tuned. + + Gray Values + + RGB pixel values that represent "gray" objects may be obtained in various + ways. For example, a picture frame can be filled with a "white" object, or + average values for a large number of pixels can be calculated, or a set of + average values collected in many sampling spotscan be used to represent the + approximated "gray" object. + + Gain Factors and White Balance + + Digital gain values are dedicated to each of the four color channels (R, Gr, Gb, + B). + + Depending on how to set gain factors, there are two ways to use White + Balance. A commonly used method is called Dynamic WB, or AWB. Under + AWB, gain values are updated automatically by ISP internal AWB control + based on the average values and peak values in {R, G1, G2, B} color channels. + Refer to #GFISP_PARA_M1WINDOW. + + - If the frame exposure is high ("Top" level, controlled by ThresholdT2M/ + ThresholdM2T), gains are calculated from the average RGrGbB values. + - If the frame exposure is low ("Bottom" level, controlled by + ThresholdM2B/ThresholdB2M), gains are calculated from peak + RGrGbB values. + - If the frame exposure is in the middle range, gains are calculated from + both average and peak values. + + Under AWB, the user can send a command to freeze the current gain value by + setting GFISP_ATTR_AWB_HOLD to 1. Then the current AWB gain value is + applied to all future frames. + + The other method is called pre-programmed WB or Static WB. It sets preprogrammed + gain values and applies them all time. Under this mode, the + programmer determines the proper gain values based on the M1/M3 + measurement window output. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_WB, GFISP_ATTR_ENABLE_AWB, + GFISP_ATTR_AWB_HOLD, GFISPM1WINDOW +*/ +typedef struct _GFISPWBCONTROL +{ + // Static WB. + NvU16 RGain, /**< Static gain factor for Red. Only effective when GFISP_ATTR_ENABLE_AWB==0. */ + GrGain, /**< Static gain factor for Green on Red. Only effective when GFISP_ATTR_ENABLE_AWB==0. */ + BGain, /**< Static gain factor for Blue. Only effective when GFISP_ATTR_ENABLE_AWB==0. */ + GbGain; /**< Static gain factor for Green on Blue. Only effective when GFISP_ATTR_ENABLE_AWB==0. */ + + // Both statis and auto WB. + NvU16 TopClipLimit; /**< Lower limit of gain based clipping. Effective for both Static WB and Auto WB. Value 0 effectively turns off Top-clipping. */ + + // Auto WB. + NvU16 PeakRef; /**< White reference level for gain adjustment. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + + NvU16 RGainMax, RGainMin; /**< Max/Min Gain factor for Red. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + NvU16 GGainMax, GGainMin; /**< Max/Min Gain factor for Green. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + NvU16 BGainMax, BGainMin; /**< Max/Min Gain factor for Blue. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + + NvU16 ThresholdT2M, /**< Top-to-Middle transition level. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + ThresholdM2T, /**< Middle-to-Top transition level. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + ThresholdM2B, /**< Middle-to-Bottom transition level. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + ThresholdB2M; /**< Bottom-to-Middle transition level. Only effective when GFISP_ATTR_ENABLE_AWB==1. */ + +} GFISPWBCONTROL, *PGFISPWBCONTROL; + + +/** Demosaic mode enum for #GFISPDEMOSAICCONTROL. +*/ +typedef enum +{ + GFISP_DM3X3 = 0, // 3x3 one-shot demosaicing + GFISP_DM3X3BPNR = 1, // 3x3 demosaicing/bad-pixel/noise-reduction + GFISP_DM5X5 = 2, // 5x5 one-shot demosaicing + GFISP_DM5X5BP = 3, // 5x5 demosaicing/bad-pixel + GFISP_DM5X5BPNR = 4 // 5x5 demosaicing/bad-pixel/noise-reduction +} GFISP_DEMOSAIC_MODE_SEL; + +/** Demosaic control. + + This structure controls the demosaic process, which uses 2D interpolation to + convert Bayer format R/G/B pixel signals obtained from the imager to + generate R/G/B component values. + + Under the SC15 hardware implementation, the Demosaic unit is built with + bad pixel (BP) and noise reduction (NR) control inside, so picking demosaic + mode affects bad pixel and noise reduction control. Unless limited by + memory bandwidth, programmers should always pick BPNR modes. Otherwise, BP + and NR features are not available, even if you try to turn on BP or NR + controls with GFISPSetAttribute(). + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_DEMOSAIC, + GFISPBADPIXELCONTROL, GFISPNOISECONTROL1 +*/ +typedef struct _GFISPDEMOSAICCONTROL +{ + GFISP_DEMOSAIC_MODE_SEL DemosaicMode; /**< Demosaic mode selection. */ +} GFISPDEMOSAICCONTROL, *PGFISPDEMOSAICCONTROL; + + +/** Coring limit scaling selection enum for #GFISPEDGEENHANCECONTROL. */ +typedef enum +{ + GFISP_GCLIMIT_SCALE_4 = 0, // range [1,4.5] + GFISP_GCLIMIT_SCALE_8 = 1, // range [1,8.5] + GFISP_GCLIMIT_SCALE_16= 2, // range [1,16.5] + GFISP_GCLIMIT_SCALE_32= 3 // range [1,32.5] +} GFISP_GCORINGLIMIT_SCALE_SEL; + +/** Edge enhancement control. + + This structure controls the edge enhancement process, accomplished by the + following: + -# Extracting the high frequency component (HF) of the pixel + -# Amplifying HF if the extracted value is "large" (that is, coring) + -# Adding the amplified HF back to the Y channel of the pixel. + + In the SC15 implementation, edge enhancement control resides in the + Demosaic unit. It is effective only if DM3X3BPNR, DM5X5NR, or DM5X5BPNR + demosaic mode is selected. The threshold that's used for coring is not a predetermined + fixed value, but instead is adaptive depending on the brightness + level. If the pixel surround is bright (more visible), the coring threshold will + be larger, which means only stronger edges are enhanced. Weaker edges are + considered more noise-prone and therefore are not enhanced. + + Two control parameters are used to determine the adaptive coring threshold: + GCoringLimit and GCoreScaleSel. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_EDGE_ENHANCE +*/ +typedef struct _GFISPEDGEENHANCECONTROL +{ + NvU16 StrengthLevel; /**< How heavily the edge enhancement is applied. Unsigned fixed-point format. Valid range is [0, 3 7/8] with a precision of 1/8, plus [4, 15 1/2] with a precision of 1/2. */ + + NvU16 GCoringLimit; /**< Minimum coring level. The coring level increases when the pixel's surrounding brightness level goes up. Valid range is [0-63]. */ + GFISP_GCORINGLIMIT_SCALE_SEL GCoringScaleSel; /**< Scaling factor of GCoringLimit. Specifies the influence of the brightness level to the coring level. The higher the GCoreScaleSel is, the larger the coring level grows under the same brightness. */ +} GFISPEDGEENHANCECONTROL, *PGFISPEDGEENHANCECONTROL; + + +/** Noise Reduction 1 control. + + There are two noise reduction functions in ISP datapath: + -# 3D noise reduction + -# False color reduction + + GFISPNOISECONTROL1 applies to the first method. + It resides in Demosaic unit along with edge enhancement. It is effective + only if DM3X3BPNR, DM5X5NR, or DM5X5BPNR demosaic mode is selected. + + This method reduces noise not only in the image plane but also in the + intensity domain. In other words, low pass filtering is applied to pixels that + have a similar pixel value and are also close to the same location. + FilterStrengthLevel defines the filter kernel size on the intensity + domain. Larger FilterStrengthLevel generates a smoother but blurry + image. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_NOISE_CONTROL1 +*/ +typedef struct _GFISPNOISECONTROL1 +{ + NvU16 FilterStrengthLevel; /**< Weighted average scaling factor. Valid range is [0,7]. */ +} GFISPNOISECONTROL1, *PGFISPNOISECONTROL1; + + +/** Noise Reduction 2 control. + + There are two noise reduction functions in ISP datapath: + -# 3D noise reduction + -# False color reduction + + GFISPNOISECONTROL2 applies to the second method. + It resides in color correction unit. + + This method reduces the colorfulness of pixels at shadow region or at edges + to de-emphasize color noise and color aliasing effects. HighLimit and + TransitionWidth specify the pixels that will undergo the color reduction. + If the luminance level of the pixel is larger than (HighLimit + + TransitionWidth), the pixel's colorfulness is intact. If the luminance level + is smaller than HighLimit, the colorfulness is reduced to a minimum (i.e., no + color correction is applied). Pixels with luminance levels between these limits + pass through an intermediate colorfulness reduction factor. CCScaleFactor + specifies how much color reduction should be applied at edge pixels. Larger + CCScaleFactor creates a more noticeable color reduction at the edges. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_NOISE_CONTROL2 +*/ +typedef struct _GFISPNOISECONTROL2 +{ + NvU16 HighLimit; /**< Upper-limit level of noise reduction curve. */ + NvU16 TransitionWidth; /**< Width of noise reduction curve. Valid values are {16, 32, 64, 128}. */ + NvU16 CCScaleFactor; /**< Slope of noise reduction curve. Unsigned fixed point format. Valid range is [0, 31]. */ +} GFISPNOISECONTROL2, *PGFISPNOISECONTROL2; + + + +/** Bad pixel control. + + This structure controls a method to conceal bad pixels. + + The process resides in the Demosaic unit along with edge enhancement + and noise control 1. It is effective only if DM3X3BPNR or DM5X5BPNR demosaic + mode is selected. + + If a pixel value deviates greatly from its surrounding pixels, the pixel is + considered to be a bad pixel. The deviation is defined in terms of the + percentage of the average value of the surrounding pixels. + + Two ratio coefficients are used: + - If the pixel is within a flat area, LowCoef is used, + - If the pixel is at an edge region, UpCoef is used. + If the average of the surrounding pixels is lower than DarkLevel, it is + considered to be at a shadow region, and DarkLevel instead of the average + value will be used to calculate the deviation threshold. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_BAD_PIXEL +*/ +typedef struct _GFISPBADPIXELCONTROL +{ + NvU16 DarkLevel; /**< Bad-pixel dark level. */ + NvU16 UpCoef, /**< Coefficient for upper threshold. Unsigned fixed point format. Valid range is [0, 1 7/8] with precision of 1/8. */ + LowCoef; /**< Coefficient for lower threshold. Unsigned fixed point format. Valid range is [0, 1 7/8] with precision of 1/8. */ +} GFISPBADPIXELCONTROL, *PGFISPBADPIXELCONTROL; + + +/** Color correction control. + + This structure controls the color correction process. + + In a strict sense, the color correction module transforms a given color space + (based on the optical characteristics of the imager) to a specific color space + such as described by the CCIR 601 standard. The color component signals are + then handled according to that standard color space from that point on. + + For high-end cameras, color correction is used to match some sensitive colors + such as flesh tone to a desired shade of colors, and is handled primarily by + experts who know what they are doing. + + In practice, there may be a simpler means with fewer control parameters, + where the color shade of images is adjusted to suit the viewer's taste. So, gain + and offset of R, G, and B pixels are individually adjusted. + + GFISP color correction consists of 3x3 matrix factors for the camera RGB + (cRGB) to standard RGB (sRGB) conversion. Subjective adjustment of color + can also be included. + - Coefficients on the main diagonal are unsigned. Valid range is [0, 7 255/256]. + - Off-diagonal coefficients are unsigned. Valid range is [-7 255/256, 7 255/256]. + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_COLOR_CORRECTION +*/ +typedef struct _GFISPCOLORCORRECTION +{ + NvU16 R2R; /**< Red-to-red coefficient. Unsigned fixed point format. Valid range is [0, 7 255/256]. */ + NvS16 R2G; /**< Red-to-green coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvS16 R2B; /**< Red-to-blue coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvS16 G2R; /**< Green-to-red coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvU16 G2G; /**< Green-to-green coefficient. Unsigned fixed point format. Valid range is [0, 7 255/256]. */ + NvS16 G2B; /**< Green-to-blue coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvS16 B2R; /**< Blue-to-red coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvS16 B2G; /**< Blue-to-green coefficient. Signed fixed point format. Valid range is [-7 255/256, 7 255/256]. */ + NvU16 B2B; /**< Blue-to-blue coefficient. Unsigned fixed point format. Valid range is [0, 7 255/256]. */ + NvS16 Vividity; /**< Multiplier to boost the diagonal elements. Signed fixed point format. Valid Range [-64/256, 64/256]. */ + NvS16 VividityScaleFactor; /**< Multiplier to boost the diagonal elements. Signed fixed point format. Valid Range [-OffDiagona/64, OffDiagonal/64]. */ + NvU16 GainStart; /**< Starting Gain for Auto Vividity . */ + NvU16 GainEnd; /**< End Gain for Auto Vividity. */ +} GFISPCOLORCORRECTION, *PGFISPCOLORCORRECTION; + + +/** This structure describes one approximated linear segment for gamma. + @see GFISPGAMMACONTROL +*/ +typedef struct _GFISPGAMMAENTRY +{ + NvU16 inputStart; /**< Input start value of line segment. Valid range is [0, 1023]. */ + NvU16 outputStart; /**< Output start value of line segment. Valid range is [0, 255]. */ + NvS16 slope; /**< Slope of the line segment. Signed fixed point format. Valid range is [-7 63/64, 7 63/64]. */ + NvU16 reserved; +} GFISPGAMMAENTRY, *PGFISPGAMMAENTRY; + +/** Gamma correction control. + + This structure controls the gamma correction process. + + Gamma correction applies non-linear characteristics to compensate for the + non-linear characteristics of display devices such as cathode ray tubes driven + by R, G, B primary color signals. So, in a strict sense, this must be applied to + R, G, B signals. + + In SC15 implementation, gamma correction is approximated using up to 16 + line segments. Each line entry must be provided in ascending order (within + the input range). + + @see GFISPGetParameter, GFISPSetParameter, GFISP_ATTR_ENABLE_GAMMA_CORRECTION +*/ +typedef struct _GFISPGAMMACONTROL +{ + NvU32 nEntries; /**< Number of entries in the pEntries table. Valid range is [1-16]. */ + GFISPGAMMAENTRY *pEntries; /**< Gamma entry table. */ +} GFISPGAMMACONTROL, *PGFISPGAMMACONTROL; + + +/** Y signal range selection enum for #GFISPYUVCONVERSION. +*/ +typedef enum +{ + GFISP_YRANGE_FULL = 0, /**< Range of [0,255]. */ + GFISP_YRANGE_NEARFULL = 1, /**< Rage of [1,254] (exclude 00 and FF). */ + GFISP_YRANGE_ITU601 = 2 /**< ITU601 standard. */ +} GFISP_YRANGE_SEL; + +/** RGB to YUV conversion control. + This structure controls the YUV conversion process, which converts RGB + color space to corresponding YUV color space, based on the 3x3 matrix. + + {Y, U, V} shall have offset values that are not shown in the formula above. +*/ +typedef struct _GFISPYUVCONVERSION +{ + GFISP_YRANGE_SEL YRangeSel; /**< YUV output signal range. */ + NvS16 YOff; /**< Y value offset. Valid range is [-128, 127]. */ + + // 3x3 YUV conversion matrix. + // G2Y is unsigned fixed point format. Valid range is [0, 1 255/256]. + // R2Y and B2Y are unsigned fixed point format. Valid range is [0, 255/256]. + // R2U, G2U, B2U, R2V, G2V, B2V are signed fixed point format. + // Valid range is [-255/256, 255/256]. + NvS16 R2Y; /**< Red-to-Y coefficient. Unsigned fixed point format. Valid range is [0, 255/256]. */ + NvS16 G2Y; /**< Green-to-Y coefficient. Unsigned fixed point format. Valid range is [0, 1 255/256]. */ + NvS16 B2Y; /**< Blue-to-Y coefficient. Unsigned fixed point format. Valid range is [0, 1 255/256]. */ + NvS16 R2U; /**< Red-to-U coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 G2U; /**< Green-to-U coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 B2U; /**< Blue-to-U coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 R2V; /**< Red-to-V coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 G2V; /**< Green-to-V coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ + NvS16 B2V; /**< Blue-to-V coefficient. Signed fixed point format. Valid range is [-255/256, 255/256]. */ +} GFISPYUVCONVERSION, *PGFISPYUVCONVERSION; + +/** Isp set mode + This structure set ISP parameters to the specified mode, as specidied in the ISP script. +*/ +typedef struct _GFISPSETMODE +{ + NvS32 Mode; /**< Mode number. */ +} GFISPSETMODE, *PGFISPSETMODE; + +/** 3A AE parameter + These enum contains 3A AE control parameters. +*/ + +typedef enum +{ + GFISP_AE_FRAME_CHOICE_FIXED = 0, /**< fixed frame rate. At lowlux AE will use only digital gain to increase brightness */ + GFISP_AE_FRAME_CHOICE_FLEXIBLE = 1 /**< At lowlux AE will increase frame height first (i.e., lower frame rate) to increase brightness Frame height is bounded by FrameHeight at GFISP_AE_SENSORINFO. */ +}GFISP_AE_FRAME_CHOICE; + +typedef enum +{ + GFISP_AE_METERING_CHOICE_EVALUATIVE = 0, /**< calculate luminance average by propriotary algorithm */ + GFISP_AE_METERING_CHOICE_SPOT = 1, /**< calculate luminance average from center window only */ + GFISP_AE_METERING_CHOICE_CENTER = 2, /**< GFISP_AE_METERING_CHOICE_CENTER: calculate luminance average from weighted sum of center window and whole frame */ + GFISP_AE_METERING_CHOICE_MATRIX = 3 /**< calculate luminance average from weighted sum of 3x3 sub-windows */ +}GFISP_AE_METERING_CHOICE; + +typedef enum +{ + GFISP_AE_ANTIFLICKER_CHOICE_50HZ = 0, /**< use AEStep_50Hz in GFISP_AE_SENSORINFO as exposure steps */ + GFISP_AE_ANTIFLICKER_CHOICE_60HZ = 1, /**< use AEStep_60Hz in GFISP_AE_SENSORINFO as exposure steps */ + GFISP_AE_ANTIFLICKER_CHOICE_MANUAL = 2, /**< use ManualAntiFlickerStep in GFISP_AE_CONTROL1 as exposure steps */ + GFISP_AE_ANTIFLICKER_CHOICE_AUTO = 3 /**< enable auto anti-flickering */ +}GFISP_AE_ANTIFLICKER_CHOICE; + +/** 3A AE parameter + This structure contains 3A AE parameters. +*/ +typedef struct _GFISP3AAE +{ + NvU16 AETarget; /**< [0..255]. Target average luminance value for AE convergence. Higher value renders brighter image. */ + NvU16 AEToleranceIn; /**< [0..255]. Convergence tolerance from AESTATE_OUT to AESTATE_IN */ + NvU16 AEToleranceOut; /**< [0..255]. Convergence tolerance from AESTATE_OUT to AESTATE_IN. Normally AEToleranceOut >= AEToleranceIn */ + GFISP_AE_FRAME_CHOICE FrameRateChoice; /**< GFISP_AE_FRAME_CHOICE */ + GFISP_AE_METERING_CHOICE MeteringChoice; /**< GFISP_AE_METERING_CHOICE */ + GFISP_AE_ANTIFLICKER_CHOICE AntiFlickerChoice; /**< GFISP_AE_ANTIFLICKER_CHOICE */ + NvU8 ConvergeSpeed; /**< [1..15]. AE convergence speed. 1 being the fastest (immediate update) */ + NvS32 Status; /**< 3A AE Status. Read only */ + + NvU32 ManualAntiFlickerStep; // manual exposure step. Used when AntiFlickerChoice=GFISP_AE_ANTIFLICKER_CHOICE_MANUAL + NvS32 CenterWeight, FrameWeight; // weights for MeteringChoice=GFISP_AE_METERING_CHOICE_CENTER + NvS32 Metering11, Metering12, Metering13,// weights for MeteringChoice=GFISP_AE_METERING_CHOICE_MATRIX + Metering21, Metering22, Metering23, + Metering31, Metering32, Metering33; + NvU16 AdditionalLumaIncreaseForFlatScene;// [0..255]. give final exposure additional increase if scene is flat. + NvU16 BacklightTbright; // [0..255]. Threshold for determining "bright regions" (for backlight checking) + NvU16 BacklightTdark; // [0..255]. Threshold for determining "dark regions" (for backlight checking) + NvU16 TOverexposed; // [0..255]. Threshold for determining overexposed condition. + NvU16 TDark; // [0..255]. Threshold for determining dark condition. + NvU8 AutoNoiseControl; /**< Auto Noise Control */ +} GFISP3AAE, *PGFISP3AAE; + +/* Exposure parameter USED for Manual Exposure and Gain settings +*/ +typedef struct _GFISPEXPOSURECONTROL +{ + NvU32 MaxFrameHeight; // longest exposure time allowed. >= DefaultFrameHeight, in unit + // of per scanline. + // For constant framerate application, set MaxFrameHeight=FrameHeight. + + NvU32 DefaultFrameHeight; // sensor's default time difference betwee two consecutive VSYNC pulses, + // in unit of per scanline. + NvU32 DefaultFrameHeightIS; // Limit the frame height corresponding to ET of 1/60 sec + + NvU16 MaxGain; // [1..128]. max digital gains allowed. Normally set to 2 (=200%) + // if anti-flickering is on. If larger sensitivity boost is needed + // at lowlux condition set MaxGain to higher value. + NvU16 MinGain; //Minimum Exposure Gain in ISP Format + + NvU16 MaxGainIS; // max digital gain allowed in the case of image stabilization + +}GFISPEXPOSURECONTROL, *PGFISPEXPOSURECONTROL; + +/* Manual Exposure and Gain settings +*/ +typedef struct _GFISPMANUALEXPOSURE +{ + NvU32 Exposure; // exposure time + NvU32 Gain; // digital gain +}GFISPMANUALEXPOSURE, *PGFISPMANUALEXPOSURE; + + +/** 3A AWB parameter + This structure contains 3A AWB parameters. +*/ + +typedef enum +{ + GFISP_AWB_WBMODE_CLOUDY = 0, /**<: for cloudy conditions (7,000K - 8,000K) */ + GFISP_AWB_WBMODE_SUNNY = 1, /**<: for sunny conditions (5,500K - 6,000K) */ + GFISP_AWB_WBMODE_FLASH = 2, /**<: for strobe or xenon flashes (~5,000K) */ + GFISP_AWB_WBMODE_FLUORESCENT = 3, /**<: for indoor office conditions (~3,000K) */ + GFISP_AWB_WBMODE_INCANDESCENT = 4, /**<: for indoor home conditions (~2,800K) */ +}GFISP_AWB_WBCUSTOM; + +typedef enum +{ + GFISP_AWB_COPLEXITY_HIGH = 0, /***/ + GFISP_AWB_COPLEXITY_MEDIUM = 1, /***/ + GFISP_AWB_COPLEXITY_LOW = 2 /***/ +}GFISP_AWB_COMPLEXITY; + +typedef struct _GFISP3AAWB +{ + NvU8 fWBCustom; // =0 when WB Custom Setting OFF + // =1 when WB Custom Setting ON + GFISP_AWB_WBCUSTOM WBCustomK; // Choose one of the defined illum class when fWBCustom=1 + // GFISP_AWB_WBMODE_CLOUDY = 0, /**<: for cloudy conditions (7,000K - 8,000K) */ + // GFISP_AWB_WBMODE_SUNNY = 1, /**<: for sunny conditions (5,500K - 6,000K) */ + // GFISP_AWB_WBMODE_FLASH = 2 /**<: for strobe or xenon flashes (~5,000K) */ + // GFISP_AWB_WBMODE_FLUORESCENT = 3, /**<: for indoor office conditions (~3,000K) */ + // GFISP_AWB_WBMODE_INCANDESCENT = 4, /**<: for indoor home conditions (~2,800K) */ + // Must be < NumWBCustom + + GFISP_AWB_COMPLEXITY ComplexityMode; + NvS8 WBShift; /**< Moves up or down illuminant class. For white balance bracketing. */ + /**< timing and stability control */ + NvU8 ConvergeSpeed; /**< [0..6], 6 being the fastest (immediate update) */ + NvU8 ToleranceIn; /**< [0..255], tolerance for convergence. */ + NvU8 ToleranceOut; /**< [0..255], threshold for triggering new AWB update. Normally ToleranceIn < ToleranceOut, and both toelrances are small (e.g., 5 to 10). */ + NvU32 FilterCoefficient; /**< [0-20] Filter coefficient used for scene change detection . */ + NvU32 M3FilterCoefficient; /**< [0-60] Filter coefficient used for temporal low pass filtering of M3 Buffer . */ + NvU32 UseM3LPFilter; /**< Flag for M3 Low Pass Filter. 1 = Enable LPF, 0 = Disable */ + NvU32 KXYCorrelation; /**< To be used for scene change detection. */ + + NvS32 Status; /**< 3A AWB Status. Read only */ +} GFISP3AAWB, *PGFISP3AAWB; + +typedef enum +{ + GFISP_AFSTATE_IN = 0, + GFISP_AFSTATE_OUT = 1, + GFISP_AFSTATE_INIT = 2 +}GFISP_AF_STATE; + +typedef enum +{ + GFISP_AF_TYPE_CENTER = 1, + GFISP_AF_TYPE_AUTO_EVALUATE = 2, + GFISP_AF_TYPE_FACE_PRIORITY = 3 +}GFISP_AF_TYPE; + +typedef enum +{ + GFISP_AF_MODE_CONTINUOUS = 0, + GFISP_AF_MODE_SINGLE = 1 +}GFISP_AF_MODE; + +/** 3A AF parameter + This structure contains 3A AF parameters. +*/ +typedef struct _GFISP3AAF +{ + GFISP_AF_STATE Status; /**< 3A AF Status. Read only */ + GFISP_AF_MODE Mode; + NvU8 Speed; + NvU8 LockTillAE; + NvU8 LockTillAWB; + NvU8 TakeSnapshot; +} GFISP3AAF, *PGFISP3AAF; + +/** ISP 3A Capability. +To get the 3A capability for a particular sensor. +*/ +typedef struct _GFISPSENSORCAPABILITY +{ + NvU8 AWBCapability; /***/ + NvU8 AECapability; /***/ + NvU8 AFCapability; /***/ + NvU8 ManualOBCapability; /***/ + NvU8 AutoOBCapability; /***/ +}GFISPSENSORCAPABILITY, *PGFISPSENSORCAPABILITY; + + + +typedef enum +{ + GFISP_SENSOR_I2C_8_BIT_REGISTER = 0, + GFISP_SENSOR_I2C_16_BIT_REGISTER = 1, +} REGISTERTYPE; + +typedef struct _GFISPSENSORRWREGISTER +{ + REGISTERTYPE RegisterType; //0: 8-bit register , 1: 16-bit register + NvU32 Addr; /**< Address : data read-write address>*/ + NvU32 Data; /**< Value of data at that address >*/ +}GFISPSENSORRWREGISTER, *PGFISPSENSORRWREGISTER; + +/** 3A algorithm type + These enum contains 3A algorithm type required for checking convergence. +*/ +typedef enum +{ + GFISP_CB_REGISTER_3A_AWB = 0, + GFISP_CB_REGISTER_3A_AE = 1, + GFISP_CB_REGISTER_3A_AF = 2 +} GFISP3ATYPE; + +/** Enabling or disabling the "gain reduction and gamma compression" property for reducing noise introduced due to high gain +* in case of Image Stabilization. +*/ +typedef enum +{ + GFISP_REDUCE_GAIN_COMPRESS_GAMMA_ON, + GFISP_REDUCE_GAIN_COMPRESS_GAMMA_OFF +} GFISPGAINGAMMACTRL; +/** Public exposed ISP API function table. See @ref groupIspFunctions. */ +typedef struct _GFISPTABLE +{ + GF_RETTYPE (* ISPGetProperty) ( GFIspHandle ISPHandle, PGFISPPROPERTY pIspProp ); + +#if defined(DVS_DEVELOPMENT) + GF_RETTYPE (* ISPSetup) ( GFIspHandle ISPHandle, GFVxHandle VxHandle, PGFCAMERARESOLUTIONTYPE pCameraResolution, GFVXBLT vxBlt ); +#else + GF_RETTYPE (* ISPSetup) ( GFIspHandle ISPHandle, PGFCAMERARESOLUTIONTYPE pCameraResolution ); +#endif + + GF_RETTYPE (* ISPSetResolution) ( GFIspHandle ISPHandle, PGFCAMERARESOLUTIONTYPE pCameraResolution ); + + GF_RETTYPE (* ISPGetAttribute) ( GFIspHandle ISPHandle, + GFISPATTRIBUTES aid, + NvU32 *attr); + GF_RETTYPE (* ISPSetAttribute) ( GFIspHandle ISPHandle, + GFISPATTRIBUTES aid, + NvU32 attr); + + GF_RETTYPE (* ISPSetAttributeToDefault) (GFIspHandle ISPHandle, GFISPATTRIBUTES aid); + + GF_RETTYPE (* ISPGetParameter) ( GFIspHandle ISPHandle, + GFISPPARAMETERS pid, + NvU32 *pSize, + void *pPara); + GF_RETTYPE (* ISPSetParameter) ( GFIspHandle ISPHandle, + GFISPPARAMETERS pid, + NvU32 size, + void *pPara); + + GF_RETTYPE (* ISPSetParameterToDefault) (GFIspHandle ISPHandle, GFISPPARAMETERS pid); + + GF_RETTYPE (* ISPTriggerMWindowGather) (GFIspHandle ISPHandle); + + GF_RETTYPE (* ISPReadMWindowValues) ( GFIspHandle ISPHandle, + NvS32 szM1Buffer, + NvU32 *pM1Buffer, + NvS32 szM2Buffer, + NvU32 *pM2Buffer, + NvS32 szM3Buffer, + NvU32 *pM3Buffer, + NvS32 szM4Buffer, + NvU32 *pM4Buffer); + + GF_RETTYPE (* ISPOEMScriptFunc) (GFIspHandle ISPHandle, + NvU32 ScriptFuncTag, + NvU32 size, + NvU32 *pBuffer); + + GF_RETTYPE (* ISP3APeriodicTrigger)(GFIspHandle ISPHandle); + + GF_RETTYPE (* ISPAeBracketingSetET) (NvS32 mode, NvU32 *pRetExposure, NvS32 *pRetGain); + + GF_RETTYPE (* ISPAwbBracketingSetIllum) (NvS32 mode, NvU16 *pRetCCT); + + GF_RETTYPE (* ISPRegister3ACallback) (GFIspHandle ISPHandle, GFISP3ATYPE type, void (*func)(void *), void *pParameter); + +} GFISPTABLE, *PGFISPTABLE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFIspOpen(GFRmHandle hRm, GFIspHandle *phIsp, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFIspClose(GFIspHandle *phIsp); + +/** @defgroup groupIspFunctions ISP Function macros + These function macros represent the function calls for GFISPAPI. +*/ +/*@{*/ + +/** Returns information about the GFISPAPI. + + @param handle Valid handle to GFISPAPI component. + @param pIspProp Pointer to a #GFISPPROPERTY struct. + For the sake of future expansion, the caller should put the size of + the structure into the #GFISPPROPERTY::size field; GFISPAPI will not + fill the structure beyond this size. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_SIZE_TOO_SMALL Error: size parameter is too small to fit even partial results. + + This function returns information about the GFISPAPI, including the + following: + - GFISPAPI module version + - ISP capability + - ISP limit parameters + It is good practice to use this function to query for the API version and + capabilities before using other GFISPAPI functions. + + @see GFISPPROPERTY, groupIspCapability +*/ +#define GFISPGetProperty( handle, pIspProp ) \ + ((PGFISPTABLE)handle)->ISPGetProperty( handle, pIspProp ) + +/** Sets up the ISP API for use with a particular camera. + + @param handle Valid handle to GFISPAPI component. + @param pCameraResolution Pointer to a #GFCAMERARESOLUTIONTYPE structure + with valid BayerInfo. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + + You must call GFISPGetProperty before calling any other ISP API functions, + with the exception of GFISPGetProperty. This function initializes ISP + to work with a particular resolution of camera. + +*/ +#if defined(DVS_DEVELOPMENT) +#define GFISPSetup( handle, vxhandle, pCameraResolution, vxBlt ) \ + ((PGFISPTABLE)handle)->ISPSetup( handle, vxhandle, pCameraResolution, vxBlt ) +#else +#define GFISPSetup( handle, pCameraResolution ) \ + ((PGFISPTABLE)handle)->ISPSetup( handle, pCameraResolution ) +#endif + +/** Resizes/repositions all windows based on resolution data. + + @param handle Valid handle to GFISPAPI component. + @param pCameraResolution Pointer to a #GFCAMERARESOLUTIONTYPE structure + with valid BayerInfo. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + This function resizes and repositions the windows for several ISP parameters + based on the provided BayerInfo struct. Affected parameters are: + - Timing + - M1-M4 statistics windows + - Optical black regions + - Lens shading center point + +*/ +#define GFISPSetResolution( handle, pCameraResolution ) \ + ((PGFISPTABLE)handle)->ISPSetResolution( handle, pCameraResolution ) + +/** Get an attribute of the GFISPAPI. + + @param handle Valid handle to GFISPAPI component. + @param aid Attribute ID. One of #GFISPATTRIBUTES enumeration type. + @param pAttrData Pointer to an #NvU32 to be filled with the attribute value. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPATTRIBUTES +*/ +#define GFISPGetAttribute( handle, aid, pAttrData ) \ + ((PGFISPTABLE)handle)->ISPGetAttribute( handle, aid, pAttrData ) + +/** Set an attribute of the GFISPAPI. + + @param handle Valid handle to GFISPAPI component. + @param aid Attribute ID. A #GFISPATTRIBUTES enumeration type value. + @param attrData Pointer to an #NvU32 to be filled with the attribute value. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + Under the NVIDIA ISP implementation, certain ISP functions can be turned + on or off independent of parameter settings. In most cases, this function + simply switches certain ISP functions on or off. + + To set parameters for specific ISP functions, see GFISPSetParameter(). + + @see GFISPATTRIBUTES +*/ +#define GFISPSetAttribute( handle, aid, attrData ) \ + ((PGFISPTABLE)handle)->ISPSetAttribute( handle, aid, attrData ) + +/** Set an attribute of the GFISPAPI to its default value. + + @param handle Valid handle to GFISPAPI component. + @param aid Attribute ID. A #GFISPATTRIBUTES enumeration type value. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPATTRIBUTES +*/ +#define GFISPSetAttributeToDefault( handle, aid ) \ + ((PGFISPTABLE)handle)->ISPSetAttributeToDefault( handle, aid ) + +/** Get parameters for a given ISP functional block. + + @param handle Valid handle to GFISPAPI component. + @param pid Parameter ID. A #GFISPPARAMETERS enumeration type value. + @param pSize Pointer to an #NvU32 to be filled with the parameter size. Can be NULL. + @param pPara Pointer to a certain GFISPAPI data structure, depending on #pid. Can be NULL. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPPARAMETERS +*/ +#define GFISPGetParameter( handle, pid, pSize, pPara ) \ + ((PGFISPTABLE)handle)->ISPGetParameter( handle, pid, pSize, pPara ) + +/** Set parameters for a given ISP functional block. + + @param handle Valid handle to GFISPAPI component. + @param pid Parameter ID. A #GFISPPARAMETERS enumeration type value. + @param size #NvU32 with actual size of GFISPAPI structure pointed to by #pPara. + @param pPara Pointer to a certain GFISPAPI data structure, depending on #pid. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_SIZE_TOO_SMALL #size parameter is too small + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPPARAMETERS +*/ +#define GFISPSetParameter( handle, pid, size, pPara ) \ + ((PGFISPTABLE)handle)->ISPSetParameter( handle, pid, size, pPara ) + +/** Set parameters for a given ISP functional block to their default value. + + @param handle Valid handle to GFISPAPI component. + @param pid Parameter ID. A #GFISPPARAMETERS enumeration type value. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_ILLEGAL_PARAMETER One or more parameters is NULL or out-of-range. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + @see GFISPPARAMETERS +*/ +#define GFISPSetParameterToDefault( handle, pid ) \ + ((PGFISPTABLE)handle)->ISPSetParameterToDefault( handle, pid ) + +/** Triggers MWindow statistics to be gathered on the next frame. + + @param handle Valid handle to GFISPAPI component. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + This function will trigger MWindow statistics to be gathered for + any of the M2, M3, M4 statistics that are turned on. M1 statistics + are constantly gathered. The statistics will become available at + the end of the next frame, and can be read by calling + GFISPReadMWindowValues(). + + Calling GFISPTriggerMWindowGather implicitly sets + #GFISP_ATTR_ENABLE_STATS_INT to 1. + + @see GFISPReadMWindowValues +*/ +#define GFISPTriggerMWindowGather( handle ) \ + ((PGFISPTABLE)handle)->ISPTriggerMWindowGather( handle ) + +/** Reads gathered MWindow statistics if they are ready. + + @param handle Valid handle to GFISPAPI component. + @param szM1Buffer Maximum size of M1Buffer provided by caller (in bytes). The + GFISPAPI fills the buffer as much as it can. If zero, the GFISPAPI + doesn't fill the M1Buffer. + @param pM1Buffer Array of 8 data. First four 32-bit values will be filled with average + RGGB pixel values. Next four values will be filled with peak pixel values. + Can be NULL, then the GFISPAPI doesn't fill M1Buffer. + @param szM2Buffer Maximum size of M2Buffer provided by caller (in bytes). The + GFISPAPI fills the buffer as much as it can. If zero, the GFISPAPI + doesn't fill the M2Buffer. + @param pM2Buffer Array of 16 data. Data is arranged in 32-bit words as follows: + {R1, Gr1, Gb1, B1, + R2, Gr2, Gb2, B2, ...} + Can be NULL, then the GFISPAPI doesn't fill M2Buffer. + @param szM3Buffer Maximum size of M3Buffer provided by caller (in bytes). The + GFISPAPI fills the buffer as much as it can. If zero, the GFISPAPI + doesn't fill the M3Buffer. + @param pM3Buffer Array to hold pixel samples. The size matches the M3 Window specification. + The data is arranged as follows: + {R1, R2, R3, R4}, + {Gr1, Gr2, Gr3, Gr4}, + {Gb1, Gb2, Gb3, Gb4}, + {B1, B2, B3, B4}, + {R5, R6, R7, R8}, + ... + Can be NULL, then the GFISPAPI doesn't fill M3Buffer. + @param szM4Buffer Maximum size of M4Buffer provided by caller (in bytes). The + GFISPAPI fills the buffer as much as it can. If zero, the GFISPAPI + doesn't fill the M4Buffer. + @param pM4Buffer Array of 2*M4WindowNumber data. Data is arranged as follows: + {HF1, Luma1, HF2, Luma2, ...} + Can be NULL, then the GFISPAPI doesn't fill M4Buffer. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_STATISTICS_NOT_READY M2/M3/M4 statistics not ready. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + Call this function to read the MWindow values gathered by the last call to + GFISPTriggerMWindowGather(). The user may either poll for statistics ready + by checking the return code, or use the interrupt mechanism to only call + GFISPReadMWindowValues once the statistics are ready. + + After the statistics are gathered, they will remain available for reading + until the next call to GFISPTriggerMWindowGather(). + + M1 statistics are gathered every frame regardless of whether + GFISPTriggerMWindowGather() has been called. The user can read + the last frame's M1 statistics without ever triggering a gather by + passing 0 and NULL for the M2-M4 parameters to GFISPReadMWindowValues(). + + @see GFISPTriggerMWindowGather +*/ +#define GFISPReadMWindowValues( handle, szM1Buffer, pM1Buffer, \ + szM2Buffer, pM2Buffer, szM3Buffer, pM3Buffer, szM4Buffer, pM4Buffer ) \ + ((PGFISPTABLE)handle)->ISPReadMWindowValues( handle, szM1Buffer, pM1Buffer, \ + szM2Buffer, pM2Buffer, szM3Buffer, pM3Buffer, szM4Buffer, pM4Buffer ) + +/** Call Oem function defined in ISP script. + + @param handle Valid handle to GFISPAPI component. + @param ScriptFuncTag Function tag used by the script. + @param size Number of entries in the buffer pointed to by #pBuffer. + @param pBuffer Point to a @param #NvU32 buffer that will be passed to script function. + Use it to send parameter to script function and get data back. + + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + Call this function to access script function OemScriptFunc(). +*/ +#define GFISPOEMScriptFunc( handle, ScriptFuncTag, size, pBuffer ) \ + ((PGFISPTABLE)handle)->ISPOEMScriptFunc( handle, ScriptFuncTag, size, pBuffer ) + +/** Trigger periodic software 3A function. + + @param handle Valid handle to GFISPAPI component. + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR_CALL_SETUP_FIRST The application did not call GFISPSetup() prior to calling this function. + + Call this function at every vertical blank to trigger periodic software 3A function +*/ +#define GFISP3APeriodicTrigger( handle ) \ + ((PGFISPTABLE)handle)->ISP3APeriodicTrigger( handle ) + +/** Exposure Bracketing Function + @param handle Valid handle to GFISPAPI component + @param mode Range: 0 Exposure value output by AC Algo + -1 Less by one-third stop than AC Output + 1 More by one-third stop than AC Output + @param.pRetExpsoure Expsoure at current mode is returned through this pointer + @param pGain Gain at current mode is returned through this pointer + @retval GF_SUCCESS or GF_ERROR + + Call this function three times with different modes each time in order to record images with exposure bracketing +*/ +#define GFISPAeBracketingSetET(handle, mode, pRetExposure, pRetGain) \ + ((PGFISPTABLE)handle)->ISPAeBracketingSetET( mode, pRetExposure, pRetGain ) + +/** White Balance Bracketing Function + @param handle Valid handle to GFISPAPI component + @param mode Range: 0 Exposure value output by AC Algo + -1 Less by one Illuminant than AC Output + 1 More by one Illuminant than AC Output + @param pRetCCT Color Temprature at current mode is returned through this pointer + @retval GF_SUCCESS or GF_ERROR + + Call this function three times with different modes each time in order to record images with White Balance bracketing +*/ +#define GFISPAwbBracketingSetIllum(handle, mode, pRetCCT) \ + ((PGFISPTABLE)handle)->ISPAwbBracketingSetIllum( mode, pRetCCT ) + +/** Register callback function for the convergence of software Auto White balance + + @param handle Valid handle to GFISPAPI component. + @param algoType whether AWB, AE or AF + @param func Pointer to the callback function + @param pParameter pointer to the argument of function call + @retval GF_SUCCESS Success + @retval GFISP_ERROR_BAD_HANDLE #handle is invalid. + @retval GFISP_ERROR If invalid function pointer is passed + + Call this function when application wants to know whether the auto white balance algorithm is converged or not. + When algorithm converges it calls the function func which is registered as callback function. +*/ +#define GFISPRegister3ACallback(handle, algoType, func, pParameter) \ + ((PGFISPTABLE)handle)->ISPRegister3ACallback( handle, algoType, func, pParameter ) + +/*@}*/ // End function macros + +/*@}*/ // End ISP API Doxygen + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GF_ISP__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFIspError.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFIspError.h new file mode 100755 index 00000000..4f173424 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFIspError.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFIspError.h + * GFSDK Image Signal Processor API error code header file. + */ + +#ifndef __GFISPERROR_H__ +#define __GFISPERROR_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define GFISP_ERROR_ILLEGAL_PARAMETER (GFISP_ERROR | 0x00000001L) +#define GFISP_ERROR_BAD_HANDLE (GFISP_ERROR | 0x00000002L) +#define GFISP_ERROR_SIZE_TOO_SMALL (GFISP_ERROR | 0x00000003L) +#define GFISP_ERROR_STATISTICS_NOT_READY (GFISP_ERROR | 0x00000004L) +#define GFISP_ERROR_CALL_SETUP_FIRST (GFISP_ERROR | 0x00000005L) +#define GFISP_ERROR_OUT_OF_MEMORY (GFISP_ERROR | 0x00000006L) + +#ifdef __cplusplus +} +#endif + +#endif // __GFISPERROR_H__ + + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFJxDec.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFJxDec.h new file mode 100755 index 00000000..879f10ed --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFJxDec.h @@ -0,0 +1,508 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFJxDec.h +GFSDK JPEG Decode API header file. +*/ +#ifndef _GF_JPEG_DEC__ +#define _GF_JPEG_DEC__ + +#include "nvtypes.h" +#include "GFVx.h" + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif + +/** @addtogroup groupJx JxDecAPI JPEG Decoder API +*/ + /*
        +
      • @ref pageGxAppNotes +
          +
        • @ref pageGxAppNotes1 +
        +
      + */ + +/*@{*/ + +// JXDECCapFlags + +/** JxDecAPI property flag: Support for Sequential encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_SEQUENTIAL_DCT 0x00000001 + +/** JxDecAPI property flag: Support for Progressive encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_PROGRESS_DCT 0x00000002 + +/** JxDecAPI property flag: Support for lossless encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_LOSSLESS 0x00000004 + +/** JxDecAPI property flag: Support for hierarchical encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_HIERARCHICAL 0x00000008 + +/** JxDecAPI property flag: Support for 8 bits encoded JPEG. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_8_BIT 0x00000010 + +/** JxDecAPI property flag: "No" Support for 12 bits encoded JPEG Presently. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_12_BIT 0x00000020 + +/** JxDecAPI property flag: Support for Interleaved mode. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_INTERLEAVE 0x00000040 + +/** JxDecAPI property flag: "No" Support presently for Interleaved mode. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_NO_INTERLEAVE 0x00000080 + +/** JxDecAPI property flag: Support for Huffman Coding. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_HUFFMAN 0x00000100 + +/** JxDecAPI property flag: No Support for Arithematic Coding presently. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_ARITHMETIC 0x00000200 + +/** JxDecAPI property flag: No Support for Interchange format coding. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_INTERCHANGE 0x00000400 + +/** JxDecAPI property flag: Support for Pixel Based Cropping(MCU based Cropping). + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_CROPPING 0x00001000 + +/** JxDecAPI property flag: Support for YUV444 encoded JPEG images. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_YUV444 0x00002000 + +/** JxDecAPI property flag: Support for YUV422 encoded JPEG images. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_YUV422 0x00004000 + +/** JxDecAPI property flag: YUV422 Rotation Supported. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_ROTATED_YUV422 0x00008000 + +/** JxDecAPI property flag: Support for YUV420 encoded JPEG images. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_YUV420 0x00010000 + +/** JxDecAPI property flag: Support for Gray Scale encoded JPEG images. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_GRAY_SCALE 0x00020000 + +/** JxDecAPI property flag: Support for Extended RGB format 24/32 bpp. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_EXTEND_RGB 0x00040000 + +/** JxDecAPI property flag: Support for YUV420 output decoded format. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_420_OUTPUT 0x00080000 + +/** JxDecAPI property flag: Support for YUV422 output decoded format. + @see GFJxDecGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JXDEC_CAP_422_OUTPUT 0x00100000 + +/** Image source dimensions and color format of the input JPEG to be decoded. + This structure is passed as parameter to GFJxDecGetImageInfo(). + + @see GFRMSURFACE::ColorFormat, GFJxDecGetImageInfo() +*/ +typedef struct _GFJXDECIMAGEINFO +{ + NvU32 IIFlag; /**< Deprecated, do not use. + This variable is set to the same error code as returned by GFJxDecGetImageInfo(). + @deprecated + */ + NvU32 Width; /**< Width of the input image */ + NvU32 Height; /**< Height of the input image */ + NvU32 ColorFormat; /**< Color Format of input image (YUV420, YUV422, ...) + @see GFRMSURFACE.ColorFormat */ +}GFJXDECIMAGEINFO, *PGFJXDECIMAGEINFO; + +/** GFJxDecStart parameter structure. + This structure specifies target surface, scaling, source + and destination cropping for the decode operation. + + @see GFJxDecStart() +*/ +typedef struct _GFJXDECSTART +{ + NvU32 SFlag; /**< Deprecated, do not use. @deprecated */ + PGFRMSURFACE pDestSurf; /**< Destination Surface to hold the decoded image. + The color format of the surface controls the output color format. + If no destination cropping rectangle is given, the decoded picture + is scaled to match the surface size. + */ + PGFRECT pCroppingRect; /**< Source cropping area to be decoded, or NULL for no cropping. + Top-left position of the cropping rectangle must be aligned + to an MCU boundary. + */ + PGFRECT pDestRect; /**< Destination cropping area, or NULL for no cropping. + If a destination cropping rectangle is given, the decoded picture + will be scaled to fit this rectangle. + */ + NvU32 Error; /**< Deprecated, do not use. + This variable will be set to the same value as returned by GFJxDecStart(). + @deprecated + */ +} GFJXDECSTART, *PGFJXDECSTART; + + +//SFlag: not used anymore. Cropping is decided on whether +//the pCroppingRect is NULL or not +#define GF_JXDEC_SFLAG_CROPPING 0 + +/** GF_DECODER_IDLE is returned if hardware decoder is idle by GFJxDecGetStatus(). + @see GFJxDecGetStatus() +*/ +#define GF_DECODER_IDLE 0x00000001 + +/** GF_DECODER_BUSY is returned if hardware decoder is busy by GFJxDecGetStatus(). + @see GFJxDecGetStatus() +*/ +#define GF_DECODER_BUSY 0x00000002 + + +/** JxDecAPI Pass JX_DEC_SET_READBITSTREAM to GFJxDecSet to register call back function +@see GFJxDecSet() +*/ +#define JX_DEC_SET_READBITSTREAM 1 + +/** Structure holding the callback function pointer. + Used in registering the callback function +*/ +typedef struct _GFJXDECCALLBACK +{ + void *pPara; /**< Not used anymore */ + NvU32 (*pCallBack)(void * pPara, NvU8 ** ppBuffer, NvS32 * BufferLength); + /**< + Application callback function pointer. + Register a callback function for fetching JPEG Image data. + + @param *pPara Not used anymore + @param ppBuffer Buffer Pointer + @param BufferLength Buffer Length in bytes, 0 if no bytes read. + + @retval The number of bytes read successfully, 0 if no bytes read. + */ + +}GFJXDECCALLBACK, *PGFJXDECCALLBACK; + +/** Structure holding the callback function pointer. + Used in registering the callback function +*/ +typedef struct _GFJXDECGETIMAGECALLBACK +{ + void *pPara; + /**< pPara is a parameter passed from application, + and application wants API to call back with this parameter + */ + NvU32 (*pCallBack)(void * pPara, PGFRMSURFACE pImageSurf, PGFRECT pImageRect, NvU32 uiImageFlag); + /**< + Application callback function pointer. + Register a callback function for fetching decoded JPEG Image data. + + @param *pPara Parameter to pass on to application callback function + @param pImageSurf Surface Pointer + @param pImageRect Source rectangle + @param uiImageFlag + + + +
      #JX_DEC_IF_LAST_PORTION_IMAGEThis is the last portion of decoded image
      + @retval 0 + */ +}GFJXDECGETIMAGECALLBACK, *PGFJXDECGETIMAGECALLBACK; + + +/** This is the last portion of the Image. + @see GFJXDECGETIMAGECALLBACK +*/ +#define JX_DEC_IF_LAST_PORTION_IMAGE 0x00000001 //this is the last portion of decoded image + +//Attribute uiFeature + +/** Set get decoded image call back(inorder to dump the decoded YUV from JPEG). + @see GFJXDECGETIMAGECALLBACK, GFJxDecGetImageInfo +*/ +#define JX_DEC_GETIMAGE 0x00000001 + +/** Pass JX_DEC_GETIMAGE_COLORFORMAT with GFJxDecGetAttribute to get JPEG image color format. */ +#define JX_DEC_GETIMAGE_COLORFORMAT 0x00000002 + + +/** Call this function get the JxDec Component's handle. + @param hRm (#GFRmHandle) Handle to the Resource Manager + @param phJxDec (#GFJxDECHandle) Pointer to the JxDecAPI Handle + @param state Set to Default state. + @param hCh (#GFRmChHandle) Channel Handle + @retval #GF_SUCCESS JxDec component registered successfully + @retval #GF_ERROR Some error occured +*/ +GF_RETTYPE GFJxDecOpen(GFRmHandle hRm, GFJxDecHandle *phJxDec, GF_STATE_TYPE state, GFRmChHandle hCh); + + +/** The function releases the JxDec's Component handle. + @param phJxDec (#GFJxDECHandle) Pointer to the JxDecAPI Handle +*/ +void GFJxDecClose(GFJxDecHandle *phJxDec); + +/** This function returns version and capabilities of JPEG decoder. + + @param hJxDec Handle to JxDecAPI + @param pJXProp Pointer to property structure to be filled in + + @retval #GF_SUCCESS \a pJXProp filled in successfully + @retval #GF_ERROR Some error occured + + @see GFPROPERTY +*/ +GF_RETTYPE GFJxDecGetProperty(GFJxDecHandle hJxDec, PGFPROPERTY pJXProp); + +/** This function returns the status of the JPEG Decoder + + @param hJxDec Handle to JxDecAPI + @param pStatus Returns status, GF_DECODER_BUSY or GF_DECODER_IDLE. +*/ +GF_RETTYPE GFJxDecGetStatus(GFJxDecHandle hJxDec, NvU32* pStatus); + +/** The funtion gets the information about the input image and fills it into the pInfo + + If the function fails, it will return an error code describing the failure cause. + + @param hJxDec Handle to JxDecAPI + @param pInfo Pointer to Image Information structure to be filled in + + @retval GF_SUCCESS \a pInfo filled in successfully + @retval GF_JXDEC_IFLAG_INVALID_MARKER Invalid Marker in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_HDR_LEN Invalid header (marker) length in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_SIG Invalid Image Signature(eg: JFIF, AVI, ..) in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_DQT Invalid Quantization Table in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_DHT Invalid Huffman Tables in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_VALUE Invalid image parameters (eg: width, height , ...) in JPEG file + @retval GF_JXDEC_IFLAG_INVALID_FORMAT Invalid format in JPEG file + @retval GF_JXDEC_IFLAG_PROGRESSIVE_MARKER Invalid Marker in JPEG file + @see GFJXDECIMAGEINFO +*/ +GF_RETTYPE GFJxDecGetImageInfo(GFJxDecHandle hJxDec, PGFJXDECIMAGEINFO pInfo); + +/** This function sets up a callback function + @param hJxDec Handle to JxDecAPI + @param uiFeature Feature ID to set + @param pInfo Feature specific parameter + + + + + + + + +
      \a uiFeature\a pInfo interpretationMeaning
      JX_DEC_SET_READBITSTREAMGFJXDECCALLBACK*Set up Jpeg bitstream feed callback
      + + @retval #GF_SUCCESS If successful + @retval #GFJXD_ERROR_INVALID_PARAMETER Invalid parameter + + @see GFJXDECCALLBACK +*/ +GF_RETTYPE GFJxDecSet(GFJxDecHandle hJxDec, NvU32 uiFeature, void* pInfo); + +/** Set attributes for the decoder. + @param hJxDec Handle to JxDecAPI, + @param attrID Attribute ID to be set + @param pInfo Attruvyte specific parameter + + + + + + +
      #JX_DEC_GETIMAGE Get the YUV decoded JPEG image into a file, Sets the decoder image callback
      #JX_DEC_GETIMAGE_COLORFORMAT Set get decoded image color format.
      + + @retval #GF_SUCCESS +*/ +GF_RETTYPE GFJxDecSetAttribute(GFJxDecHandle hJxDec, NvU32 attrID, NvU32* pInfo); + +/** Gets attributes for the decoder + @param hJxDec Handle to JxDecAPI, + @param attrID Attribute ID to read + @param pInfo Pointer to block returning attribute specific data + + + + + +
      #JX_DEC_GETIMAGE Get the YUV decoded JPEG image into a file, Sets the decoder image callback
      #JX_DEC_GETIMAGE_COLORFORMAT Set get decoded image color format.
      +*/ +GF_RETTYPE GFJxDecGetAttribute(GFJxDecHandle hJxDec, NvU32 attrID, NvU32* pInfo); + +/** Setup JxDecAPI for JPEG decoding a frame. + + If GFJxDecStart() fails, it will return an error code describing the failure cause. + If GFJxDecStart() succeeded, GFJxDecEnd() must be called later. + + @param hJxDec Handle to JxDecAPI + @param pStart Pointer to #GFJXDECSTART parameter structure. + + @retval GF_SUCCESS Success + @retval GFRM_ERROR_OUT_MEMORY Not enough free GPU or system memory + @retval GF_JXDEC_NOT_SUPPORT_DESTSURFACE_FORMAT Destination Surface format not supported by the decoder + @retval GF_JXDEC_DECODER_WIDTH_TOO_BIG Image source width exceeds max decoder width + @retval GF_JXDEC_DECODER_HEIGHT_TOO_BIG Image source height exceeds max decoder height + + @see GFJXDECSTART, GFJxDecSetAttribute(),GFJxDecEnd() +*/ +GF_RETTYPE GFJxDecStart(GFJxDecHandle hJxDec, PGFJXDECSTART pStart); + +/** Decode the image + @param hJxDec Handle to JxDecAPI + @param uiFlag Reserved, must be 0. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @see GFJxDecGetImageInfo(), GFJxDecStart(), GFJxDecSetAttribute(), GFJxDecEnd() + +*/ +GF_RETTYPE GFJxDecDecodeImage(GFJxDecHandle hJxDec, NvU32 uiFlag); + +/** End or cancel decoding a frame. + Must be called only, if GFJxDecStart() has been called before. + @param hJxDec Handle to JxDecAPI +*/ +GF_RETTYPE GFJxDecEnd(GFJxDecHandle hJxDec); + + +/** GFJxDecAPI Error Codes. */ +enum +{ + /** GFJxDecAPI API called with invalid parameters. */ + GFJXD_ERROR_INVALID_PARAMETER = GFJXD_ERROR, + + /** Operation not supported. */ + GFJXD_ERROR_NOT_SUPPORTED, + + /** Encountered incomplete bitstream during decoding. */ + GFJXD_ERROR_INCOMPLETE_BITSTREAM, + + /** GFJxDecStart() return code: Can't support this destination surface type. + @see GFJXDECSTART, GFJxDecStart() + */ + GF_JXDEC_NOT_SUPPORT_DESTSURFACE_FORMAT, + + /** GFJxDecStart() return code: Image width is too big for hardware decoder to handle + @see GFJXDECSTART, GFJxDecStart() + */ + GF_JXDEC_DECODER_WIDTH_TOO_BIG, + + /** GFJxDecStart() return code: Image height is too big for hardware decoder to handle + @see GFJXDECSTART, GFJxDecStart() + */ + GF_JXDEC_DECODER_HEIGHT_TOO_BIG, + + /** GFJxDecGetImageInfo() return code: If set then the input marker is Invalid, + if unset its a valid marker. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_MARKER, + + /** GFJxDecGetImageInfo() return code: If set then the Header Length is Invalid, + if unset its a valid header length. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_HDR_LEN, + + /** GFJxDecGetImageInfo() return code: If set then the Signature(eg: JFIF, AVI, ..) is Invalid, + if unset its a valid signature. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_SIG, + + /** GFJxDecGetImageInfo() return code: If set then the there occured an error in reading the Quantization Table, + if unset the Quantization Table was read clean. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_DQT, + + /** GFJxDecGetImageInfo() return code: If set then the Huffman Tables were not loaded properly + if unset Huffman Tables were loaded. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_DHT, + + /** GFJxDecGetImageInfo() return code: If set then there was an invalid value(eg : erroneous/incomplete bitstream) in the stream, + if unset its a valid Iflag. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_VALUE, + + /** GFJxDecGetImageInfo() return code: If set then the progressive marker not supported, + if unset its a valid marker. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + + GF_JXDEC_IFLAG_PROGRESSIVE_MARKER, + /** GFJxDecGetImageInfo() return code: If set then there was an invalid header format encountered in the stream, + if unset its a valid Iflag. + @see GFJXDECIMAGEINFO, GFJxDecGetImageInfo() + */ + GF_JXDEC_IFLAG_INVALID_FORMAT +}; + + +/** @page pageJxDecAppNotes JxDecAPI Application Notes + @section pageJxDecAppNotes Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start GFSDK usage. + -# Call GFJxDecOpen() to obtain JxDecHandle which will be passed to different functions of JxDecAPI. + -# Query the properties through GFJxDecGetProperty() to check whether the desired JxDec features can be supported. + -# Call GFRmSurfaceAlloc() to allocate one surface to hold the decoded image. + -# Register the call back function using GFJxDecSet() + -# Call GFJxDecGetImageInfo() to get the JPEG image information, such as width and height. + -# GFJxDecStart() is the next function to call. This function will setup the decoder. + -# Call GFJxDecDecodeImage() to do the real decoding. + -# After the whole bitstream has been fed, call GFJxDecEnd() to end the decoding process. + -# Release surface by calling GFRmSurfaceFree(). + -# Release JPEG decoder by calling GFJxDecClose(). +*/ + +/*@}*/ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFJxEnc.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFJxEnc.h new file mode 100755 index 00000000..c5170b44 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFJxEnc.h @@ -0,0 +1,1306 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFJxEnc.h + GFSDK JPEG Encode API header file. +*/ + +#ifndef _GF_JPEG_ENC__ +#define _GF_JPEG_ENC__ + +#include "GF.h" +#include "GFRm.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupJxEnc JxEncAPI JPEG Encoder API +
        +
      • @ref pageJxEncAppNotes +
          +
        • @ref pageJxEncAppNotes1 +
        +
      +*/ +/*@{*/ + +/** JxEncAPI property flag: JPEG quantization table is programmable. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_QTABLE 0x00000001 + +/** JxEncAPI property flag: Interrupt data capture mode and polling mode + supported, if this flag is off then only polling mode is supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_INTERRUPT 0x00000004 + +/** JxEncAPI property flag: Digital zoom supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_DIGITAL_ZOOM 0x00000008 + +/** JxEncAPI property flag: Motion JPEG mode supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_MOTION_JPEG 0x00000010 + +/** JxEncAPI property flag: Rate control supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_RATE_CONTROL 0x00000020 + +/** JxEncAPI property flag: Planar YUV422 data supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_422_PLANAR 0x00000040 + +/** JxEncAPI property flag: Rotation supported. + @see GFJxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_JX_ENC_CAP_ROTATION 0x00000080 + + +/** Image source/target dimensions and data source for JPEG encoding. + + This structure is passed as parameter to GFJxEncStart() and describes + data source, source cropping rectangle and destination image size. + + The surface the application wants to encode is pSrcSurf. If the application + wants to encode an image from a camera or to re-encode a JPEG bitstream, + this field should be set to NULL. If the application wants to encode an + image from the display, this field should point to the primary surface. If + an application wants to encode an existing image, it must create a system + memory surface to hold the image and set this field to the system memory + surface. + + @see GFJxEncStart() +*/ +typedef struct _GFJXENCSTART +{ + PGFRMSURFACE pSrcSurf;/**< Surface to encode, + NULL for camera or re-encode JPEG + */ + PGFRECT pSrcRect; /**< Source image area need to encode */ + NvU32 DestWidth; /**< Final encoded image width */ + NvU32 DestHeight; /**< Final encode image height */ + NvU32 uiOptions; /**< Bitmask of flags to control encoding + + + + + + + +
      #GF_CAPT_BITSTREAM If set only bitstream is output, if + unset JFIF header will be added
      #GF_CAPT_PIECE_MEALPiecemeal encoding @todo clarify + meaning
      + */ + NvU32 Error; /**< Returns detailed error code on GFJxEncStart() failure + + + + + + + +
      #GF_CAPT_ERROR_VIDEO_MEMORY_NOT_BIG_ENOUGHNot enough free video memory, try to release + unnecessary video surfaces
      #GF_CAPT_ERROR_WRONG_CONFIGWrong input parameters, for example srcRect + size greater than pSrcSurf dimensions
      #GF_CAPT_ERROR_NO_CALLBACKNo callback function available
      + */ +} GFJXENCSTART, *PGFJXENCSTART; + +/** JxEncAPI GFJXENCSTART::uiOptions flagbit: If set only bitstream is output, + if unset JFIF header will be added. + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_BITSTREAM 1 + +/** JxEncAPI GFJXENCSTART::uiOptions flagbit: Piecemeal encoding + @todo clarify meaning + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_PIECE_MEAL 2 + +/** JxEncAPI GFJXENCSTART::Error return code: Not enough free video memory. + Try to release unnecessary video surfaces. + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_ERROR_VIDEO_MEMORY_NOT_BIG_ENOUGH 1 + +/** JxEncAPI GFJXENCSTART::Error return code: Wrong input parameters. + E.g. srcRect size greater than pSrcSurf dimensions. + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_ERROR_WRONG_CONFIG 2 + +/** JxEncAPI GFJXENCSTART::Error return code: No callback function available. + @todo clarify + @see GFJXENCSTART, GFJxEncStart() +*/ +#define GF_CAPT_ERROR_NO_CALLBACK 4 + +/** Descriptor for JPEG encode buffers. + This structure describes a buffer and its fill status for encoded + JPEG data or raw YUV transfered from the JPEG encoder to the + application. It is used with GFJxEncCapture() and GFJxEncFetchImage() + in either polling or callback data fetch mode. + + @see GFJxEncCapture(), GFJxEncFetchImage(), GFJxEncPRComplete() +*/ +typedef struct _GFJXENC_BUF { + NvU8 *pBuf; /**< Pointer to the buffer */ + NvU32 bufSize; /**< Size of the buffer in bytes */ + NvU32 nBytesCaptured; /**< Number of bytes captured, + app initializes to 0 + */ +} GFJXENC_BUF, *PGFJXENC_BUF; + +/** Fetch buffer descriptor for use with GFJxEncFetchImage(). + This data structure is used by GFJxEncInterruptHandler() to fetch encoded + image data when IntType is GFJX_ENC_STREAM_BUF_INTR or GFJX_ENC_DONE_INTR. +*/ +typedef struct _GFJXENC_FETCH_BUF{ + PGFJXENC_BUF pBuf; + NvU32 numOfBuf; + NvU32 status; +} GFJXENC_FETCH_BUF, *PGFJXENC_FETCH_BUF; + + +/** JxEncAPI data fetch status code: All data of the current frame was fetched. + @see GFJxEncFetchImage(), GFJxEncCapture() +*/ +#define JXENC_DATA_COMPLETE 0x1 + +/** JxEncAPI data fetch status code: Data was fetched only partially. + The application should make more calls to GFJxEncFetchImage() to fetch + the rest. + @see GFJxEncFetchImage(), GFJxEncCapture() +*/ +#define JXENC_MORE_FETCH 0x2 + +/** JxEncAPI data fetch status code: New frame was encoded and is ready to + fetch. + @see GFJxEncFetchImage(), GFJxEncCapture() +*/ +#define JXENC_NEW_FRAME 0x8 + +/** JxEncAPI data fetch status code: Time out error occured while encoded data is fetching. + fetch. + @see GFJxEncFetchImage(), GFJxEncCapture() +*/ +#define JXENC_TIME_OUT 0x10 + +// definition of uiFeature for GFJxEncSetAttribute +//the following definations are for set only + +/** JxEncAPI attribute: Choose preset QTable, coefficients in luma and chroma + Qtable are all 1. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_100QUALITY 0 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable A and B, + divided by 2. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_85QUALITY 1 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable A and B. + + Interpretation of associated data block: None. + + Attribute is set-only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_75QUALITY 2 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable C and D. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_50QUALITY 3 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable C and D, + multiplied by 2. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_25QUALITY 4 + +/** JxEncAPI attribute: Choose preset QTable, standard Qtable C and D, + multiplied by 4. + + Interpretation of associated data block: None. + + Attribute is set-only. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_SET_12QUALITY 5 + +//the following definations can be used for set and get + +/** JxEncAPI attribute: Set custom luma QTable. + + Interpretation of associated data block: + A table of 64 16-bit (type NvU16) entries with quantization coefficients + to be used for luma MCU's. + + Attribute can be set and get. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_LQTABLE 6 + +/** JxEncAPI attribute: Set custom chroma QTable. + + Interpretation of associated data block: + A table of 64 16-bit (type NvU16) entries with quantization coefficients + to be used for chroma MCU's. + + Attribute can be set and get. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_CQTABLE 7 + +/** JxEncAPI attribute: Decimation filter enable/disable. + + Interpretation of associated data block: +
      +    NvU32 decimation enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_FILTER 8 + +/** JxEncAPI attribute: Huffman bit stuffing. + + Interpretation of associated data block: +
      +    NvU32 Huffman stuffing enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_HUFF_BSTUFF 13 + +/** JxEncAPI attribute: Motion JPEG capturing mode enable/disable. + + Interpretation of associated data block: +
      +    NvU32 Motion JPEG capturing mode enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_MOTION_JPEG 14 + +/** JxEncAPI attribute: Raw data capturing mode enable/disable. + + Interpretation of associated data block: +
      +    NvU32 Raw data capturing mode enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_RAW_DATA 15 + +/** JxEncAPI attribute: Re-encode a JPEG bitstream. + + Registration of callback function for JPEG re-encode application: +
      +    #PGFJXDECCALLBACK structure
      +    
      + + Attribute is set only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_BITSTREAM 16 + +/** JxEncAPI attribute: JPEG encoding colour format. + + Only YUV420 and YUV422 encoding is supported. The JPEG encoder converts + the incoming image to the configured colour format, and then encodes it + in the JPEG bitstream. + + Only YUV420 and YUV422 are + valid. + + Interpretation of associated data block: +
      +    NvU32 Colour format identifier, one of:
      +          #GF_SURFACE_PLANAR_YUV422
      +          #GF_SURFACE_YUV420
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute(), GFRMSURFACE::ColorFormat +*/ +#define JX_ENC_ENCODE_FORMAT 17 + +/** JxEncAPI attribute: Maximum JPEG byte size. + + The JPEG encoder will not generate a JPEG bitstream larger than this. + + Interpretation of associated data block: +
      +    NvU32 Maximum size in bytes
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_MAX_SIZE 18 + +/** JxEncAPI attribute: Camera focal point. + + Image area which is close to the focal point will be encoded with higher + quality. Takes effect only when #JX_ENC_MAX_SIZE is set. + + Interpretation of associated data block: +
      +    NvU32 Focal point X position
      +    NvU32 Focal point Y position
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute(), #JX_ENC_DEGRADATION, + #JX_ENC_MAX_SIZE +*/ +#define JX_ENC_FOCAL_POINT 19 + +/** JxEncAPI attribute: Image quality degradation from focal point. + + Image areas further from the focal point get encoded with fewer bits. + The number of bits is linearly degraded based on the percentage of + degradation in the X and Y directions. This attribute takes effect only + when JX_ENC_MAX_SIZE is set. + + Interpretation of associated data block: +
      +    NvU32 X direction degradation percentage
      +    NvU32 Y direction degradation percentage
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute(), #JX_ENC_FOCAL_POINT, + #JX_ENC_MAX_SIZE +*/ +#define JX_ENC_DEGRADATION 20 + +/** JxEncAPI attribute: JPEG encode rotation and flip control. + + Interpretation of associated data block: +
      +    NvU32 Rotation and flip control, one of the following constants
      +            #JX_ENC_ROTATE_0
      +            #JX_ENC_ROTATE_90
      +            #JX_ENC_ROTATE_180
      +            #JX_ENC_ROTATE_270
      +          optionally logically ORed with zero or more of the following flags
      +            #JX_ENC_H_FLIP
      +            #JX_ENC_V_FLIP
      +    
      + + Default is #JX_ENC_ROTATE_0. + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATION 21 + +/** JxEncAPI attribute: Rotation and flip control for rartial rotation API. + + Enables and configures the partial rotation engine for partially rotated + JPEG encoding. Partially rotated JPEG encoding allows for rotated encoding + of large image sizes with a small image capture buffer. + + Interpretation of associated data block: +
      +    NvU32 Rotation and flip control, one of the following constants
      +            #JX_PRENC_ROTATE_UNSET - reset and disable partial rotation engine
      +            #JX_ENC_ROTATE_0
      +            #JX_ENC_ROTATE_90
      +            #JX_ENC_ROTATE_180
      +            #JX_ENC_ROTATE_270
      +          if not #JX_PRENC_ROTATE_UNSET optionally logically ORed with zero or
      +          more of the following flags
      +            #JX_ENC_H_FLIP
      +            #JX_ENC_V_FLIP
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_PARTIAL_ROTATE 22 + +/** JxEncAPI attribute: Bypass FIFO. + + Interpretation of associated data block: +
      +    NvU32 Raw data capturing mode enable
      +          0 = Fetching encoded data through DMA FIFO
      +          1 = Fetching encoded data directly through output buffer not through
      +              DMA FIFO
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_BYPASS_FIFO 23 + +/** JxEncAPI attribute: Piece-Meal encoding. + + Interpretation of associated data block: +
      +    NvU32 Piece-Meal encoding enable
      +          0 = enable
      +          1 = disable
      +    
      + + Attribute is get only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_PIECE_MEAL 24 + +/** JxEncAPI attribute: Fetch Low bitstream. + + Registration of callback function for fetching raw data stream from JPEG encoder: +
      +    #PGFJXDECCALLBACK structure
      +    
      + + Attribute is set only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ + +#define JX_ENC_RAW_DATA_STREAM 25 + +/** JxEncAPI attribute: Fetch Low JPEG bitstream. + + Registration of callback function for fetching JPEG raw data stream from JPEG encoder: +
      +    #PGFJXDECCALLBACK structure
      +    
      + + Attribute is set only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ + +#define JX_ENC_RAW_JPEG_CAPTURE 26 + +/** JxEncAPI attribute: Set Timeout value + + + Interpretation of associated data block: +
      +    NvU32 timeout   timeout value
      +        0       = no timeout
      +        > 0     = timeout value
      +    
      + + Attribute is set only. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ + +#define JX_ENC_TIMEOUT_CONF 27 + +/** JxEncAPI attribute: Stop preview enable/disable. + + Interpretation of associated data block: +
      +    NvU32 Stop preview mode enable
      +          0 = disable
      +          1 = enable
      +    
      + + Attribute can be set and get. + @see GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ + +#define JX_ENC_STOP_PREVIEW 28 + + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + Non-rotated JPEG encode. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ + +#define JX_ENC_ROTATE_0 0x0 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode rotated 90 degrees. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATE_90 0x1 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode rotated 180 degrees. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATE_180 0x2 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode rotated 270 degrees. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATE_270 0x3 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode horizontally flipped. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_H_FLIP 0x10 + +/** Option for attributes #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE: + JPEG encode vertically flipped. + @see #JX_ENC_ROTATION, #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), + GFJxEncGetAttribute() +*/ +#define JX_ENC_V_FLIP 0x20 + +/** Option for attribute #JX_ENC_PARTIAL_ROTATE: Reset and disable partial + rotation. + Pass this to GFJxEncSetAttribute() for attribute #JX_ENC_PARTIAL_ROTATE + to unset the Partial Rotation Flag and reset the PR Engine. + @see #JX_ENC_PARTIAL_ROTATE, GFJxEncSetAttribute(), GFJxEncGetAttribute() +*/ +#define JX_ENC_ROTATE_UNSET 0xff + +typedef void (*GFJX_ENC_CALLBACK)(void *userData); + +/** JxEncAPI interrupt operation types. + Constants to specify operation for a call to GFJxEncInterruptControl(). + @see GFJX_ENC_INTERRUPT_TYPE, GFJxEncInterruptControl() +*/ +typedef enum +{ + /** Enable interrupt/status assertion for an interrupt type. */ + GFJX_ENC_INTERRUPT_ENABLE, + + /** Disable interrupt/status assertion for an interrupt type. */ + GFJX_ENC_INTERRUPT_DISABLE, + + /** Clear interrupt/status assertion for an interrupt type. */ + GFJX_ENC_INTERRUPT_CLEAR, + + /** Query for interrupt/status assertion for an interrupt type. */ + GFJX_ENC_INTERRUPT_QUERY_STATUS, + + /** Set DMA FIFO threshold. */ + GFJX_ENC_INTERRUPT_SET_DMA_FIFO_THRESHOLD, + + /** Get DMA FIFO threshold. */ + GFJX_ENC_INTERRUPT_GET_DMA_FIFO_THRESHOLD, + + /** Set strean buffer threshold. */ + GFJX_ENC_INTERRUPT_SET_BUF_THRESHOLD, + + /** Get strean buffer threshold. */ + GFJX_ENC_INTERRUPT_GET_BUF_THRESHOLD + +} GFJX_ENC_INTERRUPT_OPERATION_TYPE; + + +/** JxEncAPI interrupt types. + @see GFJX_ENC_INTERRUPT_OPERATION_TYPE, GFJxEncInterruptControl() +*/ +typedef enum +{ + /** JPEG read DMA FIFO low threshold. + Interrupt/status is asserted if the JPEG read DMA FIFO status is less + than the JPEG read DMA FIFO threshold value. + */ + GFJX_ENC_DMA_FIFO_LOW_INTR = 0, + + /** JPEG read DMA FIFO high threshold. + Interrupt/status is asserted if the JPEG read DMA FIFO status is + greater than or equal to the JPEG read DMA FIFO threshold value. + */ + GFJX_ENC_DMA_FIFO_HIGH_INTR = 0x1, + + /** Stream buffer threshold interrupt. */ + GFJX_ENC_STREAM_BUF_INTR = 0x2, + + /** Main buffer end hit interrupt. */ + GFJX_ENC_MAIN_BUF_HIT_INTR = 0x4, + + /** Encoding done interrupt. */ + GFJX_ENC_DONE_INTR = 0x8, + + /** Encoded stream transfer done interrupt. */ + GFJX_ENC_TRANSFER_DONE_INTR = 0x10, + + /** Maximum bit count hit interrupt. */ + GFJX_ENC_MAX_BIT_HIT_INTR = 0x20, + + /** Circular buffer overflow interrupt. */ + GFJX_ENC_CIR_BUF_OVERFLOW_INTR = 0x40 + +} GFJX_ENC_INTERRUPT_TYPE; + +/** JxEncAPI virtual function pointer table. */ +typedef struct _GFJXENCTABLE +{ + GF_RETTYPE (* JxEncGetProperty)(GFJxEncHandle hJxEnc, PGFPROPERTY pJXProp); + GF_RETTYPE (* JxEncSetAttribute)(GFJxEncHandle hJxEnc, + NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* JxEncGetAttribute)(GFJxEncHandle hJxEnc, + NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* JxEncStart)(GFJxEncHandle hJxEnc, PGFJXENCSTART pStart); + GF_RETTYPE (* JxEncFetchImage)(GFJxEncHandle hJxEnc, + PGFJXENC_BUF aBuf, NvU32 nBuf, NvU32 *pStatus); + GF_RETTYPE (* JxEncEnd)(GFJxEncHandle hJxEnc); + GF_RETTYPE (* JxEncSetupInterrupt)(GFJxEncHandle hJxEnc, + void (*Inter)(void *), void *IPara); + GF_RETTYPE (* JxEncCapture)(GFJxEncHandle hJxEnc, + PGFJXENC_BUF aBuf, NvU32 nBuf, NvU32 *pStatus); + GF_RETTYPE (* JxEncInterruptControl)(GFJxEncHandle hJxEnc, + GFJX_ENC_INTERRUPT_TYPE IntType, GFJX_ENC_INTERRUPT_OPERATION_TYPE op, + void * pData); + GF_RETTYPE (* JxEncInterruptHandler)(GFJxEncHandle hJxEnc, + GFJX_ENC_INTERRUPT_TYPE IntType, void * pData); // Reserved. + GF_RETTYPE (*JxEncPRComplete)(GFJxEncHandle hJxEnc, + PGFJXENC_BUF inBuf,NvU32 inBufNum,PGFJXENC_BUF outBuf, + NvU32 outBufNum,PGFJXENC_BUF dcacBuf,NvU32 dcacBufNum); + GF_RETTYPE (*JxEncBracket)(GFJxEncHandle hJxEnc, + GFJX_ENC_CALLBACK before, + GFJX_ENC_CALLBACK after, + void *userData); +} GFJXENCTABLE, *PGFJXENCTABLE; + +#ifdef PROJECT_SEC_G1 +// Attribute constant and data structure for EXIF +#define JX_ENC_SET_EXIF_INFO 30 + +typedef struct _GFJXENCEXIFINFO +{ + NvS8 CameraMaker[32]; + NvS8 CameraModel[40]; + NvS8 FirmwareVersion[5]; + NvU32 FNumberNum; + NvU32 FNumberDenom; + NvS32 ExpBiasNum; + NvS32 ExpBiasDenom; + NvU16 WhiteBalance; + NvU32 DigitalZoomNum; + NvU32 DigitalZoomDenom; +} GFJXENCEXIFINFO; +#endif + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFJxEncOpen(GFRmHandle hRm, GFJxEncHandle *phJxEnc, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFJxEncClose(GFJxEncHandle *phJxEnc); + +/* #### JxEnc Helper macros. Maybe useful for backward compatible API. #### */ + +/** @name Functions +@{*/ + +/** This function returns version and capabilities of API and hardware. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param pJXProp (PGFPROPERTY) Pointer to property structure to be filled in + + @retval #GF_SUCCESS \a pJXProp filled in successfully + @retval #GF_ERROR Some error occured + + The #GFPROPERTY structure passed with parameter \a pJXProp will be + filled in on successfull return. The GFPROPERTY::Capability field + will hold a combination of flagbits indicating capabilities specific + to the JxEncAPI: + + + + + + + + + + + + + + + + +
      #GF_JX_ENC_CAP_QTABLE JPEG quantization table is programmable.
      #GF_JX_ENC_CAP_INTERRUPT Interrupt data capture mode and polling mode supported, + if this flag is off then only polling mode is supported.
      #GF_JX_ENC_CAP_DIGITAL_ZOOMDigital zoom supported.
      #GF_JX_ENC_CAP_MOTION_JPEG Motion JPEG mode supported.
      #GF_JX_ENC_CAP_RATE_CONTROLRate control supported.
      #GF_JX_ENC_CAP_422_PLANAR Planar YUV422 data supported.
      #GF_JX_ENC_CAP_ROTATION Rotation supported.
      + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the JxEncAPI functions. + + @see GFPROPERTY +*/ +#define GFJxEncGetProperty(hJxEnc, pJXProp) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncGetProperty(hJxEnc, pJXProp) + +/** Set configuration of a feature of the JPEG encoder hardware. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param uiFeature (NvU32) Feature type identifier, see table. + @param pInfo (NvU32*) Pointer to feature specific input parameter block. + Pointer type will be reinterpreted according to + feature type. + + @retval #GF_SUCCESS Configuration changed successfully + @retval #GF_ERROR Some error occured + + The feature to be set is identified with parameter \a uiFeature, + specific input parameters are passed via a block in parameter \a pInfo. + The contents of this data block is interpreted depending on the + feature to be set. + + The following features are defined, for the data to be provided in + \a pInfo see the individual attribute's documentation. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      \b Attribute \b Direction \b Synopsis
      #JX_ENC_SET_100QUALITYset Choose preset QTable, coefficients in luma + and chroma Qtable are all 1.
      #JX_ENC_SET_85QUALITY set Choose preset QTable, standard Qtable A and B, + divided by 2.
      #JX_ENC_SET_75QUALITY set Choose preset QTable, standard Qtable A and B.
      #JX_ENC_SET_50QUALITY set Choose preset QTable, standard Qtable C and D.
      #JX_ENC_SET_25QUALITY set Choose preset QTable, standard Qtable C and D, + multiplied by 2.
      #JX_ENC_SET_12QUALITY set Choose preset QTable, standard Qtable C and D, + multiplied by 4.
      #JX_ENC_LQTABLE set, getSet custom luma QTable.
      #JX_ENC_CQTABLE set, getSet custom chroma QTable.
      #JX_ENC_FILTER set, getDecimation filter enable/disable.
      #JX_ENC_HUFF_BSTUFF set, getHuffman bit stuffing.
      #JX_ENC_MOTION_JPEG set, getMotion JPEG capturing mode enable/disable.
      #JX_ENC_RAW_DATA set, getRaw data capturing mode enable/disable.
      #JX_ENC_BITSTREAM set Re-encode a JPEG bitstream.
      #JX_ENC_ENCODE_FORMAT set, getJPEG encoding colour format.
      #JX_ENC_MAX_SIZE set, getMaximum JPEG byte size.
      #JX_ENC_FOCAL_POINT set, getCamera focal point.
      #JX_ENC_DEGRADATION set, getImage quality degradation from focal point.
      #JX_ENC_ROTATION set, getJPEG encode rotation and flip control.
      #JX_ENC_PARTIAL_ROTATEset, getRotation and flip control for Partial Rotation API.
      #JX_ENC_BYPASS_FIFO set, getBypass FIFO.
      #JX_ENC_PIECE_MEAL get Piece-Meal encoding.
      #JX_ENC_STOP_PREVIEW set, getStop preview mode enable/disable.
      #JX_ENC_RAW_JPEG_CAPTURE set Fetch Low JPEG bitstream.
      #JX_ENC_RAW_DATA_STREAM set Fetch Low bitstream.
      #JX_ENC_TIMEOUT_CONF set, getSet Timeout value.
      + + Most of the time an application should only set a quantization table for + luminance or chrominance. These quantization tables are in the same format + as standard quantization tables (1 to 255). Other features are hardware + dependent. + + @see GFJxEncGetAttribute() +*/ +#define GFJxEncSetAttribute(hJxEnc, uiFeature, pInfo) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncSetAttribute(hJxEnc, uiFeature, pInfo) + +/** Get current configuration of a feature of the JPEG encoder hardware. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param uiFeature (NvU32) Feature type identifier, + see table in GFJxEncSetAttribute(). + @param pInfo (NvU32*) Pointer to feature specific input parameter block. + Pointer type will be reinterpreted according to + feature type. + + @retval #GF_SUCCESS \a pInfo filled in successfully + @retval #GF_ERROR Some error occured + + @see GFJxEncSetAttribute() +*/ +#define GFJxEncGetAttribute(hJxEnc, uiFeature, pInfo) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncGetAttribute(hJxEnc, uiFeature, pInfo) + +/** Setup JxEncAPI for JPEG encoding. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param pStart (#PGFJXENCSTART) Pointer to #GFJXENCSTART structure for + definition of encode source and destination + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured, check GFJXENCSTART::Error for + detailed error reason code. + + Before starting capture, the application should call this function to setup + the encoder. Once this function has been called, the application can use + GFJxEncCapture() to capture as many frames as desired. JxEncCapture() + starts and optionally fetches data for a frame. JxEncFetchImageData() + fetches the image data to host CPU side. An application should keep calling + it until all encoded data is processed. Finally GFJxEncEnd() has to be + called to release the encoder. + + Parameter \a pStart passes a #GFJXENCSTART structure describing image data + source, source cropping area, and destination size. + + Encoding is from one of the following sources: + - VI (Camera, cropping and scale up/down is done via VxVIPSet(), + Rotation/flip is done via JxEncSelectEPPRotation() ) + - Screen encoding (GC, source is primary surface) + - Bitstream encoding. This is used to re-encode a JPEG bit stream, and + invokes JxDecAPI internally to decode the existing bitstream. + The following options are available for bitstream re-encoding: + - Crop image size + - Scale up + - Change QTables + - Apply rate control + - Rotation (0, 90, 180, 270, H-Flip, V-Flip) + + On failure an error reason code is returned in field GFJXENCSTART::Error of + parameter \a pStart. + + @see GFJXENCSTART, GFJxEncSetAttribute(), GFJxEncCapture(), + GFJxEncFetchImage(), GFJxEncEnd() +*/ +#define GFJxEncStart(hJxEnc, pStart) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncStart(hJxEnc, pStart) + +/** Polls JxEncAPI for data fetch from JPEG encoder. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param aBuf (#PGFJXENC_BUF) Pointer to array of #GFJXENC_BUF structures + @param nBuf (NvU32) Number of pointers passed with \a aBuf. + @param pStatus (NvU32) Returns data fetch status, see table + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Captures the JPEG encoded bit stream in the given application owned + buffers. Capturing the encoded image can be done in polling or interrupt + mode. This function should be called after GFJxEncCapture(). It is usually + called from either the application's fetching poll loop, or the interrupt + callback routine set up with GFJxEncSetupInterrupt(). + + The application must fill all the fields in the referenced buffer + structures and must make sure each PGFJXENC_BUF::nBytesCaptured is set + to 0. The PGFJXENC_BUF::nBytesCaptured field is updated by the JXEncAPI + to show the actual number of bytes captured. JXEncAPI keeps filling the + buffers in the array until it exhausts all the buffers. If all the buffers + are exhausted and there is more data to be copied, the function returns + and sets \a pStatus to #JXENC_MORE_FETCH. The application should then keep + calling GFJxEncFetchImage() to fetch the remaining data. Each buffer in + the array should be a multiple of 64 bytes for best performance. + + The status of the data fetch is returned in \a pStatus as one of the + following reason codes: + + + + + + +
      #JXENC_DATA_COMPLETEAll data of the current frame was + fetched.
      #JXENC_MORE_FETCH Data was fetched only partially. + The application should make more calls to GFJxEncFetchImage() to + fetch the rest.
      #JXENC_NEW_FRAME A new frame was encoded and is ready + to fetch.
      #JXENC_TIME_OUT Timeout on GFJxEncFetchImage +
      + + @see GFJxEncCapture(), GFJxEncSetupInterrupt(), #GFJXENC_BUF +*/ +#define GFJxEncFetchImage(hJxEnc, aBuf, nBuf, pStatus) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncFetchImage(hJxEnc, aBuf, nBuf, pStatus) + +/** Polls JxEncAPI for data fetch from JPEG encoder. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function disables the encoder and releases internal resources related + to the current capture. + + @see GFJxEncStart() +*/ +#define GFJxEncEnd(hJxEnc) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncEnd(hJxEnc) + +/** Register a callback function for fetching encoded JPEG data. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param Inter (void(*)(void *)) Application callback function pointer + @param IPara (void*) Parameter to pass on to application callback function + + @retval #GF_SUCCESS Callback installed successfully + @retval #GF_ERROR Some error occured + + This function can be used to register a callback function for fetching + encoded JPEG data. This function must be called before GFJxEncCapture(). + The callback function must meet the following prototype: + +
      +    void InterruptCallback(void* lPara);
      +    
      + + Whenever encoding is triggered, JXEncAPI calls the registered interrupt + callback function, passing on the application defined parameter \a IPara. + + Inside the callback function, the application can call GFJxEncFetchImage() + to portionally fetch the encoded datastream. + + If no callback function shall be used, the application could alternatively + use a polling scheme. + + @see GFJxEncCapture() +*/ +#define GFJxEncSetupInterrupt(hJxEnc, Inter, IPara) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncSetupInterrupt(hJxEnc, Inter, IPara) + +/** Trigger JPEG encoder for one frame and optionally display capture preview. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param aBuf (#PGFJXENC_BUF) Pointer to array #GFJXENC_BUF structures + @param nBuf (NvU32) Number of pointers passed with \a aBuf, if + passing 0 then the function is non-blocking + @param pStatus (NvU32) Returns data fetch status, for reason codes + see table at GFJxEncFetchImage() + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + Triggers the JPEG encoder for a frame and optionally displays the same + frame in a preview window in decimated form. + + Encoded data can be fetched via a polling scheme or via an interrupt + handler set up with GFJxEncSetupInterrupt(). In any case + GFJxEncFetchImage() is used to transfer encoded data to application + buffers. + + If application set up an interrupt handler to fetch encoded data, then + \a nBuf should be passed as 0. + + This function can optionally fetch data right after triggering encoding to + buffers provided via \a aBuf. This will block the CPU until all data is + returned or buffer space is exhausted. If \a nBuf is 0, the function + returns right away and \a pStatus is updated to #JXENC_NEW_FRAME to + indicate data is pending. The application should then call + GFJxEncFetchImage() either from an interrupt handler or from same thread to + fetch the encoded/raw data. + + If \a nBuf is not 0, it specifies the number of buffers in the array + \a aBuf. The function will block until it runs out of buffers. It + will return #JXENC_MORE_FETCH in parameter \a pStatus if more data is + available. The application must call GFJxEncFetchImage() to fetch the + remaining data. See GFJxEncFetchImage() for information on return + status codes and how the passed buffers are handled. + + JPEG Encoding from camera or raw data capture from camera happens in + realtime, so if the internal circular buffer in GPU memory is not big + enough then GFJxEncFetchImage() should be called more fequently to empty + the outputBuf and avoid buffer overflows. + + @see GFJxEncSetupInterrupt(), GFJxEncFetchImage(), #GFJXENC_BUF +*/ +#define GFJxEncCapture(hJxEnc, aBuf, nBuf, pStatus) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncCapture(hJxEnc, aBuf, nBuf, pStatus) + +/** JxEncAPI Component-level interrupt control. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param IntType (#GFJX_ENC_INTERRUPT_TYPE) JxEncAPI interrupt type + @param op (#GFJX_ENC_INTERRUPT_OPERATION_TYPE) GFJxEncAPI interrupt + operation + @param pData (void*) Pointer to input or output data block, see table + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GF_ERROR_BAD_PARAMETER Invalid parameters + + The following operations (parameter op) are defined for this call. + + Operation #GFJX_ENC_INTERRUPT_ENABLE + + Enable status/interrupt generation for interrupts of type specified by + \a IntType. + + Depending on the interrupt type additional action and the parameter + \a pData is interpreted as following: + + + + + + + + + + + + + + + + + +
      #GFJX_ENC_DMA_FIFO_LOW_INTR JPEG read DMA FIFO status/interrupt generation is put into low + threshold mode, i.e. interrupt/status is asserted if the JPEG + read DMA FIFO status is less than the threshold value. + + \a pData points to block containing:
      + NvU32 DMA FIFO low threshold value in range 0..15 + + \a pData can be NULL to leave the threshold value unchanged. +
      #GFJX_ENC_DMA_FIFO_HIGH_INTRJPEG read DMA FIFO status/interrupt generation is put into + high threshold mode, i.e. interrupt/status is asserted if the + JPEG read DMA FIFO status is greater than or equal toless than + the threshold value. + + \a pData points to block containing:
      + NvU32 DMA FIFO high threshold value in range 0..15 + + \a pData can be NULL to leave the threshold value unchanged. +
      #GFJX_ENC_STREAM_BUF_INTR \a pData points to block containing:
      + NvU32 JPEG stream buffer threshold value in bytes, must + be multiple of 8 + + \a pData can be NULL to leave the threshold value unchanged. +
      otherwise\a pData is ignored
      + + Operation #GFJX_ENC_INTERRUPT_DISABLE + + Disable status/interrupt generation for interrupts of type specified by + \a IntType. + + Operation #GFJX_ENC_INTERRUPT_CLEAR + + Clear status/interrupt assertion for interrupt of type specified by + \a IntType. + + Operation #GFJX_ENC_INTERRUPT_QUERY_STATUS + + Return current status/interrupt assertion for interrupt of type + specified by \a IntType. The state is returned in the block referenced + by \a pData. + + Interpretation of associated data block \a pData +
      +        NvU32 Interrupt/status assertion state, one of:
      +              GF_INTERRUPT_ON_STATUS_TRUE = asserted
      +              GF_INTERRUPT_ON_STATUS_FALSE = not asserted
      +        
      + + Operation #GFJX_ENC_INTERRUPT_SET_DMA_FIFO_THRESHOLD + + Set DMA FIFO threshold value that controls interrupt/status assertion + for interrupt types #GFJX_ENC_DMA_FIFO_LOW_INTR and + #GFJX_ENC_DMA_FIFO_HIGH_INTR. + + Interpretation of associated data block \a pData +
      +        NvU32 DMA FIFO threshold value in range 0..15
      +        
      + + Operation #GFJX_ENC_INTERRUPT_GET_DMA_FIFO_THRESHOLD + + Return DMA FIFO threshold value that controls interrupt/status + assertion for interrupt types #GFJX_ENC_DMA_FIFO_LOW_INTR and + #GFJX_ENC_DMA_FIFO_HIGH_INTR. + + Interpretation of associated data block \a pData +
      +        NvU32 DMA FIFO threshold value in range 0..15
      +        
      + + Operation #GFJX_ENC_INTERRUPT_SET_BUF_THRESHOLD + + Set JPEG stream buffer threshold value that controls interrupt/status + assertion for interrupt type #GFJX_ENC_STREAM_BUF_INTR. + + Interpretation of associated data block \a pData +
      +        NvU32 DMA read buffer threshold value in bytes, must be multiple of 8
      +        
      + + Operation #GFJX_ENC_INTERRUPT_GET_BUF_THRESHOLD + + Return JPEG stream buffer threshold value that controls + interrupt/status assertion for interrupt type + #GFJX_ENC_STREAM_BUF_INTR. + + Interpretation of associated data block \a pData +
      +        NvU32 DMA read buffer threshold value in bytes, must be multiple of 8
      +        
      + + @see GFJX_ENC_INTERRUPT_TYPE, GFJX_ENC_INTERRUPT_OPERATION_TYPE +*/ +#define GFJxEncInterruptControl(hJxEnc, IntType, op, pData)\ + ((PGFJXENCTABLE)hJxEnc)->JxEncInterruptControl(hJxEnc, IntType, op, pData) + +/** Standard interrupt handler for fetching encoded JPEG data. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param IntType (#GFJX_ENC_INTERRUPT_TYPE) JxEncAPI interrupt type + @param pData (void*) Pointer to input or output data block, + depending on \a IntType. See table. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + + + +
      \a IntType Interpretation of \a pData
      #GFJX_ENC_STREAM_BUF_INTR, GFJX_ENC_DONE_INTR#PGFJXENC_FETCH_BUF
      + + Usually this callback is not used, because the interrupt service thread + at the application level can call GFJxEncFetchImage() directly to + complete the task of fetching encoded data. + + @todo clarify + @see GFJxEncFetchImage() +*/ +#define GFJxEncInterruptHandler(hJxEnc, IntType, pData)\ + ((PGFJXENCTABLE)hJxEnc)->JxEncInterruptHandler(hJxEnc, IntType, pData) + +/** Generate final JPEG bitstream from a partially rotated bitstream. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param inBuf (#PGFJXENC_BUF) Pointer to array of #GFJXENC_BUF structs + holding fragmented input bitstream + @param inBufNum (NvU32) Size of array \a inBuf + @param outBuf (#PGFJXENC_BUF) Pointer to array of #GFJXENC_BUF structs + to output fragmented JPEG bitstream + @param outBufNum (NvU32) Size of array \a outBuf + @param dcacBuf (#PGFJXENC_BUF) ? + @param dcacBufNum (NvU32) Size of array \a dcacBuf + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @todo clarify +*/ +#define GFJxEncPRComplete(hJxEnc,inBuf,inBufNum,outBuf,outBufNum,dcacBuf,dcacBufNum)\ + ((PGFJXENCTABLE)hJxEnc)->JxEncPRComplete(hJxEnc,inBuf,inBufNum,outBuf,outBufNum,dcacBuf,dcacBufNum) + +/** Provide callbacks for immediately before and after any encode events. + These will be called by JxEncode() when it is invoked. + Calling this routine a second time will overwrite previously set + values. + + @param hJxEnc (#GFJxEncHandle) Handle to JxEncAPI + @param before (#GFJX_ENC_CALLBACK) proc to call before capture + @param after (#GFJX_ENC_CALLBACK) proc to call after capture + @param userData (void *) data to be supplied to before() and + after() when they are invoked. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +#define GFJxEncBracket(hJxEnc, before, after, userData) \ + ((PGFJXENCTABLE)hJxEnc)->JxEncBracket(hJxEnc, before, after, userData) + +/*@}*/ +/*@}*/ + /** @page pageJxEncAppNotes JxEncAPI Application Notes + + @section pageJxEncAppNotes1 Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start GFSDK usage. + The description is for a typical case where encoding of a still image being captured + from a camera is done and preview shown on the display. + + 1. In case of camera encoding, setup the camera & initialize VIP.
      + + 2. Obtain the handle specific to JPEG encoder by calling GFJxEncOpen().
      + + 3. Call GFRmSurfaceAlloc() to allocate one referance surface for encoding purposes.
      + + 4. Call GFJxEncSetAttribute() if specific features need to be set, + such as encoding width, encoding height, rotation, quality factor, etc.
      + + 5. Start the encoding by calling GFJxEncStart().
      + + 6. If the current source image is from the CPU, the application should call GFJxEncFeedImage() + to feed the image to the GFJxEncAPI via GFJxEncCapture().
      + + 7. The application should fetch the encoded stream by calling GFJxEncFetchImage(). + Application should keep it calling till whole encoded data is out.
      + + 8. For exiting, free all relevent resources and call GFJxEncEnd() to free the JPEG encoder component.
      + + */ +#ifdef __cplusplus +} // only need to export C interface if + // used by C++ source code +#endif + +#endif //_GF_JPEG_ENC__ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMinimalIsp.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMinimalIsp.h new file mode 100755 index 00000000..5f5546d3 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMinimalIsp.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2007 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef __GFMINIMALISP_H_ +#define __GFMINIMALISP_H_ + +#include "GF.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +GF_RETTYPE GFMinimalIspOpen(GFRmHandle hRm, GFMinimalIspHandle *phIsp, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMinimalIspClose(GFMinimalIspHandle *phIsp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMmProc.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMmProc.h new file mode 100755 index 00000000..1489db73 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMmProc.h @@ -0,0 +1,1766 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFMmProc.h + GFSDK Multimedia Processor API header file. +*/ + +#ifndef __GFMmProc_H__ +#define __GFMmProc_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupMmProc MmProcAPI Multimedia Processor API +*/ +/*@{*/ + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFMmProcOpen(GFRmHandle hRm, GFMmProcHandle *phMmProc, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMmProcClose(GFRmHandle hRm, GFMmProcHandle *phMmProc); + +//***************************************************************************** +//***************************************************************************** +// +// Packages +// +//***************************************************************************** +//***************************************************************************** + +// +// These defines are used to import or remove functionality within the audio +// engine. +// +//#define GFMMPROC_BASIC_AUDIO + +// +// Adds audio controls to the package beyond basic playback. +// +//#define GFMMPROC_BASIC_AUDIO + +// +// Adds advanced multimedia processing and functionality. +// +// NOTE: Currently the advanced feature set requires the basic level of audio +// support. This requirement may not be present in future revisions. +// +//#define GFMMPROC_BASIC_AUDIO +//#define GFMMPROC_ADVANCED + +// +// Adds 3D audio controls (requires GFMMPROC_ADVANCED). +// +//#define GFMMPROC_BASIC_AUDIO +//#define GFMMPROC_ADVANCED +//#define GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS + +// +// Adds advanced controls (requires GFMMPROC_ADVANCED). +// +//#define GFMMPROC_BASIC_AUDIO +//#define GFMMPROC_ADVANCED +//#define GFMMPROC_ADVANCED_CONTROLS + +// +// Adds global effect audio controls (requires GFMMPROC_ADVANCED_CONTROLS). +// +//#define GFMMPROC_BASIC_AUDIO +//#define GFMMPROC_ADVANCED +//#define GFMMPROC_ADVANCED_CONTROLS +//#define GFMMPROC_ADVANCED_AUDIO_EFFECT_CONTROLS + + +//***************************************************************************** +//***************************************************************************** +// +// Defines +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_BASIC_AUDIO || defined GFMMPROC_ADVANCED +#define GFMMPROC_TIME_UNITS_PER_SECOND 1000000 +#endif + +typedef GF_HANDLE GFMMPROC_OBJECT; + + +//***************************************************************************** +// Object +//***************************************************************************** +// +typedef struct _GFMMPROC_OBJECT_TABLE +{ + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + +} GFMMPROC_OBJECT_TABLE; + +#define GFMMPROC_OBJECT_DEFAULT_STR "Object" +#define GFMMPROC_OBJECT_MANAGER_STR "Manager" +#define GFMMPROC_OBJECT_GLOBAL_MANAGER_STR "GlobalManager" +#define GFMMPROC_OBJECT_PLAYER_STR "Player" +#define GFMMPROC_OBJECT_SOUND_SOURCE_3D_STR "SoundSource3D" +#define GFMMPROC_OBJECT_SPECTATOR_STR "Spectator" +#define GFMMPROC_OBJECT_MODULE_STR "Module" +#define GFMMPROC_OBJECT_MEDIA_PROCESSOR_STR "MediaProcessor" +#define GFMMPROC_OBJECT_CODEC_STR "Codec" + +#define GFMMPROC_CONTROL_DEFAULT_STR "Control" +#define GFMMPROC_CONTROL_MIDI_STR "MIDI" +#define GFMMPROC_CONTROL_PITCH_STR "Pitch" +#define GFMMPROC_CONTROL_RATE_STR "Rate" +#define GFMMPROC_CONTROL_RECORD_STR "Record" +#define GFMMPROC_CONTROL_STOP_TIME_STR "StopTime" +#define GFMMPROC_CONTROL_TEMPO_STR "Tempo" +#define GFMMPROC_CONTROL_TONE_STR "Tone" +#define GFMMPROC_CONTROL_VOLUME_STR "Volume" + +#define GFMMPROC_CONTROL_AUDIO_FORMAT_STR "AudioFormat" +#define GFMMPROC_CONTROL_EFFECT_STR "Effect" +#define GFMMPROC_CONTROL_EFFECT_ORDER_STR "EffectOrder" +#define GFMMPROC_CONTROL_FORMAT_STR "Format" +#define GFMMPROC_CONTROL_MIDI_CHANNEL_STR "MIDIChannel" +#define GFMMPROC_CONTROL_PAN_STR "Pan" +#define GFMMPROC_CONTROL_PRIORITY_STR "Priority" + +#define GFMMPROC_CONTROL_COMMIT_STR "Commit" +#define GFMMPROC_CONTROL_ORIENTATION_STR "Orientation" +#define GFMMPROC_CONTROL_DIRECTIVITY_STR "Directivity" +#define GFMMPROC_CONTROL_DISTANCE_ATTENUATION_STR "DistanceAttenuation" +#define GFMMPROC_CONTROL_DOPPLER_STR "Doppler" +#define GFMMPROC_CONTROL_LOCATION_STR "Location" +#define GFMMPROC_CONTROL_MACROSCOPIC_STR "Macroscopic" +#define GFMMPROC_CONTROL_OBSTRUCTION_STR "Obstruction" +#define GFMMPROC_CONTROL_3DCOEFFICIENTS_STR "3DCoefficients" + +#define GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_STR "AudioVirtualizer" +#define GFMMPROC_CONTROL_EFFECT_ACOUSTIC_ECHO_CANCELLATION_STR "AcousticEchoCancellation" +#define GFMMPROC_CONTROL_EFFECT_SBC_STR "SBC" +#define GFMMPROC_CONTROL_EFFECT_SBR_STR "SBR" +#define GFMMPROC_CONTROL_EFFECT_DRC_STR "DRC" +#define GFMMPROC_CONTROL_EFFECT_CHORUS_STR "Chorus" +#define GFMMPROC_CONTROL_EFFECT_EQUALIZER_STR "Equalizer" +#define GFMMPROC_CONTROL_EFFECT_REVERB_STR "Reverb" +#define GFMMPROC_CONTROL_REVERB_SOURCE_STR "ReverbSource" + + +#define GFMmProcObjectIsInstance(handle, objectType) \ + ((GFMMPROC_OBJECT_TABLE*)handle)->MmProcObjectIsInstance(handle, objectType) + +GF_HANDLE GFMmProcObjectAlloc(GFMmProcHandle component, const char* objectType); +void GFMmProcObjectFree(GF_HANDLE handle); + +#if defined GFMMPROC_BASIC_AUDIO || defined GFMMPROC_ADVANCED + +typedef GF_HANDLE GFMMPROC_STREAM; + +//***************************************************************************** +// Stream +//***************************************************************************** +// +typedef struct _GFMMPROC_STREAM_TABLE +{ + void (*MmProcStreamClose)(GFMMPROC_STREAM handle); + NvS32 (*MmProcStreamGetBuffer)(GFMMPROC_STREAM handle, NvU32 tag, void** descriptor, void** buffer); + void (*MmProcStreamReleaseBuffer)(GFMMPROC_STREAM handle, NvU32 tag, NvU32 status, NvU32 size); + void (*MmProcStreamReset)(GFMMPROC_STREAM handle); + +} GFMMPROC_STREAM_TABLE; + +#define GFMMPROC_STREAM_END_OF_MEDIA 0x00000001 + +#define GFMmProcStreamClose(handle) \ + ((GFMMPROC_STREAM_TABLE*)handle)->MmProcStreamClose(handle) +#define GFMmProcStreamGetBuffer(handle, tag, descriptor, buffer) \ + ((GFMMPROC_STREAM_TABLE*)handle)->MmProcStreamGetBuffer(handle, tag, descriptor, buffer) +#define GFMmProcStreamReleaseBuffer(handle, tag, status, size) \ + ((GFMMPROC_STREAM_TABLE*)handle)->MmProcStreamReleaseBuffer(handle, tag, status, size) +#define GFMmProcStreamReset(handle) \ + ((GFMMPROC_STREAM_TABLE*)handle)->MmProcStreamReset(handle) + +#endif // #if defined GFMMPROC_BASIC_AUDIO || defined GFMMPROC_ADVANCED + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_BASIC_AUDIO +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_BASIC_AUDIO + +typedef GFMMPROC_OBJECT GFMMPROC_CONTROL; +typedef GF_HANDLE GFMMPROC_CONTROLLABLE; +typedef GFMMPROC_OBJECT GFMMPROC_MANAGER; +typedef GFMMPROC_CONTROLLABLE GFMMPROC_PLAYER; +typedef GF_HANDLE GFMMPROC_PLAYER_LISTENER; +typedef GF_HANDLE GFMMPROC_TIME_BASE; +typedef enum { + GFMMPROC_CODEC_TYPE_UNSPECIFIED = 0, + GFMMPROC_CODEC_TYPE_I2S, + GFMMPROC_CODEC_TYPE_AC97 +} GFMMPROC_CODEC_TYPE; + +//***************************************************************************** +// Control +//***************************************************************************** +// +typedef GFMMPROC_OBJECT_TABLE GFMMPROC_CONTROL_TABLE; + + +//***************************************************************************** +// Controllable +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROLLABLE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + GFMMPROC_CONTROL (*MmProcControllableGetControl)(GFMMPROC_CONTROLLABLE handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcControllableGetControls)(GFMMPROC_CONTROLLABLE handle); + +} GFMMPROC_CONTROLLABLE_TABLE; + +#define GFMmProcControllableGetControl(handle, controlType) \ + ((GFMMPROC_CONTROLLABLE_TABLE*)handle)->MmProcControllableGetControl(handle, controlType) +#define GFMmProcControllableGetControls(handle) \ + ((GFMMPROC_CONTROLLABLE_TABLE*)handle)->MmProcControllableGetControls(handle) + + +//***************************************************************************** +// Manager +//***************************************************************************** +// +typedef struct _GFMMPROC_MANAGER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + GFMMPROC_PLAYER (*MmProcManagerCreatePlayer)(GFMMPROC_MANAGER handle, char* locator); +// GFMMPROC_PLAYER (*MmProcManagerCreatePlayerForDataSource)(GFMMPROC_MANAGER handle, DataSource source); + GFMMPROC_PLAYER (*MmProcManagerCreatePlayerForStream)(GFMMPROC_MANAGER handle, GFMMPROC_STREAM stream, char* contentType); + char* (*MmProcManagerGetSupportedContentTypes)(GFMMPROC_MANAGER handle, char* protocol); + char* (*MmProcManagerGetSupportedProtocols)(GFMMPROC_MANAGER handle, char* contentType); + GFMMPROC_TIME_BASE (*MmProcManagerGetSystemTimeBase)(GFMMPROC_MANAGER handle); + void (*MmProcManagerPlayTone)(GFMMPROC_MANAGER handle, NvU32 note, NvU32 duration, NvU32 volume); + void (*MmProcManagerProcess)(GFMMPROC_MANAGER handle); + GFMMPROC_CODEC_TYPE (*MmProcManagerGetCodecType)(GFMMPROC_MANAGER handle); + void (*MmProcManagerCodecWrite)(GFMMPROC_MANAGER handle, NvU32 offset, NvU32 value); + NvU32 (*MmProcManagerCodecRead)(GFMMPROC_MANAGER handle, NvU32 offset); + +} GFMMPROC_MANAGER_TABLE; + +#define GFMMPROC_MANAGER_MIDI_DEVICE_LOCATOR "device://midi" +#define GFMMPROC_MANAGER_TONE_DEVICE_LOCATOR "device://tone" + +#define GFMmProcManagerCreatePlayer(handle, locator) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCreatePlayer(handle, locator) +//#define GFMmProcManagerCreatePlayerForDataSource(handle, source) Add multiline delineator here +// ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCreatePlayerForDataSource(handle, source) +#define GFMmProcManagerCreatePlayerForStream(handle, stream, contentType) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCreatePlayerForStream(handle, stream, contentType) +#define GFMmProcManagerGetSupportedContentTypes(handle, protocol) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerGetSupportedContentTypes(handle, protocol) +#define GFMmProcManagerGetSupportedProtocols(handle, contentType) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerGetSupportedProtocols(handle, contentType) +#define GFMmProcManagerGetSystemTimeBase(handle) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerGetSystemTimeBase(handle) +#define GFMmProcManagerPlayTone(handle, note, duration, volume) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerPlayTone(handle, note, duration, volume) +#define GFMmProcManagerProcess(handle) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerProcess(handle) +#define MmProcManagerGetCodecType(handle) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerGetCodecType(handle) +#define MmProcManagerCodecWrite(handle, offset, value) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCodecWrite(handle, offset, value) +#define MmProcManagerCodecRead(handle, offset) \ + ((GFMMPROC_MANAGER_TABLE*)handle)->MmProcManagerCodecRead(handle, offset) + + +//***************************************************************************** +// Player +//***************************************************************************** +// +typedef struct _GFMMPROC_PLAYER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Controllable Methods + // + GFMMPROC_CONTROL (*MmProcControllableGetControl)(GFMMPROC_CONTROLLABLE handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcControllableGetControls)(GFMMPROC_CONTROLLABLE handle); + + void (*MmProcPlayerAddPlayerListener)(GFMMPROC_PLAYER handle, GFMMPROC_PLAYER_LISTENER playerListener); + void (*MmProcPlayerClose)(GFMMPROC_PLAYER handle); + void (*MmProcPlayerDeallocate)(GFMMPROC_PLAYER handle); + char* (*MmProcPlayerGetContentType)(GFMMPROC_PLAYER handle); + NvS64 (*MmProcPlayerGetDuration)(GFMMPROC_PLAYER handle); + NvS64 (*MmProcPlayerGetMediaTime)(GFMMPROC_PLAYER handle); + NvU32 (*MmProcPlayerGetState)(GFMMPROC_PLAYER handle); + GFMMPROC_TIME_BASE (*MmProcPlayerGetTimeBase)(GFMMPROC_PLAYER handle); + NvU32 (*MmProcPlayerPrefetch)(GFMMPROC_PLAYER handle); + void (*MmProcPlayerPull)(GFMMPROC_PLAYER handle, NvS32 allow); + void (*MmProcPlayerRealize)(GFMMPROC_PLAYER handle); + void (*MmProcPlayerRemovePlayerListener)(GFMMPROC_PLAYER handle, GFMMPROC_PLAYER_LISTENER playerListener); + void (*MmProcPlayerSetLoopCount)(GFMMPROC_PLAYER handle, NvS32 count); + NvS64 (*MmProcPlayerSetMediaTime)(GFMMPROC_PLAYER handle, NvS64 now); + void (*MmProcPlayerSetTimeBase)(GFMMPROC_PLAYER handle, GFMMPROC_TIME_BASE master); + void (*MmProcPlayerStart)(GFMMPROC_PLAYER handle); + void (*MmProcPlayerStop)(GFMMPROC_PLAYER handle); + +} GFMMPROC_PLAYER_TABLE; + +#define GFMMPROC_PLAYER_UNREALIZED 100 +#define GFMMPROC_PLAYER_REALIZED 200 +#define GFMMPROC_PLAYER_PREFETCHED 300 +#define GFMMPROC_PLAYER_STARTED 400 +#define GFMMPROC_PLAYER_CLOSED 0 +#define GFMMPROC_PLAYER_TIME_UNKNOWN -1 + +#define GFMmProcPlayerAddPlayerListener(handle, playerListener) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerAddPlayerListener(handle, playerListener) +#define GFMmProcPlayerClose(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerClose(handle) +#define GFMmProcPlayerDeallocate(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerDeallocate(handle) +#define GFMmProcPlayerGetContentType(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetContentType(handle) +#define GFMmProcPlayerGetDuration(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetDuration(handle) +#define GFMmProcPlayerGetMediaTime(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetMediaTime(handle) +#define GFMmProcPlayerGetState(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetState(handle) +#define GFMmProcPlayerGetTimeBase(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerGetTimeBase(handle) +#define GFMmProcPlayerPrefetch(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerPrefetch(handle) +#define GFMmProcPlayerPull(handle, allow) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerPull(handle, allow) +#define GFMmProcPlayerRealize(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerRealize(handle) +#define GFMmProcPlayerRemovePlayerListener(handle, playerListener) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerRemovePlayerListener(handle, playerListener) +#define GFMmProcPlayerSetLoopCount(handle, count) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerSetLoopCount(handle, count) +#define GFMmProcPlayerSetMediaTime(handle, now) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerSetMediaTime(handle, now) +#define GFMmProcPlayerSetTimeBase(handle, master) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerSetMediaTime(handle, master) +#define GFMmProcPlayerStart(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerStart(handle) +#define GFMmProcPlayerStop(handle) \ + ((GFMMPROC_PLAYER_TABLE*)handle)->MmProcPlayerStop(handle) + + +//***************************************************************************** +// PlayerListener +//***************************************************************************** +// +typedef struct _GFMMPROC_PLAYER_LISTENER_TABLE +{ + void (*MmProcPlayerListenerPlayerUpdate)(GFMMPROC_PLAYER_LISTENER handle, GFMMPROC_PLAYER player, const char* event, void* eventData); + +} GFMMPROC_PLAYER_LISTENER_TABLE; + +#define GFMMPROC_PLAYER_LISTENER_BUFFERING_STARTED "bufferingStarted" +#define GFMMPROC_PLAYER_LISTENER_BUFFERING_STOPPED "bufferingStopped" +#define GFMMPROC_PLAYER_LISTENER_CLOSED "closed" +#define GFMMPROC_PLAYER_LISTENER_END_OF_MEDIA "endOfMedia" +#define GFMMPROC_PLAYER_LISTENER_DEVICE_AVAILABLE "deviceAvailable" +#define GFMMPROC_PLAYER_LISTENER_DEVICE_UNAVAILABLE "deviceUnavailable" +#define GFMMPROC_PLAYER_LISTENER_DURATION_UPDATED "durationUpdated" +#define GFMMPROC_PLAYER_LISTENER_ERROR "error" +#define GFMMPROC_PLAYER_LISTENER_FORMAT_CHANGED "formatChanged" +#define GFMMPROC_PLAYER_LISTENER_RECORD_ERROR "recordError" +#define GFMMPROC_PLAYER_LISTENER_RECORD_STARTED "recordStarted" +#define GFMMPROC_PLAYER_LISTENER_RECORD_STOPPED "recordStopped" +#define GFMMPROC_PLAYER_LISTENER_STARTED "started" +#define GFMMPROC_PLAYER_LISTENER_STOPPED "stopped" +#define GFMMPROC_PLAYER_LISTENER_STOPPED_AT_TIME "stoppedAtTime" +#define GFMMPROC_PLAYER_LISTENER_VOLUME_CHANGED "volumeChanged" + +#define GFMmProcPlayerListenerPlayerUpdate(handle, player, event, eventData) \ + ((GFMMPROC_PLAYER_LISTENER_TABLE*)handle)->MmProcPlayerListenerPlayerUpdate(handle, player, event, eventData) + + +//***************************************************************************** +// TimeBase +//***************************************************************************** +// +typedef struct _GFMMPROC_TIME_BASE_TABLE +{ + NvU32 (*MmProcTimeBaseGetTime)(GFMMPROC_TIME_BASE handle); + +} GFMMPROC_TIME_BASE_TABLE; + +#define GFMmProcTimeBaseGetTime(handle) \ + ((GFMMPROC_TIME_BASE_TABLE*)handle)->MmProcTimeBaseGetTime(handle) + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_BASIC_AUDIO_CONTROLS +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_BASIC_AUDIO_CONTROLS + +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_MIDI; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_PITCH; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_RATE; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_RECORD; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_STOP_TIME; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_TEMPO; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_TONE; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_VOLUME; + + + +//***************************************************************************** +// MIDIControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_MIDI_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32* (*MmProcControlMidiGetBankList)(GFMMPROC_CONTROL_MIDI hande, NvS32 custom); + NvS8 (*MmProcControlMidiGetChannelVolume)(GFMMPROC_CONTROL_MIDI hande, NvU8 channel); + char* (*MmProcControlMidiGetKeyName)(GFMMPROC_CONTROL_MIDI hande, NvS32 bank, NvS32 program, NvS32 key); + NvS32* (*MmProcControlMidiGetProgram)(GFMMPROC_CONTROL_MIDI hande, NvU8 channel); + NvS32* (*MmProcControlMidiGetProgramList)(GFMMPROC_CONTROL_MIDI hande, NvS32 bank); + char* (*MmProcControlMidiGetProgramName)(GFMMPROC_CONTROL_MIDI hande, NvS32 bank, NvS32 program); + NvS32 (*MmProcControlMidiIsBankQuerySupported)(GFMMPROC_CONTROL_MIDI hande); + NvS32 (*MmProcControlMidiLongMidiEvent)(GFMMPROC_CONTROL_MIDI hande, NvS8* data, NvS32 offset, NvS32 length); + void (*MmProcControlMidiShortMidiEvent)(GFMMPROC_CONTROL_MIDI hande, NvS32 type, NvS32 data1, NvS32 data2); + +} GFMMPROC_CONTROL_MIDI_TABLE; + +#define GFMMPROC_CONTROL_MIDI_CONTROL_CHANGE 176 +#define GFMMPROC_CONTROL_MIDI_NOTE_ON 144 + +#define GFMmProcControlMidiGetBankList(handle, custom) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetBankList(handle, custom) +#define GFMmProcControlMidiGetChannelVolume(handle, channel) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetChannelVolume(handle, channel) +#define GFMmProcControlMidiGetKeyName(handle, bank, program, key) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetKeyName(handle, bank, program, key) +#define GFMmProcControlMidiGetProgram(handle, channel) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetProgram(handle, channel) +#define GFMmProcControlMidiGetProgramList(handle, bank) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetProgramList(handle, bank) +#define GFMmProcControlMidiGetProgramName(handle, bank, program) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiGetProgramName(handle, bank, program) +#define GFMmProcControlMidiIsBankQuerySupported(handle) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiIsBankQuerySupported(handle) +#define GFMmProcControlMidiLongMidiEvent(handle) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->MmProcControlMidiLongMidiEvent(handle, data, offset, length) +#define GFMmProcControlMidiShortMidiEvent(handle, type, data1, data2) \ + ((GFMMPROC_CONTROL_MIDI_TABLE*)handle)->(handle, type, data1, data2) + + +//***************************************************************************** +// PitchControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_PITCH_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlPitchGetMaxPitch)(GFMMPROC_CONTROL_PITCH handle); + NvS32 (*MmProcControlPitchGetMinPitch)(GFMMPROC_CONTROL_PITCH handle); + NvS32 (*MmProcControlPitchGetPitch)(GFMMPROC_CONTROL_PITCH handle); + NvS32 (*MmProcControlPitchSetPitch)(GFMMPROC_CONTROL_PITCH handle, NvS32 millisemitones); + +} GFMMPROC_CONTROL_PITCH_TABLE; + +#define GFMmProcControlPitchGetMaxPitch(handle) \ + ((GFMMPROC_CONTROL_PITCH_TABLE*)handle)->MmProcControlPitchGetMaxPitch(handle) +#define GFMmProcControlPitchGetMinPitch(handle) \ + ((GFMMPROC_CONTROL_PITCH_TABLE*)handle)->MmProcControlPitchGetMinPitch(handle) +#define GFMmProcControlPitchGetPitch(handle) \ + ((GFMMPROC_CONTROL_PITCH_TABLE*)handle)->MmProcControlPitchGetPitch(handle) +#define GFMmProcControlPitchSetPitch(handle, millisemitones) \ + ((GFMMPROC_CONTROL_PITCH_TABLE*)handle)->MmProcControlPitchSetPitch(handle, millisemitones) + + +//***************************************************************************** +// RateControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_RATE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlRateGetMaxRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateGetMinRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateGetRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateSetRate)(GFMMPROC_CONTROL_RATE handle, NvS32 millirate); + +} GFMMPROC_CONTROL_RATE_TABLE; + +#define GFMmProcControlRateGetMaxRate(handle) \ + ((GFMMPROC_CONTROL_RATE_TABLE*)handle)->MmProcControlRateGetMaxRate(handle) +#define GFMmProcControlRateGetMinRate(handle) \ + ((GFMMPROC_CONTROL_RATE_TABLE*)handle)->MmProcControlRateGetMinRate(handle) +#define GFMmProcControlRateGetRate(handle) \ + ((GFMMPROC_CONTROL_RATE_TABLE*)handle)->MmProcControlRateGetRate(handle) +#define GFMmProcControlRateSetRate(handle, millirate) \ + ((GFMMPROC_CONTROL_RATE_TABLE*)handle)->MmProcControlRateSetRate(handle, millirate) + + +//***************************************************************************** +// RecordControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_RECORD_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlRecordCommit)(GFMMPROC_CONTROL_RECORD handle); + char* (*MmProcControlRecordGetContentType)(GFMMPROC_CONTROL_RECORD handle); + void (*MmProcControlRecordSetRecordLocation)(GFMMPROC_CONTROL_RECORD handle, char* locator); + void (*MmProcControlRecordSetRecordStream)(GFMMPROC_CONTROL_RECORD handle, GFMMPROC_STREAM stream, char* contentType); + NvS32 (*MmProcControlRecordSetRecordSizeLimit)(GFMMPROC_CONTROL_RECORD handle, NvS32 size); + void (*MmProcControlRecordStartRecord)(GFMMPROC_CONTROL_RECORD handle); + void (*MmProcControlRecordStopRecord)(GFMMPROC_CONTROL_RECORD handle); + void (*MmProcControlRecordReset)(GFMMPROC_CONTROL_RECORD handle); + +} GFMMPROC_CONTROL_RECORD_TABLE; + +#define GFMmProcControlRecordCommit(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordCommit(handle) +#define GFMmProcControlRecordGetContentType(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordGetContentType(handle) +#define GFMmProcControlRecordSetRecordLocation(handle, locator) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordSetRecordLocation(handle, locator) +#define GFMmProcControlRecordSetRecordStream(handle, stream, contentType) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordSetRecordStream(handle, stream, contentType) +#define GFMmProcControlRecordSetRecordSizeLimit(handle, size) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordSetRecordSizeLimit(handle, size) +#define GFMmProcControlRecordStartRecord(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordStartRecord(handle) +#define GFMmProcControlRecordStopRecord(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordStopRecord(handle) +#define GFMmProcControlRecordReset(handle) \ + ((GFMMPROC_CONTROL_RECORD_TABLE*)handle)->MmProcControlRecordReset(handle) + + +//***************************************************************************** +// StopTimeControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_STOP_TIME_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS64 (*MmProcControlStopTimeGetStopTime)(GFMMPROC_CONTROL_STOP_TIME handle); + void (*MmProcControlStopTimeSetStopTime)(GFMMPROC_CONTROL_STOP_TIME handle, NvS64 stopTime); + +} GFMMPROC_CONTROL_STOP_TIME_TABLE; + +#define GFMMPROC_CONTROL_STOP_TIME_RESET -1 + +#define GFMmProcControlStopTimeGetStopTime(handle) \ + (GFMMPROC_CONTROL_STOP_TIME_TABLE*)handle)->MmProcControlStopTimeGetStopTime(handle) +#define GFMmProcControlStopTimeSetStopTime(handle, stopTime) \ + ((GFMMPROC_CONTROL_STOP_TIME_TABLE*)handle)->MmProcControlStopTimeSetStopTime(handle, stopTime) + + +//***************************************************************************** +// TempoControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_TEMPO_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Rate Methods + // + NvS32 (*MmProcControlRateGetMaxRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateGetMinRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateGetRate)(GFMMPROC_CONTROL_RATE handle); + NvS32 (*MmProcControlRateSetRate)(GFMMPROC_CONTROL_RATE handle, NvS32 millirate); + + NvS32 (*MmProcControlTempoGetTempo)(GFMMPROC_CONTROL_TEMPO handle); + NvS32 (*MmProcControlTempoSetTempo)(GFMMPROC_CONTROL_TEMPO handle, NvS32 millitempo); + +} GFMMPROC_CONTROL_TEMPO_TABLE; + +#define GFMmProcControlTempoGetTempo(handle) \ + ((GFMMPROC_CONTROL_TEMPO_TABLE*)handle)->MmProcControlTempoGetTempo(handle) +#define GFMmProcControlTempoSetTempo(handle) \ + ((GFMMPROC_CONTROL_TEMPO_TABLE*)handle)->MmProcControlTempoSetTempo(handle, millitempo) + + +//***************************************************************************** +// ToneControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_TONE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlToneSetSequence)(GFMMPROC_CONTROL_TONE handle, NvS8* sequence); + +} GFMMPROC_CONTROL_TONE_TABLE; + +#define GFMMPROC_CONTROL_TONE_VERSION -2 +#define GFMMPROC_CONTROL_TONE_TEMPO -3 +#define GFMMPROC_CONTROL_TONE_RESOLUTION -4 +#define GFMMPROC_CONTROL_TONE_BLOCK_START -5 +#define GFMMPROC_CONTROL_TONE_BLOCK_END -6 +#define GFMMPROC_CONTROL_TONE_PLAY_BLOCK -7 +#define GFMMPROC_CONTROL_TONE_SET_VOLUME -8 +#define GFMMPROC_CONTROL_TONE_REPEAT -9 +#define GFMMPROC_CONTROL_TONE_C4 60 +#define GFMMPROC_CONTROL_TONE_SILENCE -1 + +#define GFMmProcControlToneSetSequence(handle, sequence) \ + ((GFMMPROC_CONTROL_TONE_TABLE*)handle)->MmProcControlToneSetSequence(handle, sequence) + + +//***************************************************************************** +// VolumeControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_VOLUME_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlVolumeGetLevel)(GFMMPROC_CONTROL_VOLUME handle); + NvS32 (*MmProcControlVolumeIsMuted)(GFMMPROC_CONTROL_VOLUME handle); + NvS32 (*MmProcControlVolumeSetLevel)(GFMMPROC_CONTROL_VOLUME handle, NvS32 level); + void (*MmProcControlVolumeSetMute)(GFMMPROC_CONTROL_VOLUME handle, NvS32 mute); + +} GFMMPROC_CONTROL_VOLUME_TABLE; + +#define GFMmProcControlVolumeGetLevel(handle) \ + ((GFMMPROC_CONTROL_VOLUME_TABLE*)handle)->MmProcControlVolumeGetLevel(handle) +#define GFMmProcControlVolumeIsMuted(handle) \ + ((GFMMPROC_CONTROL_VOLUME_TABLE*)handle)->MmProcControlVolumeIsMuted(handle) +#define GFMmProcControlVolumeSetLevel(handle, level) \ + ((GFMMPROC_CONTROL_VOLUME_TABLE*)handle)->MmProcControlVolumeSetLevel(handle, level) +#define GFMmProcControlVolumeSetMute(handle, mute) \ + ((GFMMPROC_CONTROL_VOLUME_TABLE*)handle)->MmProcControlVolumeSetMute(handle, mute) + + +#endif // GFMMPROC_BASIC_AUDIO_CONTROLS + +#endif // GFMMPROC_BASIC_AUDIO + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_ADVANCED +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_ADVANCED + +typedef GF_HANDLE GFMMPROC_MODULE; +typedef GFMMPROC_MODULE GFMMPROC_EFFECT_MODULE; +typedef GFMMPROC_MANAGER GFMMPROC_GLOBAL_MANAGER; +typedef GFMMPROC_CONTROLLABLE GFMMPROC_MEDIA_PROCESSOR; +typedef GF_HANDLE GFMMPROC_MEDIA_PROCESSOR_LISTENER; +typedef GFMMPROC_CONTROLLABLE GFMMPROC_SPECTATOR; +typedef GFMMPROC_MODULE GFMMPROC_SOUND_SOURCE_3D; + + +//***************************************************************************** +// Module +//***************************************************************************** +// +typedef struct _GFMMPROC_MODULE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Controllable Methods + // + GFMMPROC_CONTROL (*MmProcControllableGetControl)(GFMMPROC_CONTROLLABLE handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcControllableGetControls)(GFMMPROC_CONTROLLABLE handle); + + void (*MmProcModuleAddMIDIChannel)(GFMMPROC_MODULE handle, GFMMPROC_PLAYER player, NvS32 channel); + void (*MmProcModuleAddPlayer)(GFMMPROC_MODULE handle, GFMMPROC_PLAYER player); + void (*MmProcModuleRemoveMIDIChannel)(GFMMPROC_MODULE handle, GFMMPROC_PLAYER player, NvS32 channel); + void (*MmProcModuleRemovePlayer)(GFMMPROC_MODULE handle, GFMMPROC_PLAYER player); + +} GFMMPROC_MODULE_TABLE; + +#define GFMmProcModuleAddMIDIChannel(handle, player, channel) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleAddMIDIChannel(handle, player, channel) +#define GFMmProcModuleAddPlayer(handle, player) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleAddPlayer(handle, player) +#define GFMmProcModuleGetControl(handle, controlType) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleGetControl(handle, controlType) +#define GFMmProcModuleGetControls(handle) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleGetControls(handle) +#define GFMmProcModuleRemoveMIDIChannel(handle, player, channel) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleRemoveMIDIChannel(handle, player, channel) +#define GFMmProcModuleRemovePlayer(handle, player) \ + ((GFMMPROC_MODULE_TABLE*)handle)->MmProcModuleRemovePlayer(handle, player) + + +//***************************************************************************** +// EffectModule +//***************************************************************************** +// +typedef GFMMPROC_MODULE_TABLE GFMMPROC_EFFECT_MODULE_TABLE; + + +//***************************************************************************** +// GlobalManager +//***************************************************************************** +// +typedef struct _GFMMPROC_GLOBAL_MANAGER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Manager Methods + // + GFMMPROC_PLAYER (*MmProcManagerCreatePlayer)(GFMMPROC_MANAGER handle, char* locator); +// GFMMPROC_PLAYER (*MmProcManagerCreatePlayerForDataSource)(GFMMPROC_MANAGER handle, DataSource source); + GFMMPROC_PLAYER (*MmProcManagerCreatePlayerForStream)(GFMMPROC_MANAGER handle, GFMMPROC_STREAM stream, char* type); + char* (*MmProcManagerGetSupportedContentTypes)(GFMMPROC_MANAGER handle, char* protocol); + char* (*MmProcManagerGetSupportedProtocols)(GFMMPROC_MANAGER handle, char* contentType); + GFMMPROC_TIME_BASE (*MmProcManagerGetSystemTimeBase)(GFMMPROC_MANAGER handle); + void (*MmProcManagerPlayTone)(GFMMPROC_MANAGER handle, NvU32 note, NvU32 duration, NvU32 volume); + void (*MmProcManagerProcess)(GFMMPROC_MANAGER handle); + GFMMPROC_CODEC_TYPE (*MmProcManagerGetCodecType)(GFMMPROC_MANAGER handle); + void (*MmProcManagerCodecWrite)(GFMMPROC_MANAGER handle, NvU32 offset, NvU32 value); + NvU32 (*MmProcManagerCodecRead)(GFMMPROC_MANAGER handle, NvU32 offset); + + GFMMPROC_EFFECT_MODULE (*MmProcGlobalManagerCreateEffectModule)(GFMMPROC_GLOBAL_MANAGER handle); + GFMMPROC_MEDIA_PROCESSOR (*MmProcGlobalManagerCreateMediaProcessor)(GFMMPROC_GLOBAL_MANAGER handle); + GFMMPROC_SOUND_SOURCE_3D (*MmProcGlobalManagerCreateSoundSource3D)(GFMMPROC_GLOBAL_MANAGER handle); + GFMMPROC_CONTROL (*MmProcGlobalManagerGetControl)(GFMMPROC_GLOBAL_MANAGER handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcGlobalManagerGetControls)(GFMMPROC_GLOBAL_MANAGER handle); + GFMMPROC_SPECTATOR (*MmProcGlobalManagerGetSpectator)(GFMMPROC_GLOBAL_MANAGER handle); + char* (*MmProcGlobalManagerGetSupportedMediaProcessorInputTypes)(GFMMPROC_GLOBAL_MANAGER handle); + NvS32 (*MmProcGlobalManagerGetUnitsPerMeter)(GFMMPROC_GLOBAL_MANAGER handle); + void (*MmProcGlobalManagerSetUnitsPerMeter)(GFMMPROC_GLOBAL_MANAGER handle, NvS32 newScalingFactor); + +} GFMMPROC_GLOBAL_MANAGER_TABLE; + +#define GFMmProcGlobalManagerCreateEffectModule(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerCreateEffectModule(handle) +#define GFMmProcGlobalManagerCreateMediaProcessor(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerCreateMediaProcessor(handle) +#define GFMmProcGlobalManagerCreateSoundSource3D(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerCreateSoundSource3D(handle) +#define GFMmProcGlobalManagerGetControl(handle, controlType) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetControl(handle, controlType) +#define GFMmProcGlobalManagerGetControls(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetControls(handle) +#define GFMmProcGlobalManagerGetSpectator(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetSpectator(handle) +#define GFMmProcGlobalManagerGetSupportedMediaProcessorInputTypes(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetSupportedMediaProcessorInputTypes(handle) +#define GFMmProcGlobalManagerGetUnitsPerMeter(handle) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerGetUnitsPerMeter(handle) +#define GFMmProcGlobalManagerSetUnitsPerMeter(handle, newScalingFactor) \ + ((GFMMPROC_GLOBAL_MANAGER_TABLE*)handle)->MmProcGlobalManagerSetUnitsPerMeter(handle, newScalingFactor) + + +//***************************************************************************** +// MediaProcessor +//***************************************************************************** +// +typedef struct _GFMMPROC_MEDIA_PROCESSOR_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Controllable Methods + // + GFMMPROC_CONTROL (*MmProcControllableGetControl)(GFMMPROC_CONTROLLABLE handle, char* controlType); + GFMMPROC_CONTROL* (*MmProcControllableGetControls)(GFMMPROC_CONTROLLABLE handle); + + void (*MmProcMediaProcessorAbort)(GFMMPROC_MEDIA_PROCESSOR handle); + void (*MmProcMediaProcessorAddMediaProcessorListener)(GFMMPROC_MEDIA_PROCESSOR handle, + GFMMPROC_MEDIA_PROCESSOR_LISTENER mediaProcessorListener); + void (*MmProcMediaProcessorComplete)(GFMMPROC_MEDIA_PROCESSOR handle); + NvS32 (*MmProcMediaProcessorGetProgress)(GFMMPROC_MEDIA_PROCESSOR handle); + void (*MmProcMediaProcessorRemoveMediaProcessorListener)(GFMMPROC_MEDIA_PROCESSOR handle, + GFMMPROC_MEDIA_PROCESSOR_LISTENER mediaProcessorListener); + void (*MmProcMediaProcessorStart)(GFMMPROC_MEDIA_PROCESSOR handle); + void (*MmProcMediaProcessorStop)(GFMMPROC_MEDIA_PROCESSOR handle); + GFMMPROC_PLAYER (*MmProcMediaProcessorSetInput)(GFMMPROC_MEDIA_PROCESSOR handle, GFMMPROC_STREAM input, char* contentType, NvS32 length); + GFMMPROC_PLAYER (*MmProcMediaProcessorSetOutput)(GFMMPROC_MEDIA_PROCESSOR handle, GFMMPROC_STREAM output, char* contentType); + +} GFMMPROC_MEDIA_PROCESSOR_TABLE; + +#define GFMMPROC_MEDIA_PROCESSOR_UNKNOWN -1 + +#define GFMmProcMediaProcessorAbort(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorAbort(handle) +#define GFMmProcMediaProcessorAddMediaProcessorListener(handle, mediaProcessorListener) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorAddMediaProcessorListener(handle, mediaProcessorListener) +#define GFMmProcMediaProcessorComplete(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorComplete(handle) +#define GFMmProcMediaProcessorGetProgress(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorGetProgress(handle) +#define GFMmProcMediaProcessorRemoveMediaProcessorListener(handle, mediaProcessorListener) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorRemoveMediaProcessorListener(handle, mediaProcessorListener) +#define GFMmProcMediaProcessorStart(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorStart(handle) +#define GFMmProcMediaProcessorStop(handle) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorStop(handle) +#define GFMmProcMediaProcessorSetInput(handle, input, contentType, length) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorSetInput(handle, input, contentType, length) +#define GFMmProcMediaProcessorSetOutput(handle, output, contentType) \ + ((GFMMPROC_MEDIA_PROCESSOR_TABLE*)handle)->MmProcMediaProcessorSetOutput(handle, output, contentType) + + +//***************************************************************************** +// MediaProcessorListener +//***************************************************************************** +// +typedef struct _GFMMPROC_MEDIA_PROCESSOR_LISTENER_TABLE +{ + void (*MmProcMediaProcessorListenerMediaProcessorUpdate)(GFMMPROC_MEDIA_PROCESSOR_LISTENER handle, + GFMMPROC_MEDIA_PROCESSOR processor, char* event, + void* eventData); + +} GFMMPROC_MEDIA_PROCESSOR_LISTENER_TABLE; + +#define GFMMPROC_MEDIA_PROCESSOR_LISTENER_PROCESSING_COMPLETED "processingCompleted" +#define GFMMPROC_MEDIA_PROCESSOR_LISTENER_PROCESSING_ERROR "processingError" + +#define GFMmProcMediaProcessorListenerMediaProcessorUpdate(handle, processor, event, eventData) \ + ((GFMMPROC_MEDIA_PROCESSOR_LISTENER_TABLE*)handle)->MmProcMediaProcessorListenerMediaProcessorUpdate(handle, processor, event, eventData) + + +//***************************************************************************** +// Spectator +//***************************************************************************** +// +typedef GFMMPROC_CONTROLLABLE_TABLE GFMMPROC_SPECTATOR_TABLE; + + +//***************************************************************************** +// SoundSource3D +//***************************************************************************** +// +typedef GFMMPROC_MODULE_TABLE GFMMPROC_SOUND_SOURCE_3D_TABLE; + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS + +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_COMMIT; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_ORIENTATION; +typedef GFMMPROC_CONTROL_ORIENTATION GFMMPROC_CONTROL_DIRECTIVITY; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_DISTANCE_ATTENUATION; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_DOPPLER; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_LOCATION; +typedef GFMMPROC_CONTROL_ORIENTATION GFMMPROC_CONTROL_MACROSCOPIC; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_OBSTRUCTION; + +#include "GFAudio.h" + +//***************************************************************************** +// CommitControl +//***************************************************************************** +typedef struct _GFMMPROC_CONTROL_COMMIT_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlCommitCommit)(GFMMPROC_CONTROL_COMMIT handle); + NvS32 (*MmProcControlCommitIsDeferred)(GFMMPROC_CONTROL_COMMIT handle); + void (*MmProcControlCommitSetDeferred)(GFMMPROC_CONTROL_COMMIT handle, NvS32 deferred); + +} GFMMPROC_CONTROL_COMMIT_TABLE; + +#define GFMmProcControlCommitCommit(handle) \ + ((GFMMPROC_CONTROL_COMMIT_TABLE*)handle)->MmProcControlCommitCommit(handle) +#define GFMmProcControlCommitIsDeferred(handle) \ + ((GFMMPROC_CONTROL_COMMIT_TABLE*)handle)->MmProcControlCommitIsDeferred(handle) +#define GFMmProcControlCommitSetDeferred(handle, deferred) \ + ((GFMMPROC_CONTROL_COMMIT_TABLE*)handle)->MmProcControlCommitSetDeferred(handle, deferred) + + + +//***************************************************************************** +// OrientationControl +//***************************************************************************** +typedef struct _GFMMPROC_CONTROL_ORIENTATION_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlOrientationGetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32* frontVector, NvVectorS32* aboveVector); + void (*MmProcControlOrientationSetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32 frontVector, NvVectorS32 aboveVector); + +} GFMMPROC_CONTROL_ORIENTATION_TABLE; + +#define GFMmProcControlOrientationGetOrientation(handle, frontVector, aboveVector) \ + ((GFMMPROC_CONTROL_ORIENTATION_TABLE*)handle)->MmProcControlOrientationGetOrientation(handle, frontVector, aboveVector) +#define GFMmProcControlOrientationSetOrientation(handle, frontVector, aboveVector) \ + ((GFMMPROC_CONTROL_ORIENTATION_TABLE*)handle)->MmProcControlOrientationSetOrientation(handle, frontVector, aboveVector) + + +//***************************************************************************** +// DirectivityControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_DIRECTIVITY_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Orientation Methods + // + void (*MmProcControlOrientationGetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32* frontVector, NvVectorS32* aboveVector); + void (*MmProcControlOrientationSetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32 frontVector, NvVectorS32 aboveVector); + + void (*MmProcControlDirectivityGetParameters)(GFMMPROC_CONTROL_DIRECTIVITY handle, NvVectorS32* vector); + void (*MmProcControlDirectivitySetParameters)(GFMMPROC_CONTROL_DIRECTIVITY handle, + NvS32 minAngle, NvS32 maxAngle, NvS32 rearLevel); + +} GFMMPROC_CONTROL_DIRECTIVITY_TABLE; + +#define GFMmProcControlDirectivityGetParameters(handle, vector) \ + ((GFMMPROC_CONTROL_DIRECTIVITY_TABLE*)handle)->MmProcControlDirectivityGetParameters(handle, vector) +#define GFMmProcControlDirectivitySetParameters(handle, minAngle, maxAngle, rearLevel) \ + ((GFMMPROC_CONTROL_DIRECTIVITY_TABLE*)handle)->MmProcControlDirectivitySetParameters(handle, minAngle, maxAngle, rearLevel) + + +//***************************************************************************** +// DistanceAttenuationControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlDistanceAttenuationGetMaxDistance)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle); + NvS32 (*MmProcControlDistanceAttenuationGetMinDistance)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle); + NvS32 (*MmProcControlDistanceAttenuationGetMuteAfterMax)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle); + NvS32 (*MmProcControlDistanceAttenuationGetRolloffFactor)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle); + void (*MmProcControlDistanceAttenuationSetParameters)(GFMMPROC_CONTROL_DISTANCE_ATTENUATION handle, + NvS32 minDistance, NvS32 maxDistance, + NvS32 muteAfterMax, NvS32 rolloffFactor); + +} GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE; + +#define GFMmProcControlDistanceAttenuationGetMaxDistance(handle) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationGetMaxDistance(handle) +#define GFMmProcControlDistanceAttenuationGetMinDistance(handle) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationGetMinDistance(handle) +#define GFMmProcControlDistanceAttenuationGetMuteAfterMax(handle) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationGetMuteAfterMax(handle) +#define GFMmProcControlDistanceAttenuationGetRolloffFactor(handle) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationGetRolloffFactor(handle) +#define GFMmProcControlDistanceAttenuationSetParameters(handle, minDistance, maxDistance, muteAfterMax, rolloffFactor) \ + ((GFMMPROC_CONTROL_DISTANCE_ATTENUATION_TABLE*)handle)->MmProcControlDistanceAttenuationSetParameters(handle, minDistance, maxDistance, muteAfterMax, rolloffFactor) + + +//***************************************************************************** +// DopplerControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_DOPPLER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlDopplerGetVelocityCartesian)(GFMMPROC_CONTROL_DOPPLER handle, NvVectorS32* vector); + NvS32 (*MmProcControlDopplerIsEnabled)(GFMMPROC_CONTROL_DOPPLER handle); + void (*MmProcControlDopplerSetEnabled)(GFMMPROC_CONTROL_DOPPLER handle, NvS32 dopplerEnabled); + void (*MmProcControlDopplerSetVelocityCartesian)(GFMMPROC_CONTROL_DOPPLER handle, NvVectorS32 vector); + void (*MmProcControlDopplerSetVelocitySpherical)(GFMMPROC_CONTROL_DOPPLER handle, + NvS32 azimuth, NvS32 elevation, NvS32 radius); + +} GFMMPROC_CONTROL_DOPPLER_TABLE; + +#define GFMmProcControlDopplerGetVelocityCartesian(handle, vector) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerGetVelocityCartesian(handle, vector) +#define GFMmProcControlDopplerIsEnabled(handle) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerIsEnabled(handle) +#define GFMmProcControlDopplerSetEnabled(handle, dopplerEnabled) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerSetEnabled(handle, dopplerEnabled) +#define GFMmProcControlDopplerSetVelocityCartesian(handle, vector) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerSetVelocityCartesian(handle, vector) +#define GFMmProcControlDopplerSetVelocitySpherical(handle, azimuth, elevation, radius) \ + ((GFMMPROC_CONTROL_DOPPLER_TABLE*)handle)->MmProcControlDopplerSetVelocitySpherical(handle, azimuth, elevation, radius) + + +//***************************************************************************** +// LocationControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_LOCATION_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + void (*MmProcControlLocationGetCartesian)(GFMMPROC_CONTROL_LOCATION handle, NvVectorS32* vector); + void (*MmProcControlLocationSetCartesian)(GFMMPROC_CONTROL_LOCATION handle, NvVectorS32 vector); + void (*MmProcControlLocationSetSpherical)(GFMMPROC_CONTROL_LOCATION handle, NvS32 azimuth, NvS32 elevation, NvS32 radius); + void (*MmProcControlLocationSetCoefficients)(GFMMPROC_CONTROL_LOCATION handle,GFMMPROC_SOUND_SOURCE_3D SS3D,GFMMPROC_SPECTATOR spec, NvS32 CurrVec[],NvS32 TargVec[]); + void (*MmProcControlLocationGetCoefficients)(GFMMPROC_CONTROL_LOCATION handle, void* Coeff); + +} GFMMPROC_CONTROL_LOCATION_TABLE; + +#define GFMmProcControlLocationGetCartesian(handle, vector) \ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationGetCartesian(handle, vector) +#define GFMmProcControlLocationSetCartesian(handle, vector) \ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationSetCartesian(handle, vector) +#define GFMmProcControlLocationSetSpherical(handle, azimuth, elevation, radius) \ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationSetSpherical(handle, azimuth, elevation, radius) +#define GFMmProcControlLocationSetCoefficients(handle, SS3D,spec, CurrVec,TargVec) \ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationSetCoefficients(handle, SS3D,spec, CurrVec,TargVec) +#define GFMmProcControlLocationGetCoefficients(handle,pCoeff)\ + ((GFMMPROC_CONTROL_LOCATION_TABLE*)handle)->MmProcControlLocationGetCoefficients(handle,pCoeff) + +//***************************************************************************** +// MacroscopicControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_MACROSCOPIC_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + // + // Orientation Methods + // + void (*MmProcControlOrientationGetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32* frontVector, NvVectorS32* aboveVector); + void (*MmProcControlOrientationSetOrientation)(GFMMPROC_CONTROL_ORIENTATION handle, + NvVectorS32 frontVector, NvVectorS32 aboveVector); + + void (*MmProcControlMacroscopicGetSize)(GFMMPROC_CONTROL_MACROSCOPIC handle, NvVectorS32* vector); + void (*MmProcControlMacroscopicSetSize)(GFMMPROC_CONTROL_MACROSCOPIC handle, NvVectorS32 vector); + +} GFMMPROC_CONTROL_MACROSCOPIC_TABLE; + +#define GFMmProcControlMacroscopicGetSize(handle, vector) \ + ((GFMMPROC_CONTROL_MACROSCOPIC_TABLE*)handle)->MmProcControlMacroscopicGetSize(handle, vector) +#define GFMmProcControlMacroscopicSetSize(handle, vector) \ + ((GFMMPROC_CONTROL_MACROSCOPIC_TABLE*)handle)->MmProcControlMacroscopicSetSize(handle, vector) + + +//***************************************************************************** +// ObstructionControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_OBSTRUCTION_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlObstructionGetHFLevel)(GFMMPROC_CONTROL_OBSTRUCTION handle); + NvS32 (*MmProcControlObstructionGetLevel)(GFMMPROC_CONTROL_OBSTRUCTION handle); + void (*MmProcControlObstructionSetHFLevel)(GFMMPROC_CONTROL_OBSTRUCTION handle, NvS32 HFLevel); + void (*MmProcControlObstructionSetLevel)(GFMMPROC_CONTROL_OBSTRUCTION handle, NvS32 level); + +} GFMMPROC_CONTROL_OBSTRUCTION_TABLE; + +#define GFMmProcControlObstructionGetHFLevel(handle) \ + ((GFMMPROC_CONTROL_OBSTRUCTION_TABLE*)handle)->MmProcControlObstructionGetHFLevel(handle) +#define GFMmProcControlObstructionGetLevel(handle) \ + ((GFMMPROC_CONTROL_OBSTRUCTION_TABLE*)handle)->MmProcControlObstructionGetLevel(handle) +#define GFMmProcControlObstructionSetHFLevel(handle, HFLevel) \ + ((GFMMPROC_CONTROL_OBSTRUCTION_TABLE*)handle)->MmProcControlObstructionSetHFLevel(handle, HFLevel) +#define GFMmProcControlObstructionSetLevel(handle, level) \ + ((GFMMPROC_CONTROL_OBSTRUCTION_TABLE*)handle)->MmProcControlObstructionSetLevel(handle, level) + + +#endif // GFMMPROC_ADVANCED_3D_AUDIO_CONTROLS + + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_ADVANCED_CONTROLS +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_ADVANCED_CONTROLS + +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_AUDIO_FORMAT; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_EFFECT; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_EFFECT_ORDER; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_FORMAT; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_MIDI_CHANNEL; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_PAN; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_PRIORITY; + + + +//***************************************************************************** +// FormatControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_FORMAT_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlFormatGetEstimatedBitRate)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetFormat)(GFMMPROC_CONTROL_FORMAT handle); + NvS32 (*MmProcControlFormatGetIntParameterValue)(GFMMPROC_CONTROL_FORMAT handle, char* parameter); + NvS32 (*MmProcControlFormatGetMetadataOverride)(GFMMPROC_CONTROL_FORMAT handle); + NvS32 (*MmProcControlFormatGetMetadataSupportMode)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetStrParameterValue)(GFMMPROC_CONTROL_FORMAT handle, char* parameter); + char* (*MmProcControlFormatGetSupportedFormats)(GFMMPROC_CONTROL_FORMAT handle); + NvS32* (*MmProcControlFormatGetSupportedIntParameterRange)(GFMMPROC_CONTROL_FORMAT handle, char* parameter); + char* (*MmProcControlFormatGetSupportedIntParameters)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetSupportedMetadataKeys)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetSupportedStrParameters)(GFMMPROC_CONTROL_FORMAT handle); + char* (*MmProcControlFormatGetSupportedStrParameterValues)(GFMMPROC_CONTROL_FORMAT handle, char* parameter); + void (*MmProcControlFormatSetFormat)(GFMMPROC_CONTROL_FORMAT handle, char* format); + void (*MmProcControlFormatSetMetadata)(GFMMPROC_CONTROL_FORMAT handle, char* key, char* value); + void (*MmProcControlFormatSetMetadataOverride)(GFMMPROC_CONTROL_FORMAT handle, NvS32 override); + void (*MmProcControlFormatSetParameterStr)(GFMMPROC_CONTROL_FORMAT handle, char* parameter, char* value); + NvS32 (*MmProcControlFormatSetParameterInt)(GFMMPROC_CONTROL_FORMAT handle, char* parameter, NvS32 value); + +} GFMMPROC_CONTROL_FORMAT_TABLE; + +#define GFMMPROC_CONTROL_FORMAT_METADATA_NOT_SUPPORTED 0 +#define GFMMPROC_CONTROL_FORMAT_METADATA_SUPPORTED_FIXED_KEYS 1 +#define GFMMPROC_CONTROL_FORMAT_METADATA_SUPPORTED_FREE_KEYS 2 + +#define GFMMPROC_CONTROL_FORMAT_PARAM_BITRATE "bitrate" +#define GFMMPROC_CONTROL_FORMAT_PARAM_BITRATE_TYPE "bitrate type" +#define GFMMPROC_CONTROL_FORMAT_PARAM_BITS_PER_SAMPLE "bits per sample" +#define GFMMPROC_CONTROL_FORMAT_PARAM_CHANNELS "channels" +#define GFMMPROC_CONTROL_FORMAT_PARAM_FRAMERATE "frame rate" +#define GFMMPROC_CONTROL_FORMAT_PARAM_QUALITY "quality" +#define GFMMPROC_CONTROL_FORMAT_PARAM_SAMPLERATE "sample rate" +#define GFMMPROC_CONTROL_FORMAT_PARAM_TRACK "track" +#define GFMMPROC_CONTROL_FORMAT_PARAM_TRACKS_AVAILABLE "tracks available" +#define GFMMPROC_CONTROL_FORMAT_PARAM_VERSION_TYPE "version type" + +#define GFMMPROC_CONTROL_FORMAT_TRACK_ALL -1 +#define GFMMPROC_CONTROL_FORMAT_TRACK_DEFAULT 0 +#define GFMMPROC_CONTROL_FORMAT_TRACK_ONE 1 + + +#define GFMmProcControlFormatGetEstimatedBitRate(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetEstimatedBitRate(handle) +#define GFMmProcControlFormatGetFormat(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetFormat(handle) +#define GFMmProcControlFormatGetIntParameterValue(handle, parameter) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetIntParameterValue(handle, parameter) +#define GFMmProcControlFormatGetMetadataOverride(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetMetadataOverride(handle) +#define GFMmProcControlFormatGetMetadataSupportMode(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetMetadataSupportMode(handle) +#define GFMmProcControlFormatGetStrParameterValue(handle, parameter) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetStrParameterValue(handle, parameter) +#define GFMmProcControlFormatGetSupportedFormats(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedFormats(handle) +#define GFMmProcControlFormatGetSupportedIntParameterRange(handle, parameter) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedIntParameterRange(handle, parameter) +#define GFMmProcControlFormatGetSupportedIntParameters(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedIntParameters(handle) +#define GFMmProcControlFormatGetSupportedMetadataKeys(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedMetadataKeys(handle) +#define GFMmProcControlFormatGetSupportedStrParameters(handle) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedStrParameters(handle) +#define GFMmProcControlFormatGetSupportedStrParameterValues(handle, parameter) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatGetSupportedStrParameterValues(handle, parameter) +#define GFMmProcControlFormatSetFormat(handle, format) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetFormat(handle, format) +#define GFMmProcControlFormatSetMetadata(handle, key, value) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetMetadata(handle, key, value) +#define GFMmProcControlFormatSetMetadataOverride(handle, override) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetMetadataOverride(handle, override) +#define GFMmProcControlFormatSetParameterStr(handle, parameter, value) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetParameterStr(handle, parameter, value) +#define GFMmProcControlFormatSetParameterInt(handle, parameter, value) \ + ((GFMMPROC_CONTROL_FORMAT_TABLE*)handle)->MmProcControlFormatSetParameterInt(handle, parameter, value) + + + +//***************************************************************************** +// AudioFormatControl +//***************************************************************************** +// +typedef GFMMPROC_CONTROL_FORMAT_TABLE GFMMPROC_CONTROL_AUDIO_FORMAT_TABLE; + + +//***************************************************************************** +// EffectControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + +} GFMMPROC_CONTROL_EFFECT_TABLE; + +#define GFMMPROC_CONTROL_EFFECT_SCOPE_LIVE_ONLY 1 +#define GFMMPROC_CONTROL_EFFECT_SCOPE_RECORD_ONLY 2 +#define GFMMPROC_CONTROL_EFFECT_SCOPE_LIVE_AND_RECORD 3 + +#define GFMmProcControlEffectGetPreset(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectGetPreset(handle) +#define GFMmProcControlEffectGetPresetNames(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectGetPresetNames(handle) +#define GFMmProcControlEffectGetScope(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectGetScope(handle) +#define GFMmProcControlEffectIsEnabled(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectIsEnabled(handle) +#define GFMmProcControlEffectIsEnforced(handle) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectIsEnforced(handle) +#define GFMmProcControlEffectSetEnabled(handle, enable) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectSetEnabled(handle, enable) +#define GFMmProcControlEffectSetEnforced(handle, enforced) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectSetEnforced(handle, enforced) +#define GFMmProcControlEffectSetPreset(handle, preset) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectSetPreset(handle, preset) +#define GFMmProcControlEffectSetScope(handle, scope) \ + ((GFMMPROC_CONTROL_EFFECT_TABLE*)handle)->MmProcControlEffectSetScope(handle, scope) + + +//***************************************************************************** +// EffectOrderControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_ORDER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlEffectOrderGetEffectOrder)(GFMMPROC_CONTROL_EFFECT_ORDER handle, GFMMPROC_CONTROL_EFFECT effect); + GFMMPROC_CONTROL_EFFECT (*MmProcControlEffectOrderGetEffectOrders)(GFMMPROC_CONTROL_EFFECT_ORDER handle); + NvS32 (*MmProcControlEffectOrderSetEffectOrder)(GFMMPROC_CONTROL_EFFECT_ORDER handle, GFMMPROC_CONTROL_EFFECT effect, NvS32 order); + +} GFMMPROC_CONTROL_EFFECT_ORDER_TABLE; + +#define GFMmProcControlEffectOrderGetEffectOrder(handle, effect) \ + ((GFMMPROC_CONTROL_EFFECT_ORDER_TABLE*)handle)->(handle, effect) +#define GFMmProcControlEffectOrderGetEffectOrders(handle) \ + ((GFMMPROC_CONTROL_EFFECT_ORDER_TABLE*)handle)->MmProcControlEffectOrderGetEffectOrders(handle) +#define GFMmProcControlEffectOrderSetEffectOrder(handle, effect, order) \ + ((GFMMPROC_CONTROL_EFFECT_ORDER_TABLE*)handle)->MmProcControlEffectOrderSetEffectOrder(handle, effect, order) + + +//***************************************************************************** +// MIDIChannelControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_MIDI_CHANNEL_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + GFMMPROC_CONTROL (*MmProcControlMidiChannelGetChannelControl)(GFMMPROC_CONTROL_MIDI_CHANNEL handle, char* controlType, NvS32 channel); + GFMMPROC_CONTROL* (*MmProcControlMidiChannelGetChannelControls)(GFMMPROC_CONTROL_MIDI_CHANNEL handle, NvS32 channel); + +} GFMMPROC_CONTROL_MIDI_CHANNEL_TABLE; + +#define GFMmProcControlMidiChannelGetChannelControl(handle, controlType, channel) \ + ((GFMMPROC_CONTROL_MIDI_CHANNEL_TABLE*)handle)->MmProcControlMidiChannelGetChannelControl(handle, controlType, channel) +#define GFMmProcControlMidiChannelGetChannelControls(handle, channel) \ + ((GFMMPROC_CONTROL_MIDI_CHANNEL_TABLE*)handle)->MmProcControlMidiChannelGetChannelControls(handle, channel) + + +//***************************************************************************** +// PanControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_PAN_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlPanGetPan)(GFMMPROC_CONTROL_PAN handle); + NvS32 (*MmProcControlPanSetPan)(GFMMPROC_CONTROL_PAN handle, NvS32 pan); + +} GFMMPROC_CONTROL_PAN_TABLE; + +#define GFMmProcControlPanGetPan(handle) \ + ((GFMMPROC_CONTROL_PAN_TABLE*)handle)->MmProcControlPanGetPan(handle) +#define GFMmProcControlPanSetPan(handle, pan) \ + ((GFMMPROC_CONTROL_PAN_TABLE*)handle)->MmProcControlPanSetPan(handle, pan) + + +//***************************************************************************** +// PriorityControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_PRIORITY_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlPriorityGetPriority)(GFMMPROC_CONTROL_PRIORITY handle); + void (*MmProcControlPrioritySetPriority)(GFMMPROC_CONTROL_PRIORITY handle, NvS32 level); + +} GFMMPROC_CONTROL_PRIORITY_TABLE; + +#define GFMmProcControlPriorityGetPriority(handle) \ + ((GFMMPROC_CONTROL_PRIORITY_TABLE*)handle)->MmProcControlPriorityGetPriority(handle) +#define GFMmProcControlPrioritySetPriority(handle, level) \ + ((GFMMPROC_CONTROL_PRIORITY_TABLE*)handle)->MmProcControlPrioritySetPriority(handle, level) + + + +//***************************************************************************** +//***************************************************************************** +// +// +// GFMMPROC_ADVANCED_AUDIO_EFFECT_CONTROLS +// +// +//***************************************************************************** +//***************************************************************************** + +#if defined GFMMPROC_ADVANCED_AUDIO_EFFECT_CONTROLS + +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_ACOUSTIC_ECHO_CANCELLATION; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_CHORUS; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_EQUALIZER; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_REVERB; +typedef GFMMPROC_CONTROL_EFFECT GFMMPROC_CONTROL_EFFECT_DRC; +typedef GFMMPROC_CONTROL GFMMPROC_CONTROL_REVERB_SOURCE; + +//***************************************************************************** +// AudioVirtualizerControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectAudioVirtualizerGetSpread)(GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER handle); + void (*MmProcControlEffectAudioVirtualizerSetSpread)(GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER handle, NvS32 width); + +} GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_TABLE; + +#define GFMmProcControlEffectAudioVirtualizerGetSpread(handle) \ + ((GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_TABLE*)handle)->MmProcControlEffectAudioVirtualizerGetSpread(handle) +#define GFMmProcControlEffectAudioVirtualizerSetSpread(handle, width) \ + ((GFMMPROC_CONTROL_EFFECT_AUDIO_VIRTUALIZER_TABLE*)handle)->MmProcControlEffectAudioVirtualizerSetSpread(handle, width) + + +//***************************************************************************** +// AcousticEchoCancellationControl +//***************************************************************************** +// +typedef GFMMPROC_CONTROL_EFFECT_TABLE GFMMPROC_CONTROL_EFFECT_ACOUSTIC_ECHO_CANCELLATION_TABLE; + +//***************************************************************************** +// SBCControl +//***************************************************************************** +// +typedef GFMMPROC_CONTROL_EFFECT_TABLE GFMMPROC_CONTROL_EFFECT_SBC_TABLE; + +//***************************************************************************** +// SBRControl +//***************************************************************************** +// +typedef GFMMPROC_CONTROL_EFFECT_TABLE GFMMPROC_CONTROL_EFFECT_SBR_TABLE; + + +//***************************************************************************** +// ChorusControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectChorusGetAverageDelay)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetMaxAverageDelay)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetMaxModulationDepth)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetMaxModulationRate)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetMinModulationRate)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetModulationDepth)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetModulationRate)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + NvS32 (*MmProcControlEffectChorusGetWetLevel)(GFMMPROC_CONTROL_EFFECT_CHORUS handle); + void (*MmProcControlEffectChorusSetAverageDelay)(GFMMPROC_CONTROL_EFFECT_CHORUS handle, NvS32 delay); + void (*MmProcControlEffectChorusSetModulationDepth)(GFMMPROC_CONTROL_EFFECT_CHORUS handle, NvS32 depth); + void (*MmProcControlEffectChorusSetModulationRate)(GFMMPROC_CONTROL_EFFECT_CHORUS handle, NvS32 rate); + NvS32 (*MmProcControlEffectChorusSetWetLevel)(GFMMPROC_CONTROL_EFFECT_CHORUS handle, NvS32 level); + +} GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE; + +#define GFMmProcControlEffectChorusGetAverageDelay(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetAverageDelay(handle) +#define GFMmProcControlEffectChorusGetMaxAverageDelay(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetMaxAverageDelay(handle) +#define GFMmProcControlEffectChorusGetMaxModulationDepth(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetMaxModulationDepth(handle) +#define GFMmProcControlEffectChorusGetMaxModulationRate(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetMaxModulationRate(handle) +#define GFMmProcControlEffectChorusGetMinModulationRate(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetMinModulationRate(handle) +#define GFMmProcControlEffectChorusGetModulationDepth(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetModulationDepth(handle) +#define GFMmProcControlEffectChorusGetModulationRate(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetModulationRate(handle) +#define GFMmProcControlEffectChorusGetWetLevel(handle) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusGetWetLevel(handle) +#define GFMmProcControlEffectChorusSetAverageDelay(handle, delay) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusSetAverageDelay(handle, delay) +#define GFMmProcControlEffectChorusSetModulationDepth(handle, depth) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusSetModulationDepth(handle, depth) +#define GFMmProcControlEffectChorusSetModulationRate(handle, rate) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusSetModulationRate(handle, rate) +#define GFMmProcControlEffectChorusSetWetLevel(handle, level) \ + ((GFMMPROC_CONTROL_EFFECT_CHORUS_TABLE*)handle)->MmProcControlEffectChorusSetWetLevel(handle, level) + + +//***************************************************************************** +// EqualizerControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectEqualizerGetBand)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 frequency); + NvS32 (*MmProcControlEffectEqualizerGetBandLevel)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 band); + NvS32 (*MmProcControlEffectEqualizerGetBass)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + NvS32 (*MmProcControlEffectEqualizerGetCenterFreq)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 band); + NvS32 (*MmProcControlEffectEqualizerGetMaxBandLevel)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + NvS32 (*MmProcControlEffectEqualizerGetMinBandLevel)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + NvS32 (*MmProcControlEffectEqualizerGetNumberOfBands)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + NvS32 (*MmProcControlEffectEqualizerGetTreble)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle); + void (*MmProcControlEffectEqualizerSetBandLevel)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 level, NvS32 band); + NvS32 (*MmProcControlEffectEqualizerSetBass)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 level); + NvS32 (*MmProcControlEffectEqualizerSetTreble)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 level); + NvS32 (*MmProcControlEffectEqualizerSetBandX)(GFMMPROC_CONTROL_EFFECT_EQUALIZER handle, NvS32 *levelptr); + +} GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE; + +#define GFMMPROC_CONTROL_EFFECT_EQUALIZER_UNDEFINED -1004 + +#define GFMmProcControlEffectEqualizerGetBand(handle, frequency) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->(handle, frequency) +#define GFMmProcControlEffectEqualizerGetBandLevel(handle, band) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetBandLevel(handle, band) +#define GFMmProcControlEffectEqualizerGetBass(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetBass(handle) +#define GFMmProcControlEffectEqualizerGetCenterFreq(handle, band) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetCenterFreq(handle, band) +#define GFMmProcControlEffectEqualizerGetMaxBandLevel(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetMaxBandLevel(handle) +#define GFMmProcControlEffectEqualizerGetMinBandLevel(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetMinBandLevel(handle) +#define GFMmProcControlEffectEqualizerGetNumberOfBands(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetNumberOfBands(handle) +#define GFMmProcControlEffectEqualizerGetTreble(handle) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerGetTreble(handle) +#define GFMmProcControlEffectEqualizerSetBandLevel(handle, level, band) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerSetBandLevel(handle, level, band) +#define GFMmProcControlEffectEqualizerSetBass(handle, level) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerSetBass(handle, level) +#define GFMmProcControlEffectEqualizerSetTreble(handle, level) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerSetTreble(handle, level) +#define GFMmProcControlEffectEqualizerSetBandX(handle, levelptr) \ + ((GFMMPROC_CONTROL_EFFECT_EQUALIZER_TABLE*)handle)->MmProcControlEffectEqualizerSetBandX(handle, levelptr) + + +//***************************************************************************** +// Dynamic Range Control (DRC) +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_DRC_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectDRCGetDRCEnable)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetDRCEnable)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); + NvS32 (*MmProcControlEffectDRCGetNoiseGateTh)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetNoiseGateTh)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); + NvS32 (*MmProcControlEffectDRCGetLowerCompTh)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetLowerCompTh)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); + NvS32 (*MmProcControlEffectDRCGetUpperCompTh)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetUpperCompTh)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); + NvS32 (*MmProcControlEffectDRCGetClipTh)(GFMMPROC_CONTROL_EFFECT_DRC handle); + void (*MmProcControlEffectDRCSetClipTh)(GFMMPROC_CONTROL_EFFECT_DRC handle, NvS32 Param); +} GFMMPROC_CONTROL_EFFECT_DRC_TABLE; + +#define GFMmProcControlEffectDRCGetDRCEnable(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetDRCEnable(handle) +#define GFMmProcControlEffectDRCSetDRCEnable(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetDRCEnable(handle, Param) +#define GFMmProcControlEffectDRCGetNoiseGateTh(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetNoiseGateTh(handle) +#define GFMmProcControlEffectDRCSetNoiseGateTh(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetNoiseGateTh(handle, Param) +#define GFMmProcControlEffectDRCGetLowerCompTh(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetLowerCompTh(handle) +#define GFMmProcControlEffectDRCSetLowerCompTh(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetLowerCompTh(handle, Param) +#define GFMmProcControlEffectDRCGetUpperCompTh(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetUpperCompTh(handle) +#define GFMmProcControlEffectDRCSetUpperCompTh(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetUpperCompTh(handle, Param) +#define GFMmProcControlEffectDRCGetClipTh(handle) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCGetClipTh(handle) +#define GFMmProcControlEffectDRCSetClipTh(handle, Param) \ + ((GFMMPROC_CONTROL_EFFECT_DRC_TABLE*)handle)->MmProcControlEffectDRCSetClipTh(handle, Param) + + + + +//***************************************************************************** +// ReverbControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_EFFECT_REVERB_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + char* (*MmProcControlEffectGetPreset)(GFMMPROC_CONTROL_EFFECT handle); + char** (*MmProcControlEffectGetPresetNames)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectGetScope)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnabled)(GFMMPROC_CONTROL_EFFECT handle); + NvS32 (*MmProcControlEffectIsEnforced)(GFMMPROC_CONTROL_EFFECT handle); + void (*MmProcControlEffectSetEnabled)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enable); + void (*MmProcControlEffectSetEnforced)(GFMMPROC_CONTROL_EFFECT handle, NvS32 enforced); + void (*MmProcControlEffectSetPreset)(GFMMPROC_CONTROL_EFFECT handle, char* preset); + void (*MmProcControlEffectSetScope)(GFMMPROC_CONTROL_EFFECT handle, NvS32 scope); + + NvS32 (*MmProcControlEffectReverbGetReverbLevel)(GFMMPROC_CONTROL_EFFECT_REVERB handle); + NvS32 (*MmProcControlEffectReverbGetReverbTime)(GFMMPROC_CONTROL_EFFECT_REVERB handle); + NvS32 (*MmProcControlEffectReverbSetReverbLevel)(GFMMPROC_CONTROL_EFFECT_REVERB handle, NvS32 level); + void (*MmProcControlEffectReverbSetReverbTime)(GFMMPROC_CONTROL_EFFECT_REVERB handle, NvS32 time); + +} GFMMPROC_CONTROL_EFFECT_REVERB_TABLE; + +#define GFMmProcControlEffectReverbGetReverbLevel(handle) \ + ((GFMMPROC_CONTROL_EFFECT_REVERB_TABLE*)handle)->MmProcControlEffectReverbGetReverbLevel(handle) +#define GFMmProcControlEffectReverbGetReverbTime(handle) \ + ((GFMMPROC_CONTROL_EFFECT_REVERB_TABLE*)handle)->MmProcControlEffectReverbGetReverbTime(handle) +#define GFMmProcControlEffectReverbSetReverbLevel(handle, level) \ + ((GFMMPROC_CONTROL_EFFECT_REVERB_TABLE*)handle)->MmProcControlEffectReverbSetReverbLevel(handle, level) +#define GFMmProcControlEffectReverbSetReverbTime(handle, time) \ + ((GFMMPROC_CONTROL_EFFECT_REVERB_TABLE*)handle)->MmProcControlEffectReverbSetReverbTime(handle, time) + + +//***************************************************************************** +// ReverbSourceControl +//***************************************************************************** +// +typedef struct _GFMMPROC_CONTROL_REVERB_SOURCE_TABLE +{ + // + // Object Methods + // + NvS32 (*MmProcObjectIsInstance)(GF_HANDLE handle, const char* objectType); + + NvS32 (*MmProcControlReverbSourceGetRoomLevel)(GFMMPROC_CONTROL_REVERB_SOURCE handle); + void (*MmProcControlReverbSourceSetRoomLevel)(GFMMPROC_CONTROL_REVERB_SOURCE handle, NvS32 level); + +} GFMMPROC_CONTROL_REVERB_SOURCE_TABLE; + +#define GFMMPROC_CONTROL_REVERB_SOURCE_DISCONNECT -2147483648 + +#define GFMmProcControlReverbSourceGetRoomLevel(handle) \ + ((GFMMPROC_CONTROL_REVERB_SOURCE_TABLE*)handle)->MmProcControlReverbSourceGetRoomLevel(handle) +#define GFMmProcControlReverbSourceSetRoomLevel(handle, level) \ + ((GFMMPROC_CONTROL_REVERB_SOURCE_TABLE*)handle)->MmProcControlReverbSourceSetRoomLevel(handle, level) + + + +#endif // GFMMPROC_ADVANCED_AUDIO_EFFECT_CONTROLS + +#endif // GFMMPROC_ADVANCED_CONTROLS + +#endif // GFMMPROC_ADVANCED + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDec.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDec.h new file mode 100755 index 00000000..78cc7c5c --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDec.h @@ -0,0 +1,727 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an +* express license agreement from NVIDIA Corporation is strictly prohibited. +*/ + +/** @file GFMxDec.h +GFSDK MPEG Decode API header file. +*/ + +#ifndef _GF_MPEG_DEC__ +#define _GF_MPEG_DEC__ + +#include "nvtypes.h" +#include "GFVx.h" +#include "GFDef.h" + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif + + /** @addtogroup groupMxDec MxDecAPI MPEG Decode API +
        +
      • @ref pageMxDecAppNotes +
          +
        • @ref pageMxDecAppNotes1 +
        +
      + */ + /*@{*/ + + /****************************************************************************************************/ + // MXDECCapFlags + /** MxDecAPI property flag: Support for Simple Profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_SIMPLE 0x00000001 + /** MxDecAPI property flag: Support for simple profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ + +#define GF_MXDEC_CAP_SCALE 0x00000002 + /** MxDecAPI property flag: Support for simple scale profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ + +#define GF_MXDEC_CAP_CORE 0x00000004 + /** MxDecAPI property flag: Support for CORE profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ + +#define GF_MXDEC_CAP_MAIN 0x00000008 + /** MxDecAPI property flag: Support for MAIN profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ + + /** MxDecAPI property flag: Support for N_bit profile. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_N_BIT 0x00000010 + + /** MxDecAPI property flag: Support for LEVEL 1. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_LEVEL1 0x00000100 + + /** MxDecAPI property flag: Support for LEVEL 2. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_LEVEL2 0x00000200 + + /** MxDecAPI property flag: Support for LEVEL 3. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_LEVEL3 0x00000400 + + /** MxDecAPI property flag: Support for LEVEL 4. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_LEVEL4 0x00000800 + + /** MxDecAPI property flag: Support for Post Processing's de-blocking. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_DB 0x00001000 + + /** MxDecAPI property flag: Support for Post Processing's de-ringing. + @see GFMXDECTABLE::MxDecGetProperty, GFPROPERTY::Capability + */ +#define GF_MXDEC_CAP_DR 0x00002000 + + /****************************************************************************************************/ + /** This structure holds the video object plane (VOP) information. */ + typedef struct _GFMXDECVOP + { + NvU32 uiVOPinfo; /**< Set new VOP information */ + NvU32 uiFFORWARD; /**< FCODE_FORWARD, ignore this value if it is I frame */ + PGFRMSURFACE pRef; /**< Reference VOP, ignore this item, if current VOP is an I */ + PGFRMSURFACE pCur; /**< Current VOP */ + PGFRECT pRefRect; /**< Specifies a rectangular area within the pRef surface for the + GFMxDecAPI to use with the reference image. This field only takes + effect when MXDEC_VOP_SPECIFY_REFSURF_RECT is set. The rectangle’s + top and left should be aligned by the application, which should call + GFMxDecGetAttribute() with MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT + and MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT to get the required + alignment. The rectangle's width and height should exactly match the + image width and height that is encoded in the bit stream. */ + + PGFRECT pCurRect; /**< Specifies a rectangular area of the pCur surface within which the + GFMxDecAPI should place the decoded image output. This field only takes + effect if MXDEC_VOP_SPECIFY_CURSURF_RECT is set. The rectangle’s top and + left should be aligned by the application, which should call GFMxDecGetAttribute() + with MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT and + MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT to get the required alignment. + The rectangle's width and height should exactly match the image width and + height that is encoded in the bit stream. */ + }GFMXDECVOP, *PGFMXDECVOP; + + /****************************************************************************************************/ + //uiVOPinfo values + /** GFMXDECVOP::uiVOPinfo : If set, this is P VOP. If unset, it is I VOP. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_P_VOP 0x1 + + /** GFMXDECVOP::uiVOPinfo : This parameter comes as a part of the bitstream. + This indicates that rounding should be performed while doing Motion Compensation. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_ROUNDING_ONE 0x2 + + /** GFMXDECVOP::uiVOPinfo : If set, this bitstream is short video header format. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_SHORT_HEADER 0x4 + + /** GFMXDECVOP::uiVOPinfo : If set, If this flag is set, pRefSurfRect must be set. + GFMxDec will reference image in pRefSurfRect area of pRef surface. Otherwise, GFMxDec will reference the whole pRef surface area. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_SPECIFY_REFSURF_RECT 0x8 + + /** GFMXDECVOP::uiVOPinfo : If this flag is set, pCurSurfRect must be set. GFMxDec will output decoded image to + pCurSurfRect area of pCur surface. Otherwise, GFMxDec will output to pCur surface starting from top left corner , the width and + height are equal to pCur surface width and height. + @see GFMXDECVOP, GFMXDECTABLE::MxDecSetVOP */ +#define MXDEC_VOP_SPECIFY_CURSURF_RECT 0x10 + + /****************************************************************************************************/ + /** This structure holds the postprocessing information. */ + typedef struct _GFMXDECPP + { + PGFRMSURFACE* pDestSurf; /**< Pointer to an array of surfaces that will hold the result from Post Processing + pointer to an array of surfaces to accommodate auto post processing. */ + PGFRMSURFACE* pSrcSurf; /**< Pointer to an array of surfaces to be post processed pointer to an array of surfaces + to accommodate auto post processing. */ + PGFRECT pRect; /**< Rectangular area to be processed for both source and destination surfaces. + @see GFRECT */ + NvU32 numofDestSurf; /**< Number of Destination Surfaces. If MXDEC_PP_AUTO flag is set, this parameter must be filled. */ + NvU32 numofSrcSurf; /**< Number of Source Surfaces. If MXDEC_PP_AUTO flag is set, this parameter must be filled. */ + NvU8 * lpQuantiser; /**< Pointer to array of quantization steps (QPs) for macroblocks in + the source VOP. The GFMxDecAPI automatically saved the last + two decoded VOP’s QP tables. The application may not need to + reload the table if it can make sure the source VOP is one of the + last decoded VOPs. This field must be filled if + MXDEC_PP_RELOAD_QUANTIZER is set. */ + NvU32 PPOption; /**< Post-processing option. */ + /**< + + + + + + + + + + +
      #MXDEC_PP_DB_ONTurn on DeBlocking filter for this frame
      #MXDEC_PP_DR_ONTurn on DeRinging filter for this frame
      #MXDEC_PP_AUTOAuto trigger Post Processing by Hardware
      #MXDEC_PP_RELOAD_QUANTIZERReload the source VOP's qunantizers
      #MXDEC_PP_OP_ASYNCEnables ASYNC mode
      + */ + } GFMXDECPP, *PGFMXDECPP; + + /****************************************************************************************************/ + // PPOption + /** GFMXDECPP::PPOption : Turn on DeBlocking filter for this frame. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_DB_ON 0x1 + + /** GFMXDECPP::PPOption : Turn on DeRinging filter for this frame. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_DR_ON 0x2 + + /** GFMXDECPP::PPOption : Auto trigger Post Processing by Hardware. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_AUTO 0x4 + + /** GFMXDECPP::PPOption : Reload the source VOP's qunantizers. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_RELOAD_QUANTIZER 0x8 + + /** GFMXDECPP::PPOption : enables ASYN mode. GFMxDecPostProcessing() + will return after pushing the commands but without waiting for them to + complete. This option is useful to achieve some paralellism because + post-processed frame is usually not used right away for rendering. So + there is enough time for hardware to complete the decoding before this + frame will be used by app. It is ok to call PostProcessing even when + decoding of this frame is not complete. Inside GPU, hardware synchronizes + with the decoder. + @see GFMXDECPP, GFMXDECTABLE::MxDecPostProcessing */ +#define MXDEC_PP_OP_ASYNC 0x00000010 + + /****************************************************************************************************/ + //pStatus + /** Argument pStatus in GFMxDecGetStatus() : GFMxDecGetStatus() can be called by the application to indicate whether 1 frame + has been decoded or not. + @see GFMXDECTABLE::MxDecGetStatus */ +#define GF_DECODER_FRAME_DONE 0x00000010 + + /** Argument pStatus in GFMxDecGetStatus() : GFMxDecGetStatus() can be called by the application to indicate whether post-processing + engine is done with the frame or not. + @see GFMXDECTABLE::MxDecGetStatus */ +#define GF_DECODER_PP_FRAME_DONE 0x00000020 + + /****************************************************************************************************/ + /** GFMxDecSet::uiFeature : Application sets this attribute to register a callback function and + its correpnding parameter to read bitstream data */ +#define MXDEC_SET_READBITSTREAM 1 + + /** GFMxDecSet::uiFeature Application needs to set this flag in order to send MPEG4 bitstream data in Prefill Mode; + When this is set: + - application does not need to register any bitstream-read callback function as data will be fed upfront. + - application needs to set an attribute MXDEC_ATTR_PRE_DETERMINED_BOUNDARY to indicate that data will be fed on frame boundary. + @see GFMXDECTABLE::MxDecSet */ +#define GFMXDEC_OPTION_PREFILLBUFFER 0x00000002 + + /****************************************************************************************************/ + /** Structure holding the callback function pointer. + Used in registering the callback function + The callback function is a function which the API calls to request a portion of the bit stream from the application. + @see GFMXDECTABLE::MxDecSet + */ + typedef struct _GFMXDECCALLBACK + { + void *pPara; /**< pPara is a parameter passed from application and the application + wants the API to callback with this parameter. */ + NvU32 (*pCallBack)(void * pPara, NvU8 ** ppBuffer, NvS32 * BufferLength, NvU32 uFlag); + /**< + Application callback function pointer. + Register a callback function for fetching MPEG stream data. + + If application set MXDEC_ATTR_PRE_DETERMINED_BOUNDARY, application should + return MXDEC_BOUNDARY_REACHED when the boundary is detected. + If APP does not set MXDEC_ATTR_PRE_DETERMINED_BOUNDARY, 0 should be returned. + + @param *pPara Parameter to pass on to application callback function + @param ppBuffer Buffer Pointer + @param BufferLength Parameter to pass on to application callback function + @param uFlag Flag for reading bitstream backward/forward. + + + + + +
      #MXDEC_READ_BITSTREAM_FORWARDRead bitstream in forward direction
      #MXDEC_READ_BITSTREAM_BACKWARDRead bitstream in backward direction
      + + @retval The number of bytes read successfully, 0 if no bytes read. + */ + }GFMXDECCALLBACK, *PGFMXDECCALLBACK; + + /****************************************************************************************************/ + /** Returned by application when MXDEC_ATTR_PRE_DETERMINED_BOUNDARY is set and boundary is detected. */ +#define MXDEC_BOUNDARY_REACHED 0x00000001 + + // for backward/forward reading bitstream flags + /** Read bitstream in forward direction. + @see GFMXDECCALLBACK + */ +#define MXDEC_READ_BITSTREAM_FORWARD 0x00000002 + + /** Read bitstream in backward direction. + @see GFMXDECCALLBACK + */ +#define MXDEC_READ_BITSTREAM_BACKWARD 0x00000003 + + /****************************************************************************************************/ + //uiVOLinfo + /** GFMXDECMP4SETVOL::uiVOLinfo : If set indicates that VOL is in short header format. + @see GFMXDECMP4SETVOL*/ +#define MXDEC_MP4_SET_SHORT_HEADER 0x00000001 + + /****************************************************************************************************/ + /** This structure hold information of the PreFill buffer. + */ + typedef struct _GFMXDECPREFILLBUFFER + { + NvU8* pPreFillBuffer; /**< Input, Prefill buffer pointer filled by application. */ + NvU32 PreFillBufferLength; /**< Input, Length of pref-fill buffer. */ + NvU32 PreFillBufferBytesConsumed; /**< Output, Amount of bytes consumed by the component. */ + NvU32 prefill_enabled; /**< Flag to identify if prefill buffer is supplied by application. */ + } GFMXDECPREFILLBUFFER; + + /****************************************************************************************************/ + /** This structure hold the information needed for decoding a Video Object Layer (VOL). + @see GFMXDECTABLE::MxDecMP4DecVOL */ + typedef struct _GFMXDECMP4DECVOL + { + NvU32 uiVOLinfo; /**< Indicates format of the VOL. Set by API. */ + /**< + + + + + + + + + + + + + + + + + + +
      #MXDEC_MP4_SHORT_HEADERShort header format detected
      #MXDEC_MP4_DATA_PARTITIONData Partitioning mode detected
      #MXDEC_MP4_PROFILE_LEVELProfile and level field is valid
      #MXDEC_MP4_PRIORITYPriority field is valid
      #MXDEC_MP4_VSOTYPEVisual object type field is valid
      #MXDEC_MP4_VIDEO_SIGNALVideoFormat and VideoRange fields are valid
      #MXDEC_MP4_COLOR_DESCRIPTIONColor, Transfer and Matrix fields are valid
      #MXDEC_MP4_VOIDVObjectID field is valid
      #MXDEC_MP4_VOLIDVOLID field is valid
      + */ + NvU32 uiWidth; /**< Display width, set by API */ + NvU32 uiHeight; /**< Display height, set by API */ + unsigned int Profile; /**< Mpeg4 Profile. Set by API.*/ + /**< + + +
      #MXDEC_MP4_SIMPLE_PROFILEProfile is simple profile
      #MXDEC_MP4_ADVANCE_SIMPLE_PROFILEProfile is advance simple profile
      + */ + unsigned int Level; /**< Mpeg4 Level. Set by API. */ + unsigned int VObjectID; /**< Video Object ID. Set by API. */ + unsigned int VOLID; /**< Video Object Layer ID. Set by API. */ + unsigned int Priority; /**< Priority(of what (???)). Set by API. */ + unsigned int VSOType; /**< VSO(full form(???)) Type. Set by API. */ + unsigned int VideoFormat; /**< Video Format (what are the possible values (???)). Set by API. */ + unsigned int VideoRange; /**< Video Range. Set by API. */ + unsigned int Color; /**< Color primaries. */ + unsigned int Transfer; /**< Transfer charateristics. */ + unsigned int Matrix; /**< Matrix coefficients(???). */ + GFMXDECPREFILLBUFFER prefill; + }GFMXDECMP4DECVOL, *PGFMXDECMP4DECVOL; + + /****************************************************************************************************/ + //uiVOLinfo + /** GFMXDECMP4DECVOL::uiVOLinfo : Short header format detected. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_SHORT_HEADER 0x00000001 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Data Partitioning mode detected. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_DATA_PARTITION 0x00000002 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Profile and level field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_PROFILE_LEVEL 0x00000004 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Priority field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_PRIORITY 0x00000008 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Visual object type field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_VSOTYPE 0x00000010 + + /** GFMXDECMP4DECVOL::uiVOLinfo : VideoFormat and VideoRange fields are valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_VIDEO_SIGNAL 0x00000020 + + /** GFMXDECMP4DECVOL::uiVOLinfo : Color, Transfer and Matrix fields are valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_COLOR_DESCRIPTION 0x00000040 + + /** GFMXDECMP4DECVOL::uiVOLinfo : VObjectID field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_VOID 0x00000080 + + /** GFMXDECMP4DECVOL::uiVOLinfo : VOLID field is valid. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_VOLID 0x00000100 + + /****************************************************************************************************/ + //Profile + /** GFMXDECMP4DECVOL::Profile : Profile is simple profile. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_SIMPLE_PROFILE 0x00000000 + + /** GFMXDECMP4DECVOL::Profile : Profile is advance simple profile. + @see GFMXDECMP4DECVOL, GFMXDECTABLE::MxDecMP4DecVOL */ +#define MXDEC_MP4_ADVANCE_SIMPLE_PROFILE 0x00000009 + + /****************************************************************************************************/ + //resync options + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next nearest VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEAREST_VOL 0x1 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next nearest VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEAREST_VOP 0x2 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next nearest I-VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEAREST_I_VOP 0x4 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEXT_VOL 0x8 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEXT_VOP 0x10 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to next I-VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_FORWARD_NEXT_I_VOP 0x20 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous nearest VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_NEAREST_VOL 0x40 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous nearest VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_NEAREST_VOP 0x80 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous nearest I-VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_NEAREST_I_VOP 0x100 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous VOL. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_PREVIOUS_VOL 0x200 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_PREVIOUS_VOP 0x400 + + /** Argument ResyncOption for GFMXDECTABLE::MxDecMP4DecResync : Resync to previous I-VOP. + @see GFMXDECTABLE::MxDecMP4DecResync */ +#define MXDEC_MP4_RESYNC_BACKWARD_PREVIOUS_I_VOP 0x800 + + /****************************************************************************************************/ + /** This structure hold the information needed for decoding a Video Object Plane (VOP). + @see GFMXDECTABLE::MxDecMP4DecVOP */ + typedef struct _GFMXDECMP4DECVOP + { + PGFRMSURFACE pRef; /**< Reference VOP, ignore this item, if current VOP is an I. Set by application. */ + PGFRMSURFACE pCur; /**< Current VOP. Set by application. */ + PGFRECT pRefRect; /**< Reference rectangle. Set by application. + pRefRect specifies a rectangle area for GFMxDec to reference the reference image. + This rectangle area should be within the pRef surface. The rectangle top, left should + be aligned by application. Application should call GFMxDecGetAttribute() with + MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT and MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT + attributions to get the required alignment. This rectangle's width and height should + exactly match with the image width and height which has been coded in bit stream. If + pRefRect is NULL, GFMxDec will use pRef surface width and height as reference image dimension. + */ + PGFRECT pCurRect; /**< Current rectangle. Set by application. + pCurRect specifies a rectangle area for GFMxDec to output the decoded image. + This field only take effect when MXDEC_MP4_DEC_VOP_SPECIFY_REFSURF_RECT flag is set. + This rectangle area should be within the pCur surface. The rectangle top, left should be + aligned by application. Application should call GFMxDecGetAttribute() with + MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT and MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT + attributions to get the required alignment. This rectangle's width and height should exactly + match with the image width and height which has been coded in bit stream. If pCurRect is NULL, + GFMxDec will use pCur surface dimension as decoded image dimension. + */ + NvU32 uiVOPinfo; /**< Get current VOP information. Set by API. + + +
      #MXDEC_MP4_VOP_PVOP is coded as P-VOP
      #MXDEC_MP4_NOT_CODEDVOP is not coded
      (???)What about I-VOP?(???)
      + */ + NvU32 uiTimeStamp; /**< Time to display this VOP, in milliseconds. Set by API. */ + NvU8 *pMBInfo; /**< Pointer to array where information of whether the MB is decoded or not is stored. + Each element will tell if this corresponding MB is wrong. Set by API. */ + NvU32 uiVOPOption; /**< Must be used to set ASYNC option */ + + GFMXDECPREFILLBUFFER prefill; + }GFMXDECMP4DECVOP, *PGFMXDECMP4DECVOP; + + /** GFMXDECMP4DECVOP::uiVOPOption: enables ASYNC mode. GFMxDecMP4DecVOP() + will return after pushing the commands but without waiting for them to + complete. This option is useful to achieve some paralellism because + decoded frame is usually not used right away for rendering. So + there is enough time for hardware to complete the decoding before this + frame will be used by app. It is ok to call PostProcessing even when + decoding of this frame is not complete. Inside GPU, hardware synchronizes + with the decoder. */ +#define MXDEC_MP4DECVOP_OP_ASYNC 0x00000001 + + + /****************************************************************************************************/ + //uiVOPinfo + /** GFMXDECMP4DECVOP::uiVOPinfo : VOP is coded as P-VOP. + @see GFMXDECMP4DECVOP */ +#define MXDEC_MP4_VOP_P 0x00000001 + + /** GFMXDECMP4DECVOP::uiVOPinfo : VOP is not coded. + @see GFMXDECMP4DECVOP */ +#define MXDEC_MP4_NOT_CODED 0x00000002 //Not coded VOP + + /****************************************************************************************************/ + //when GF_ERROR is return check the following flag + /** This flag is set when atleast one MB is wrong. If application has setup pMBinfo, it can check which MB is wrong. */ +#define MXDEC_MP4_BAD_MB 0x00010000 + + /****************************************************************************************************/ + +#define MXDEC_ATTR_PRE_DETERMINED_BOUNDARY 0x00000001 + /**< MxDecAPI Attribute : Application will determine the decoding boundary, for MPEG4, this boundary means VOL + and VOP boundary. For certain file formats, those boundary information are stored in the video file, application + can easily use those information to determine the boundary. If APP wants API to detect the boundary, application + should not disable this attribute. This is mainly for streaming case, where application does not have those handy + boundary information. API will automatically detect those boundaries. Application does not need to parse the + bitstream to detect those boundaries.\n + Value to be passed to GFMxDecSetAttribute for setting this attribute: + +
      *pInfo == 1Application will determine the decoding boudary
      *pInfo == 0Application will not determine the decoding boudary
      + @see GFMXDECTABLE::MxDecSetAttribute + */ + +#define MXDEC_ATTR_MP4_DEC_VOP_RECT_TOP_ALIGNMENT 0x00000002 + /**< MxDecAPI Attribute : This attribute only can be used for GFMxDecGetAttribute. If application wants to set pDestRect + in GFMXDECVOP or GFMXDECMP4DECVOP, application must use this attribute to get alignment information and align the rectangle + top & left corner accordingly. Value returned by GFMxDecGetAttribute:\n + *pInfo: Top field alignment in term of lines + @see GFMXDECTABLE::MxDecGetAttribute + */ + +#define MXDEC_ATTR_MP4_DEC_VOP_RECT_LEFT_ALIGNMENT 0x00000003 + /**< MxDecAPI Attribute : This attribute only can be used for GFMxDecGetAttribute. If application wants to set pDestRect + in GFMXDECVOP or GFMXDECMP4DECVOP, application must use those attributes to get alignment information and align the rectangle + top & left corner accordinately. Value returned by GFMxDecGetAttrubute:\n + *pInfo: left field alignment in term of pixels + @see GFMXDECTABLE::MxDecGetAttribute + */ + +#define GF_MXDEC_ATTR_DEC_ENABLE_RAISE_WAIT 0x00000004 + /**< MxDecAPI Attribute : This attribute only can be used for GFMxDecSetAttribute. + Value passed to GFMxDecSetAttribute:\n + + + + + +
      *pInfo == 1Raisevectors are allocated per Surface.\n + There will be 2 (3 if PostProcessing is ON) sets of raise-wait happening\n + 1) Decoder raises On_Frame_Decoded, and VxBlt waits.\n + 2) (If enabled in APP) PostProcessing API raises On_PP_Frame_Done, and VxBlt waits.\n + 3) VxBlt raises On_Bltted, and Decoder waits.
      *pInfo == 0 (Default)We do not allocate surface raise vectors but a single raise vector.\n + 1) In Decoder, we poll Frame_done, and return only after its done.\n + 2) In PostProcessing we poll PP_Frame_done, and return only after its done.\n + 3) It is observed that Frame_done & PP_Frame_done bits are affected only if raise is done on those.\n + Thats why single raise vector is still needed. This raise vector is not in any suface but in MxDecHandle.
      + @see GFMXDECTABLE::MxDecSetAttribute + */ + +#define MXDEC_ATTR_DISABLE_EC 0x00000005 + /**< MxDecAPI Attribute : Application can disable Error Concealment (EC) by setting this attribute. By default, EC is enabled. + Decoder has The Error Robustness (ER) and Concealment (EC) for mpeg4 decoding. + + Error Robustness (Always ON) : + The ER means the code will detect any error in the bitstream at proper places and will still proceed ahead for decoding the + remaining stream, for posible non-errored data. + + Error Concealment (Default ON): Can be disabled by this very attribute MXDEC_ATTR_DISABLE_EC. + EC means, the decoder will try to use previously decoded information to simulate the lost data. The below steps of EC: + + Lost Motion Vector recovery and concealment: + 1. Rational interpolation: Predict the lost MV from the current frame + 2. Use MV from prev frame + 3. Use MV from step 3 and 4, to reconstruct 2 sets of the texture data for lost MB. + + @see GFMXDECTABLE::MxDecSetAttribute */ + +#define MXDEC_ATTR_MP4_DEC_GET_MBERR_MAP_MATRIX 0x00000006 + /**< MxDecAPI Attribute : This attribute only can be used for GFMxDecGetAttribute. If application wants to get MB error map for + till recently decoded frame. Input parameter is a character array pMBErrMapMatrix of size "number of MBs in a frame". On returning + this call fills this char array with 1s & 0s. 1: MB correctly decoded & 0: MB corrupted. This is cumulative err map till this call + is made. In this API call after copying the err map to the char array, internal map is resit to all clean MBs. \n + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU8 * pMBErrMapMatrix
      +    
      + @see GFMXDECTABLE::MxDecGetAttribute + */ + + /****************************************************************************************************/ + + /** Typesafe function for opening this component. + + @param hRm (GFRmHandle) Handle specific to Resource Manager API + @param phMxDec (GFMxDecHandle *) Pointer to handle specific to MxDecAPI + @param state (GF_STATE_TYPE) The state is used to decide if a new ChHandle is to be allocated for MxDec component or not. + The values that state can take are: + + + +
      #GF_STATE_DEFAULT
      #GF_STATE_NEW_OR_SHARE
      #GF_STATE_NEW_ONLY
      #GF_STATE_SHARE_ONLY
      + + @param hCh (GFRmChHandle) Resource Manager Channel Handle + + @retval GF_SUCCESS : If successful + @retval GF_ERROR : If error occured + */ + /**< Typesafe functions for opening and closing this component. + This API also checks for hardware resources needed through GFRmHwResourceConstraint(). + Trying to open a second video instance will fail due to existing open context. + */ + +GF_RETTYPE GFMxDecOpen(GFRmHandle hRm, GFMxDecHandle *phMxDec, + GF_STATE_TYPE state, GFRmChHandle hCh); + + /** Typesafe function for opening this component. + + @param phMxDec (GFMxDecHandle *) Pointer to handle specific to MxDecAPI + + Close the video instance. + */ +void GFMxDecClose(GFMxDecHandle *phMxDec); + +GF_RETTYPE GFMxDecGetProperty (GFMxDecHandle MxHandle, PGFPROPERTY pMXProp); +GF_RETTYPE GFMxDecPostProcessing (GFMxDecHandle pdec, PGFMXDECPP pP); +GF_RETTYPE GFMxDecSetAttribute (GFMxDecHandle pdec, NvU32 uiFeature, NvU32 *pInfo); +GF_RETTYPE GFMxDecGetAttribute (GFMxDecHandle pdec, NvU32 uiFeature, NvU32 *pInfo); +GF_RETTYPE GFMxDecSet (GFMxDecHandle pdec, NvU32 uiFeature, void *pInfo); +GF_RETTYPE GFMxDecMP4DecVOL (GFMxDecHandle pdec, PGFMXDECMP4DECVOL pVOL); +GF_RETTYPE GFMxDecMP4DecVOP (GFMxDecHandle pdec, PGFMXDECMP4DECVOP pVOP); +GF_RETTYPE GFMxDecMP4DecResync (GFMxDecHandle pdec, NvU32 ResyncOption); + + //return value +#define GFMXDEC_ERROR_NOT_SUPPORT_FORMAT (GFMXD_ERROR | 0x00000001) + /**< This error is returned when the input file format is not supported by the decoder. */ +#define GFMXDEC_ERROR_HEADER_DAMAGED (GFMXD_ERROR | 0x00000002) + /**< This error is returned when the header of the mpeg4 stream is damaged. */ +#define GFMXDEC_ERROR_NO_VOL_HEADER (GFMXD_ERROR | 0x00000003) + /**< This error is returned when no Video Object Layer (VOL) header is detected. */ +#define GFMXDEC_ERROR_NOT_ENOUGH_SYSTEM_MEM (GFMXD_ERROR | 0x00000004) + /**< This error is returned when system is out of memory. */ + + //return value +#define GFMXDEC_ERROR_DETECTED_VOL (GFMXD_ERROR | 0x00000005) + /**< This error is returned when VOL was detected while decoding VOP. */ +#define GFMXDEC_ERROR_END_OF_FILE (GFMXD_ERROR | 0x00000006) + /**< This error is returned when end of file is reached. */ +#define GFMXDEC_ERROR_CORRUPTED_VOP (GFMXD_ERROR | 0x00000007) + /**< This error is returned when the VOP is corrupted and cannot be recovered. */ + + //return value +#define GFMXDEC_ERROR_RESYNC_END_OF_FILE (GFMXD_ERROR | 0x00000008) + /**< This error is returned when end of file is reached while looking for resync marker. */ +#define GFMXDEC_ERROR_RESYNC_DETECTED_VOL (GFMXD_ERROR | 0x00000009) + /**< This error is returned when a VOL start is detected while searching for VOP resync marker. */ +#define GFMXDECMP4_DSP_TIMEOUT (GFMXD_ERROR | 0x00000010) + /**< This error is returned when DSP does not return anything for a predetermined timeout period. This error indicates possibility of DSP hang. */ +#define GFMXDEC_ERROR_START_CODE (GFMXD_ERROR | 0x00000011) + /**< This error is returned when no start code is found in a chunk of data. */ + + /*@}*/ + + /** @page pageMxDecAppNotes MxDecAPI Application Notes + @section pageMxDecAppNotes1 Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start + GFSDK usage. + + + 1. Initialize the display panel by using GFRmIxInit().\n + + 2. Open the display component by calling GFDxOpen() to get the GFMxDecAPI Dxhandle.\n + + 3. Initialize the display start address, stride and bits per pixel using GFDxSetDisplay().\n + + 4. Get the various attributes of the display panel (width, height, etc) using GFDxGetAttribute().\n + + 5. For clearing the screen, open the graphics component using GFGxOpen() and use GFGxFillRect() for filling the screen with + some color (say, black).\n + + 6. Open the FDev component for performing file I/O using GFFDevOpen() and mount it using GFFDevMount().\n + + 7. Open the Vx component using GFVxOpen() and get the GFVxAPI VxHandle. \n + + 8. Query the properties with GFVxGetProperty() to see whether this GFVxAPI version supports MPEG decoding.\n + + 9. If it supports MPEG decoding, call GFMxDecOpen() to get the GFMxDecAPI MxHandle.\n + + 10. Call GFMxDecGetProperty() to query properties. Check whether this GFMxDAPI version can support the desired + MPEG profile and level.\n + + 11. If the properties check out, call GFRmSurfaceAlloc() to allocate at least one reference surface and one + current surface for decoding purposes.\n + + 12. If the postprocessing engine is needed, allocate one surface to hold the postprocessing results.\n + + 13. For display purposes, the decoder application could call GFVxBlt() for the following two scenarios. \n + (a) Performing color space conversion and then a stretch blit to the primary surface directly. \n + (b) Blitting to the overlay surface.\n + Please refer to the latest GFVxAPI document for additional information. \n + + 14. The decoder application should decode VOP-by-VOP. Call GFMxDecSetVOP() to set up the VOP’s characteristics.\n + + 15. After the decoder application has decoded enough macroblocks, call GFMxDecSetMBs() to trigger the hardware + to decode those macroblocks until all macroblocks in the current VOP are finished. GFMxDecSetMBs() may initiate + the postprocessing engine or video engine automatically.\n + + 16. Before exiting the application, the decoder application should call GFRmSurfaceFree() to free the surfaces + that have been allocated. \n + + 17. Call GFMxClose() with the MxHandle to release the resources of the decoder module.\n + + 18. Similarly, call the close functions of the other components which have been opened.\n + + */ + +#ifdef __cplusplus +} // only need to export C interface if +// used by C++ source code +#endif + +#endif + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecH264.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecH264.h new file mode 100755 index 00000000..351ca7ca --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecH264.h @@ -0,0 +1,1536 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an +* express license agreement from NVIDIA Corporation is strictly prohibited. +*/ + +/** @file GFMxDecH264.h +GFSDK H264 Decode API header file. +*/ + +#ifndef _GF_MPEG_DEC_H264__ +#define _GF_MPEG_DEC_H264__ + +#include "nvtypes.h" +#include "GFVx.h" +#include "GFDef.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /** @addtogroup groupMxDecH264 MxDecH264API H264 Decode API + + The H.264/AVC decoder API handles H.264/AVC baseline-compliant bit + streams for this version, but has been defined to handle all of the three + profiles for future expansion. + + The H.264/AVC decoder API has two sets of API—a high level API and a low + level API. + + Using the High Level API + + The high level API has a built-in entropy decoder. It decodes the bit stream + and performs error concealment if the bit stream has an error. This high level + API calls the low level API internally. When using the high level API, the + application can ignore the low level API. + + The MxDecH264API high level functions include the following: + - GFMxDecH264DecSequence() + - GFMxDecH264DecPicture() + - GFMxDecH264Set() + - GFMxDecH264DecSEI() + - GFMxDecH264DecNewFrameNum() + + Using the Low Level API + + The low level API is essentially a macroblock decoder engine. It decodes + macroblock by macroblock. When using the low level API, the application + needs to handle the entropy decoding and error concealment. The low level + API assumes that the information passed from caller is correct, and does not + have any error concealment functionality build in. The application which + called the low level API must make sure that no macroblocks are missing for + any picture. + + The MxDecH264API low level functions include the following: + - GFMxDecH264SetSequence() + - GFMxDecH264SetPicture() + - GFMxDecH264SetSlice() + - GFMxDecH264SetMBs() + + Application Notes + +
        +
      • @ref pageMxDecH264AppNotes +
          +
        • @ref pageMxDecH264AppNotes1 +
        • @ref pageMxDecH264AppNotes2 +
        +
      + */ + /*@{*/ + + /** MxDecH264API property flag: Baseline profile supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_BASELINE 0x00000001UL + + /** MxDecH264API property flag: Main profile supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_MAIN 0x00000002UL + + /** MxDecH264API property flag: Extended profile supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_EXTENDED 0x00000004UL + + /** MxDecH264API property flag: LEVEL 1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL10 0x00000100UL + + /** MxDecH264API property flag: LEVEL 1.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL11 0x00000200UL + + /** MxDecH264API property flag: LEVEL 1.2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL12 0x00000400UL + + /** MxDecH264API property flag: LEVEL 1.3 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL13 0x00000800UL + + /** MxDecH264API property flag: LEVEL 2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL20 0x00001000UL + + /** MxDecH264API property flag: LEVEL 2.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL21 0x00002000UL + + /** MxDecH264API property flag: LEVEL 2.2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL22 0x00004000UL + + /** MxDecH264API property flag: LEVEL 3 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL30 0x00008000UL + + /** MxDecH264API property flag: LEVEL 3.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL31 0x00010000UL + + /** MxDecH264API property flag: LEVEL 3.2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL32 0x00020000UL + + /** MxDecH264API property flag: LEVEL 4 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL40 0x00040000UL + + /** MxDecH264API property flag: LEVEL 4.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL41 0x00080000UL + + /** MxDecH264API property flag: LEVEL 4.2 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL42 0x00100000UL + + /** MxDecH264API property flag: LEVEL 5 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL50 0x00200000UL + + /** MxDecH264API property flag: LEVEL 5.1 supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_LEVEL51 0x00400000UL + + /** MxDecH264API property flag: Post Processing de-blocking supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_DB 0x01000000UL + + /** MxDecH264API property flag: Post Processing de-ringing supported. + @see GFMxDecH264GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_H264_CAP_DR 0x02000000UL + + /** VUI Parameters for GFMXDECH264DECSEQUENCE + */ + typedef struct _GFMXDECH264DECVUI + { + NvU32 num_units_in_tick; + NvU32 time_scale; + NvU32 fixed_frame_rate_flag; + }GFMXDECH264DECVUI, *PGFMXDECH264DECVUI; + + /** Parameter structure for MxDecH264DecSequence(). + Both input and output parameters are passed via this structure to MxDecH264DecSequence(). + @see MxDecH264DecSequence() + */ + typedef struct _GFMXDECH264DECSEQUENCE + { + NvU32 uiSequenceOption; /**< Input flags, see GFMXDECH264_DECSEQUENCEOPTION_* */ + NvU32 SequenceInfo; /**< Output flags, see GF_MXDEC_H264_DEC_SEQUENCE_* */ + NvU16 profile_idc; /**< Output, H264 profile ID */ + NvU16 level_idc; /**< Output, H264 level ID */ + NvU16 seq_parameter_set_id;/** PicOrderCnt(CurrPic) + Greater than 1 specifies that the pan-scan rectangle information persists until + - A new coded video sequence begins + - A picture in an access unit containing a pan-scan rectangle SEI message with the + same value of pan_scan_rect_id is output having + (PicOrderCnt() > PicOrderCnt(CurrPic)) && (PicOrderCnt()<= PicOrderCnt(CurrPic) + pan_scan_rect_repetition_period ) + */ + } GFMXDECH264DECSEIPANSCAN, *PGFMXDECH264DECSEIPANSCAN; + + typedef struct _GFMXDECH264DECSEISUBSEQLAYER + { + NvU32 num_sub_seq_layers_minus1; /**< Output, Specifies the number of sub-sequence layers in the sequence */ + NvU32 accurate_statistics_flag; /**< Output, This flag when equal to 1 indicates that the values of average_bit_rate and + average_frame_rate are rounded from statistically correct values. + When equal to 0 indicates that the average_bit_rate and the average_frame_rate are estimates + and may deviate somewhat from the correct values. + */ + NvU32 average_bit_rate; /**< Output, Indicates the average bit rate in units of 1000 bits per second. */ + NvU32 average_frame_rate; /**< Output, Indicates the average frame rate in units of frames/(256 seconds). */ + } GFMXDECH264DECSEISUBSEQLAYER, *PGFMXDECH264DECSEISUBSEQLAYER; + + typedef struct _GFMXDECH264DECSEISUBSEQ + { + NvU32 sub_seq_layer_num; /**< Output, Identifies the sub-sequence layer number of the target sub-sequence */ + NvU32 sub_seq_id; /**< Output, Identifies the target sub-sequence. */ + NvU32 duration_flag; /**< Output, Equal to 0 indicates that the duration of the target sub-sequence is not specified. */ + NvU32 sub_seq_duration; /**< Output, Specifies the duration of the target sub-sequence in clock ticks of a 90-kHz clock. */ + NvU32 average_rate_flag; /**< Output, equal to 0 indicates that the average bit rate and the average frame rate of the target + sub-sequence are unspecified + */ + NvU32 accurate_statistics_flag; /**< Output, Same as accurate_statistics_flag in _GFMXDECH264DECSEISUBSEQLAYER*/ + NvU32 average_bit_rate; /**< Output, Indicates the average bit rate in (1000 bits)/second of the target sub-sequence.*/ + NvU32 average_frame_rate; /**< Output, Indicates the average frame rate in units of frames/(256 seconds) of the target sub-sequence.*/ + NvU32 num_referenced_subseqs; /**< Output, Specifies the number of sub-sequences that contain pictures that are used as reference pictures + for inter prediction in the pictures of the target sub-sequence. + */ + NvU32 ref_sub_seq_layer_num; + NvU32 ref_sub_seq_id; + NvU32 ref_sub_seq_direction; /**< Output, ref_sub_seq_layer_num, ref_sub_seq_id, and ref_sub_seq_direction identify the sub-sequence + that contains pictures that are used as reference pictures for inter prediction in the pictures + of the target sub-sequence. + */ + } GFMXDECH264DECSEISUBSEQ, *PGFMXDECH264DECSEISUBSEQ; + + + + /** ulBitMask, ulBitpayloadType: Application will set the corresponding bit of ulBitMask depending upon its requirement of the + particular payload type of SEI Message. + H264 Decoder API will set the corresponding bit of ulBitpayloadType depending upon the availability of the + particular payload type indicated by ulBitMask flag in the SEI NAL unit. + + @see ulBitpayloadType, ulBitMask in _GFMXDECH264DECSEI + */ + + /** Bit 0: SEI message for buffering period. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_BUFFERING_PERIOD 0x00000001UL + + /** Bit 1: SEI message for picture timing. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_PICTURE_TIMING 0x00000002UL + + /** Bit 2: SEI message for Pan Scan Rect. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_PAN_SCAN 0x00000004UL + + /** Bit 11: SEI message for Sequence Layer Characterization. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_SEQ_LAYER_CHARECTERIZATION 0x00000800UL + + /** Bit 12: SEI message for Sequence Characterization. + */ +#define GF_MXDEC_H264_SEI_MESSAGE_SEQ_CHARECTERIZATION 0x00001000UL + + /** Parameter structure for MxDecH264DecSEI(). + Both input and output parameters are passed via this structure to MxDecH264DecSEI(). + @see MxDecH264DecSEI() + */ + typedef struct _GFMXDECH264DECSEI + { + NvU32 payloadType; /**< Output, Specifies the type of SEI payload */ + NvU32 payloadSize; /**< Output, Specifies the number of bytes in SEI payload */ + GFMXDECH264DECSEIBUFFERINGPERIOD buffperiod; /**< Output, Complete information after parsing the buffering period message of SEI NAL unit + GFMXDECH264DECSEIBUFFERINGPERIOD structure + */ + GFMXDECH264DECSEIPICTIMING pictiming; /**< Output, Complete information after parsing the pic_timing message of SEI NAL unit + GFMXDECH264DECSEIPICTIMING structure + */ + GFMXDECH264DECSEIPANSCAN panscan; /**< Output, Complete information after parsing the Pan Scan message of SEI NAL unit + GFMXDECH264DECSEIPANSCAN structure + */ + GFMXDECH264DECSEISUBSEQLAYER subseqlayer; /**< Output, Complete information after parsing the sub-Seqlayer message of SEI NAL unit + GFMXDECH264DECSEISUBSEQLAYER structure + */ + GFMXDECH264DECSEISUBSEQ subseq; /**< Output, Complete information after parsing the sub-Seqlayer message of SEI NAL unit + GFMXDECH264DECSEISUBSEQ structure + */ + NvU8 *pPreFillBuffer; /**< Input, Pointer bitstream for sequence header to decode */ + NvU32 PreFillBufferLength;/**< Input, Length of bitstream in bytes, must cover the entire sequence header */ + NvU32 ulBitpayloadType; /**< Output, Each Bit Informs a particular SEI message required by the application + so that the H264 decoder only parses that message related data stream + */ + NvU32 ulBitMask; /**< Input, Each Masking Bit indicated which information is required by the application */ + } GFMXDECH264DECSEI, *PGFMXDECH264DECSEI; + + /** GFMXDECH264DECSEQUENCE::SequenceInfo ouput flagbit: constraint_set0_flag is on in the bitstream. + */ +#define GF_MXDEC_H264_DEC_SEQUENCE_CONSTRAINT_SET0_FLAG 0x00000001 + + /** GFMXDECH264DECSEQUENCE::SequenceInfo ouput flagbit: constraint_set1_flag is on in the bitstream. + */ +#define GF_MXDEC_H264_DEC_SEQUENCE_CONSTRAINT_SET1_FLAG 0x00000002 + + /** GFMXDECH264DECSEQUENCE::SequenceInfo ouput flagbit: constraint_set2_flag is on in the bitstream. + */ +#define GF_MXDEC_H264_DEC_SEQUENCE_CONSTRAINT_SET2_FLAG 0x00000004 + + /** GFMXDECH264DECSEQUENCE::SequenceInfo output flagbit: Frame cropping. + If this flag is set GFMXDECH264DECSEQUENCE::CroppingRect contains a valid + frame cropping rectangle. + */ +#define GF_MXDEC_H264_DEC_SEQUENCE_FRAME_CROPPING_FLAG 0x00000008 + + /** GFMXDECH264DECSEQUENCE::uiSequenceOption input flagbit: Bitstream is passed with GFMxDecH264DecSequence(). + If this flag is set bitstream data is passed with the call to GFMxDecH264DecSequence() + instead via the read bitstrem callback. This can be used only with boundary detection + on application level. The bitstream data is passed via GFMXDECH264DECSEQUENCE::pPreFillBuffer and + GFMXDECH264DECSEQUENCE::PreFillBufferLength. + */ +#define GFMXDECH264_DECSEQUENCEOPTION_PREFILLBUFFER 0x00000001 + +#define GFMXDECH264_MAX_NUM_REF_FRAMES 17 + typedef struct + { + NvU32 POC; + NvU8 isNotDisplayed; + NvU8 RetainDuringDPBFlush; + NvU8 status; + }GFMXDECH264_DPB_DATA; + + + /** Parameter structure for MxDecH264DecPicture(). + Both input and output parameters are passed via this structure to MxDecH264DecPicture(). + @see MxDecH264DecPicture() + */ + typedef struct _GFMXDECH264DECPICTURE + { + NvU32 uiPictureOption; /**< Input flagbits, see GF_MXDEC_H264_DEC_PICTURE_SPECIFY_*. */ + PGFRECT pPictureRect; /**< Input, Target rectangle. + GFMXDECH264DECPICTURE::pPictureRect specifies a rectangle on the + output surface for GFMxDec to output the decoded image. + + This field only take effect when MXDEC_H264_DEC_PICTURE_SPECIFY_SURF_RECT + flag is set. + + The rectangle must be within the surface. The rectangle's top and + left position must be aligned by application. Call GFMxDecGetAttribute() + with #MXDEC_ATTR_H264_DEC_PICTURE_RECT_TOP_ALIGNMENT and + #MXDEC_ATTR_H264_DEC_PICTURE_RECT_LEFT_ALIGNMENT to read the alignment + requirements. The rectangle's width and height must match the video frame + width and height as returned from MxDecH264DecSequence() in + GFMXDECH264DECSEQUENCE::pic_width and GFMXDECH264DECSEQUENCE::pic_height. + + Note: Feature not yet implemented. + */ + NvU32 uiPictureInfo; /**< Output flags, see GF_MXDEC_H264_DEC_PICTURE_*. */ + PGFRMSURFACE reconstructedSurf; /**< Output, Surface holding the decoded picture. + If frame is not decoded then reconstructedSurf will not get initialsed i.e. NULL + So VXBLT is called if the reconstructedSurf is not NULL. + */ + NvU32 uiPictureOrderCount; /**< Output */ + NvU32 uiTimeStamp; /**< Output, frame timestamp in miliseconds, valid only if GF_MXDEC_H264_DEC_PICTURE_TIME_STAMP set. */ + NvU8 * pMBInfo; /**< Output, each element tells the particular MB is wrong or not. */ + NvU32 UsedAsReference; /**< Output */ + NvU8* pPreFillBuffer; /**< Input, Pointer bitstream for frame to decode + The bitstream pointer needs to be 4-bytes aligned. + */ + NvU32 PreFillBufferLength; /**< Input, Length of bitstream in bytes, must cover the entire frame */ + NvU32 PreFillBufferBytesConsumed; /**< Output, Amount of bytes consumed by the component */ + NvU16 flushDPB; /**< Output, set to !=0 by the decoder when it encounters a memory_management_control_operation = 5 + indication in the bitstream. The application should display (if the + NoOutputofPriorPics flag is not set) and flush the entire DPB, i.e remove + all previously stored frames from DPB. + Current frame should not be displayed/flushed. + + See \a NoOutputofPriorPics for more info. + */ + NvU16 NoOutputofPriorPics; /**< Output, set by the decoder when it encounters a no_output_of_prior_pics_flag in + the bitstream. If this set, then flushDPB will also be set. The application + should flush the entire DPB, i.e remove all previously stored frames from DPB. + Current frame should not be displayed/flushed. + + Summary: + + + + + +
      NoOutputofPriorPicsflushDPBApplications response
      1 1 Remove all previously stored frames. No display.
      0 1 Display all previously stored frames and then remove from DPB.
      0 0 Normal operation of decoder.
      + */ + NvU32 ReconSurfaceNumber; /**< Index of reconstructed surface, this is an index into GFMXDECH264SURFLIST::surfList[]. + valid only if GFMXDECH264DECPICTURE::reconstructedSurf is not NULL. + Invalid for streams with picture reordering. + */ + GFMXDECH264_DPB_DATA dpb_data[GFMXDECH264_MAX_NUM_REF_FRAMES]; + } GFMXDECH264DECPICTURE, *PGFMXDECH264DECPICTURE; + + //uiPictureOption + + /** GFMXDECH264DECPICTURE::uiPictureOption input flagbit: Use target rectangle. + If this flag is set, the GFMXDECH264DECPICTURE::pPictureRect will point to + a rectangle on the output surface, where the reconstructed frame is placed. + */ +#define GF_MXDEC_H264_DEC_PICTURE_SPECIFY_SURF_RECT 0x00000001 + + /** GFMXDECH264DECPICTURE::uiPictureOption input flagbit: Bitstream is passed with MxDecH264DecPicture(). + If this flag is set bitstream data is passed with the call to MxDecH264DecPicture() + instead via the read bitstrem callback. This can be used only with frame boundary detection + on application level. The bitstream data is passed via GFMXDECH264DECPICTURE::pPreFillBuffer and + GFMXDECH264DECPICTURE::PreFillBufferLength. + */ +#define GF_MXDEC_H264_DEC_PICTURE_SPECIFY_PREFILLBUFFER 0x00000002 + + //PictureInfo: + + /** GFMXDECH264DECSEQUENCE::PictureInfo output flagbit: Current picture is IDR. + */ +#define GF_MXDEC_H264_DEC_PICTURE_IDR 0x00000001 + + /** GFMXDECH264DECSEQUENCE::PictureInfo output flagbit: GFMXDECH264DECSEQUENCE::uiTimeStamp field is valid. + */ +#define GF_MXDEC_H264_DEC_PICTURE_TIME_STAMP 0x00000002 + + /** GFMXDECH264DECSEQUENCE::PictureInfo output flagbit: Decoded picture has at least one corrupted macroblock. + */ +#define GF_MXDEC_H264_DEC_PICTURE_BAD_MB 0x00000004 + + /** GFMXDECH264DECSEQUENCE::PictureInfo output flagbit: + Required by the application to decide whether post processing should be applied for a particular frame + DeblockingFlag is set, when Deblocking Filtering is disabled for all the slices + DeblockingFlag is reset even if deblocking filtering is enabled for atleast one slice + */ +#define GF_MXDEC_H264_DEC_PICTURE_DEBLOCKING_FILTER 0x00000008 + + typedef struct _GFMXDECH264SEQUENCE + { + NvU32 SequenceInfo; + NvU16 pic_width_in_mbs_minus1; + NvU16 pic_height_in_map_units_minus1; + } GFMXDECH264SEQUENCE, *PGFMXDECH264SEQUENCE; + //PictureInfo: +#define GF_MXDEC_H264_SEQUENCE_FRAME_MB_ONLY_FLAG 0x00000001 + //if frame_mb_only_flag is on, this flag must be on +#define GF_MXDEC_H264_SEQUENCE_MB_ADAPTIVE_FRAME_FIELD_FLAG 0x00000002 + //if mb_adaptive_frame_filed_flag is on, this flag must be on +#define GF_MXDEC_H264_SEQUENCE_DIRECT_8X8_INFERENCE_FLAG 0x00000004 + //if direct_8x8_inference_flag is on, this flag must be on + + + typedef struct _GFMXDECH264PICTURE + { + NvU32 PictureInfo; + PGFRMSURFACE reconstructedSurf; //surface to hold the decoded picture + PGFRECT pRect; + NvU8 weighted_bidpred_idc; + NvS8 chroma_qp_index_offset; + } GFMXDECH264PICTURE, *PGFMXDECH264PICTURE; + //PictureInfo: +#define GF_MXDEC_H264_PICTURE_WEIGHTED_PRED_FLAG 0x00000001 + //if weighted_pred_flag is on, this flag must be on +#define GF_MXDEC_H264_PICTURE_DEBLOCKING_FILTER_CONTROL_PRESENT_FLAG 0x00000002 + //if deblocing_filter_control_present_flag is on, this flag must be on +#define GF_MXDEC_H264_PICTURE_CONSTRAINED_INTRA_PRED_FLAG 0x00000004 + //if constrained_intra_pred_flag is on, this flag must be on +#define GF_MXDEC_H264_PICTURE_IDR 0x00000008 +#define GF_MXDEC_H264_PICTURE_SPECIFY_SURFACE_RECT 0x00000010 + // If this flag is set, pRect must be set. GFMxDec will reference image + // in pRect area of reference surface and output the decoded image in + // the pRect area of reconstructedSurf. Otherwise, GFMxDec will use + // the whole surface area. + + + typedef struct _GFMXDECH264WEIGHT + { + NvS8 luma_weight; + NvS8 luma_offset; + NvS8 Cb_weight; + NvS8 Cb_offset; + NvS8 Cr_weight; + NvS8 Cr_offset; + } GFMXDECH264WEIGHT, *PGFMXDECH264WEIGHT; + + + + typedef struct _GFMXDECH264SLICE + { + NvU32 SliceInfo; + NvU16 first_mb_in_slice; + NvU16 reserved; + NvU8 slice_type; + NvU8 num_ref_idx_l0_active_minues1; + NvU8 num_ref_idx_l1_active_minues1; + NvU8 disable_deblocking_filter_idc ; + NvU8 slice_alpha_c0_offset_div2; + NvU8 slice_beta_offset_div2; + PGFRMSURFACE ref_l0_surfaces[16]; + PGFRMSURFACE ref_l1_surfaces[16]; + GFMXDECH264WEIGHT weighttableL0[16]; + GFMXDECH264WEIGHT weighttableL1[16]; + } GFMXDECH264SLICE, *PGFMXDECH264SLICE; + //SliceInfo: +#define GF_MXDEC_H264_SLICE_FILED_PIC_FLAG 0x01 + //when filed_pic_flag is on, this flag must be set +#define GF_MXDEC_H264_SLICE_BOTTOM_FILED_FLAG 0x02 + //when bottom_field_flag is on, this flag must be set +#define GF_MXDEC_H264_SLICE_DIRECT_SPATIAL_MV_PRED_FLAG 0x04 + //when DIRECT_SPATIAL_MV_PRED_FLAG is on, this flag must be set + + + typedef struct _GFMXDECH264I4X4LPREDMODE + { + NvU32 uiPredMode0to7; //Luma4X4 Blk 0 to 7's prediction modes. + NvU32 uiPredMode8to15; //Luma4X4 Blk 8 to 15's prediction modes. + } GFMXDECH264I4X4LPREDMODE, *PGFMXDECH264I4X4LPREDMODE; + + typedef struct _GFMXDECH264MV + { + NvS16 Horizontal; + //Horizonal motion vector component. + NvS16 Vertical; + //Vertical motion vector component + } GFMXDECH264MV, *PGFMXDECH264MV; + + + typedef struct _GFMXDECH264REFIDX + { + NvU8 Ref_idx_l0[4]; //PartIdx's reference index + NvU8 Ref_idx_l1[4]; //PartIdx's reference index + } GFMXDECH264REFIDX, *PGFMXDECH264REFIDX; + + + typedef struct _GFMXDECH264SUBMBTYPE + { + NvU8 sub_mb_type[4]; //PartIdx's sub_mb_type + } GFMXDECH264SUBMBTYPE, *PGFMXDECH264SUBMBTYPE; + + + typedef struct _GFMXDECH264MB + { + NvU16 uiTotalSize; + //Total size in bytes for current macroblock, including this structure + //itself and necessary following structure behind of this structure. + //Reference the data following GFMXDECH264MB. + NvU16 uiTotalCOEFs;// total Coefs for this macroblock + NvU32 curMBAddress; // current macroblock address + NvU8 MBInfo; + // this is the mb_type in bit stream and mb_field_decoding_flag + NvU8 uiQP; //this is QPy + NvU8 coded_block_pattern; + //This field is only valid when current macroblock is not Intra_16x16 + NvU8 Intra_chroma_pred_mode; + //This field is valid only when current macroblock is Intra + GFMXDECH264SUBMBTYPE sub_mb_type; + union + { + GFMXDECH264I4X4LPREDMODE I4X4LPredMode; //Intra_4X4 only + GFMXDECH264REFIDX RefIdx; //Inter only + } mode; // TODO: Name this better + NvS32 numCoefsPerSubMB[32]; + NvS16 index; + } GFMXDECH264MB, *PGFMXDECH264MB; + + //MBInfo: +#define GF_MXDEC_H264_MB_FILED_DECODING_ENABLE 0x80 + //when mb_field_decoding_flag is on, this flag must be set +#define GF_MXDEC_H264_MB_SKIP_MB 0x40 + //skip MB + + //The data following GFMXDECH264MB: + //If current macroblock is skipped macroblock, no further data is needed. + + //If current macroblock is IPCM, there are 384 bytes following GFMXDECH264MB. + + //If current macroblock is Inter macroblock, and is using picture list 0 only, + //necessary number of GFMXDECH264MV are following. If current macroblock is + //using picture list 1 only, necessary number of GFMXDECH264MV are following. + //If current macroblock is using both picture list 0 and list 1, necessary + //number of GFMXDECH264MV for list 0, and necessary number of GFMXDECH264MV + //for list 1 are following GFMXDECH264MB. + + //For both Intra and Inter macroblock, the last portion of data which follows + //GFMXDECH264MB is GFMXDECH264MB.uiTotalCOEFs of GFMXDECH264COEF. + + + + // definition for attribute + + /** GFMxDecH264 Attribute: Application will determine the decoding boundaries. + For H.264/AVC, this boundary means sequence and picture boundary. For certain file formats, + those boundary information are stored in a meta data file. Alternatively the application + could parse NAL unit boundaries from the H264 stream and determine decoding units. + If application wants GFMxDecH264 to detect the boundary, it should not enable this + attribute. + + If prefill mode (see #GFMXDECH264_DECSEQUENCEOPTION_PREFILLBUFFER) is used, + this attribute must be enabled. Disabled by default. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 1: APP will determine the decoding boudary
      +    0: APP will not determine the decoding boundary
      +    
      + + @see GFMxDecH264GetAttribute(), GFMxDecH264SetAttribute() + */ +#define GF_MXDEC_H264_ATTR_PRE_DETERMINED_BOUNDARY 0x00000001 + + /** GFMxDecH264 Attribute: Enforce display ordering for sequences containing out of order frames. + + Disabled by default. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 !=0: Enable reordering
      +    0: Disable reordering
      +    
      + + @see GFMxDecH264GetAttribute(), GFMxDecH264SetAttribute() + */ +#define GF_MXDEC_H264_ATTR_DISPLAY_REORDERING 0x00000002 + +#define GF_MXDEC_H264_ATTR_DSP_STREAM_BUFFERING 0x00000003 + //This Attribute only can be used for GFMxDecH264SetAttribute + //If the Application wants to set the mode DSP_STREAM_BUFFERING in H264Decoder, enable the #define DSP_STREAM_BUFFERING in App, + //then APP will enable the attribute by calling the GFMxDecH264SetAttribute. + //this attribute is used to pass the buffer details, from Application to the host side of GFSDK H264 component. + + /** GFMxDecH264 Attribute: Enable decode surface locking in MxDecH264DecPicture(). + + MxDecH264DecPicture() returns the decoded surface number in GFMXDECH264DECPICTURE::ReconSurfaceNumber, + which is an index into the decode surface list GFMXDECH264SURFLIST::surfList[] set via + #GF_MXDEC_H264_SET_SURFACE_LIST. If surface locking is enabled, MxDecH264DecPicture() will + automatically 'lock' the returned surface and exclude it from its list of + surfaces used for further decoding. GFMxDecH264 can still read from a locked surface + (for reference frames), but it will not overwrite it. The application must not + write into a locked surface, since it still may be used as reference frame. + + This locking mechanism is intended for usecases, where the application directly displays + the decode surface as video overlay. See also @ref pageMxDecH264AppNotes2 + + With surface locking enable, each successfully decoded surface has to be unlocked by the + application with GFMxDecH264Set / #GF_MXDEC_H264_SET_UNLOCK_SURFACE. + + Since locked surfaces cannot be used for decoding, the number of decoding surfaces + set with #GF_MXDEC_H264_SET_SURFACE_LIST must be R+1+N, where R is the maximum number of + reference frames and N the maximum number of simultaneously locked surfaces. + Otherwise MxDecH264DecPicture() may fail. + + Disabled by default. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 !=0: Enable surface locking
      +    0: Disable surface locking
      +    
      + + @see GFMxDecH264GetAttribute(), GFMxDecH264SetAttribute(), GF_MXDEC_H264_SET_UNLOCK_SURFACE, @ref pageMxDecH264AppNotes2 + */ +#define GF_MXDEC_H264_ATTR_SURFACE_LOCKING 0x00000004 + + /** GFMxDecH264 Attribute: Get H264 decoder's DSP handle. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 DSP handle
      +    
      + + GFMxDecH264GetAttribute() returns error GFMXDECH264_ERROR_INVALID_STATE, if DSP side not initialized. + Can be get only. + + @internal + @see GFMxDecH264GetAttribute() + */ +#define GF_MXDEC_H264_ATTR_GETDSPHANDLE 0x00000005 + +#define GF_MXDEC_H264_ATTR_DEC_PICTURE_RECT_TOP_ALIGNMENT 0x00000007 + //This attribute only can be used for GFMxDecGetAttribute + //If application wants to set pDestRect in GFMXDECPICTURE or GFMXDECH264DECPICTURE, + //application must use this attributes to get allignment information and + //align the rectangle top & left corner accordinately. + //*pInfo: top fieled alignment in term of lines + +#define GF_MXDEC_H264_ATTR_DEC_PICTURE_RECT_LEFT_ALIGNMENT 0x00000008 + //This attribute only can be used for GFMxDecGetAttribute + //If application wants to set pDestRect in GFMXDECH264PICTURE or GFMXDECH264DECPICTURE, + //application must use those attributes to get allignment information and + //align the rectangle top & left corner accordinately. + //*pInfo: left fieled alignment in term of pixels + +#define GF_MXDEC_H264_ATTR_DEC_ENABLE_RAISE_WAIT 0x00000009 + /* + * This attribute only can be used for GFMxDecSetAttribute + * if (*pInfo == 1) + * { + * Raisevectors are allocated per Surface. + * There will be 2 (3 if PostProcessing is ON) sets of raise-wait happening + * 1) Decoder raises On_Frame_Decoded, and VxBlt waits. + * 2) (If enabled in APP) PostProcessing API raises On_PP_Frame_Done, and VxBlt waits. + * 3) VxBlt raises On_Bltted, and Decoder waits. + * } + * else // DEFAULT + * { + * We do not allocate surface raise vectors but a single raise vector + * - In Decoder, we poll Frame_done, and return only after its done + * - In PostProcessing we poll PP_Frame_done, and return only after its done + * - I observed that Frame_done & PP_Frame_done bits are affected only if raise is done on those. Thats why single raise vector is still needed. + * This raise vector is not in any suface but in pdec. + * } + */ + +#define GF_MXDEC_H264_ATTR_LEN_OF_NALSIZE 0x0000000a + /*To support the decoding of .264 stream where NAL size appears instead of StartCode + This is to get the length of the NAL size value*/ +#define GF_MXDEC_H264_ATTR_NALSIZE_DECODING 0x0000000b + /* To support runtime decision making between the start code decoding and NAL size decoding*/ + + + /** GFMxDecH264 Attribute: Indicate to the H264 decoder that surfaces have + already been allocated by the Application before the sps is decoded. + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 (Height << 16)| (Width)
      +    
      + + Can be set only. + */ +#define GF_MXDEC_H264_ATTR_SURFACE_ALLOCATED 0x0000000c + + /** GFMxDecH264 Attribute: Set number of maximum supported reference frames. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 Number of reference frames 
      +    
      + + This can be called before or after GFMxDecH264Set(GF_MXDEC_H264_SET_SURFACE_LIST). + The number of reference frames must be smaller than the number of surfaces + set via GFMxDecH264Set(GF_MXDEC_H264_SET_SURFACE_LIST). + + If this attribute is not set, the number of supported reference frames will be + equal to one less the number of surfaces set in GFMxDecH264Set(GF_MXDEC_H264_SET_SURFACE_LIST). + + Can be set only. + + @see GF_MXDEC_H264_SET_SURFACE_LIST + */ +#define GF_MXDEC_H264_ATTR_MAXREFFRAMES 0x0000000d + + /** GFMxDecH264 Attribute: Get Error Map Matrix for MBs in last decoded frame. + + This attribute only can be used for GFMxDecGetAttribute. If application wants to get MB error map for + till recently decoded frame. Input parameter is a character array pMBErrMapMatrix of size "number of MBs in a frame". On returning + this call fills this char array with 1s & 0s. 1: MB correctly decoded & 0: MB corrupted. This is cumulative err map till this call + is made. In this API call after copying the err map to the char array, internal map is reset to all clean MBs. + Internal map is reset to all clean MBs also when I or SI slice is found. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU8 * pMBErrMapMatrix
      +    
      + + @internal + @see GFMxDecH264GetAttribute() + */ +#define GF_MXDEC_H264_ATTR_GET_MBERR_MAP_MATRIX 0x0000000e + +/** GFMxDecH264 Attribute: Set Error Concealment (EC) Mode ON or OFF. + + EC is Dynamically ON by default. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 !=0: Enable EC
      +            0: Disable EC
      +    
      + + @see GFMxDecH264SetAttribute() +*/ +#define GF_MXDEC_H264_ATTR_SWITCH_EC_MODE 0x0000000f + +/** GFMxDecH264 Attribute: Set Single Slice Per Frame Mode ON or OFF. + + By default multiple slices per frame is assumed. + + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 !=0: Single slice per frame
      +            0: Multiple slices per frame
      +    
      + + @see GFMxDecH264SetAttribute() +*/ +#define GF_MXDEC_H264_ATTR_SINGLE_SLICE_PER_FRAME 0x00000010 + + + +/** GFMxDecH264 Attribute: Put the h264 decoder in the TSPlayer + mode. This has to be done first, and sets up the h264 decoder to cooperate + with the TS Demux task on the AVP. Does nothing when decode is on the + host +*/ +#define GF_MXDEC_H264_ATTR_SET_TSPLAYER_MODE 0x00000011 + + +/** Parameter structure for MxDecH264PostProcessing(). + Both input and output parameters are passed via this structure to MxDecH264PostProcessing(). + @see MxDecH264PostProcessing() +*/ + + typedef struct _GFMXDECHH264PP + { + PGFRMSURFACE* pDestSurf;/**< input, + pointer to an array of surfaces that will + hold the result from Post Processing + pointer to an array of surfaces to + accommodate auto post processing + */ + PGFRMSURFACE* pSrcSurf; /**< input, + pointer to an array of surfaces to be //post processed + pointer to an array of surfaces to + accommodate auto post processing + */ + PGFRECT pRect; /**< input, + Rectangle area to be processed for both + src and dest surface + */ + + NvU32 numofDestSurf; /**< input, + If MXDEC_PP_AUTO flag is set, this + parameter must be filled + */ + NvU32 numofSrcSurf; /**< input, + If MXDEC_PP_AUTO flag is set, this + parameter must be filled + */ + NvU8 * lpQuantiser; /**< input, + point to array of QPs for Macro Blocks in + the source VOP. GFMX automatically saved + the last two decoded VOP's QP tables, + Decoder application may not need to reload + the table if it can make sure the source + VOP is the one within the last decoded + VOPs. If MXDEC_PP_RELOAD_QUANTIZER is set, + this field must be filled. + */ + NvU32 PPOption; /** + NvS32 >0 Surface index which was returned in GFMXDECH264DECPICTURE::ReconSurfaceNumber. + NvS32 -1 Reset all locked surfaces to unlocked + NvS32 -2 Reserved for internal use + + + @see GF_MXDEC_H264_ATTR_SURFACE_LOCKING + */ +#define GF_MXDEC_H264_SET_UNLOCK_SURFACE 3 + + /** GFMxDecH264Set() feature ID: Sync host side H264 state from DSP side. + @internal + */ +#define GF_MXDEC_H264_SET_SYNC_WITH_DSP 4 + + /** GFMxDecH264Set() feature ID: Set or reset DSP idle callback. + Can be called on DSP side only. + \a pInfo is a pointer to a #GFMXDECH264CALLBACK structure. + @internal + */ +#define GF_MXDEC_H264_SET_DSPIDLEHANDLER 5 + +/** GFMxDecH264Set() feature ID: Allow the DSP message poll thread to wake up and terminate. + Can be called on Host side only. + \a pInfo is ignored. + @internal +*/ +#define GF_MXDEC_H264_SET_EXITDSPMSGTHREAD 6 + + /** Parameter structure for GFMxDecH264Set() feature #GF_MXDEC_H264_SET_DSPIDLEHANDLER. + @internal + */ + typedef struct _GFMXDECH264DSPIDLECALLBACK + { + /** Application defined parameter to forward to GFMXDECH264DSPIDLECALLBACK::pCallBack. */ + void *pPara; + + /** Callback function, which is called from AVP idle loop. + @param pPara Application defined parameter, forwarded from GFMXDECH264DSPIDLECALLBACK::pPara + */ + void (*pCallBack)(void* pPara); + + } GFMXDECH264DSPIDLECALLBACK; + + + /** Parameter structure for GFMxDecH264Set() feature #GF_MXDEC_H264_SET_READBITSTREAM. */ + typedef struct _GFMXDECH264CALLBACK + { + /** Application defined parameter to forward to GFMXDECH264CALLBACK::pCallBack. */ + void *pPara; + + /** Callback function, which is called by MxDecH264 to fetch a portion of bitstream data. + @param pPara Application defined parameter, forwarded from GFMXDECH264CALLBACK::pPara + @param ppBuffer Callback returns address of the next portion of stream data in \a *ppBuffer + @param pBufferLength Callback returns number of bytes in \a ppBuffer in \a *pBufferLength + @param uFlag Specifies scan stream direction + + + +
      GF_MXDEC_H264_READ_BITSTREAM_FORWARD Forward scan
      GF_MXDEC_H264_READ_BITSTREAM_BACKWARDBackward scan
      + + @return If the #MXDEC_ATTR_PRE_DETERMINED_BOUNDARY attribute is set, the callback + should return #GF_MXDEC_H264_BOUNDARY_REACHED when a frame boundary is + detected, or 0 if no boundary is detected. + If the #MXDEC_ATTR_PRE_DETERMINED_BOUNDARY attribute is not set, the callback + should return 0. + */ + NvU32 (*pCallBack)(void* pPara, NvU8** ppBuffer, NvS32* pBufferLength, NvU32 uFlag); + + }GFMXDECH264CALLBACK, *PGFMXDECH264CALLBACK; + + + + /** GFMXDECH264CALLBACK::pCallBack return code */ +#define GF_MXDEC_H264_BOUNDARY_REACHED 0x00000001 + /** GFMXDECH264CALLBACK::pCallBack uFlag value: Stream forward scan. */ +#define GF_MXDEC_H264_READ_BITSTREAM_FORWARD 0x00000002 + /** GFMXDECH264CALLBACK::pCallBack uFlag value: Stream backward scan. */ +#define GF_MXDEC_H264_READ_BITSTREAM_BACKWARD 0x00000003 + + /** Maximum number of surface pointers GFMXDECH264SURFLIST::surfList[]. */ +#define MXDEC_H264_NUM_SURFACES 17 + + /** Parameter structure for GFMxDecH264Set() feature #GF_MXDEC_H264_SET_READBITSTREAM. */ + typedef struct _GFMXDECH264SURFLIST + { + /** Number of valid surfaces in GFMXDECH264SURFLIST::surfList[]. + The number of valid surfaces includes reference, decode surfaces and optional buffer frames. + Must be within range 1 and 17. + */ + NvU32 numSurfs; + + /** Surface pointer list. + + Assuming N is the number of reference frames, the first N+1 surfaces + in this list will be used as reference and decode surfaces. The currently + decoded surface can refer to the N remaining surfaces in this set as + reference frames. + + If surface locking mode (#GF_MXDEC_H264_ATTR_SURFACE_LOCKING) is enabled, + The remaining M = numSurfs - (N+1) surfaces are used as extra surfaces, + to fascilate pre-buffered decoding. + */ + PGFRMSURFACE surfList[MXDEC_H264_NUM_SURFACES]; + + }GFMXDECH264SURFLIST, *PGFMXDECH264SURFLIST; + + + typedef enum + { + GFMX_DEC_H264_INTERRUPT_ENABLE, + GFMX_DEC_H264_INTERRUPT_DISABLE, + GFMX_DEC_H264_INTERRUPT_CLEAR + } GFMX_DEC_H264_INTERRUPT_OPERATION_TYPE; // Interrupt operation. + + typedef enum + { + GFMX_DEC_H264_DSP_COMMAND_INTR, + GFMX_DEC_H264_POST_PROCESSING_DONE_INTR, + GFMX_DEC_H264_DECODE_DONE_INTR + } GFMX_DEC_H264_INTERRUPT_TYPE; + + typedef struct _GFMXDECH264TABLE + { + GF_RETTYPE (* MxDecH264GetProperty)(GFMxDecH264Handle hMxDecH264, PGFPROPERTY pMXProp ); + GF_RETTYPE (* MxDecH264GetStatus)(GFMxDecH264Handle hMxDecH264, NvU32 * pStatus); + GF_RETTYPE (* MxDecH264DecSequence)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264DECSEQUENCE pSequence); + GF_RETTYPE (* MxDecH264DecPicture)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264DECPICTURE pPicture); + GF_RETTYPE (* MxDecH264SetSequence)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264SEQUENCE pSequence); + GF_RETTYPE (* MxDecH264SetPicture)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264PICTURE pPicture); + GF_RETTYPE (* MxDecH264SetSlice)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264SLICE pSlice); + GF_RETTYPE (* MxDecH264SetMBs)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264MB pMBs); + GF_RETTYPE (* MxDecH264PostProcessing)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264PP pP); + GF_RETTYPE (* MxDecH264SetAttribute)(GFMxDecH264Handle hMxDecH264, NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* MxDecH264GetAttribute)(GFMxDecH264Handle hMxDecH264, NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* MxDecH264Set)(GFMxDecH264Handle hMxDecH264, NvU32 uiFeature, void * pInfo); + GF_RETTYPE (* MxDecH264InterruptControl)(GFMxDecH264Handle hMxDecH264, + GFMX_DEC_H264_INTERRUPT_TYPE IntType, GFMX_DEC_H264_INTERRUPT_OPERATION_TYPE op, + void * pData); + GF_RETTYPE (* MxDecH264InterruptHandler)(GFMxDecH264Handle hMxDecH264, + GFMX_DEC_H264_INTERRUPT_TYPE IntType, void * pData); // Reserved. + GF_RETTYPE (* MxDecH264DSPPoll)(GFMxDecH264Handle hMxDecH264, NvU32 timeout); + GF_RETTYPE (* MxDecH264DecSEI)(GFMxDecH264Handle hMxDecH264, PGFMXDECH264DECSEI pSEI); + GF_RETTYPE (* MxDecH264DecNewFrameNum)(GFMxDecH264Handle hMxDecH264,NvU8* VideoBuffPtr,NvU32 VideoBufferLength); + } GFMXDECH264TABLE, *PGFMXDECH264TABLE; + + /**< Typesafe functions for opening and closing this component. + This API also checks for hardware resources needed through GFRmHwResourceConstraint(). + Trying to open a second video instance will fail due to existing open context. + */ +GF_RETTYPE GFMxDecH264Open(GFRmHandle hRm, GFMxDecH264Handle *phMxDecH264, + GF_STATE_TYPE state, GFRmChHandle hCh); + + /**< Close the video instance. + */ +void GFMxDecH264Close(GFMxDecH264Handle *phMxDecH264); + +#if NVCPU_IS_XTENSA +#define MXDH264OFFSET sizeof(GFMXDECH264TABLE) +#else +#define MXDH264OFFSET 0 +#endif + + + /** GFMxDecH264 error code: GFMxDecH264DecSequence() encountered end of bitstream. + @see GFMxDecH264DecSequence() + */ +#define GFMXDECH264_ERROR_SEQUENCE_END_OF_FILE (GFMXDH264_ERROR | 0x00000001) + + /** GFMxDecH264 error code: GFMxDecH264DecSequence() bitstream format not supported. + The sequence header specifies a bitstream format, that is not supported. Most likely + reason for this error is that the H.264 profile is not supported. + @see GFMxDecH264DecSequence() + */ +#define GFMXDECH264_ERROR_SEQUENCE_NOT_SUPPORTED (GFMXDH264_ERROR | 0x00000002) + + /** GFMxDecH264 error code: GFMxDecH264DecSequence() encountered out of GPU memory error. + The application can try to free GPU memory and call GFMxDecH264DecSequence() again. + @see GFMxDecH264DecSequence() + */ +#define GFMXDECH264_ERROR_SEQUENCE_NOT_ENOUGH_MEM (GFMXDH264_ERROR | 0x00000003) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() encountered sequence header. + The application should call GFMxDecH264DecSequence() in response to this return code, + to decode the sequence header. + @see GFMxDecH264DecPicture(), GFMxDecH264DecSequence() + */ +#define GFMXDECH264_ERROR_PICTURE_DETECTED_SEQUENCE (GFMXDH264_ERROR | 0x00000004) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() encountered end of bitstream. + @see GFMxDecH264DecPicture() + */ +#define GFMXDECH264_ERROR_PICTURE_END_OF_FILE (GFMXDH264_ERROR | 0x00000005) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() encountered an unrecoverable bitstream error. + The application should call GFMxDecH264DecPicture() again, MxDecH264 will then + scan for the next frame boundary and try to decode this frame. + @see GFMxDecH264DecPicture() + */ +#define GFMXDECH264_ERROR_PICTURE_CORRUPTED_PICTURE (GFMXDH264_ERROR | 0x00000006) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() encountered out of GPU memory error. + The application can try to free GPU memory and call GFMxDecH264DecPicture() again. + @see GFMxDecH264DecPicture() + */ +#define GFMXDECH264_ERROR_PICTURE_NOT_ENOUGH_MEM (GFMXDH264_ERROR | 0x00000007) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() returns status to inform application + whether picture parameter set is not initialized, which may happen either when picture + parameter set is absent or corrupted. pic_parameter_set_id is checked for negative value. + */ +#define GFMXDECH264_ERROR_PICTURE_PARAMETER_SET_NOT_INITIALIZED (GFMXDH264_ERROR | 0x00000008) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() returns error status to inform application + that picture parameter set is corrupted. + */ +#define GFMXDECH264_ERROR_PICTURE_PARAMETER_SET_CORRUPTED (GFMXDH264_ERROR | 0x00000009) + + /** GFMxDecH264 error code: GFMxDecH264 API was used in invalid state of the decoder. + */ +#define GFMXDECH264_ERROR_INVALID_STATE (GFMXDH264_ERROR | 0x0000000A) + + /** GFMxDecH264 error code: GFMxDecH264DecPicture() returns status to inform application that + all the surfaces where it could decode are locked. + */ +#define GFMXDECH264_ERROR_PICTURE_ALL_SURFACES_LOCKED (GFMXDH264_ERROR | 0x0000000B) + + /*For DecPic timeout on DSP side.*/ +#define GFMXDECH264_ERROR_MXDEC_PIC_TIMEOUT (GFMXDH264_ERROR + 0x0000000C) + + + /** GFMxDecH264 error code: GFMxDecH264DecSEI() is not supported in bitstream callback mode. + @see GFMxDecH264DecSEI() + */ +#define GFMXDECH264_ERROR_SEI_NOT_SUPPORTED_FOR_BITSTREAM_CALLBACK_MODE (GFMXDH264_ERROR | 0x0000000D) + + /** GFMxDecH264 error code: GFMxDecH264DecSEI() encountered end of bitstream. + @see GFMxDecH264DecSEI() + */ +#define GFMXDECH264_ERROR_SEI_END_OF_FILE (GFMXDH264_ERROR | 0x0000000E) + + /** GFMxDecH264 error code: GFMxDecH264DecSEI() cannot decode this NAL Unit as its not SEI. + @see GFMxDecH264DecSEI() + */ +#define GFMXDECH264_ERROR_SEI_NOT_SEI_RBSP (GFMXDH264_ERROR | 0x0000000F) + + /** GFMxDecH264 error code: GFMxDecH264DecSEI() Timed out on DSP side. + @see GFMxDecH264DecSEI() + */ +#define GFMXDECH264_ERROR_SEI_TIMEOUT (GFMXDH264_ERROR | 0x00000010) + + /** GFMxDecH264 error code: GFMxDecH264DecNewFrameNum() cannot decode this NAL Unit as + it does not contain frame number information. + @see GFMxDecH264DecNewFrameNum() + */ +#define GFMXDECH264_ERROR_DECFRAMENUM_NOTSUPPORTED (GFMXDH264_ERROR | 0x00000011) + + /* #### MxDecH264 Helper macros. Maybe useful for backward compatible API. #### */ + + /** This function returns version and capabilities of API and hardware. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pMXProp (PGFPROPERTY) Pointer to property structure to be filled in + + @retval #GF_SUCCESS \a pJXProp filled in successfully + @retval #GF_ERROR Some error occured + + The #GFPROPERTY structure passed with parameter \a pMXProp will be + filled in on successfull return. The GFPROPERTY::Capability field + will hold a combination of flagbits indicating capabilities specific + to the MxDecH264API: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GF_MXDEC_H264_CAP_BASELINEBaseline profile supported
      #GF_MXDEC_H264_CAP_MAINMain profile supported
      #GF_MXDEC_H264_CAP_EXTENDEDExtended profile supported
      #GF_MXDEC_H264_CAP_LEVEL10LEVEL 1.0 supported
      #GF_MXDEC_H264_CAP_LEVEL11LEVEL 1.1 supported
      #GF_MXDEC_H264_CAP_LEVEL12LEVEL 1.2 supported
      #GF_MXDEC_H264_CAP_LEVEL13LEVEL 1.3 supported
      #GF_MXDEC_H264_CAP_LEVEL20LEVEL 2.0 supported
      #GF_MXDEC_H264_CAP_LEVEL21LEVEL 2.1 supported
      #GF_MXDEC_H264_CAP_LEVEL22LEVEL 2.2 supported
      #GF_MXDEC_H264_CAP_LEVEL30LEVEL 3.0 supported
      #GF_MXDEC_H264_CAP_LEVEL31LEVEL 3.1 supported
      #GF_MXDEC_H264_CAP_LEVEL32LEVEL 3.2 supported
      #GF_MXDEC_H264_CAP_LEVEL40LEVEL 4.0 supported
      #GF_MXDEC_H264_CAP_LEVEL41LEVEL 4.1 supported
      #GF_MXDEC_H264_CAP_LEVEL42LEVEL 4.2 supported
      #GF_MXDEC_H264_CAP_LEVEL50LEVEL 5.0 supported
      #GF_MXDEC_H264_CAP_LEVEL51LEVEL 5.1 supported
      #GF_MXDEC_H264_CAP_DBPost Processing de-blocking supported
      #GF_MXDEC_H264_CAP_DRPost Processing de-ringing supported
      + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxDecH264API functions. + + @see GFPROPERTY + */ +#define GFMxDecH264GetProperty(hMxDecH264, pMXProp) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264GetProperty(hMxDecH264, pMXProp) + +#define GFMxDecH264GetStatus(hMxDecH264, pStatus) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264GetStatus(hMxDecH264, pStatus) + + /** Decode sequence header. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pSequence (PGFMXDECH264DECSEQUENCE) Pointer to #GFMXDECH264DECSEQUENCE parameter structure + + @retval GF_SUCCESS Sequence header was decoded successfully + + NAL units with nal_unit_type = 7 should be passed to GFMxDecH264DecSequence(). Such NAL units + contain Sequence Parameter Set (SPS). The nal_ref_idc should be a non-zero value. + + This function will be called whenever a sequence header is found in the bitstream, decode + it and return its characteristics. + + @see GFMXDECH264DECSEQUENCE + */ +#define GFMxDecH264DecSequence(hMxDecH264, pSequence)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264DecSequence(hMxDecH264, pSequence) + + /** Decode a picture. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pPicture (PGFMXDECH264DECPICTURE) Pointer to #GFMXDECH264DECPICTURE parameter structure + + @retval GF_SUCCESS Frame was decoded successfully + @retval GFMXDECH264_ERROR_PICTURE_DETECTED_SEQUENCE Sequence header detected + @retval GFMXDECH264_ERROR_PICTURE_END_OF_FILE End of stream encountered + @retval GFMXDECH264_ERROR_PICTURE_CORRUPTED_PICTURE Unrecoverable bitstream error during frame decode + @retval GFMXDECH264_ERROR_PICTURE_NOT_ENOUGH_MEM Out of GPU memory + + All NAL units with nal_unit_type other than 7, should be passed to GFMxDecH264DecPicture(). + In specific, for nal_unit_type value as 8, the NAL Unit contains a Picture Parameter Set (PPS) and + for nal_unit_type ranging between 1 and 5, the NAL units contain coded slices. + + GFMxDecH264DecPicture decodes one picture from the bit stream. If GFMxDecH264DecPicture detects an + error, it will perform error concealment. If the error is not concealable, GFMxDecH264DecPicture returns + the error back to the application. + If the current stream position is not on the start of a frame, the function scans forward until a frame + start or sequence header is detected. + + For actions to take on the particular return codes, refer to the return code documentation. + + @see GFMXDECH264DECPICTURE + */ +#define GFMxDecH264DecPicture(hMxDecH264, pPicture)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264DecPicture(hMxDecH264, pPicture) + + + /** Decode a SEI rbsp. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pSEI (PGFMXDECH264DECSEI) Pointer to #GFMXDECH264DECSEI parameter structure + + @retval GF_SUCCESS SEI rbsp was decoded successfully + @retval GFMXDECH264_ERROR_SEI_NOT_SUPPORTED_FOR_BITSTREAM_CALLBACK_MODE This API is not supported in bitstream callback mode + @retval GFMXDECH264_ERROR_PICTURE_END_OF_FILE End of stream encountered + @retval GFMXDECH264_ERROR_SEI_NOT_SEI_RBSP cannot decode this NAL Unit as its not SEI + + All NAL units with nal_unit_type 6 can be passed to GFMxDecH264DecSEI() for decoding in prefill mode. + + GFMxDecH264DecSEI decodes SEI rbsp. + + For actions to take on the particular return codes, refer to the return code documentation. + + @see GFMXDECH264DECSEI + */ +#define GFMxDecH264DecSEI(hMxDecH264, pSEI)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264DecSEI(hMxDecH264, pSEI) + + + /** Decode slice header and extract framenumber. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param VideoBuffPtr Pointer to bitstream + @param VideoBufferLength Length of bitstream data available in the buffer + + @retval framenum Framenumber of current nal unit data + @retval GFMXDECH264_ERROR_DECFRAMENUM_NOTSUPPORTED Nal unit type not supported + + NAL units with nal_unit_type 1 and 5 can be passed to parse slice header and extract + framenumber. + This function can be used in prefill buffer mode to find all nal units which + belongs to same frame before calling GFMxDecH264DecPicture. + + */ + + +#define GFMxDecH264DecNewFrameNum(hMxDecH264,VideoBuffPtr,VideoBufferLength) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264DecNewFrameNum(hMxDecH264,VideoBuffPtr,VideoBufferLength) + + +#define GFMxDecH264SetSequence(hMxDecH264, pSequence)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetSequence(hMxDecH264, pSequence) + +#define GFMxDecH264SetPicture(hMxDecH264, pPicture)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetPicture(hMxDecH264, pPicture) + +#define GFMxDecH264SetSlice(hMxDecH264, pSlice)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetSlice(hMxDecH264, pSlice) + +#define GFMxDecH264SetMBs(hMxDecH264, pMBs) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetMBs(hMxDecH264, pMBs) + +/** Post Processing on a decoded YUV surface. + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param pP (PGFMXDECH264PP) Pointer to #GFMXDECH264PP parameter structure + + @retval GF_SUCCESS Applied post processing on decoded surface successfully + + GFMxDecH264PostProcessing() function can perform DeRinging and DeBlocking or DeBlocking only on a decoded YUV surface data. + + GFMXDECH264DECSEQUENCE::PictureInfo output flagbit (GF_MXDEC_H264_DEC_PICTURE_DEBLOCKING_FILTER) + is set by the API if H264 bit stream does not have in-the-loop DeBlocking. + This means app can perform out-of-the-loop DeBlocking by calling GFMxDecH264PostProcessing(). + If H264 bit stream has in-the-loop processing then hardware H264 decoder will perform in-the-loop DeBlokcing + and API resets this flag to zero to indicate that app should not perform DeBlocking. + + GFMxDecH264PostProcessing can be called any time. we need decoded YUV surface data and Qp values for each MB. + If video is decoded by our hardware decoder then Qp values are saved in the internal SRAM for the last frame. + + + @see GFMXDECH264PP + +*/ + + + +#define GFMxDecH264PostProcessing(hMxDecH264, pP) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264PostProcessing(hMxDecH264, pP) + +#define GFMxDecH264SetAttribute(hMxDecH264, uiFeature, pInfo) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264SetAttribute(hMxDecH264, uiFeature, pInfo) + +#define GFMxDecH264GetAttribute(hMxDecH264, uiFeature, pInfo) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264GetAttribute(hMxDecH264, uiFeature, pInfo) + + /** Set various runtime parameters. + + @param hMxDecH264 (GFMxDecH264Handle) Handle to MxDecH264 component + @param uiFeature (NvU32) ID of feature to set + @param pInfo (void*) Feature specific data + + @retval GF_SUCCESS Success + @retval GF_FAILURE Failure + + The following features identified by parameter \a uiFeature can be set, see documentation + for the individual \a uiFeature IDs for interpretation of data in parameter \a pInfo: + + + + + + + + + + + +
      uiFeatureMeaningpInfo interpretation
      #GF_MXDEC_H264_SET_READBITSTREAMSet up a stream callback function.GFMxDec calls + that callback function to request a portion of the bit stream from the application.#GFMXDECH264CALLBACK *
      #GF_MXDEC_H264_SET_SURFACE_LISTSet a list of surfaces for to be used to store reference and decode frames.#GFMXDECH264SURFLIST *
      #GF_MXDEC_H264_SET_UNLOCK_SURFACEUnlock one or all locked surface.NvS32
      + */ +#define GFMxDecH264Set(hMxDecH264, uiFeature, pInfo) \ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264Set(hMxDecH264, uiFeature, pInfo) + +#define GFMxDecH264InterruptControl(hMxDecH264, IntType, op, pData)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264InterruptControl(hMxDecH264, IntType, op, pData) + +#define GFMxDecH264InterruptHandler(hMxDecH264, IntType, pData)\ + ((PGFMXDECH264TABLE)((NvU32)hMxDecH264+MXDH264OFFSET))->MxDecH264InterruptHandler(hMxDecH264, IntType, pData) + +#define GFMxDecH264DSPPoll(MxHandle, timeout)\ + ((PGFMXDECH264TABLE)((NvU32)MxHandle+MXDH264OFFSET))->MxDecH264DSPPoll(MxHandle, timeout) + + //Use the following flags in the setattribute function for the picture boundary mode. + //If you wish to send the sequence header separately from the first frame use the first flag(SEPARATE_SEQUENCE_HEADER) + //else use the second flag. +#define GFMXDECH264_SEPARATE_SEQUENCE_HEADER 0x1 +#define GFMXDECH264_COMBINED_SEQUENCE_HEADER 0x2 + + + /*@}*/ + + /** @page pageMxDecH264AppNotes MxDecH264API Application Notes + + @section pageMxDecH264AppNotes1 Programming Sequence + + Todo + + @section pageMxDecH264AppNotes2 Decode Surface Locking + + The H264 decoder can operate in a surface locking mode, which is activated by + attribute #GF_MXDEC_H264_ATTR_SURFACE_LOCKING. In this mode, GFMxDecH264DecPicture() + will automatically 'lock' the current surface with the decoded frame, and exclude it + from its surface pool available for decoding new frames. + + Surface locking is intended for usecases, were the decode surface is directly used as overlay. + For the duration it is displayed as overlay, the locked state ensures, that it won't be + overwritten. With this mechanism H264 decode and screen update can run in independent thread + contexts. + + If a surface from the pool is locked, it can still be used as a reference frame. + However it will never be reused and overwritten during a succeeding call to + GFMxDecH264DecPicture(). + + The application can re-add the locked surface to the set of writable surfaces by + calling GFMxDecH264Set / GF_MXDEC_H264_SET_UNLOCK_SURFACE. + + A locked surface is identified on return from GFMxDecH264DecPicture() via + GFMXDECH264DECPICTURE::ReconSurfaceNumber. This ID needs to be passed later to + GF_MXDEC_H264_SET_UNLOCK_SURFACE to perform the unlocking. + + The application has to ensure that at least + 1 surfaces + in the pool stay unlocked. If GFMxDecH264DecPicture() is called with unsufficient + free surfaces, error GFMXDECH264_ERROR_PICTURE_ALL_SURFACES_LOCKED will be returned. + + The number of surfaces set via GFMxDecH264Set / GF_MXDEC_H264_SET_SURFACE_LIST / + GFMXDECH264SURFLIST::surfList must be at least N+1+M, where N is the number of reference + frames and M the maximum allowed number of simulteneously locked surfaces. + + The lock-state of all surfaces can be reset via GFMxDecH264Set / GF_MXDEC_H264_SET_UNLOCK_SURFACE + passing -1 as surface ID. + */ + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecRV9.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecRV9.h new file mode 100755 index 00000000..a341d500 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecRV9.h @@ -0,0 +1,853 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFMxDecRV9.h + GFSDK RV9 Decode API header file. +*/ + +#ifndef _GF_MPEG_DEC_RV9__ +#define _GF_MPEG_DEC_RV9__ + +#include "nvtypes.h" +#include "GFVx.h" + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif +/** @addtogroup group MxDecRV9API +*/ +/*@{*/ + + +// MXDECRV9 CapabilityEx Flag +#define GF_MXDEC_RV9_CAPEx_USE_DSP 0x00000001 +// Whenever DSP is used for decoding +// Surace type should be = GF_SURFACE_VIDEO_MEMORY +// Surface hint type = GF_MEMORY_HINT_BOTTOM_UP +// In case of Host Used for decoding +// Surace type = GF_SURFACE_SYSTEM_MEMORY +// Surface hint type = 0 +// MXDECRV9CapFlags +/************************************************************************************************************/ + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_SIMPLE 0x00000001 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_MEDIUM 0x00000002 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_COMPLEX 0x00000004 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_LEVEL1 0x00000100 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_LEVEL2 0x00000200 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_LEVEL3 0x00000400 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_LEVEL4 0x00000800 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_DB 0x00001000 + +/** Argument "GFPROPERTY pMXProp" for MxDecRV9GetProperty().\n + Application returns the properties, in GFPROPERTY structure \n +@see GFMXDECRV9TABLE::MxDecRV9GetProperty , GFPROPERTY::Capability +*/ +#define GF_MXDEC_RV9_CAP_DR 0x00002000 +/*********************************************************************************************************************/ + + + + /** This structure holds various informations each of the frame to be decoded . +This structure is passed as parameter to GFMXDECRV9TABLE::MxDecRV9DecodeFrame. +*/ + +typedef struct _GFMXDECRV9FRAME +{ + + + NvU32 uiFrameOption; /**< uiFrameOption values + + + +
      #GF_MXDEC_RV9_DEC_FRAME_SPECIFY_SURF_RECTspecify rect area to hold the reconstructed image.
      + */ + PGFRECT pFrameRect; /**< not in use */ + NvU32 uiFrameType; /**< set new frame type information +
      + + + + + + +
      #GF_MXDEC_RV9_DISPLAY_FRAME
      #GF_MXDEC_RV9_KEY_FRAME
      #GF_MXDEC_RV9_P_FRAME
      #GF_MXDEC_RV9_B_FRAME
      #GF_MXDEC_RV9_DONT_DISPLAY_FRAME
      #GF_MXDEC_RV9_ERRONEOUS_FRAME
      + */ + PGFRMSURFACE pReconstructedSurf;/**< This is the surface to hold the decoded picture */ + NvU32 uiFrameSequenceCount; /**< set by GFMxDecRV9API */ + NvU32 uiTimeStamp; /**< in terms of millisecond */ + NvU8* pPreFillBuffer; /**< Input, Pointer bitstream for frame to decode */ + NvU32 PreFillBufferLength; /**< Input, Length of bitstream in bytes, must cover the entire frame */ + +}GFMXDECRV9FRAME, *PGFMXDECRV9FRAME; + +//uiFrameOption +/******************************************************************************************/ +/** uiFrameOption for GFMXDECRV9FRAME passed as an argument in MxDecRV9DecodeFrame(). \n +specify rect area to hold the reconstructed image.\n +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame. +*/ +#define GF_MXDEC_RV9_DEC_FRAME_SPECIFY_SURF_RECT 0x00000001 + +//uiFrameType values + +/******************************************************************************************/ +/** uiFrameType values for GFMXDECRV9FRAME set by MxDecRV9DecodeFrame(). \n + +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_DISPLAY_FRAME 0x0 + +/** uiFrameType values for GFMXDECRV9FRAME set by MxDecRV9DecodeFrame(). \n + The decoded Frame is I-frame. +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_KEY_FRAME 0x1 + +/** uiFrameType values for GFMXDECRV9FRAME set by MxDecRV9DecodeFrame(). \n +The Decoded Frame is P-frame. +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_P_FRAME 0x2 + +/** uiFrameType values for GFMXDECRV9FRAME set by MxDecRV9DecodeFrame(). \n + The decoded Frame is B-frame. +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_B_FRAME 0x4 + +/** uiFrameType values for GFMXDECRV9FRAME passed as an argument in MxDecRV9DecodeFrame(). \n + +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_DONT_DISPLAY_FRAME 0x8 + +/** uiFrameType values for GFMXDECRV9FRAME passed as an argument in MxDecRV9DecodeFrame(). \n + Decode frame is Erroneous +@see GFMXDECRV9FRAME, GFMXDECRV9TABLE::MxDecRV9DecodeFrame +*/ +#define GF_MXDEC_RV9_ERRONEOUS_FRAME 0x16 +/***********************************************************************************************************************/ + +/** This structure holds various informations needed for Post Processing of decoded frame . +This structure is passed as parameter to MxDecRV9PostProcessing(). +*/ +typedef struct _GFMXDECRV9PP +{ + PGFRMSURFACE pPPSurf; + /**< pointer to surface that will + hold the result from Post Processing + */ + PGFRECT pPPRect; + /**< Rectangle area to be processed for both + source and destination surface + */ + + PGFRMSURFACE pSrcSurf; + /**< pointer to surface that will + hold the result from Post Processing + */ + PGFRECT pSrcRect; + /**< Rectangle area to be processed for both + source and destination surface + */ +} GFMXDECRV9PP, *PGFMXDECRV9PP; + +// PPOption +#define GF_MXDEC_RV9_PP_SM_OFF 0x0 //Turn OFF Smoothing filter for this frame +#define GF_MXDEC_RV9_PP_SM_ON 0x1 //Turn ON Smoothing filter for this frame +#define GF_MXDEC_RV9_PP_DR_ON 0x2 //Turn ON DeRinging filter for this frame + + +// Hardware Status +/************************************************************************************************************/ + +#define GF_DECODER_FRAME_DONE 0x00000010 + + + +#define GF_DECODER_PP_FRAME_DONE 0x00000020 + +/*********************************************************************************************************/ +#define GF_DECODER_PP_FRAME_RV9 0x00000040// + + +/** Attribute MxDecRV9Set::uiFeature.\n + Application sets this attribute to register a callback function and + its correpnding parameter to read bitstream data . +@see GFMXDECRV9TABLE::MxDecRV9Set, pInfo should be a pointer to PGFMXDECRV9CALLBACK \n +*/ +#define GF_MXDEC_RV9_SET_READBITSTREAM 0x1 + + + +/** Attribute MxDecRV9Set::uiFeature \n + This will setup the surface list, including all of the ref surface and one reconstructed one. \n +@see GFMXDECRV9TABLE::MxDecRV9Set, pInfo should a pointer PGFMXDECRV9SURFLIST +*/ +#define GF_MXDEC_RV9_SET_SURFACE_LIST 0x2 + + + +/** Attribute MxDecRV9Set::uiFeature \n + This will Set the GFMxDecRV9API to decode the RV8 stream + By default GFMxDecRV9API will assume the stream to be RV9 stream\n +@see GFMXDECRV9TABLE::MxDecRV9Set +*/ +#define GF_MXDEC_RV9_BITSTREAM_RV8 0x4 + + +/** Attribute GFMxDecRV9SetAttribute::uiFeature and GFMxDecRV9GetAttribute::uiFeature \n + Application will determine the decoding boundary, for RV9, this boundary means VOL + and VOP boundary. For certain file formats, those boundary information are + stored in the video file, APP can easily use those information to determine + the boundary. + If APP wants API to detect the boundary,App should not disable this attribute. This is mainly for streaming case, APP does + not have those handy boundary information. API will automatically detects those + boundaries. APP does not need to parse the bitstream to detect those boundaries.\n + *pInfo: 1: APP will determine the decoding boudary\n + *pInfo: 0: APP will not determine the decoding boundary \n +@see GFMXDECRV9TABLE::MxDecRV9SetAttribute +*/ +#define GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY 0x00000001 + + + +/** Attribute GFMxDecRV9GetAttribute::uiFeature \n + This attribute only can be used for GFMxDecGetAttribute + If application wants to set pDestRect in GFMXDECVOP or GFMXDECMP4DECVOP, + application must use this attributes to get allignment information and + align the rectangle top & left corner accordinately.\n + *pInfo: top fieled alignment in term of lines \n +@see GFMXDECRV9TABLE::MxDecRV9GetAttribute +*/ +#define GF_MXDEC_ATTR_RV9_DEC_FRAME_RECT_TOP_ALIGNMENT 0x00000002 + + + +/** Attribute GFMxDecRV9GetAttribute::uiFeature \n + This attribute only can be used for GFMxDecGetAttribute + If application wants to set pDestRect in GFMXDECVOP or GFMXDECMP4DECVOP, + application must use those attributes to get allignment information and + align the rectangle top & left corner accordinately.\n + *pInfo: left fieled alignment in term of pixels\n + +@see GFMXDECRV9TABLE::MxDecRV9GetAttribute +*/ +#define GF_MXDEC_ATTR_RV9_DEC_FRAME_RECT_LEFT_ALIGNMENT 0x00000003 + + +/** Attribute GFMxDecRV9SetAttribute::uiFeature and GFMxDecRV9GetAttribute::uiFeature \n + Application will fill the buffer and push the data to the decoder. +*/ +#define GF_MXDEC_RV9_ATTR_PREFILLBUFFER 0x00000008 + +/********************************************************************************************************/ + +/** Structure holding the callback function pointer. +Used in registering the callback function +The callback function is a function which the API calls to request a portion of the bit stream from the application. +@see GFMXDECRV9TABLE::MxDecRV9Set +*/ + + + +typedef struct _GFMXDECRV9CALLBACK +{ + void *pPara;/**< pPara is a parameter passed from APP, + and APP wants API to call back with this parameter + */ + NvU32 (*pCallBack)(void * pPara, NvU8 ** ppBuffer, NvU32 * BufferLength,NvU32 uFlag); + /**< Application callback function pointer. + Register a callback function for fetching RV9 data. + + @param *pPara Parameter to pass on to application callback function + @param ppBuffer Buffer Pointer + @param BufferLength Parameter to pass on to application callback function + + If APP set GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY, + APP should return GF_MXDEC_RV9HD_BOUNDARY_REACHED when the boundary is + detected. + If APP does not set GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY, + 0 should be returned. + */ + +}GFMXDECRV9CALLBACK, *PGFMXDECRV9CALLBACK; + +#define GF_MXDEC_RV9HD_ENDOFFILE 0x00000200 +#define GF_MXDEC_RV9HD_APP_DETECT_BOUNDARY 0x00001000 +#define GF_MXDEC_RV9HD_BOUNDARY_REACHED 0x00002000 +#define GF_MXDEC_RV9HD_ENDOFFILE_REACHED 0x00004000 +#define GF_MXDEC_RV9HD_APP_PREFILLBUFFER 0x00008000 +#define GF_MXDEC_RV9HD_BEGININGOFFILE_REACHED 0x00010000 + + + +/** MxDecRV9API GFMXDECRV9CALLBACK::(*pCallBack)(, , ,uFlag)\n + for reading bitstream in forward direction +@see GFMXDECRV9CALLBACK +*/ +#define GF_MXDEC_RV9_READ_BITSTREAM_FORWARD 0x00000002 + +/** MxDecRV9API GFMXDECRV9CALLBACK::(*pCallBack)(, , ,uFlag) \n + for reading bitstream in reverse direction. +@see GFMXDECRV9CALLBACK +*/ +#define GF_MXDEC_RV9_READ_BITSTREAM_BACKWARD 0x00000003 + +//Resync options : + +/** MxDecRV9API GFMxDecRV9Resync( ,ResyncOption)\n + Resynchronize forward to the nearest I frame. If the GFMxDecRV9API is right + before an I frame, GFMxDecRV9Resync() returns immediately. Otherwise, + GFMxDecRV9Resync() moves forward, parsing bits until it reaches the first bit of the next I frame. +@see ResyncOption, GFMXDECRV9TABLE::MxDecRV9Resync +*/ + +#define GF_MXDEC_RV9_RESYNC_FORWARD_NEAREST_I_FRAME 0x00000001 + +/** MxDecRV9API GFMxDecRV9Resync(,ResyncOption)\n + Resynchronize backward to the nearest I frame. + GFMxDecRV9Resync() moves backward, parsing bits until it reaches the first bit of the previous I frame. +@see ResyncOption, GFMXDECRV9TABLE::MxDecRV9Resync +*/ +#define GF_MXDEC_RV9_RESYNC_BACKWARD_NEAREST_I_FRAME 0x00000002 + +/** MxDecRV9API GFMxDecRV9Resync(,ResyncOption)\n + Resynchronize backward to the nearest P frame. + GFMxDecRV9Resync() moves backward, parsing bits until it reaches the first bit of the previous P frame. +@see ResyncOption, GFMXDECRV9TABLE::MxDecRV9Resync +*/ +#define GF_MXDEC_RV9_RESYNC_BACKWARD_NEAREST_P_FRAME 0x00000004 + + + +/** this macro is used in GFMXDECRV9SURFLIST structure \n + Reference surfaces for RV9 decoder. */ +#define GF_MXDEC_RV9_NUM_SURFACES 3 + +/** This structure is used to Set up a list of surfaces for RV9 + decoder . +*/ + +typedef struct _GFMXDECRV9SURFLIST +{ + + PGFRMSURFACE SurfList[GF_MXDEC_RV9_NUM_SURFACES]; + /**< an array of PGFRMSURFACE + @see #GF_MXDEC_RV9_NUM_SURFACES + */ + + +}GFMXDECRV9SURFLIST, *PGFMXDECRV9SURFLIST; + +/** This structure is passed to MxDecRV9DecodePictureHeader() function, which sets + different fields of this structure. +*/ +typedef struct _GFMXDECRV9PICHDR +{ + NvU32 uiRV8StreamInfo; + /**< set by GFMxDecRV9API. Valid only if it is RV8 stream + + + + + + + + + + + +
      #GF_MXDEC_RV8_UMVUnrestricted Motion Vector
      #GF_MXDEC_RV8_DFIn loop Deblocking filter
      #GF_MXDEC_RV8_SSSlice Structured
      #GF_MXDEC_RV8_RPRReference Picture Resampling
      #GF_MXDEC_RV8_ROUNDRound off for half pixel motion compensation
      + */ + NvU32 uiRV9StreamInfo; + /**< set by GFMxDecRV9API. Valid only if it is RV9 stream + + + + + +
      #GF_MXDEC_RV9_INTERLACEInterlaced mode used
      #GF_MXDEC_RV9_DF_PASS_THRUIn loop Deblocking filter is disabled
      + */ + NvU32 uiWidth; /**< Video width */ + NvU32 uiHeight; /**< Video height */ + NvU32 uiTR; /**< Temporal reference in milliseconds */ + +}GFMXDECRV9PICHDR, *PGFMXDECRV9PICHDR; + +//uiRV8StreamInfo + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo \n + Unrestricted Motion Vector. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_UMV 0x00000001 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo \n + In loop Deblocking filter. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_DF 0x00000002 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo\n + Slice Structured. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_SS 0x00000004 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo \n + Reference Picture Resampling. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_RPR 0x00000008 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV8StreamInfo \n + Round off for half pixel motion compensation. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV8_ROUND 0x00000010 + +//uiRV9StreamInfo + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV9StreamInfo \n + Interlaced mode used. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV9_INTERLACE 0x00000001 + +/** MxDecRV9API GFMXDECRV9PICHDR::uiRV9StreamInfo \n + In loop Deblocking filter is disabled. +@see GFMXDECRV9PICHDR, GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_MXDEC_RV9_DF_PASS_THRU 0x00000002 + +//resync options +//TBD + +//when GF_ERROR is return check the following flag +#define GF_MXDEC_RV9_BAD_MB 0x00010000 //there is at least one MB is wrong + //if APP set up pMBInfo, APP can check which MB is wrong + +/** MxDecRV9API interrupt operation types. +Constants to specify operation for a call to MxDecRV9InterruptControl(). +@see GF_MXDEC_RV9_INTERRUPT_OPERATION_TYPE, GFMXDECRV9TABLE::MxDecRV9InterruptControl +*/ +typedef enum +{ + /** Enable interrupt/status assertion for an interrupt type. */ + GF_MXDEC_RV9_INTERRUPT_ENABLE, + + /** Disable interrupt/status assertion for an interrupt type. */ + GF_MXDEC_RV9_INTERRUPT_DISABLE, + + /** Clear interrupt/status assertion for an interrupt type. */ + GF_MXDEC_RV9_INTERRUPT_CLEAR +} GF_MXDEC_RV9_INTERRUPT_OPERATION_TYPE; // Interrupt operation. + + + +/** MxDecRV9API interrupt types. +@see GF_MXDEC_RV9_INTERRUPT_TYPE, GFMXDECRV9TABLE::MxDecRV9InterruptControl and GFMXDECRV9TABLE::MxDecRV9InterruptHandler +*/ +typedef enum +{ + /** Interrupt type is DSP Command Interrupt */ + GF_MXDEC_RV9_DSP_COMMAND_INTR, + + /** Interrupt type Post Processing done */ + GF_MXDEC_RV9_POST_PROCESSING_DONE_INTR, + + /** Interrupt type is Decoding done Interrupt */ + GF_MXDEC_RV9_DECODE_DONE_INTR +} GF_MXDEC_RV9_INTERRUPT_TYPE; + +/** MxDecRV9API virtual function pointer table. */ +typedef struct _GFMXDECRV9TABLE +{ + + /** This function returns version and capabilities of API and hardware. + + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param pMXProp (PGFPROPERTY) Pointer to GFPROPERTY structure to be filled in + + @retval GF_SUCCESS \a pMXProp filled in successfully + @retval GF_ERROR Some error occured + + The GFPROPERTY structure passed with parameter \a pMXProp will be + filled in on successfull return. The GFPROPERTY::Capability field + will hold a combination of flagbits indicating capabilities specific + to the MxDecRV9API: + + + + + + + + + + + + + + + + + + + + +
      #GF_MXDEC_RV9_CAP_SIMPLE support simple profile.
      #GF_MXDEC_RV9_CAP_MEDIUM support medium profile.
      #GF_MXDEC_RV9_CAP_COMPLEX support complex profile
      #GF_MXDEC_RV9_CAP_LEVEL1support LEVEL 1.
      #GF_MXDEC_RV9_CAP_LEVEL2 support LEVEL 2.
      #GF_MXDEC_RV9_CAP_LEVEL3 support LEVEL 3.
      #GF_MXDEC_RV9_CAP_LEVEL4 support LEVEL 4.
      #GF_MXDEC_RV9_CAP_DB support Post Processing's smoothing filter for RV8 streams.
      #GF_MXDEC_RV9_CAP_DR support Post Processing's de-ringing.
      + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxDecRV9API functions. + + @see GFPROPERTY +*/ + GF_RETTYPE (* MxDecRV9GetProperty)(GFMxDecRV9Handle hMxDecRV9, PGFPROPERTY pMXProp ); + + + + GF_RETTYPE (* MxDecRV9GetStatus)(GFMxDecRV9Handle hMxDecRV9, NvU32 * pStatus); + + + /** This function applies the postprocessing filters to the source surface and outputs + the new image to the destitation surface. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param pP (#PGFMXDECRV9PP) Pointer to the PGFMXDECRV9PP. + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + GF_ERROR Return values for the above function + + @see PGFMXDECRV9PP +*/ + GF_RETTYPE (* MxDecRV9PostProcessing)(GFMxDecRV9Handle hMxDecRV9, PGFMXDECRV9PP pP); + + + /** This function sets the MxDecRV9API options. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param uiFeature : + + + + + +
      #GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY will determine the VOL and VOP boundary, for RV9.
      #GF_MXDEC_RV9_ATTR_PREFILLBUFFERApp will fill the buffer and push the data to the decoder.
      + @param pInfo Pointer to the information buffer. + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + +*/ + GF_RETTYPE (* MxDecRV9SetAttribute)(GFMxDecRV9Handle hMxDecRV9, NvU32 uiFeature, NvU32* pInfo); + + + /** This function gets the MxDecRV9API options. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param uiFeature : + + + + + +
      #GF_MXDEC_ATTR_RV9_DEC_FRAME_RECT_TOP_ALIGNMENT
      #GF_MXDEC_ATTR_RV9_DEC_FRAME_RECT_LEFT_ALIGNMENT
      #GF_MXDEC_RV9_ATTR_PRE_DETERMINED_BOUNDARY
      #GF_MXDEC_RV9_ATTR_PREFILLBUFFER
      + @param pInfo Pointer to the information buffer. + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + +*/ + GF_RETTYPE (* MxDecRV9GetAttribute)(GFMxDecRV9Handle hMxDecRV9, NvU32 uiFeature, NvU32* pInfo); + + + /** This function sets the MxDecRV9API options. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param uiFeature : + + + + + + + +
      #GF_MXDEC_RV9_SET_READBITSTREAM will Set up readbitstream call back function.
      #GF_MXDEC_RV9_SET_SURFACE_LISTwill setup the surface list, including all of the ref surface and one reconstructed one.
      #GF_MXDEC_RV9_BITSTREAM_RV8 will Set the GFMxDecRV9API to decode the RV8 stream.
      + @param pInfo Pointer to the information buffer. + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + +*/ + GF_RETTYPE (* MxDecRV9Set)(GFMxDecRV9Handle hMxDecRV9, NvU32 uiFeature, void * pInfo); + + + + +/** This function Decodes the picture header and gives the related information in + PictureHeader. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param pPictureHeader Pointer to the #GFMXDECRV9PICHDR. + @retval GF_SUCCESS \a if it successfully decodes the Header + @retval GF_ERROR Some error occured + GF_ERROR Return values for the above function + + + + + + + + + +
      #GF_ERROR_RV9DECPICTUREHDR_DETECTED There is a sequence header in the bit stream. + Application need to decide this sequence is an error or this + is intended to be in the bit stream.
      #GF_ERROR_RV9DECPICTUREHDR_END_OF_FILE No more bit stream from application.
      #GF_ERROR_RV9DECPICTUREHDR_CORRUPTED GFMxDecRV9DecPicture encounters an un-recoverable error + in the bit stream. Application should call GFMxDecRV9Resync + API to skip this picture.
      #GF_ERROR_RV9DECPICTUREHDR_NOT_ENOUGH_MEM There is not enough memory.
      + + @see GFMXDECRV9PICHDR +*/ + GF_RETTYPE (* MxDecRV9DecodePictureHeader)(GFMxDecRV9Handle hMxDecRV9, PGFMXDECRV9PICHDR pPictureHeader); + + + /** This function decodes one frame from the bitstream. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param pFrame pointer to #PGFMXDECRV9FRAME + @retval GF_SUCCESS \a if successful + @retval #GF_MXDEC_RV9_FRAMEDEC_EOF_REACHED \a No more bit streams from the application. + +*/ + GF_RETTYPE (* MxDecRV9DecodeFrame)(GFMxDecRV9Handle hMxDecRV9, PGFMXDECRV9FRAME pFrame); + + + +/** GFMxDecRV9Resync re-synchronizes to a specific position of a bit stream.. + @param hMxDecRV9 (GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param ResyncOption : + + + + + + + +
      #GF_MXDEC_RV9_RESYNC_FORWARD_NEAREST_I_FRAME.Resynchronize forward to the nearest I frame.
      #GF_MXDEC_RV9_RESYNC_BACKWARD_NEAREST_I_FRAME.Resynchronize backward to the nearest I frame.
      #GF_MXDEC_RV9_RESYNC_BACKWARD_NEAREST_P_FRAME.Resynchronize backward to the nearest P frame.
      + @retval GF_SUCCESS \a if successful + @retval GF_ERROR Some error occured + +*/ + GF_RETTYPE (* MxDecRV9Resync)(GFMxDecRV9Handle hMxDecRV9, NvU32 ResyncOption); + + + + + GF_RETTYPE (* MxDecRV9InterruptControl)(GFMxDecRV9Handle hMxDecRV9, + GF_MXDEC_RV9_INTERRUPT_TYPE IntType, GF_MXDEC_RV9_INTERRUPT_OPERATION_TYPE op, + void * pData); + + + + /** This function provides component-level interrupt control for the + MxDecRV9API. It is optional because an interrupt service thread (IST) at the + application level can call the MxDecRV9API to complete the task. + @param hMxDecRV9(GFMxDecRV9Handle) Handle specific to MxDecRV9API + @param IntType MxDecRV9API interrupt type as defined in + “#GF_MXDEC_RV9_INTERRUPT_TYPE” + @param pData Pointer to data being passed in or out. + @retval GF_SUCCESS \a if successful. + @retval GF_ERROR Some error occured. + +*/ + GF_RETTYPE (* MxDecRV9InterruptHandler)(GFMxDecRV9Handle hMxDecRV9, + GF_MXDEC_RV9_INTERRUPT_TYPE IntType, void * pData); // Reserved. + +} GFMXDECRV9TABLE, *PGFMXDECRV9TABLE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFMxDecRV9Open(GFRmHandle hRm, GFMxDecRV9Handle *phMxDecRV9, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMxDecRV9Close(GFMxDecRV9Handle *phMxDecRV9); + +#if NVCPU_IS_XTENSA +#define MXDRV9OFFSET sizeof(GFMXDECRV9TABLE) +#else +#define MXDRV9OFFSET 0 +#endif + + +//ERROR return values for the GFMxDecRV9DecodePictureHeader() + +/** ERROR return values for the GFMxDecRV9DecodePictureHeader() \n + There is a sequence header in the bit stream. + Application need to decide this sequence is an error or this + is intended to be in the bit stream. + @see GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_ERROR_RV9DECPICTUREHDR_DETECTED 0x00000001 + + +/**ERROR return values for the GFMxDecRV9DecodePictureHeader() \n + No more bit stream from application. + @see GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_ERROR_RV9DECPICTUREHDR_END_OF_FILE 0x00000002 + + +/** ERROR return values for the GFMxDecRV9DecodePictureHeader() \n + GFMxDecRV9DecPicture encounters an un-recoverable error + in the bit stream. Application should call GFMxDecRV9Resync + API to skip this picture. + @see GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader +*/ +#define GF_ERROR_RV9DECPICTUREHDR_CORRUPTED 0x00000003 + +/**ERROR return values for the GFMxDecRV9DecodePictureHeader() \n + There is not enough memory. +*/ +#define GF_ERROR_RV9DECPICTUREHDR_NOT_ENOUGH_MEM 0x00000004 + +//ERROR return values for MxDecRV9DecodeFrame() +/** ERROR return values for MxDecRV9DecodeFrame()\n + API returns this error when End of file is reached,i.e No more bit stream from application. + once this ERROR is returned, the application should provide more media files to decode or + exit gracefully.*/ +#define GF_MXDEC_RV9_FRAMEDEC_EOF_REACHED 0x00000001 + +/* #### MxDecRV9API Helper macros. Maybe useful for backward compatible API. #### */ + + +/* #### MxDecRV9 Helper macros. Maybe useful for backward compatible API. #### */ +#define GFMxDecRV9GetProperty(hMxDecRV9, pMXProp) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9GetProperty(hMxDecRV9, pMXProp) + +#define GFMxDecRV9GetStatus(hMxDecRV9, pStatus) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9GetStatus(hMxDecRV9, pStatus) + +#define GFMxDecRV9DecodePictureHeader(hMxDecRV9, pPictureHeader)\ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9DecodePictureHeader(hMxDecRV9, pPictureHeader) + +#define GFMxDecRV9PostProcessing(hMxDecRV9, pP) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9PostProcessing(hMxDecRV9, pP); + +#define GFMxDecRV9SetAttribute(hMxDecRV9, uiFeature, pInfo) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9SetAttribute(hMxDecRV9, uiFeature, pInfo) + +#define GFMxDecRV9GetAttribute(hMxDecRV9, uiFeature, pInfo) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9GetAttribute(hMxDecRV9, uiFeature, pInfo) + +#define GFMxDecRV9Set(hMxDecRV9, uiFeature, pInfo) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9Set(hMxDecRV9, uiFeature, pInfo) + +#define GFMxDecRV9DecodeFrame(hMxDecRV9, pFrame) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9DecodeFrame(hMxDecRV9, pFrame) + +#define GFMxDecRV9Resync(hMxDecRV9, ResyncOption) \ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9Resync(hMxDecRV9, ResyncOption) + +#define GFMxDecRV9InterruptControl(hMxDecRV9, IntType, op, pData)\ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9InterruptControl(hMxDecRV9, IntType, op, pData) + +#define GFMxDecRV9InterruptHandler(hMxDecRV9, IntType, pData)\ + ((PGFMXDECRV9TABLE)((NvU32)hMxDecRV9+MXDRV9OFFSET))->MxDecRV9InterruptHandler(hMxDecRV9, IntType, pData) + + + +/*@}*/ +/*@}*/ + + +/** @page pageMxDecRV9AppNotes MxDecRV9API Application Notes + @section pageMxDecRV9AppNotes1 Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start + GFSDK usage. + + + + 1. Call GFMxDecRV9Open() to obtain RV9Handle. This handle will be passed to different functions of MxDecRV9API. + + 2. Call GFMxDecRV9GetProperty()to querry the properties.Check whether this + MxDecRV9API version can support the desired RV9 profile and level. + + 3. Set different attributes of RV9 decoder using GFMxDecRV9SetAttribute(), + #GFMXDECRV9TABLE::MxDecRV9SetAttribute. + + 4. Decode the picture header using GFMxDecRV9DecodePictureHeader(), + #GFMXDECRV9TABLE::MxDecRV9DecodePictureHeader. + + 5. call GFRmSurfaceAlloc() to allocate at least one reference surface and one + current surface for decoding purposes. + + 6. If the postprocessing engine is needed, allocate one surface to hold the + postprocessing results. + + 7. For display purposes, the decoder application could call GFVxBlt() for + the following two scenarios. Please refer to the latest GFVxAPI document + for additional information. + + + + 8. The decoder application should decode on frame by frame basis. Call GFMxDecRV9DecodeFrame() to decode each frame. + once GF_MXDEC_RV9_FRAMEDEC_EOF_REACHED is returnd by API, application should exit gracefully. + #GFMXDECRV9TABLE::MxDecRV9DecodeFrame + + 9. If Post processing is enabled , call GFMxDecRV9PostProcessing(). + #GFMXDECRV9TABLE::MxDecRV9PostProcessing + + 10. Before exiting the application, the decoder application should call + GFRmSurfaceFree() to free the surfaces that have been allocated. + + 11. Call GFMxDecRV9Close() with RV9Handle to release the resources of the decoder module. + +*/ + + +#ifdef __cplusplus +} // only need to export C interface if + // used by C++ source code +#endif + +#endif diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecVC1.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecVC1.h new file mode 100755 index 00000000..da28a6ec --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDecVC1.h @@ -0,0 +1,732 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFMxDecVC1.h +GFSDK VC1 Decode API header file. +*/ + +#ifndef _GF_MPEG_DEC_VC1__ +#define _GF_MPEG_DEC_VC1__ + +#include "nvtypes.h" +#include "GFVx.h" +#include "GFDef.h" + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif + + /** @addtogroup groupMxDecVC1 MxDecVC1API VC1 Decode API + The VC1 decoder API handles WMV simple profile-compliant bit + streams for this version, but has been defined to handle all of the three + profiles for future expansion. + + The VC1 decoder API has two sets of API—a high level API and a low + level API. + + Using the High Level API + + The high level API has a built-in entropy decoder. It decodes the bit stream. + This high level API calls the low level API internally. When using the high level API, the + application can ignore the low level API. + + The MxDecVC1API high level functions include the following: + - GFMxDecVC1DecSequenceLayer() + - GFMxDecVC1DecPicture() + - GFMxDecVC1Set() + + Using the Low Level API + + The low level API is essentially a macroblock decoder engine. It decodes + macroblock by macroblock. When using the low level API, the application + needs to handle the entropy decoding. The low level + API assumes that the information passed from caller is correct, and does not + have any error concealment functionality build in. The application which + called the low level API must make sure that no macroblocks are missing for + any picture. + + The MxDecVC1API low level functions include the following: + - GFMxDecVC1SetPicture() + - GFMxDecVC1SetMBs() + - GFMxDecVC1SetPicture() + +
        +
      • @ref pageMxDecVC1AppNotes +
          +
        • @ref pageMxDecVC1AppNotes1 +
        +
      + */ + /*@{*/ + + // MXDECVC1CapFlags + + /** MxDecVC1API property flag: Simple profile supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_SIMPLE 0x00000001 + + /** MxDecVC1API property flag: Main profile supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_MAIN 0x00000002 + + /** MxDecVC1API property flag: Extended profile supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_ADVANCE 0x00000004 + + /** MxDecVC1API property flag: Low LEVEL supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LOWLEVEL 0x00000008 + + /** MxDecVC1API property flag: Medium LEVEL supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_MEDIUMLEVEL 0x00000010 + + /** MxDecVC1API property flag: High LEVEL supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_HIGHLEVEL 0x00000100 + + /** MxDecVC1API property flag: LEVEL 0 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL0 0x00000200 + + /** MxDecVC1API property flag: LEVEL 1 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL1 0x00000400 + + /** MxDecVC1API property flag: LEVEL 2 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL2 0x00000800 + + /** MxDecVC1API property flag: LEVEL 3 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL3 0x00001000 + + /** MxDecVC1API property flag: LEVEL 4 supported. + @see GFMxDecVC1GetProperty(), GFPROPERTY::Capability + */ +#define GF_MXDEC_VC1_CAP_LEVEL4 0x00002000 + + + /**Enable the DSP side profiling */ +//#define GF_ENABLE_PROFILER 1 + +// to divert the code for checking the non-working of hw modules as of now +#define USE_HW_MODULES + + /** Parameter structure for MxDecVC1DecSequenceLayer(). + Both input and output parameters are passed via this structure to MxDecVC1DecSequenceLayer(). + @see MxDecVC1DecSequenceLayer() + */ + + + typedef struct _GFMXDECVC1DECSEQUENCELAYER + { + + NvU32 uiSequenceOption; /**< Input flags, see GFMXDECVC1_DECSEQUENCEOPTION_* */ + NvU8 ucSequenceLayerInfo; /**< SequenceLayerInfo Definition */ + NvU16 usWidth; /**< Horizontal size of the coded picture in pixels */ + NvU16 usHeight; /**< Vertical size of the coded picture in pixels */ + NvU8 ucProfile; /**< Profile of the sequence */ + NvU8 ucLevel; /**< Level of the sequence */ + NvU32 uiHRDRate; /**< Peak transmission rate R in bits per second */ + NvU32 uiHRDBufferSize; /**< Buffer size B in milliseconds. */ + NvU32 uiFrameRate; /**< Rounding frame rate of the encoded clips */ + NvU8* pPreFillBuffer; /**< Input, Pointer bitstream for sequence header to decode */ + NvU32 PreFillBufferLength; /**< Input, Length of bitstream in bytes, must cover the entire sequence header */ + NvU32 PreFillBufferBytesConsumed;/**< Output, Amount of bytes consumed by the component */ + + } GFMXDECVC1DECSEQUENCELAYER, *PGFMXDECVC1DECSEQUENCELAYER; + + //SequenceLayerInfo: +#define MXDEC_VC1_CONSTANT_BITRATE 0x00000001 /**< Flag is set when the sequence is encoded at constant bitrate */ +#define MXDEC_VC1_MULTIRESOLUTION 0x00000002 /**< Flag indicating that the frames can be coded at smaller */ + //resolution. Resolution change is allowed only on I pictures. + //Information of the picture + + /** GFMXDECVC1DECSEQUENCELAYER::uiSequenceOption input flagbit: Bitstream is passed with GFMxDecVC1DecSequenceLayer(). + If this flag is set bitstream data is passed with the call to GFMxDecVC1DecSequenceLayer() + instead via the read bitstrem callback. This can be used only with boundary detection + on application level. The bitstream data is passed via GFMXDECVC1DECSEQUENCELAYER::pPreFillBuffer and + GFMXDECVC1DECSEQUENCELAYER::PreFillBufferLength. + */ +#define GFMXDECVC1_DECSEQUENCEOPTION_PREFILLBUFFER 0x00000001 + + + /** Parameter structure for MxDecVC1DecPicture(). + Both input and output parameters are passed via this structure to MxDecVC1DecPicture(). + @see MxDecVC1DecPicture() + */ + typedef struct _GFMXDECVC1DECPICTURE + { + /**< the following fields are set by app */ + NvU32 uiPictureOption; /**< Set by application. Set to 0 for this version.*/ + PGFRMSURFACE pRef; /**< Reference Picture Surface */ + PGFRMSURFACE pCur; /**< Current Picture Surface */ + PGFRECT pRefRect; /**< pRefSurfRect specified a rectangular area within + the pRef surface, and GFMxDecVC1 references the + image in the pRefSurfRect area of the pRef surface. + If pRefSurfRect is NULL, entire pRef surface is referred.*/ + + PGFRECT pCurRect; /**pCurSurfRect specified a rectangular area within + the pCur surface, and GFMxDecVC1 references the + image in the pCurSurfRect area of the pCur surface. + If CurSurfRect is NULL, entire pCur surface is referred. + */ + + /**< the following fields are set by MxDecVC1DecPicture API */ + NvU32 uiPictureInfo; /**< Current Picture Information. */ + + NvU8* pPreFillBuffer; /**< Input, Pointer bitstream for frame to decode */ + NvU32 PreFillBufferLength; /**< Input, Length of bitstream in bytes, must cover the entire frame */ + NvU32 PreFillBufferBytesConsumed; /**< Output, Amount of bytes consumed by the component */ + + NvU32 uiTimeStamp; /**< Value Specified in Picture Layer Header.*/ + NvU8 * pMBInfo; /**< each element tells the particular MB is wrong or not.*/ + +#ifdef GF_ENABLE_PROFILER + + NvU32 DSPTimers[10]; +#endif + + } GFMXDECVC1DECPICTURE, *PGFMXDECVC1DECPICTURE; + + //PictureInfo: +#define MXDEC_VC1_DEC_PICTURE_P 0x00000001 //Flag is set when current Picture is P type +#define MXDEC_VC1_DEC_NOT_CODED 0x00000010 //Flag is set when current picture is not coded. + +//uiPictureOption + +/** GFMXDECVC1DECPICTURE::uiPictureOption input flagbit: Use target rectangle. + If this flag is set, the GFMXDECVC1DECPICTURE::pPictureRect will point to + a rectangle on the output surface, where the reconstructed frame is placed. +*/ +#define GF_MXDEC_VC1_DEC_PICTURE_SPECIFY_SURF_RECT 0x00000001 + +/** GFMXDECVC1DECPICTURE::uiPictureOption input flagbit: Bitstream is passed with MxDecVC1DecPicture(). + If this flag is set bitstream data is passed with the call to MxDecVC1DecPicture() + instead via the read bitstrem callback. This can be used only with frame boundary detection + on application level. The bitstream data is passed via GFMXDECVC1DECPICTURE::pPreFillBuffer and + GFMXDECVC1DECPICTURE::PreFillBufferLength. +*/ +#define GF_MXDEC_VC1_DEC_PICTURE_SPECIFY_PREFILLBUFFER 0x00000002 + +/** GFMXDECVC1DECPICTURE::uiPictureOption input flagbit: If This Flag is Set Reading of + .rcv wrapper will be skipped for each picture. +*/ +#define GF_MXDEC_VC1_DEC_PICTURE_SPECIFY_SKIP_RCV_WRAPPER 0x00000004 + + /**Low level API Picture structure + */ + typedef struct _GFMXDECVC1PICTURE + { + NvU32 PictureInfo; /**< Current Picture Information defined in + //GFMXDECVC1PICTURE Definitions */ + PGFRMSURFACE pRef; /**< Reference Picture Surface */ + PGFRMSURFACE pCur; /**< Current Picture Surface */ + PGFRECT pRefRect; /**< pRefSurfRect specified a rectangular area + within the pRef surface, and GFMxDecVC1 + references the image in the pRefSurfRect + area of the pRef surface. If pRefSurfRect is NULL, + entire pRef surface is referred. */ + PGFRECT pCurRect; /**< pCurSurfRect specified a rectangular area + within the pCur surface, and GFMxDecVC1 + references the image in the pCurSurfRect + area of the pRef surface. If pCurSurfRect is NULL, + entire pCur surface is referred. */ + + } GFMXDECVC1PICTURE, *PGFMXDECVC1PICTURE; + //PictureInfo: +#define MXDEC_VC1_PICTURE_P_PICTURE 0x00000001 + //Indicates a P Picture when set otherwise a I Picture +#define MXDEC_VC1_PICTURE_SPECIFY_REFSURF_RECT 0x00000002 + //If this Flag is set, pRefSurfRect must be set, and GFMxDecVC1 + //references the image in the pRefSurfRect area of the pRef surface. + //Otherwise entire pRef surface is referred. +#define MXDEC_VC1_PICTURE_SPECIFY_CURSURF_RECT 0x00000004 + //If this Flag is set, pCurSurfRect must be set, and GFMxDecVC1 outputs + //the decoded image in the pCurSurfRect area of the pCur surface. + //Otherwise entire pCur surface is referred. +#define MXDEC_VC1_PICTURE_ROUNDING_ONE 0x00000008 + //PICTURE_ROUNDING_TYPE is one + + + /**motion vector information for current macroblock*/ + + typedef struct _GFMXDECVC1VECTOR + { + NvS16 sH_MV_DATA; /**< Horizonal motion vector data. */ + NvS16 sV_MV_DATA; /**< Vertical motion vector data. */ + } GFMXDECVC1VECTOR, *PGFMXDECVC1VECTOR; + + /**coefficient information for macroblock*/ + + typedef struct _GFMXDECVC1COEF + { + NvU8 uiLAST; /**< This last non-zero coefficient in current block */ + NvU8 uiRUN; /**< How many zeroes precede this coefficient */ + NvS16 iLEVEL; /**< This coefficient's level value */ + } GFMXDECVC1COEF, *PGFMXDECVC1COEF; + + /**macroblock information*/ + + typedef struct _GFMXDECVC1MB + { + NvU16 uiX; /**< MB's x position in the picture*/ + NvU16 uiY; /**< MB's y position in the picture*/ + NvU32 uiMBInfo; /**< MacroBlock characteristics*/ + NvU32 uiBlkType[6]; /**< Block characteristics*/ + NvU8 uiBlkCoded[6]; /**< Block characteristics*/ + NvU8 uiBlkNZC[6]; /**< Block characteristics*/ + NvU8 ucFirstCodedBlk; /**< First Coded Block in Macroblock*/ + NvU16 uiQuantiser; /**< current MB's quantiser*/ + GFMXDECVC1VECTOR Vector[4]; /**< motion vector zero ~ three*/ + NvU32 uiNumofCoef; /**< number of GFMXDECVC1COEF //structures for current MB*/ + + } GFMXDECVC1MB, *PGFMXDECVC1MB; + + //MBInfo: +#define MXDEC_VC1_MB_TYPE_INTER 0x1 //inter mb + + /*Quantiser Type of MacroBlock */ +#define MXDEC_VC1_MB_NON_UNIFORM_QUANTISER 0x2 //Non Uniform Quantiser + + +#define MXDEC_VC1_MB_AC_PRED_ON 0x80 //AC prediction is on +#define MXDEC_VC1_MB_FIELDTX 0x100 +#define MXDEC_VC1_MB_MV_1_MVS 0x200 //1 motion vector coded +#define MXDEC_VC1_MB_MV_4_MVS 0x400 //4 motion vector coded +#define MXDEC_VC1_MB_SKIPPED 0x800 //Macro Block not coded + + /* Motion vector direction bits [15:14] */ +#define MXDEC_VC1_MB_DIRECT 0x1000 +#define MXDEC_VC1_MB_FORWARD 0x2000 +#define MXDEC_VC1_MB_BACKWARD 0x4000 + +#define MXDEC_VC1_MB_AUTO_DISPLAY 0x8000 +#define MXDEC_VC1_MB_OVERLAP 0x10000 + + +#define MXDEC_VC1_MB_MV_MODE1MV_HALF_PEL_BILINEAR 0x20000 +#define MXDEC_VC1_MB_MV_MODE1MV_HALF_PEL 0x40000 +#define MXDEC_VC1_MB_MV_MODE_MIXED_MV 0x100000 +#define MXDEC_VC1_MB_MV_MODE_INTENSITY_COMP 0x200000 + +#define MXDEC_VC1_MB_MV_RANGE_64_32 0x400000 +#define MXDEC_VC1_MB_MV_RANGE_128_64 0x800000 +#define MXDEC_VC1_MB_MV_RANGE_512_128 0x1000000 +#define MXDEC_VC1_MB_MV_RANGE_1024_256 0x2000000 + + + //uiBlkInfo +#define MXDEC_VC1_BLK_CODED 0x1 + + +#define MXDEC_VC1_BLK_INTER 0x2 +#define MXDEC_VC1_BLK_INTER8X8 0x4 +#define MXDEC_VC1_BLK_INTER8X4 0x8 +#define MXDEC_VC1_BLK_INTER4X8 0x10 +#define MXDEC_VC1_BLK_INTER4X4 0x20 +#define MXDEC_VC1_BLK_INTER_ANY 0x40 + +#define MXDEC_VC1_BLK_INTRA 0x80 +#define MXDEC_VC1_BLK_INTRA_TOP 0x100 +#define MXDEC_VC1_BLK_INTRA_LEFT 0x200 + + +#define MXDEC_VC1_SUBBLK_0 0x1 +#define MXDEC_VC1_SUBBLK_1 0x2 +#define MXDEC_VC1_SUBBLK_2 0x4 +#define MXDEC_VC1_SUBBLK_3 0x8 + + + + //After GFMX decodes this Macro Block, it will auto trigger video engine to display + //this VOP if decoder application set auto blt on through GFVxBlt. + //If MXDEC_MB_AUTO_PP and MXDEC_MA_AUTO_DISPLAY both on, //GFMX will trigger Post Processing first, then trigger display engine. + + + // definition for attribute + + /** GFMxDecVC1 Attribute: Application will determine the decoding boundary, this boundary + means sequence and picture layer boundary. + Interpretation of block referenced by \a pInfo parameter: +
      +    NvU32 1: APP will determine the decoding boudary
      +    0: APP will not determine the decoding boundary
      +    
      + + @see GFMxDecVC1GetAttribute(), GFMxDecVC1SetAttribute() + */ +#define GF_MXDEC_VC1_ATTR_PRE_DETERMINED_BOUNDARY 0x00000001 + + /** GFMxDecVC1 Attribute: This attribute only can be used for GFMxDecGetAttribute + If application wants to set pDestRect in GFMXDECPICTURE or GFMXDECVC1DECPICTURE, + application must use this attributes to get allignment information and + align the rectangle top & left corner accordinately. + *pInfo: top fieled alignment in term of lines + */ +#define GF_MXDEC_VC1_ATTR_DEC_PICTURE_RECT_TOP_ALIGNMENT 0x00000010 + + /** GFMxDecVC1 Attribute: This attribute only can be used for GFMxDecVC1GetAttribute + If application wants to set pDestRect in GFMXDECVC1PICTURE or GFMXDECVC1DECPICTURE, + application must use those attributes to get allignment information and + align the rectangle top & left corner accordinately. + *pInfo: left fieled alignment in term of pixels + */ +#define GF_MXDEC_VC1_ATTR_DEC_PICTURE_RECT_LEFT_ALIGNMENT 0x00000011 + + /** GFMxDecVC1 Attribute: Save decoder internal state information. This attribute only can be used for GFMxDecVC1GetAttribute + *pInfo: state handle + */ +#define GF_MXDEC_VC1_ATTR_DEC_SAVE_STATE 0x00000012 + + /** GFMxDecVC1 Attribute: Restore decoder internal state information. This attribute only can be used for GFMxDecVC1SetAttribute + *pInfo: state handle + */ +#define GF_MXDEC_VC1_ATTR_DEC_RESTORE_STATE 0x00000013 + + /** GFMxDecVC1 Attribute: Delete particular state handle. This attribute only can be used for GFMxDecVC1SetAttribute + *pInfo: state handle + */ +#define GF_MXDEC_VC1_ATTR_DEC_DELETE_STATE 0x00000014 + +#define GF_MXDEC_VC1_ATTR_DEC_ENABLE_RAISE_WAIT 0x00000015 + //Use this attribute to enable RaiseWait mechanish. This is required for OpenMax application. + //Decoder works in FRAME_DONE polling mode by default.This attribute only can be used for GFMxDecVC1SetAttribute + //*pInfo: state handle. + + typedef struct _GFMXDECVC1PP + { + PGFRMSURFACE* pDestSurf;/**< pointer to an array of surfaces that will + hold the result from Post Processing + pointer to an array of surfaces to + accommodate auto post processing + */ + PGFRMSURFACE* pSrcSurf; /**< pointer to an array of surfaces to be //post processed + pointer to an array of surfaces to + accommodate auto post processing + */ + PGFRECT pRect; /**< Rectangle area to be processed for both + src and dest surface + */ + NvU32 numofDestSurf; /**< If MXDEC_PP_AUTO flag is set, this + parameter must be filled + */ + NvU32 numofSrcSurf; /**< If MXDEC_PP_AUTO flag is set, this + parameter must be filled + */ + NvU8 * lpQuantiser; /**< point to array of QPs for Macro Blocks in + the source VOP. GFMX automatically saved + the last two decoded VOP's QP tables, + Decoder application may not need to reload + the table if it can make sure the source + VOP is the one within the last decoded + VOPs. If MXDEC_PP_RELOAD_QUANTIZER is set, + this field must be filled. + */ + NvU32 PPOption; /** + + +
      Performing color space conversion and then a stretch blit to the primary surface directly.Blitting to the overlay surface.
      GF_MXDEC_VC1_READ_BITSTREAM_FORWARD Forward scan
      GF_MXDEC_VC1_READ_BITSTREAM_BACKWARDBackward scan
      + + @return If the #MXDEC_ATTR_PRE_DETERMINED_BOUNDARY attribute is set, the callback + should return #GF_MXDEC_VC1_BOUNDARY_REACHED when a frame boundary is + detected, or 0 if no boundary is detected. + If the #MXDEC_ATTR_PRE_DETERMINED_BOUNDARY attribute is not set, the callback + should return 0. + */ + + /**pPara is a parameter passed from APP, + and APP wants API to call back with this parameter */ + + NvU32 (*pCallBack)(void * pPara, NvU8 ** ppBuffer, NvS32 * BufferLength, NvU32 uFlag); + /** If APP set GF_MXDEC_ATTR_PRE_DETERMINED_BOUNDARY, + APP should return GF_MXDEC_VC1_BOUNDARY_REACHED when the boundary is + detected. + If APP does not set GF_MXDEC_ATTR_PRE_DETERMINED_BOUNDARY, + 0 should be returned. */ + + }GFMXDECVC1CALLBACK, *PGFMXDECVC1CALLBACK; + + /** GFMXDECVC1CALLBACK::pCallBack return code */ +#define GF_MXDEC_VC1_BOUNDARY_REACHED 0x00000001 + /** GFMXDECVC1CALLBACK::pCallBack uFlag value: Stream forward scan. */ +#define GF_MXDEC_VC1_READ_BITSTREAM_FORWARD 0x00000002 + /** GFMXDECVC1CALLBACK::pCallBack uFlag value: Stream backward scan. */ +#define GF_MXDEC_VC1_READ_BITSTREAM_BACKWARD 0x00000003 + + + + typedef enum + { + GFMX_DEC_VC1_INTERRUPT_ENABLE, + GFMX_DEC_VC1_INTERRUPT_DISABLE, + GFMX_DEC_VC1_INTERRUPT_CLEAR + } GFMX_DEC_VC1_INTERRUPT_OPERATION_TYPE; // Interrupt operation. + + typedef enum + { + GFMX_DEC_VC1_DECODE_DONE_INTR, + GFMX_DEC_VC1_POST_PROCESSING_DONE_INTR, + GFMX_DEC_VC1_DSP_COMMAND_INTR, + } GFMX_DEC_VC1_INTERRUPT_TYPE; + + typedef struct _GFMXDECVC1TABLE + { + GF_RETTYPE (* MxDecVC1GetProperty)(GFMxDecVC1Handle hMxDecVC1, PGFPROPERTY pMXProp ); + GF_RETTYPE (* MxDecVC1GetStatus)(GFMxDecVC1Handle hMxDecVC1, NvU32 * pStatus); + GF_RETTYPE (* MxDecVC1DecSequenceLayer)(GFMxDecVC1Handle hMxDecVC1, PGFMXDECVC1DECSEQUENCELAYER pSequenceLayer); + GF_RETTYPE (* MxDecVC1DecPicture)(GFMxDecVC1Handle hMxDecVC1, PGFMXDECVC1DECPICTURE pPicture); + GF_RETTYPE (* MxDecVC1SetPicture)(GFMxDecVC1Handle hMxDecVC1, PGFMXDECVC1PICTURE pPicture); + GF_RETTYPE (* MxDecVC1SetMBs)(GFMxDecVC1Handle hMxDecVC1, PGFMXDECVC1MB pMBs); + GF_RETTYPE (* MxDecVC1SetAttribute)(GFMxDecVC1Handle hMxDecVC1, NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* MxDecVC1GetAttribute)(GFMxDecVC1Handle hMxDecVC1, NvU32 uiFeature, NvU32* pInfo); + GF_RETTYPE (* MxDecVC1Set)(GFMxDecVC1Handle hMxDecVC1, NvU32 uiFeature, void * pInfo); + GF_RETTYPE (* MxDecVC1InterruptControl)(GFMxDecVC1Handle hMxDecVC1, + GFMX_DEC_VC1_INTERRUPT_TYPE IntType, GFMX_DEC_VC1_INTERRUPT_OPERATION_TYPE op, + void * pData); + GF_RETTYPE (* MxDecVC1InterruptHandler)(GFMxDecVC1Handle hMxDecVC1, + GFMX_DEC_VC1_INTERRUPT_TYPE IntType, void * pData); // Reserved. + GF_RETTYPE (* MxDecVC1DecResync)(GFMxDecVC1Handle hMxDecVC1, NvU32 ResyncOption); + } GFMXDECVC1TABLE, *PGFMXDECVC1TABLE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFMxDecVC1Open(GFRmHandle hRm, GFMxDecVC1Handle *phMxDecVC1, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMxDecVC1Close(GFMxDecVC1Handle *phMxDecVC1); + +#if NVCPU_IS_XTENSA +#define MXDVC1OFFSET sizeof(GFMXDECVC1TABLE) +#else +#define MXDVC1OFFSET 0 +#endif + + /** #### MxDecVC1 Helper macros. Maybe useful for backward compatible API. #### + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxDecVC1API functions. + + @see GFPROPERTY + */ + +#define GFMxDecVC1GetProperty(hMxDecVC1, pMXProp) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1GetProperty(hMxDecVC1, pMXProp) + +#define GFMxDecVC1GetStatus(hMxDecVC1, pStatus) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1GetStatus(hMxDecVC1, pStatus) + + /** Decode sequence header. + + @param hMxDecVC1 (GFMxDecVC1Handle) Handle to MxDecVC1 component + @param pSequence (PGFMXDECVC1DECSEQUENCELAYER) Pointer to #GFMXDECVC1DECSEQUENCELAYER parameter structure + + @retval GF_SUCCESS Sequence header was decoded successfully + + This function will be called whenever a sequence header is found in the bitstream, decode + it and return its characteristics. + + @see GFMXDECVC1DECSEQUENCELAYER + */ +#define GFMxDecVC1DecSequenceLayer(hMxDecVC1, pSequenceLayer)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1DecSequenceLayer(hMxDecVC1, pSequenceLayer) + + + //return value + /** GFMxDecVC1 error code: GFMxDecVC1DecSequenceLayer() encountered end of bitstream. + @see GFMxDecVC1DecSequenceLayer() + */ +#define GFMXDECVC1_SEQUENCELAYER_ERROR_END_OF_FILE (GFMXDVC1_ERROR | 0x00000001) + + /** GFMxDecVC1 error code: GFMxDecVC1DecSequenceLayer() bitstream format not supported. + The sequence header specifies a bitstream format, that is not supported. Most likely + reason for this error is that the VC1 profile is not supported. + @see GFMxDecVC1DecSequenceLayer() + */ +#define GFMXDECVC1_SEQUENCELAYER_ERROR_NOT_SUPPORT_FORMAT (GFMXDVC1_ERROR | 0x00000002) + + /** GFMxDecVC1 error code: GFMxDecVC1DecSequenceLayer() bitstream format is damaged due to + erroroneous stream. + @see GFMxDecVC1DecSequenceLayer() + */ +#define GFMXDECVC1_SEQUENCELAYER_ERROR_HEADER_DAMAGED (GFMXDVC1_ERROR | 0x00000003) + + /** GFMxDecVC1 error code: GFMxDecVC1DecSequenceLayer() encountered out of GPU memory error. + The application can try to free GPU memory and call GFMxDecVC1DecSequenceLayer() again. + @see GFMxDecVC1DecSequenceLayer() + */ +#define GFMXDECVC1_SEQUENCELAYER_ERROR_NOT_ENOUGH_SYSTEM_MEM (GFMXDVC1_ERROR | 0x00000004) + + + /** Decode a picture. + + @param GFMxDecVC1 (GFMxDecVC1Handle) Handle to MxDecVC1 component + @param pPicture (PGFMXDECVC1DECPICTURE) Pointer to #GFMXDECVC1DECPICTURE parameter structure + + @retval GF_SUCCESS Frame was decoded successfully + @retval GFMXDECVC1_PICTURE_ERROR_END_OF_FILE End of stream encountered + @retval GFMXDECVC1_PICTURE_ERROR_CORRUPTED_PICTURE Unrecoverable bitstream error during frame decode + @retval GFMXDECVC1_PICTURE_ERROR_NOT_ENOUGH_SYSTEM_MEM Out of GPU memory + @retval GFMXDECVC1_ERROR_RESYNC_END_OF_FILE Resync was found at end of bitstream. + @retval GFMXDECVC1_ERROR_P_PICTURE_FOUND_AT_START instead of Inter frame, intra was found in beginning. + @retval GFMXDECVC1_ERROR_DSP_TIMEOUT AVP times out + + GFMxDecVC1DecPicture decodes one picture from the bit stream. If GFMxDecVC1DecPicture detects an + error, GFMxDecVC1DecPicture returns the error back to the application. + If the current stream position is not on the start of a frame, the function scans forward until a frame + start or sequence header is detected. + + @see GFMXDECVC1DECPICTURE + */ +#define GFMxDecVC1DecPicture(hMxDecVC1, pPicture)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1DecPicture(hMxDecVC1, pPicture) + + //return value + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() encountered end of bitstream. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_PICTURE_ERROR_END_OF_FILE (GFMXDVC1_ERROR | 0x00000005) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() encountered an unrecoverable bitstream error. + The application should call GFMxDecVC1DecResync() again, MxDecVC1 will then + scan for the next frame boundary and try to decode this frame. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_PICTURE_ERROR_CORRUPTED_PICTURE (GFMXDVC1_ERROR | 0x00000006) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() encountered out of GPU memory error. + System memory is not enough to decode Picture. The application can try to free GPU memory and call + GFMxDecVC1DecPicture() again. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_PICTURE_ERROR_NOT_ENOUGH_SYSTEM_MEM (GFMXDVC1_ERROR | 0x00000007) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() upon calling GFMxDecVC1DecResync() + encountered end of bitstream. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_ERROR_RESYNC_END_OF_FILE (GFMXDVC1_ERROR | 0x00000008) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() got a + "P" frame without it's prior reference frame + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_ERROR_P_PICTURE_FOUND_AT_START (GFMXDVC1_ERROR | 0x00000009) + + /** GFMxDecVC1 error code: GFMxDecVC1DecPicture() DSP times out while decoding. + @see GFMxDecVC1DecPicture() + */ +#define GFMXDECVC1_ERROR_DSP_TIMEOUT (GFMXDVC1_ERROR | 0x0000000a) // dsp hang workaround :( + +#define GFMxDecVC1SetPicture(hMxDecVC1, pPicture)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1SetPicture(hMxDecVC1, pPicture) + +#define GFMxDecVC1SetMBs(hMxDecVC1, pMBs) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1SetMBs(hMxDecVC1, pMBs); + +#define GFMxDecVC1SetAttribute(hMxDecVC1, uiFeature, pInfo) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1SetAttribute(hMxDecVC1, uiFeature, pInfo) + +#define GFMxDecVC1GetAttribute(hMxDecVC1, uiFeature, pInfo) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1GetAttribute(hMxDecVC1, uiFeature, pInfo) + +#define GFMxDecVC1Set(hMxDecVC1, uiFeature, pInfo) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1Set(hMxDecVC1, uiFeature, pInfo) + +#define GFMxDecVC1DecResync(hMxDecVC1, ResyncOption) \ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1DecResync(hMxDecVC1, ResyncOption) + +#define GFMxDecVC1InterruptControl(hMxDecVC1, IntType, op, pData)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1InterruptControl(hMxDecVC1, IntType, op, pData) + +#define GFMxDecVC1InterruptHandler(hMxDecVC1, IntType, pData)\ + ((PGFMXDECVC1TABLE)((NvU32)hMxDecVC1+MXDVC1OFFSET))->MxDecVC1InterruptHandler(hMxDecVC1, IntType, pData) + + + //resynch value +#define MXDEC_VC1_RESYNC_FORWARD_NEXT_PICTURE 0x00000001 + // resync to next picture +#define MXDEC_VC1_RESYNC_FORWARD_NEXT_I_PICTURE 0x00000002 + // resync to next I Picture +#define MXDEC_VC1_RESYNC_BACKWARD_PREVIOUS_PICTURE 0x00000004 + // resync to next picture +#define MXDEC_VC1_RESYNC_BACKWARD_PREVIOUS_I_PICTURE 0x00000008 + // resync to next I Picture + + //return value +#define VC1DECRESYNC_END_OF_FILE 0x00000002 // end of file whie resync + + /*@}*/ + + /** @page pageMxDecVC1AppNotes MxDecVC1API Application Notes + + @section pageMxDecVC1AppNotes1 Programming Sequence + + Todo + */ + + +#ifdef __cplusplus +} // only need to export C interface if +// used by C++ source code +#endif + +#endif + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDemTS.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDemTS.h new file mode 100755 index 00000000..3dbca68e --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxDemTS.h @@ -0,0 +1,725 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFMxDemTS.h + GFSDK MPEG2 Transport Stream API (host) header file. +*/ + +#ifndef _GF_MPEG_TS__ +#define _GF_MPEG_TS__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @addtogroup groupMxDemTS MxDemTSAPI MPEG2 Transport Stream Demux API + + This GFSDK component allows to create MPEG TS demux parsers either running + on the host or DSP side. TS data can be pushed from the application, + or be streamed from VIP. + + The are multiple types of parser objects, see also GFMXDEMTSPARSERTYPE: +
      +    GFMXDEMTSPARSERTYPE_HOST      - demux running on host
      +    GFMXDEMTSPARSERTYPE_DSP       - demux running on DSP  
      +    GFMXDEMTSPARSERTYPE_DSPAVSYNC - demux running on DSP with additional AVSync functionality
      +    
      + + Programming Sequence for Parsers running on Host, TS data from host + + - Call GFMxDemTSParserCreate(), in parameter structure GFMXDEMTSPARSERREQUEST pass + parameters #GFMXDEMTSPARSERTYPE_HOST and #GFMXDEMTSPARSERDATASOURCE_PUSH, + pass callback functions to handle demuxed substreams + - Poll GFMxDemTSParserPushData() to pass the incoming TS stream + - Call GFMxDemTSParserDestroy() to destroy parser object + + Programming Sequence for Parsers running on DSP, TS data from host + + - Call GFMxDemTSParserCreate(), in parameter structure GFMXDEMTSPARSERREQUEST pass + parameters #GFMXDEMTSPARSERTYPE_DSP and #GFMXDEMTSPARSERDATASOURCE_PUSH, + pass callback functions to handle demuxed substreams + - Poll GFMxDemTSParserPushData() to pass the incoming TS stream + - Call GFMxDemTSParserDestroy() to destroy parser object + - Destroy the DSP message handling thread + + Programming Sequence for Parser running on DSP, TS data from VIP + + Only one parser at a time can be created to capture data from VIP. + For this mode the parser must run on DSP. +*/ +/*@{*/ + +/** GFMxDemTSParser Maximum number of supported Services. + For ISDB-T 1seg, the max is 8 according to ARIB TR-B14, p7-28 +*/ +#define GFMXDEMTS_MAX_SERVICE_NO 8 + +/** GFMxDemTSParser Maximum number of supported Audio PES. + For ISDB-T 1seg, the max is 2. +*/ +#define GFMXDEMTS_MAX_AUDIO_PID_NO 2 + +/** Get TS Audio PID. + For detail see #GFMXDEMTSPARSERAUDIOPIDLIST. + @param audio (NvU32) Combined type and ID value + */ +#define GFMXDEMTS_GET_AUDIO_PID(audio) (audio & 0x1FFFU) // Get the lower 13 bits + +/** Get TS Service Type. + For detail see #GFMXDEMTSPARSERAUDIOPIDLIST. + @param service (NvU32) Combined type and ID value +*/ +#define GFMXDEMTS_GET_AUDIO_TYPE(audio) (audio >> 16) + +/** TS Audio Pid List. */ +typedef struct _GFMXDEMTSPARSERAUDIOPIDLIST +{ + NvU32 uAudioPidList[GFMXDEMTS_MAX_AUDIO_PID_NO]; //!< low 16 bits Audio PID, high 16 bits Audio Type + NvU32 uNoOfAudioPids; //!< Number valid entries in uAudioPidList[] + +} GFMXDEMTSPARSERAUDIOPIDLIST; + +/** Get TS Service ID. + For detail see #GFMXDEMTSPARSERPMTPIDLIST. + @param service (NvU32) Combined type and ID value +*/ +#define GFMXDEMTS_GET_PMT_PID(service) ((((NvU32)(service) & 0xffff00) >> 8) | 0x1FC8) + +/** Get TS Service Type. + For detail see #GFMXDEMTSPARSERPMTPIDLIST. + @param service (NvU32) Combined type and ID value +*/ +#define GFMXDEMTS_GET_PMT_PID_TYPE(service) ((NvU32)(service) & 0x0000ff) + +/** TS Service List. + */ +typedef struct _GFMXDEMTSPARSERPMTPIDLIST +{ + /** Array of services: + Array entries format: +
      +        32      24 23                           8 7               0
      +        +---------+------------------------------+----------------+
      +        | Invalid |             Service ID       |Service Type    |
      +        +---------+------------------------------+----------------+
      +        
      + */ + NvU32 uPmtPidList[GFMXDEMTS_MAX_SERVICE_NO]; + + /** Number of valid entries in GFMXDEMTSPARSERPMTPIDLIST::uPmtPidList[]. */ + NvU32 uNoOfServices; + +} GFMXDEMTSPARSERPMTPIDLIST; + + +/** TS parser types, parameter values for GFMXDEMTSPARSEREQUEST. */ +typedef enum +{ + /** Parser running on host system. + + Parser objects of this type run the TS demux on the host system. + In contrast to GFMXDEMTSPARSERTYPE_DSP no hardware resources are involved, + and any number of parser objects of this type can be created. + + TS data source is always of type GFMXDEMTSPARSERDATASOURCE_PUSH, i.e. + it is provided by the application via GFMxDemTSParserProcessData(). + */ + GFMXDEMTSPARSERTYPE_HOST = 0, + + /** Parser running on DSP. + + Parser objects of this type will instanciate a task on the DSP + to perform the demux processing. Demuxed data is returned to the host. + Demuxed audio data can optionally be processed entirely on DSP side + via GFMXDEMTSPARSERREQUEST::pAudioBufDesc. + + This parser type is intended for verifying demux functionality. + + TS data can be provided either from the host (GFMXDEMTSPARSERDATASOURCE_PUSH), + or acquired automatically from VIP (GFMXDEMTSPARSERDATASOURCE_VIP2DSP). + */ + GFMXDEMTSPARSERTYPE_DSP, + + /** Parser running on DSP with attached AVSync object. + + Parser objects of this type will instanciate 2 tasks on the DSP, + one to perform the demux processing, and one to decode AV-synced H264 video. + Audio is processed on DSP side via GFMXDEMTSPARSERREQUEST::pAudioBufDesc. + + TS data can be provided either from the host (GFMXDEMTSPARSERDATASOURCE_PUSH), + or acquired automatically from VIP (GFMXDEMTSPARSERDATASOURCE_VIP2DSP). + */ + GFMXDEMTSPARSERTYPE_DSPAVSYNC + +} GFMXDEMTSPARSERTYPE; + +/** TS data sources, parameter values for GFMXDEMTSPARSEREQUEST. */ +typedef enum +{ + /** TS data is pushed by the application. + + TS data is fed from the application via function calls to + GFMxDemTSParserProcessData(). + */ + GFMXDEMTSPARSERDATASOURCE_PUSH = 0, + + /** TS data is intercepted by the DSP task directly from VIP. + + The TS parser task running on the DSP will open the VIP in Type-A + interface mode to receive TS data via an interrupt handler. + + This setting can be used only for parsers running on the DSP + (#GFMXDEMTSPARSERTYPE is GFMXDEMTSPARSERTYPE_DSP). + */ + GFMXDEMTSPARSERDATASOURCE_VIP2DSP + +} GFMXDEMTSPARSERDATASOURCE; + +/** TS Parser object states. */ +typedef enum +{ + GFMXDEMTSDSPPARSERSTATE_INSTANTIATED=0, //!< Parser object instanciated, but not initialized + GFMXDEMTSDSPPARSERSTATE_READY, //!< Parser object initialized, ready to parse + GFMXDEMTSDSPPARSERSTATE_ERROR, //!< Parser object dead due to unrecoverable error (out of mem, etc) + GFMXDEMTSDSPPARSERSTATE_SHUTDOWN, //!< Parser object initialized, ready to parse, but shutdown initiated + GFMXDEMTSDSPPARSERSTATE_PAUSE //!< Parser object paused + +} GFMXDEMTSPARSERSTATE; + +/** TS Parser demux status bits. */ +typedef enum +{ + GFMXDEMTSPARSERSTATUS_PMT_READY = 0x01, + GFMXDEMTSPARSERSTATUS_NIT_READY = 0x02, + GFMXDEMTSPARSERSTATUS_VIDEO_FOUND = 0x04, + GFMXDEMTSPARSERSTATUS_AUDIO_FOUND = 0x08, + // if the number of status goes beyond 8, please change m_uStatus to 16 bits or 32 bits in #CNvTransportParser + +} GFMXDEMTSPARSERSTATUS; + +/** Parameter structure for GFMxDemTSParserGetStatus(). */ +typedef struct +{ + GFMXDEMTSPARSERSTATE state; //!< Parser object state + NvU32 status; //!< Parser status bitmask, see #GFMXDEMTSPARSERSTATUS + NvU32 frameDropCount; //!< Counts dropped frames in AVSync + +} GFMxDemTSParserStatus; + +/** TS parser notify reasoncodes for GFMXDEMTSPARSERREQUEST::OnNotify callback. */ +typedef enum +{ + /** Incoming TS starved. */ + GFMXDEMTSPARSERNOTIFY_TSSTARVED = 0, + + /** Overflow of TS data coming from VIP. */ + GFMXDEMTSPARSERNOTIFY_TSOVERFLOW, + + /** Underflow in audio buffer at demux output side. */ + GFMXDEMTSPARSERNOTIFY_AUDIOUNDERFLOW, + + /** Overflow in audio buffer at demux output side. */ + GFMXDEMTSPARSERNOTIFY_AUDIOOVERFLOW, + + /** Underflow in video buffer at demux output side. */ + GFMXDEMTSPARSERNOTIFY_VIDEOUNDERFLOW, + + /** Overflow in video buffer at demux output side. */ + GFMXDEMTSPARSERNOTIFY_VIDEOOVERFLOW, + + /** Parser detected PMT change. + Associated data: +
      +        NvU32 new PMT PID
      +        
      = 2*max ADTS frame size. + */ + NvU32 AudioBufferSize; + + /** Size of video demux buffer to claim in GPU memory. + This field is used only for parsers of type GFMXDEMTSPARSERTYPE_DSP and GFMXDEMTSPARSERTYPE_DSPAVSYNC. + Size must be power of 2 and <=2^24 bytes. + Optimum size depends on H264 bitrate, and should big enough to hold multiple NAL units. + */ + NvU32 VideoBufferSize; + + /** DSP-side handle (address to GFMXDECH264TABLE) of initialized GFMxDecH264 instance. + This address is in DSP address space. + + This field is used only for parsers of type GFMXDEMTSPARSERTYPE_DSPAVSYNC. + + @internal + */ + NvU32 MxDecH264DSPHandle; + + /** Video section callback. + Ignored for parser type GFMXDEMTSPARSERTYPE_DSPAVSYNC. + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param pllPTS Pointer to PTS, or NULL if not existent + @param pllDTS Pointer to DTS, or NULL if not existent + */ + GF_RETTYPE (*OnVideoData)(void* user, NvU8* pBytes, NvU32 cbBytes, NvU32 StreamID, NvS64* pllPTS, NvS64* pllDTS, int bPesStart); + + /** Audio section callback, or NULL to use shared DSP buffer. + + Can be NULL for parser type GFMXDEMTSPARSERTYPE_DSP. + Ignored for parser type GFMXDEMTSPARSERTYPE_DSPAVSYNC. + + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param pllPTS Pointer to PTS, or NULL if not existent + @param pllDTS Pointer to DTS, or NULL if not existent + */ + GF_RETTYPE (*OnAudioData)(void* user, NvU8* pBytes, NvU32 cbBytes, NvU32 StreamID, NvS64* pllPTS, NvS64* pllDTS, int bPesStart); + + /** PCR (Program Clock Reference) callback. + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param llPCRBase Clock + @param llPCRExt Clock + @param uDiscontinuity discontinuity flag + */ + void (*OnPCR)(void* user, NvS64 llPCRBase, NvU32 llPCRExt, NvU32 uDiscontinuity); + + /** Parser object error and status notify callback. + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param notifycode Notify reasoncode, see GFMXDEMTSPARSERNOTIFY + @param data Data specific to a notifycode + */ + void (*OnNotify)(void* user, NvU32 notifycode, void* data); + + /** Frame Decoded Callback + Will be called in sync with PTS of the frame. The passed surface will be locked, and the + application must unlock it later via GFMxDecH264Set() with feature ID GF_MXDEC_H264_SET_UNLOCK_SURFACE. + @param user Application defined parameter, forwarded from INvTransportParserCallback::user + @param surfaceID surface id + @param resolution high 16 bit for xres, low 16 bit for yres + @param pPTS Pointer to PTS of this frame + @param flags Flag bitmask, bit 0 set validity of PAN Scan Info + @param PanTopLeft Top-Left Offset for PAN Scan Rect, low 16 bit signed X, top 16 bit signed Y + @param PanBottomRight Bottom-Right Offset for PAN Scan Rect , low 16 bit signed X, top 16 bit signed Y + @param FrameType I/P Frame Type + */ + void (*OnFrameDecoded)(void* user, NvU32 sufaceID, NvU32 resolution, NvS64* pPTS, NvU32 flags, NvU32 PanTopLeft, NvU32 PanBottomRight, NvU32 FrameType); + + /** TS data callback + @param user Application defined parameter, forwarded from GFMXDEMTSPARSERREQUEST::user + @param data TS data + @param size TS data size + */ + void (*OnTS)(void* user, NvU8* data, NvU32 size); + + /** Application private data, will be forwarded to callbacks */ + void* user; + + /** Returns address of circular buffer descriptor shared with audio decoder. + This address is in DSP address space. + This member is valid only, if GFMXDEMTSPARSERREQUEST::OnAudioData is NULL, + and if the parser is of type GFMXDEMTSPARSERTYPE_DSP. + */ + GF_RM_DSP_CIRCBUFFER* pAudioBufDesc; + +} GFMXDEMTSPARSERREQUEST; + +/** H264 Frame Type, the value is equal to Nal Type*/ +typedef enum +{ + MXDEMTS_H264_FRAME_IDR = 5, + MXDEMTS_H264_FRAME_P = 1, + MXDEMTS_H264_FRAME_INVALID = 0, +} MXDEMTS_H264_FRAME_TYPE; + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFMxDemTSOpen(GFRmHandle hRm, GFMxDemTSHandle *phMxDemTS, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFMxDemTSClose(GFMxDemTSHandle *phMxDemTS); + +/** Create a TS parser. + + This function creates a TS parser running on the host. + + @param TsHandle Handle to TS component + @param pParserReq Parameter structure + @param pParserHandle Returns handle on success, unchanged on failure + + @retval GF_SUCCESS Success + @retval GF_ERROR_OUT_MEMORY Out of memory + @retval GFMXDEMTS_ERROR_CREATEDSPPARSER Failed to create parse object on DSP side + @retval GFMXDEMTS_ERROR_NODSPSUPPORT No DSP support in GFSDK +*/ +GF_RETTYPE GFMxDemTSParserCreate(GFMxDemTSHandle TsHandle, GFMXDEMTSPARSERREQUEST* pParserReq, GFMxDemTSParserHandle* pParserHandle); + +/** Destroy TS parser. + + Destroy an TS parser object previously created with GFMxDemTSParserCreate(). + Save to call on NULL handle. + + @param TsHandle Handle to TS component + @param pParserHandle Pointer to parser handle, will be reset to NULL on exit +*/ +void GFMxDemTSParserDestroy(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle* pParserHandle); + +/** Process a section of the TS stream. + + The input Transport Stream is parsed and the section type handlers passed + with GFMXDEMTSPARSERREQUEST are called as their sections are encountered in + the stream. + + A call of this function is usually triggered by an interrupt to feed the next + portion of an incoming Transport Stream. + + On each call of this function at least 188 byte (TS packet size) must be passed. + The Transport Stream is parsed in entities of 188 byte packets. If the passed buffer + contains an incomplete packet at the end, it will be copied to an internal buffer + and automatically combined with the second part on the next function call. + + Thus it is not required to pass in buffers aligned to TS packet starts, and the + buffer must not be a multiple of 188 bytes (TS packet size). However + doing so will guarant maximum demux performance since copying around incomplete packets + can be avoided. + + This function may only be called for parses created with #GFMXDEMTSPARSERDATASOURCE_PUSH. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pData Pointer to buffer containing TS, the buffer must contain + at least 188 bytes of stream data. Buffer start does not + need to be aligned with the start of an TS package. + @param pSize Pointer to buffer size, must be 188 or larger, will be updated + on exit with the number of bytes in the buffer, which where consumed. + If the parser was created on the DSP, this size must + not exceed the buffersize passed in GFMXDEMTSPARSERREQUEST::TSBufferSize. + On success GFMxDemTSParserPushData() will always consume all data, + on failure *pSize returns the number of bytes that were successfully + consumed before the failure occured. + @param timeout Time in ms to wait until DSP parser object gets ready to accept new data, + or 0 to block forever, (NvU32)-1 to return immediately if busy. + Ignored for DSP objects created with #GFMXDEMTSPARSERTYPE_HOST. + + @retval GF_SUCCESS Success + @retval GF_WAIT_TIME_OUT Timeout before data could be sent to DSP + @retval GF_ERROR_BUSY DSP was busy and data was not sent, call again, + returned only if \a timeout was (NvU32)-1 +*/ +GF_RETTYPE GFMxDemTSParserPushData(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU8* pData, NvU32* pSize, NvU32 timeout); + +/** (Re-)Start VIP TS data capture and demux on DSP. + + This function can be used only for parsers created as #GFMXDEMTSPARSERDATASOURCE_VIP2DSP. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success +*/ +GF_RETTYPE GFMxDemTSParserDSPStart(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Pause VIP TS data capture and demux on DSP. + + This function can be used only for parsers created as #GFMXDEMTSPARSERDATASOURCE_VIP2DSP. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param onOff Indicate Pause on or off + + @retval GF_SUCCESS Success +*/ +GF_RETTYPE GFMxDemTSParserDSPPause(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32 onOff); + +/** Step to the next Frame. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success +*/ +GF_RETTYPE GFMxDemTSParserDSPNextFrame(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Step to the next I Frame. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success +*/ +GF_RETTYPE GFMxDemTSParserDSPNextIFrame(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Get TS PmtPid List + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pPmtPidList Returns PMT PID List in current TS, with Service ID and Service Type combined + + @retval GF_SUCCESS Success + @retval GFMXDEMTS_ERROR_SERVICESLISTUNAVAILABLE NIT/PAT has not been parsed yet. + + @see GFMxDemTSSetPmtPid() +*/ +GF_RETTYPE GFMxDemTSParserGetPmtPidList(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, GFMXDEMTSPARSERPMTPIDLIST *pPmtPidList); + +/** Set TS Service + + PMT PID is set without any check. if the new PMT PID is successfully set, a + #GFMXDEMTSPARSERNOTIFY_TSPMTCHANGED notify will be sent to the caller application. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param uPmtPid uPmtPid to be set + + @retval GF_SUCCESS Success * + @see GFMxDemTSGetPmtPidList() + */ +GF_RETTYPE GFMxDemTSParserSetPmtPid(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32 uPmtPid); + +/** Get Active PmtPid + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pServiceID pointer to Active PmtPid. + + @retval GF_SUCCESS Success * + */ +GF_RETTYPE GFMxDemTSParserGetActivePmtPid(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32* pPmtPid); + +/** Get TS AudioPid List + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pAudioPidList Returns AUDIO PID List in current TS, with PID and Type combined + + @retval GF_SUCCESS Success + @retval GFMXDEMTS_ERROR_AUDIOPIDLISTUNAVAILABLE NIT/PAT has not been parsed yet. + + @see GFMxDemTSSetAudioPid() +*/ +GF_RETTYPE GFMxDemTSParserGetAudioPidList(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, GFMXDEMTSPARSERAUDIOPIDLIST *pAudioPidList); + +/** Set TS Audio Pid + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param uAudioPid uAudioPid to be set + + @retval GF_SUCCESS Success + @retval GFMXDEMTS_ERROR_AUDIOPIDUNAVAILABLE + @see GFMxDemTSGetAudioPidList() + */ +GF_RETTYPE GFMxDemTSParserSetAudioPid(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32 uAudioPid); + +/** Get Active AudioPid + + Audio PID is set if this AUDIO PID exists in current streams. Otherwise return an error + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pAudioPid pointer to Active AudioPid. + + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserGetActiveAudioPid(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32* pAudioPid); + +/** Reset All Table Version + + Reset all Table Versions, including PAT, NIT, and PMT. + For reset only PMT table version, see GFMxDemTSParserResetPmtTableVersion + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserResetAllTableVersions(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Reset PMT Table Version + + To reset all table version, see GFMxDemTSParserResetAllTableVersion + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserResetPmtTableVersion(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Set Play Speed + + Just used for normal play, for trick play, see xxx. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param PlaySpeed Play speed to set in 1.0 * 10^6. + A value of 100000 plays at 100% of the current sample rate. 100100 plays at 1.1%, + 100010 plays at 100.01%, the smallest increment 100001 plays at 100.001%. + Number less than 100000 will slow down the stream in the same way. + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserSetPlaySpeed(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, NvU32 PlaySpeed); + +/** Set VIP Capture + + @deprecated Do not use, will be removed from public API + + @param TsHandle Handle to TS component + @param VxHandle the Vx handle for setting VIP + @retval GF_SUCCESS Success * + */ +GF_RETTYPE GFMxDemTSSetVIP(GFMxDemTSHandle TsHandle, GFVxHandle VxHandle); + +/** VIP Capture on Host Side + + @deprecated Do not use, will be removed from public API + + it captures VIP data from host side, instead of DSP side. + For VIP Capture from DSP side, see #GFMXDEMTSPARSERREQUEST (GFMXDEMTSPARSERDATASOURCE_VIP2DSP) + + @param TsHandle Handle to TS component + @param pBuf Buffer to host VIP data + @param pBufSize Maximum buf size for input, and Number bytes captured for output + @retval GF_SUCCESS Success * + */ +GF_RETTYPE GFMxDemTSPollVIP(GFMxDemTSHandle TsHandle, NvU8* pBuf, NvU32 *pBufSize); + +/** Close VIP Capture + + @deprecated Do not use, will be removed from public API + + @param TsHandle Handle to TS component + @param VxHandle the Vx handle for setting VIP + @retval GF_SUCCESS Success * + */ +void GFMxDemTSCloseVIP(GFMxDemTSHandle TsHandle, GFVxHandle VxHandle); + +/** Get demux object state and status. + + Check Parser Status, can be called any time on the parser. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param pStatus Returns parser object state and status. + + + + +
      Bits 0-7 Parser status bitmask, see #GFMXDEMTSPARSERSTATUS
      Bits 8-24 reserved for extension
      Bits 23-31Parser state, see #GFMXDEMTSPARSERSTATE
      + @retval GF_SUCCESS Success + @retval GFRM_ERROR_BAD_PARAMETER Invalid parser handle passed + */ +GF_RETTYPE GFMxDemTSParserGetStatus(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, GFMxDemTSParserStatus* pStatus); + +/** Clear Demux Buffers. + + This will clear demux input TS buffers. For parsers of type + GFMXDEMTSPARSERTYPE_DSPAVSYNC it will also clear ES (video and audio) output buffers. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserClearBuffers(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle); + +/** Enable or disable TS data to be returned from DSP to host. + + If disabled the GFMXDEMTSPARSERREQUEST::OnTS callback won't be called anymore. + This function has effect for parsers with datasource GFMXDEMTSPARSERDATASOURCE_VIP2DSP only. + + @param TsHandle Handle to TS component + @param ParserHandle Parser handle + @param enable 0 to disable, !=0 to enable + @retval GF_SUCCESS Success + */ +GF_RETTYPE GFMxDemTSParserDSPEnableOnTS(GFMxDemTSHandle TsHandle, GFMxDemTSParserHandle ParserHandle, int enable); + +/** GFMxDemTSAPI Error code: Create Parser object on DSP failed. + @see GFMxDemTSParserCreate() +*/ +#define GFMXDEMTS_ERROR_CREATEDSPPARSER (GFMXDEMTS_ERROR + 0) + +/** GFMxDemTSAPI Error code: GFSDK not setup for DSP support. + @see GFMxDemTSParserCreate() +*/ +#define GFMXDEMTS_ERROR_NODSPSUPPORT (GFMXDEMTS_ERROR + 1) + +/** GFMxDemTSAPI Error code: GFMxDemTSGetPmtPidList() called when NIT/PAT not parsed yet. + @see GFMxDemTSGetPmtPidList() +*/ +#define GFMXDEMTS_ERROR_SERVICESLISTUNAVAILABLE (GFMXDEMTS_ERROR + 2) + +/** GFMxDemTSAPI Error code: GFMxDemTSSetPmtPid() when a wrong PMT PID is passed. + @see GFMxDemTSSetPmtPid() +*/ +#define GFMXDEMTS_ERROR_SERVICEUNAVAILABLE (GFMXDEMTS_ERROR + 3) + +/** GFMxDemTSAPI Error code: GFMxDemTSGetAudioPidList() called when PMT does not parsed yet, or + there is no Audio in current service. + @see GFMxDemTSGetAudioPidList() +*/ +#define GFMXDEMTS_ERROR_AUDIOPIDLISTUNAVAILABLE (GFMXDEMTS_ERROR + 4) + +/** GFMxDemTSAPI Error code: GFMxDemTSSetAudioPid() when a wrong Audio PID is passed. + @see GFMxDemTSSetAudioPid() +*/ +#define GFMXDEMTS_ERROR_AUDIOPIDUNAVAILABLE (GFMXDEMTS_ERROR + 5) + +/** GFMxDemTSAPI Error code: Signal frame decoded. + @internal +*/ +#define GFMXDEMTS_ERROR_AVSYNCFRAMEDECODED (GFMXDEMTS_ERROR + 6) + +/** GFMxDemTSAPI Error code: Cannot claim VIP. + @see GFMxDemTSParserCreate() +*/ +#define GFMXDEMTS_ERROR_VIPUNAVAILABLE (GFMXDEMTS_ERROR + 7) + +/** GFMxDemTSAPI Error code: GFMxDemTSParserGetActivePmtPid() called when there is pending PMT PID to be set. + @see GFMxDemTSParserGetActivePmtPid() +*/ +#define GFMXDEMTS_ERROR_GETSERVICEPMTPID (GFMXDEMTS_ERROR + 8) + +/** GFMxDemTSAPI Semaphore IDs. + These IDs can be used in the RmCreateSemaphore implementation of the + OS porting layer to identify GFMxDemTSAPI semaphores. +*/ +typedef enum +{ + GFMXDEMTS_SEMAPHORE_TSBUF = GF_MXDEMTSAPI<<24 + +} GFMXDEMTS_SEMAPHORE; + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _GF_MPEG_TS__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxEnc.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxEnc.h new file mode 100755 index 00000000..74d4bee7 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxEnc.h @@ -0,0 +1,795 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an +* express license agreement from NVIDIA Corporation is strictly prohibited. +*/ + +/** @file GFMxEnc.h +GFSDK MPEG Encode API header file. +*/ + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the GFMXENC_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// GFMXENC_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +#ifndef _GF_MPEG_ENC__ +#define _GF_MPEG_ENC__ + +#include "GFVx.h" +#include "GFDef.h" + +/** @addtogroup groupMxEnc GFMxEncAPI MPEG4 Encode API +
        +
      • @ref pageMxEncAppNotes +
          +
        • @ref pageMxEncAppNotes1 +
        +
      +*/ +/*@{*/ + +/** MxEncAPI property flag: Support Simple Profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_SIMPLE 0x00000001 //Support Simple Profile +/** MxEncAPI property flag: Support Simple Scale Profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_SCALE 0x00000002 //Support Simple Scale Profile +/** MxEncAPI property flag: Support CORE Profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_CORE 0x00000004 //Support CORE Profile +/** MxEncAPI property flag: Support MAIN Profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_MAIN 0x00000008 //Support MAIN Profile +/** MxEncAPI property flag: Support N_bit profile. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_N_BIT 0x00000010 //Support N_bit Profile +/** MxEncAPI property flag: Support LEVEL 1. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_LEVEL1 0x00000100 //Support LEVEL 1 +/** MxEncAPI property flag: Support LEVEL 2. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_LEVEL2 0x00000200 //Support LEVEL 2 +/** MxEncAPI property flag: Support LEVEL 3. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_LEVEL3 0x00000400 //Support LEVEL 3 +/** MxEncAPI property flag: Support LEVEL 4. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_LEVEL4 0x00000800 //Support LEVEL 4 +/** MxEncAPI property flag: Support Data Partitioning Mode. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_DATA_PARTITIONING 0x00001000 //Support Data Partitioning Mode +/** MxEncAPI property flag: Support RVLC Mode. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_RVLC 0x00002000 //Support RVLC Mode +/** MxEncAPI property flag: Support Rate Control. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_RATE_CONTROL 0x00004000 +//support rate control +/** MxEncAPI property flag: Support Intra MacroBlock Refreshing. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_IMRF 0x000008000 //Support Intra Macroblock Refreshing +/** MxEncAPI property flag: Support Rotation. + @see GFMxEncGetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_CAP_ROTATION 0x000010000 //Support Rotation + +/** GFMxEncSetVOL parameter struct. */ +typedef struct _GFMXENCVOL +{ + NvU32 uiVOLInfo; /**< VOL characteristics */ + /**< + + + + + + + + + + + +
      #GF_MXENC_VOL_SHORT_VIDEO_HEADER
      #GF_MXENC_VOL_BYPASS_VLC
      #GF_MXENC_VOL_RESYNC_MARK_ENABLE
      #GF_MXENC_VOL_DATA_PARTITION_ENABLE
      #GF_MXENC_VOL_REVERSIBLE_VLC_ENABLE
      #GF_MXENC_VOL_RATE_CONTROL_ENABLE
      #GF_MXENC_VOL_STUFFING_ENABLE
      #GF_MXENC_VOL_AUTO_IMRF_ENABLE
      #GF_MXENC_VOL_MC_IMRF_ENABLE
      #GF_MXENC_VOL_THUMBNAIL_ENABLE
      + */ + PGFRMSURFACE pSrcSurf;/**< Surface to encode*/ + PGFRECT pSrcRect; /** + #GF_MXENC_VOP_4MV_ENABLE + #GF_MXENC_VOP_HALF_PEL_ENABLE + #GF_MXENC_VOP_PACKET_BASED_ON_MB_NUM + #GF_MXENC_VOP_AC_PRE_ALWAYS_ON + #GF_MXENC_VOP_AC_PRE_DYNAMICALLY_ON + #GF_MXENC_VOP_CHANGE_EXPECTED_SIZE + #GF_MXENC_VOP_CHANGE_INITQP + #GF_MXENC_VOP_CHANGE_MIN_MAX_QP + #GF_MXENC_VOP_4MV_ENABLE + #GF_MXENC_VOP_REDUCE_FRAME_RATE + #GF_MXENC_VOP_ENCODE_I_ASAP + #GF_MXENC_VOP_IMRF_CONTROL_IP_RATIO + #GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE + #GF_MXENC_VOP_LOAD_IMRF_MATRIX + #GF_MXENC_VOP_TIMESTAMP_CPU + #GF_MXENC_VOP_TIMESTAMP_VI + #GF_MXENC_VOP_CHANGE_MAX_QP_RELIEF + + */ + + NvU16 uiPacketSize; /**< If GF_MXENC_VOP_PACKET_BASED_ON_MB_NUM flag is on, this field tells the number of macroblocks in a packet. Otherwise, this field tells number of bytes in a packet.*/ + NvU16 uiIntra_DC_VLC_Thr; /**< Intra DC VLC Threshold*/ + NvU16 uiHECNum; /**< Frequency to inset HEC marker. 0 means no HEC marker at all. 1~7 means to insert HEC after 1~7 resync marker(s).*/ + NvU16 uiExpectedISize; /**< If next encoded VOP is I, this field tells GFMxEncAPI the size of bit stream which application expects in number of DWORD.*/ + NvU16 uiExpectedPSize; /**< If next encoded VOP is P, this field tells GFMxEnc the size of bit stream which application expects in number of DWORD.*/ + NvU16 uiInitialIQP; /**< Initial QP value for I VOP*/ + NvU16 uiInitialPQP; /**< Initial QP value for P VOP */ + + NvU16 uiMaxIQP; /**< Max QP value for I VOP*/ + NvU16 uiMinIQP; /**< Min QP value for I VOP */ + + NvU16 uiMaxPQP; /**< Max QP value for P VOP*/ + NvU16 uiMinPQP; /**< Min QP value for P VOP */ + NvU16 uiMaxQPRelief; /**< Max qp Relief*/ + + NvU16 uiNumofP; /**< Number of consecutive P VOPs between two I VOPs.*/ + NvU16 uiRNumerator; /**< Desired Framerate value. This field must be filled if flag GF_MXENC_VOP_REDUCE_FRAME_RATE is on.*/ + NvU16 uiRDenominator; /**< Camera Framerate. This field must be filled if flag GF_MXENC_VOP_REDUCE_FRAME_RATE is on.*/ + + NvU8 uiIMRFIMinValue; /**< Those values will take effect only when GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever an I VOP is encoded, MxEnc will generate a random number in this range for each macroblock.*/ + NvU8 uiIMRFIMaxValue; /**< Those values will take effect only when GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever an I VOP is encoded, MxEnc will generate a random number in this range for each macroblock.*/ + NvU8 uiIMRFPMinValue; /**< Those values will take effect only when GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever a Macro Block counter is reduced to 0, an Intra Macro Block will be generated by MxEnc. MxEnc will generate a random number in this range for this macroblock.*/ + NvU8 uiIMRFPMaxValue; /**< Those values will take effect only when GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever a Macro Block counter is reduced to 0, an Intra Macro Block will be generated by MxEnc. MxEnc will generate a random number in this range for this macroblock.*/ + NvU8 uiIMRFDefaultCounter; /**< This value will be used as the new counter when the refresh counter in the matrix is decreased to 0.*/ + NvU8* pMIRFMatrix; /**< Pointer to an array that holds counter for each Macro Block. When this counter is decreased to 0, one Intra Macro Block will be inserted.*/ + + NvU32 uiTimeStampModel; /**< Time Stamp Model (VI or CPU). + + + +
      #GF_MXENC_VOP_TIMESTAMP_CPU
      #GF_MXENC_VOP_TIMESTAMP_VI
      + */ + +}GFMXENCVOP, *PGFMXENCVOP; + +//uiVOPInfo: +/**GFMXENCVOP::uiVOPInfo: Enable 4 motion vectors, GFMxEnc will pick 1 MV or 4 MV, depends on which mode is more efficient.*/ +#define GF_MXENC_VOP_4MV_ENABLE 0x00000001 + +/**GFMXENCVOP::uiVOPInfo : Enable Half Pel Motion Estimation search*/ +#define GF_MXENC_VOP_HALF_PEL_ENABLE 0x00000002 + +/**GFMXENCVOP::uiVOPInfo:New packet based on the number of MBs. Not the length of the bit stream*/ +#define GF_MXENC_VOP_PACKET_BASED_ON_MB_NUM 0x00000004 + +/**GFMXENCVOP::uiVOPInfo:AC prediction always on*/ +#define GF_MXENC_VOP_AC_PRE_ALWAYS_ON 0x00000008 + +/**GFMXENCVOP::uiVOPInfo:AC prediction dynamically on*/ +#define GF_MXENC_VOP_AC_PRE_DYNAMICALLY_ON 0x00000010 + +/**GFMXENCVOP::uiVOPInfo : Change the expected size for I and P encoded frames. uiExpectedISize, uiExpectedPSize must be filled*/ +#define GF_MXENC_VOP_CHANGE_EXPECTED_SIZE 0x00000020 + +/**GFMXENCVOP::uiVOPInfo : Change the initial QP for I and P. uiInitialIQP, uiInitialPQP must be filled*/ +#define GF_MXENC_VOP_CHANGE_INITQP 0x00000040 + +/**GFMXENCVOP::uiVOPInfo : Change the Min and Max QP for I and P frames. uiMaxIQP, uiMinIQP, uiMaxPQP, uiMinPQP must be filled*/ +#define GF_MXENC_VOP_CHANGE_MIN_MAX_QP 0x00000080 + +/**GFMXENCVOP::uiVOPInfo : Reduce the frame rate by skipping certain frames. uiRNumerator and uiRDenominator must be set.*/ +#define GF_MXENC_VOP_REDUCE_FRAME_RATE 0x00000100 + +/**GFMXENCVOP::uiVOPInfo : Encode I VOP as soon as possible*/ +#define GF_MXENC_VOP_ENCODE_I_ASAP 0x00000200 + +/**GFMXENCVOP::uiVOPInfo : Number of P VOPs between two I VOPs controlled by intra macro block refreshing. If this flag is off, it is controlled by uiNumofP*/ +#define GF_MXENC_VOP_IMRF_CONTROL_IP_RATIO 0x00000400 + +/**GFMXENCVOP::uiVOPInfo : Application can change the counter range by setting this flag and give the range in uiIMRFIMinValue, uiIMRFIMaxValue, uiIMRFPMinValue and uiIMRFPMaxValue. Application only can turn on this flag when GF_MXENC_VOL_AUTO_IMRF_ENABLE is on.*/ +#define GF_MXENC_VOP_LOAD_IMRF_COUNTER_RANGE 0x00000800 + +/**GFMXENCVOP::uiVOPInfo : Application must fill in uiIMRFDefaultCounter and pIMRFMatrix when this flag is on. Application only can turn on this flag when GF_MXENC_VOL_MC_IMRF_ENABLE flag is on.*/ +#define GF_MXENC_VOP_LOAD_IMRF_MATRIX 0x00001000 + +/**GFMXENCVOP::uiVOPInfo : Timestamp is provided by CPU*/ +#define GF_MXENC_VOP_TIMESTAMP_CPU 0x00010000 + +/**GFMXENCVOP::uiVOPInfo: Timestamp is generated by VI*/ +#define GF_MXENC_VOP_TIMESTAMP_VI 0x00020000 + +/**GFMXENCVOP::uiVOPInfo : Change MAX QP RELIEF value for Rate Control Algorithm*/ +#define GF_MXENC_VOP_CHANGE_MAX_QP_RELIEF 0x00100000 + +/**typedef struct _GFMXENCRCC*/ + +typedef struct _GFMXENCRCC +{ + NvU16 uiIQP; /** + #MXENC_VOP_P_VOP + #MXENC_VOP_MORE_FETCH + #MXENC_VOP_PORTION_PACKET + #MXENC_VOP_MORE_VOP + #MXENC_VOP_BEGIN_VOP + #MXENC_VOP_END_VOP + #MXENC_VOP_BUFFER_OVERFLOW + + */ + NvU32 uiAverageQP; /** + #GF_MXENC_CAP_SIMPLE + #GF_MXENC_CAP_SCALE + #GF_MXENC_CAP_CORE + #GF_MXENC_CAP_MAIN + #GF_MXENC_CAP_N_BIT + #GF_MXENC_CAP_LEVEL1 + #GF_MXENC_CAP_LEVEL2 + #GF_MXENC_CAP_LEVEL3 + #GF_MXENC_CAP_LEVEL4 + #GF_MXENC_CAP_DATA_PARTITIONING + #GF_MXENC_CAP_RVLC + #GF_MXENC_CAP_RATE_CONTROL + #GF_MXENC_CAP_IMRF + #GF_MXENC_CAP_ROTATION + + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxEncAPI functions. +*/ + +GF_RETTYPE GFMxEncGetStatus(GFMxEncHandle hMxEnc, NvU32 * pStatus); +/**< This function returns the hardware encoder’s status. + + @param MXhandle (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (NvU32 * ) @see GFMxEncGetStatus Definitions. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ +//pStatus +/**GFMxEncGetStatus Definitions : If hardware encoder is busy encoding VOPs*/ +#define GF_ENCODER_BUSY 0x00000001 + +/**GFMxEncGetStatus Definitions : At least one VOP is ready for fetching */ +#define GF_ENCODER_VOP_READY 0x00000002 + + +GF_RETTYPE GFMxEncSetVOL(GFMxEncHandle hMxEnc, PGFMXENCVOL pVOL); +/**< This function sets the characteristics of a new video object layer (VOL) and +tells the GFMxEncAPI the VOL information. The GFMxEncAPI does not +generate a VOL bit stream. The application needs to prepare a VOL by itself. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCVOL ) Set new VOL information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + + +GF_RETTYPE GFMxEncSetVOP(GFMxEncHandle hMxEnc, PGFMXENCVOP pVOP); +/**< This function sets the characteristics of a new video object plane (VOP). This +function should be called after GFMxEncSetVOL() and before +GFMxEncStart(). If the application decides to change any VOP information +during the encoding time (after GFMxEncStart()), the application can call +this function to pass the new VOP information to the GFMxEncAPI. +Otherwise, the application should not call this function, allowing the +GFMxEncAPI to reduce overhead. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCVOP ) Set new VOP information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + + +GF_RETTYPE GFMxEncRateControlConfig(GFMxEncHandle hMxEnc, PGFMXENCRCC pRCC); +/**< This function initializes the GFMxEncAPI rate control block. This function is +optional for application because the GFMxEncAPI automatically initializes +the rate control block. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCRCC ) Set rate control information.. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + +GF_RETTYPE GFMxEncFeedImage(GFMxEncHandle hMxEnc, + PGFMXENCFEEDIMAGE pFeedImage); +/**< The application can call this function if the application has the source image to feed to the encoder. +This function should not be called if the image comes directly from the video +input port (VIP), for example, from a camera. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCFEEDIMAGE ) New image information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + + +GF_RETTYPE GFMxEncFetchImage(GFMxEncHandle hMxEnc,PGFMXENCFETCHVOP pFetchVOP); +/**< An application should call this function to fetch the encoded VOP bit stream +or encoded raw data. If the source image is from the host, the application +should call this function after GFMxEncFeedImage(). If the source image is +from a video camera connected to the VIP and the application is using a +polling scheme, the application should call this function at least at the +camera’s frame rate. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param pStatus (PGFMXENCFETCHVOP ) Structure to hold encoded VOP information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + +GF_RETTYPE GFMxEncStart(GFMxEncHandle hMxEnc); +/**< This function starts the GFMxEncAPI module for encoding the bit stream. +The GFMxEncAPI assumes the first VOP it outputs is the first VOP in the +current VOL. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + +GF_RETTYPE GFMxEncPause(GFMxEncHandle hMxEnc); +/**< This function pauses the encoding process until GFMxEncPause() is called +again to Resume encoding, or GFMxEncStop() is called to totally stop encoding. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + +GF_RETTYPE GFMxEncStop(GFMxEncHandle hMxEnc); +/**< This function stops the encoding process. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + +GF_RETTYPE GFMxEncSetupInterrupt(GFMxEncHandle hMxEnc,void (*Inter)(void *), void * IPara); +/**< An application can use this function to set up the interrupt callback function. +This function must be called before GFMxEncStart(). +If this function returns GF_SUCCESS, whenever a VOP is ready the +GFMxEncAPI calls the interrupt callback function. Inside of the callback +function, the application can call GFMxEncSetVOP() if it is needed, and call +GFMxEncFetchImage() to fetch the encoded VOP. +If GF_ERROR is returned, the application should use a polling scheme. + + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param (*Inter)(void *) (void) Pointer to encoder application’s interrupt callback function. + @param IPara (void *) Pointer to parameter of encoder application’s interrupt callback function. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + + +GF_RETTYPE GFMxEncSetAttribute(GFMxEncHandle hMxEnc, NvU32 uiFeature, NvU32* pInfo); +/**< This function sets a feature of the MPEG encoder hardware. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param uiFeature (NvU32) @see GFMxEncSetAttribute Definitions + @param pInfo (NvU32*) Pointer to the information buffer. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes + + GFMxEncSetAttribute_Definitions: + + + + + +
      #MXENC_ATTR_KEEP_PREV_ENCODING_INTERNAL_RESOURCE
      #MXENC_PREVIEW_ROTATE_BUFFER
      #MXENC_GET_PREVIEW_BUFFER
      #MXENC_ENABLE_INTERRUPT_MODE
      + + MXENC_ENABLE_INTERRUPT_MODE MXENC_GET_PREVIEW_BUFFER MXENC_PREVIEW_ROTATE_BUFFER MXENC_ATTR_KEEP_PREV_ENCODING_INTERNAL_RESOURCE +*/ + + +GF_RETTYPE GFMxEncGetAttribute(GFMxEncHandle hMxEnc, NvU32 uiFeature, NvU32* pInfo); +/**< This function gets a feature of the MPEG encoder hardware.. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + @param uiFeature (NvU32) see GFMxEncGetAttribute_Definitions below. + @param pInfo (NvU32*) Pointer to the information buffer. + + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes + + + +GFMxEncGetAttribute_Definitions: +GF4800 and subsequent generation of GPUs have rotator block which can rotate +video frame before encoding. In a normal mode a Encoder doesn't need to +capture whole video frame before encoding but in rotation mode, it needs to +capture full video frame (YUV4:2:0) before encoding. This means rotation +mode requires more memory. +This option can be used to enable rotation with 4 basic modes which can be +ORed with two h-flip and v-flip options. +Total of 8 unique combination of rotation modes are available. +*pInfo rotation degree used with MXENC_ATTR_ROTATION + + + + + + + + + +
      #MXENC_ATTR_ROTATION
      #MXENC_ATTR_ROTATE_0
      #MXENC_ATTR_ROTATE_90
      #MXENC_ATTR_ROTATE_180
      #MXENC_ATTR_ROTATE_270
      #MXENC_ATTR_H_FLIP
      #MXENC_ATTR_V_FLIP
      + + + + +*/ + +/** @name GFMxEncGetAttribute_Definitions +*/ +//@{ + +/**GFMxEncGetAttribute_Definitions: +*/ + +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATION*/ +#define MXENC_ATTR_ROTATION 1 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATE_0*/ +#define MXENC_ATTR_ROTATE_0 0x0 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATE_90*/ +#define MXENC_ATTR_ROTATE_90 0x1 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATE_180*/ +#define MXENC_ATTR_ROTATE_180 0x2 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_ROTATE_270*/ +#define MXENC_ATTR_ROTATE_270 0x3 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_H_FLIP*/ +#define MXENC_ATTR_H_FLIP 0x10 +/**GFMxEncGetAttribute_Definitions::MXENC_ATTR_V_FLIP*/ +#define MXENC_ATTR_V_FLIP 0x20 +//@} + + + +GF_RETTYPE GFMxEncInterruptControl(GFMxEncHandle MxHandle); +/**< This function enables the MxEnc interrupt. + + @param hMxEnc (GFMxEncHandle) Handle specific to the GFMxEncAPI. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes +*/ + +/** @name GFMxEncAPI_Error_Codes +*/ +//@{ + +/** GFMXE_SUCCESS*/ +#define GFMXE_SUCCESS GF_SUCCESS +/** GFMXE_ERROR_NOT_SUPPORT_FORMAT */ +#define GFMXE_ERROR_NOT_SUPPORT_FORMAT (GFMXE_ERROR | 0x00000001) +/** GFMXE_ERROR_INVALID_PARAMETER */ +#define GFMXE_ERROR_INVALID_PARAMETER (GFMXE_ERROR | 0x00000002) +/** GFMXE_ERROR_NOT_ENOUGH_EMBEDDED_MEM */ +#define GFMXE_ERROR_NOT_ENOUGH_EMBEDDED_MEM (GFMXE_ERROR | 0x00000003) +/** GFMXE_ERROR_SET_ATTRIBUTE_FAILED */ +#define GFMXE_ERROR_SET_ATTRIBUTE_FAILED (GFMXE_ERROR | 0x00000004) + +//@} + + + /*@}*/ + + /** @page pageMxEncAppNotes MxEncAPI Application Notes + + @section pageMxEncAppNotes1 Programming Sequence + + Todo + */ + +#ifdef __cplusplus +} // only need to export C interface if +// used by C++ source code +#endif + +#endif //#ifndef _GF_MPEG_ENC__ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxEncH264.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxEncH264.h new file mode 100755 index 00000000..f4f81228 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFMxEncH264.h @@ -0,0 +1,788 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property +* and proprietary rights in and to this software, related documentation +* and any modifications thereto. Any use, reproduction, disclosure or +* distribution of this software and related documentation without an +* express license agreement from NVIDIA Corporation is strictly prohibited. +*/ + +/** @file GFMxEncH264.h +GFSDK H264 Encode API header file. +*/ + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the GFMXENC_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// GFMXENC_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +#ifndef _GF_MPEG_ENC_H264__ +#define _GF_MPEG_ENC_H264__ + +#include "GFVx.h" + +#include "GFDef.h" + +/** @addtogroup groupMxEncH264 MxEncH264API H264 Encode API +
        +
      • @ref pageMxEncH264AppNotes +
          +
        • @ref pageMxEncH264AppNotes1 +
        +
      +*/ +/*@{*/ + +/** @name GFMxEncH264 API Property Caps */ +//@{ +/** MxEncH264API property flag: Support baseline Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_BASELINE 0x00000001 //support baseline profile +/** MxEncH264API property flag: Support Main Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_MAIN 0x00000002 //support main profile +/** MxEncH264API property flag: Support extended Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_EXTENDED 0x00000004 //support extended profile +/** MxEncH264API property flag: Support high 10 Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_HIGH10 0x00000008 //support high 10 profile +/** MxEncH264API property flag: Support high 422 Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_HIGH422 0x00000010 //support high 422 profile +/** MxEncH264API property flag: Support high 444 Profile. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_HIGH444 0x00000020 //support high 444 profile +/** MxEncH264API property flag: Level_IDC following H.264 spec definition. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_LEVEL_IDC(Capability) \ + ((Capability >> 12) & 0xfff)//Level_IDC following H.264 spec definition +/** MxEncH264API property flag: Support data partitioning mode. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_DATA_PARTITIONING 0x10000000 //support data partitioning mode +/** MxEncH264API property flag: Support rate control. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_RATE_CONTROL 0x20000000 //support rate control +/** MxEncH264API property flag: Support intra macro block refreshing. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_IMRF 0x40000000 //support intra macro block refreshing +/** MxEncH264API property flag: Support rotation. +@see MxEncH264GetProperty(), GFPROPERTY::Capability +*/ +#define GF_MXENC_H264_CAP_ROTATION 0x80000000 //support rotation + +//@} + + + + +/**typedef struct GFMXENCH264SETSEQUENCE_TAG*/ +typedef struct GFMXENCH264SETSEQUENCE_TAG +{ + NvU32 SequenceInfo; /**< Sequence characteristics */ + /**< + + + + + + + + + + + +
      #GF_MXENC_H264_SEQUENCE_CONSTRAINT_SET0_FLAG
      #GF_MXENC_H264_SEQUENCE_CONSTRAINT_SET1_FLAG
      #GF_MXENC_H264_SEQUENCE_CONSTRAINT_SET2_FLAG
      #GF_MXENC_H264_SEQUENCE_DELTA_PIC_ORDER_ALWAYS_ZERO_FLAG
      #GF_MXENC_H264_SEQUENCE_FRAME_MBS_ONLY_FLAG
      #GF_MXENC_H264_SEQUENCE_RATE_CONTROL_ENABLE
      #GF_MXENC_H264_SEQUENCE_AUTO_IMRF_ENABLE
      #GF_MXENC_H264_SEQUENCE_MC_IMRF_ENABLE
      #GF_MXENC_H264_SEQUENCE_REALTIME_ENCODE
      #GF_MXENC_H264_SEQUENCE_DEBLK_I_SLICE
      + */ + NvU32 profile_idc; /** + #GF_MXENC_H264_PICTURE_CHANGE_INIT_QP + #GF_MXENC_H264_PICTURE_REDUCE_FRAME_RATE + #GF_MXENC_H264_PICTURE_ENCODE_IDR_ASAP + #GF_MXENC_H264_PICTURE_CHANGE_MIN_MAX_QP + #GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE + #GF_MXENC_H264_PICTURE_LOAD_IMRF_MATRIX + #GF_MXENC_H264_PICTURE_4MV_ENABLE + #GF_MXENC_H264_PICTURE_HALF_PEL_ENABLE + #GF_MXENC_H264_PICTURE_DEBLK_FILTER_ENABLE + #GF_MXENC_H264_PICTURE_MULTI_SLICE_ENABLE + + */ + NvU32 numofSlicesGroup; /**< Number of slice groups, default value = 0 */ + NvU32 sliceGroupMapType; /**< default value is 0 , interleaved slice groups */ + NvU32 num_of_ref_idx_10_active; /**< Specifies the maximum reference index for reference picture list 0 ,default value is 0 */ + NvU32 num_of_ref_idx_11_active; /**< Default value is 0 */ + NvS32 pic_init_qp; /**< Initial value of the slice QP*/ + NvS32 pic_init_qs; /**< Initial value of the slice QS */ + NvS32 chroma_qp_index_offset; /**< Specifies the offset that shall be added to QPY and QSY for addressing the table of QPC values. The value of chroma_qp_index_offset shall be in the range of -12 to +12, inclusive. */ + NvU32 uiMaxIDRQP; /**< Max QP value for IDR */ + NvU32 uiMinIDRQP; /**< Min QP value for IDR */ + + NvU32 uiMaxNONIDRQP; /**< Max QP value for non-IDR picture */ + NvU32 uiMinNONIDRQP; /**< Min QP value for non-IDR picture */ + + NvU32 SliceAlpha; /**< Aplha value for Deblocking */ + NvU32 SliceBeta; /**< Beta value for Deblocking */ + + /**< Packetisation for H264*/ + NvU32 uiPacketCtrlDisable; /**< Disables the packet mode control */ + NvU32 uiPacketMode; /**< If 1 ,then in macroblock mode else in bytes mode, bytes mode not supported */ + NvU32 uiPacketSize; /**< Packet size in MBs or bytes, packet size in bytes is not supported, Value can range from zero to the number of MBs in a frame */ + + NvU32 uiNumofPicBetween2IDRs; /**< Number of P frames in between consecutive I Frames */ + NvU32 uiRNumerator; /**< Desired Framerate value. This field must be filled if flag GF_MXENC_H264_PICTURE_REDUCE_FRAME_RATE is on. */ + NvU32 uiRDenominator; /**< Camera Framerate. This field must be filled if flag F_MXENC_H264_PICTURE_REDUCE_FRAME_RATE is on. */ + NvU32 uiIMRFIMinValue; /**< Those values will take effect only when GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever an I frame is encoded, MxEncH264 will generate a random number in this range for each macroblock */ + NvU32 uiIMRFIMaxValue; /**< Those values will take effect only when GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever an I frame is encoded, MxEncH264 will generate a random number in this range for each macroblock. */ + NvU32 uiIMRFPMinValue; /**< Those values will take effect only when GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever a Macro Block counter is reduced to 0, an Intra Macro Block will be generated by MxEncH264. MxEncH264 will generate a random number in this range for this macroblock. */ + NvU32 uiIMRFPMaxValue; /**< Those values will take effect only when GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE flag is set. Whenever a Macro Block counter is reduced to 0, an Intra Macro Block will be generated by MxEncH264. MxEncH264 will generate a random number in this range for this macroblock. */ + NvU32 uiIMRFDefaultCounter; /**< This value will be used as the new counter when the refresh counter in the matrix is decreased to 0. */ + NvU8 *pIMRFMatrix; /**< Pointer to an array that holds counter for each Macro Block. When this counter is decreased to 0, one Intra Macro Block will be inserted.*/ + + +} GFMXENCH264SETPICTURE, *PGFMXENCH264SETPICTURE; + +/** @name GFMxEncH264 API Setpicture::PictureInfo */ +//@{ +/**GFMXENCH264SETPICTURE::PictureInfo: When application enables this flag, application must set pic_init_qp, pic_init_qs and chroma_qp_index_offset.*/ +#define GF_MXENC_H264_PICTURE_CHANGE_INIT_QP 0x00000001 + +/**GFMXENCH264SETPICTURE::PictureInfo:Reduce the frame rate by skipping certain frames, Must set uiRNumerator and uiRDenominator.*/ +#define GF_MXENC_H264_PICTURE_REDUCE_FRAME_RATE 0x00000002 + +/**GFMXENCH264SETPICTURE::PictureInfo: Encode IDR as soon as possible .*/ +#define GF_MXENC_H264_PICTURE_ENCODE_IDR_ASAP 0x00000004 + +/**GFMXENCH264SETPICTURE::PictureInfo:When application set this flag, application must set uiMaxIDRQP, uiMinIDRQP, uiMaxNONIDRQP and uiMinNONIDRQP .*/ +#define GF_MXENC_H264_PICTURE_CHANGE_MIN_MAX_QP 0x00000008 + +/**GFMXENCH264SETPICTURE::PictureInfo:Application changes the counter range by setting this, flag and giving the range in uiIMRFIMinValue uiIMRFIMaxValue, uiIMRFPMinValue, and uiIMRFPMaxValue, Applications can turn on this flag only when GF_MXENC_H264_SEQUENCE_AUTO_IMRF_ENABLE is on.*/ +#define GF_MXENC_H264_PICTURE_LOAD_IMRF_COUNTER_RANGE 0x00000010 + +/**GFMXENCH264SETPICTURE::PictureInfo: Application must fill in uiIMRFDefaultCounter and pIMRFMatrix if this flag is on, Application can turn on flag only if GF_MXENC_H264_PICTURE_MC_IMRF_ENABLE is on .*/ +#define GF_MXENC_H264_PICTURE_LOAD_IMRF_MATRIX 0x00000020 + +/**GFMXENCH264SETPICTURE::PictureInfo: Enable 4 motion vectors, GFMxEncH264 will pick 1 MV or 4 MV, depends on which mode is more efficient.*/ +#define GF_MXENC_H264_PICTURE_4MV_ENABLE 0x00000040 + +/**GFMXENCH264SETPICTURE::PictureInfo: Enable half pel motion estimation search.*/ +#define GF_MXENC_H264_PICTURE_HALF_PEL_ENABLE 0x00000080 + +/**GFMXENCH264SETPICTURE::PictureInfo: Enable Deblocking.*/ +#define GF_MXENC_H264_PICTURE_DEBLK_FILTER_ENABLE 0x00000100 + +/**GFMXENCH264SETPICTURE::PictureInfo: Enable Multi Slicing. Mutli-slicing is not supported*/ +#define GF_MXENC_H264_PICTURE_MULTI_SLICE_ENABLE 0x00000200 +//@} + +/** typedef struct GFMXENCH264RCC_TAG */ +typedef struct GFMXENCH264RCC_TAG +{ + NvU16 uiIQP; /** + #GF_MXENC_H264_NALS_SEQUENCE_PARAMETER_SET + #GF_MXENC_H264_NALS_PICTURE_PARAMETER_SET + #GF_MXENC_H264_NALS_IDR_PIC + #GF_MXENC_H264_NALS_NON_IDR_PIC + #GF_MXENC_H264_NALS_BEGIN_ACCESS_UNIT + #GF_MXENC_H264_NALS_PARTIAL_ACCESS_UNIT + #GF_MXENC_H264_NALS_END_ACCESS_UNIT + #GF_MXENC_H264_NALS_DATA_NOT_READY + #GF_MXENC_H264_NALS_MORE_FETCH + #GF_MXENC_H264_NALS_MORE_NALS + + */ + NvU32 uiTime; /**< In milliseconds, the encoded picture's time stamp. First picture may start from 0. */ + NvU32 uiFetchedSize; /**< Number of available bytes */ +}GFMXENCH264FETCHNALS, *PGFMXENCH264FETCHNALS; + +/** @name GFMXENCH264FETCHNALS::uiNALsInfo definitions */ +//@{ + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current NAL unit is a Sequence Parameter Set. */ +#define GF_MXENC_H264_NALS_SEQUENCE_PARAMETER_SET 0x00000001 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current NAL unit is a Picture Parameter Set. */ +#define GF_MXENC_H264_NALS_PICTURE_PARAMETER_SET 0x00000002 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current NAL unit belongs to an IDR Pic. */ +#define GF_MXENC_H264_NALS_IDR_PIC 0x00000004 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current NAL unit belongs to a Non-IDR Pic. */ +#define GF_MXENC_H264_NALS_NON_IDR_PIC 0x00000008 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current data is the start of a new Access Unit. */ +#define GF_MXENC_H264_NALS_BEGIN_ACCESS_UNIT 0x00000010 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current data is a Partial Access Unit. */ +#define GF_MXENC_H264_NALS_PARTIAL_ACCESS_UNIT 0x00000020 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Current data is the End of the Access Unit. */ +#define GF_MXENC_H264_NALS_END_ACCESS_UNIT 0x00000040 + +/**GFMXENCH264FETCHNALS::uiNALsInfo:Data of current NAL is not ready yet.*/ +#define GF_MXENC_H264_NALS_DATA_NOT_READY 0x00000080 + +/**GFMXENCH264FETCHNALS::uiNALsInfo: Present NAL unit is larger than application's buffer size. Call FetchNALs again to get remaining data.*/ +#define GF_MXENC_H264_NALS_MORE_FETCH 0x00000100 + +/** GFMXENCH264FETCHNALS::uiNALsInfo: More NALs are encoded and ready to be fetched by the application. */ +#define GF_MXENC_H264_NALS_MORE_NALS 0x00000200 + +//@} + +/** @name GFMxEncH264SetAttribute Definitions */ +//@{ + +/**GFMxEncH264SetAttribute_Definitions::MXENC_H264_ATTR_ROTATION: +GF4800 and subsequent generation of GPUs have rotator block which can rotate +video frame before encoding. In a normal mode a Encoder doesn't need to +capture whole video frame before encoding but in rotation mode, it needs to +capture full video frame (YUV4:2:0) before encoding. This means rotation +mode requires more memory. +This option can be used to enable rotation with 4 basic modes which can be +ORed with two h-flip and v-flip options. +Total of 8 unique combination of rotation modes are available. +*pInfo rotation degree used with MXENC_ATTR_ROTATION +*/ +#define MXENC_H264_ATTR_ROTATION 1 + +#define MXENC_H264_ATTR_ROTATE_0 0x0 /**< No rotation */ +#define MXENC_H264_ATTR_ROTATE_90 0x1 /**< Rotate by 90 degree */ +#define MXENC_H264_ATTR_ROTATE_180 0x2 /**< Rotate by 180 degree */ +#define MXENC_H264_ATTR_ROTATE_270 0x3 /**< Rotate by 270 degree */ +#define MXENC_H264_ATTR_H_FLIP 0x10 /**< Flip horizontally */ +#define MXENC_H264_ATTR_V_FLIP 0x20 /**< Flip vertically */ + +/**GFMxEncH264SetAttribute_Definitions:MXENC_H264_INTRAREFRESH_MODE +This option allows you to change the INTRA REFRESH mode while encoding is in progress. +With this option, the application can switch/Turn ON MXENC_H264_INTRAREFRESH_AUTO or +MXENC_H264_INTRAREFRESH_MC. After switching to MXENC_H264_INTRAREFRESH_MC mode, the application +has to call GFMxEncH264SetPicture() with pPicture:pIMRFMatrix specifying the Intra Refresh pattern +*/ +#define MXENC_H264_INTRAREFRESH_MODE 2 +#define MXENC_H264_INTRAREFRESH_AUTO 0x1 /**< Set Intrarefresh pattern in Auto mode */ +#define MXENC_H264_INTRAREFRESH_MC 0x2 /**< Set Intrarefresh pattern in Motion Compensated mode */ + +//@} + +/** typedef enum GFMX_ENC_H264_INTERRUPT_OPERATION_TYPE : Set Interrupt Operation to perform */ +typedef enum +{ + GFMX_ENC_H264_INTERRUPT_ENABLE, /**< Enable Interrupt */ + GFMX_ENC_H264_INTERRUPT_DISABLE, /**< Disable Interrupt */ + GFMX_ENC_H264_INTERRUPT_CLEAR /**< Clear Interrupt */ +} GFMX_ENC_H264_INTERRUPT_OPERATION_TYPE; // Interrupt operation. + +/** typedef enum GFMX_ENC_H264_INTERRUPT_TYPE : Interrupt type*/ +typedef enum +{ + GFMX_ENC_H264_FRAME_ENCODE_DONE_INTR /**< Frame Encode Done Interrupt */ +} GFMX_ENC_H264_INTERRUPT_TYPE; + + +#ifdef __cplusplus +extern "C" { // only need to export C interface if + // used by C++ source code +#endif + + /** MxEncH264API virtual function pointer table. + These functions serve as the entry point to the MxEncH264API from the application. + */ + typedef struct _GFMXEncH264TABLE + { + GF_RETTYPE (* MxEncH264GetProperty)(GFMxEncH264Handle hMxEncH264, PGFPROPERTY pMXProp ); + /**< This function returns a variety of information, including the version of the + GFMxEncH264API encoder module. It is a good practice to call this function to query + for the GFMxEncH264API version and its capabilities before using the rest of the + GFMxEncH264API functions. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pMXProp (PGFPROPERTY) Pointer to GFPROPERTY. + MxEncH264API property flag below. + + MxEncH264API property flag: + + + + + + + + + + + + +
      #GF_MXENC_H264_CAP_BASELINE
      #GF_MXENC_H264_CAP_MAIN
      #GF_MXENC_H264_CAP_EXTENDED
      #GF_MXENC_H264_CAP_HIGH10
      #GF_MXENC_H264_CAP_HIGH422
      #GF_MXENC_H264_CAP_HIGH444
      #GF_MXENC_H264_CAP_LEVEL_IDC
      #GF_MXENC_H264_CAP_DATA_PARTITIONING
      #GF_MXENC_H264_CAP_RATE_CONTROL
      #GF_MXENC_H264_CAP_IMRF
      #GF_MXENC_H264_CAP_ROTATION
      + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the MxEncH264API functions. + */ + + GF_RETTYPE (* MxEncH264GetStatus)(GFMxEncH264Handle hMxEncH264, NvU32 * pStatus); + /**< This function returns the hardware encoder’s status. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pStatus (NvU32 * ) Status returned by the encoder. @see GFMxEncH264GetStatus Definitions. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264SetSequence)(GFMxEncH264Handle hMxEncH264, PGFMXENCH264SETSEQUENCE pSequence); + /**< This function sets the characteristics of a new H264 video sequence and + tells the GFMxEncH264API the sequence information. The GFMxEncH264API does not + generate a sequence bit stream. The application needs to prepare a sequence by itself. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pSequence (PGFMXENCH264SETSEQUENCE ) Set new sequence information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264SetPicture)(GFMxEncH264Handle hMxEncH264, PGFMXENCH264SETPICTURE pPicture); + /**< This function sets the characteristics of a new picture. This + function should be called after GFMxEncH264SetSequence() and before + GFMxEncH264Start(). If the application decides to change any picture information + during the encoding time (after GFMxEncH264Start()), the application can call + this function to pass the new picture information to the GFMxEncH264API. + Otherwise, the application should not call this function, allowing the + GFMxEncH264API to reduce overhead. + + @paramhMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pPicture (PGFMXENCH264SETPICTURE ) Set new picture information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264RateControlConfig)(GFMxEncH264Handle hMxEncH264, PGFMXENCH264RCC pRCC); + /**< This function initializes the GFMxEncH264API rate control block. This function is + optional for application because the GFMxEncH264API automatically initializes + the rate control block. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pRCC (PGFMXENCH264RCC ) Set rate control information.. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264FeedImage)(GFMxEncH264Handle hMxEncH264, + PGFMXENCH264FEEDIMAGE pFeedImage); + /**< The application can call this function if the application has the source image to feed to the encoder. + This function should not be called if the image comes directly from the video + input port (VIP), for example, from a camera. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pStatus (PGFMXENCH264FEEDIMAGE ) New image information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264FetchNALs)(GFMxEncH264Handle hMxEncH264, + PGFMXENCH264FETCHNALS pFetchNALs); + /**< An application should call this function to fetch the encoded NAL bit stream + or encoded raw data. If the source image is from the host, the application + should call this function after GFMxEnch264FeedImage(). If the source image is + from a video camera connected to the VIP and the application is using a + polling scheme, the application should call this function at least at the + camera’s frame rate. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param pFetchNALs (PGFMXENCH264FETCHNALS ) Structure to hold encoded NAL information. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264Start)(GFMxEncH264Handle hMxEncH264); + /**< This function starts the GFMxEncH264API module for encoding the bit stream. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + GF_RETTYPE (* MxEncH264Pause)(GFMxEncH264Handle hMxEncH264); + /**< This function pauses the encoding process until GFMxEnch264Pause() is called + again to Resume encoding, or GFMxEncH264Stop() is called to totally stop encoding. + + @param hMxEnc (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264Stop)(GFMxEncH264Handle hMxEncH264); + /**< This function stops the encoding process. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264SetupInterrupt)(GFMxEncH264Handle hMxEncH264, + void (*Inter)(void *), void * IPara); + /**< An application can use this function to set up the interrupt callback function. + + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param (*Inter)(void *) (void) Pointer to encoder application’s interrupt callback function. + @param IPara (void *) Pointer to parameter of encoder application’s interrupt callback function. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + */ + + GF_RETTYPE (* MxEncH264SetAttribute)(GFMxEncH264Handle hMxEncH264, NvU32 uiFeature, NvU32* pInfo); + /**< This function sets a feature of the H264 encoder. + + @param hMxEncH264 (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param uiFeature (NvU32) @see GFMxEncH264SetAttribute Definitions + @param pInfo (NvU32*) Pointer to the information buffer. + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncH264API_Error_Codes + + GFMxEncH264SetAttribute_Definitions: + + + +
      #MXENC_H264_ATTR_ROTATION
      #MXENC_H264_INTRAREFRESH_MODE
      + + + */ + GF_RETTYPE (* MxEncH264GetAttribute)(GFMxEncH264Handle hMxEncH264, NvU32 uiFeature, NvU32* pInfo); + /**< This function gets a feature of the H264 encoder. + + @param hMxEnc (GFMxEncH264Handle) Handle specific to the GFMxEncH264API. + @param uiFeature (NvU32) see GFMxEncH264GetAttribute_Definitions below. + @param pInfo (NvU32*) Pointer to the information buffer. + + + @retval GF_SUCCESS : If successful. + @retval GF_ERROR : If error. + @see GFMxEncAPI_Error_Codes + + */ + + }GFMXENCH264TABLE, *PGFMXENCH264TABLE; + + // Typesafe functions for opening and closing this component + GF_RETTYPE GFMxEncH264Open(GFRmHandle hRm, GFMxEncH264Handle *phMxEncH264, + GF_STATE_TYPE state, GFRmChHandle hCh); + /**< Typesafe function for opening the H264 Encoder component. + + @param hRm (GFRmHandle) RM Handle got from GFRmOpen. + @param phMxEncH264 (GFMxEncH264Handle *) Handle specific to the GFMxEncH264API is returned in this. + @param state (GF_STATE_TYPE) . + @param hCh (GFRmChHandle) Channel handle + */ + + void GFMxEncH264Close(GFMxEncH264Handle *phMxEncH264); + /**< Typesafe function for closing the H264 Encoder component. + + @param phMxEncH264 (GFMxEncH264Handle *) Pointer to handle specific to H264 encoder component. + */ + + /** @name GFMxEncH264GetStatus Definitions */ + //@{ +#define GF_ENCODER_BUSY 0x00000001 /**< Encoder is busy */ +#define GF_ENCODER_VOP_READY 0x00000002 /**< At least one VOP is ready for fetching */ + //@} + +/** @name GFMxEncH264API Helper Macros. */ + //@{ + +#define GFMxEncH264GetProperty(hMxEncH264, pMXProp) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264GetProperty(hMxEncH264, pMXProp) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264GetProperty + */ + +#define GFMxEncH264GetStatus(hMxEncH264, pStatus) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264GetStatus(hMxEncH264, pStatus) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264GetStatus + */ + +#define GFMxEncH264SetSequence(hMxEncH264, pSequence) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264SetSequence(hMxEncH264, pSequence) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264SetSequence + */ + +#define GFMxEncH264SetPicture(hMxEncH264, pPicture)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264SetPicture(hMxEncH264, pPicture) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264SetPicture + */ + +#define GFMxEncH264RateControlConfig(hMxEncH264, pRCC)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264RateControlConfig(hMxEncH264, pRCC) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264RateControlConfig + */ + +#define GFMxEncH264FeedImage(hMxEncH264, pFeedImage)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264FeedImage(hMxEncH264, pFeedImage) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264FeedImage + */ + +#define GFMxEncH264FetchNALs(hMxEncH264, pFetchNALs)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264FetchNALs(hMxEncH264, pFetchNALs) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264FetchNALs + */ + +#define GFMxEncH264Start(hMxEncH264)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264Start(hMxEncH264) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264Start + */ + +#define GFMxEncH264Pause(hMxEncH264)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264Pause(hMxEncH264) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264Pause + */ + +#define GFMxEncH264Stop(hMxEncH264)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264Stop(hMxEncH264) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264Stop + */ + +#define GFMxEncH264SetupInterrupt(hMxEncH264, Inter,IPara)\ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264SetupInterrupt(hMxEncH264, Inter,IPara) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264SetupInterrupt + */ + +#define GFMxEncH264SetAttribute(hMxEncH264, uiFeature, pInfo) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264SetAttribute(hMxEncH264, uiFeature, pInfo) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264SetAttribute + */ + +#define GFMxEncH264GetAttribute(hMxEncH264, uiFeature, pInfo) \ + ((PGFMXENCH264TABLE)hMxEncH264)->MxEncH264GetAttribute(hMxEncH264, uiFeature, pInfo) + /**< Helper macro for GFMxEncH264API. + @see GFMXENCH264TABLE::MxEncH264GetAttribute + */ + + //@} + + /** @name GFMxEncH264API_Error_Codes + */ + //@{ + + /** GFMXEH264_SUCCESS*/ +#define GFMXEH264_SUCCESS GF_SUCCESS + /** GGFMXEH264_ERROR_NOT_SUPPORT_FORMAT*/ +#define GFMXEH264_ERROR_NOT_SUPPORT_FORMAT (GFMXEH264_ERROR | 0x00000001) + /** GFMXEH264_ERROR_INVALID_PARAMETER*/ +#define GFMXEH264_ERROR_INVALID_PARAMETER (GFMXEH264_ERROR | 0x00000002) + /** GFMXEH264_ERROR_NOT_ENOUGH_EMBEDDED_MEM*/ +#define GFMXEH264_ERROR_NOT_ENOUGH_EMBEDDED_MEM (GFMXEH264_ERROR | 0x00000003) + //@} + + + /*@}*/ + + /** @page pageMxEncH264AppNotes MxEncH264API Application Notes + + @section pageMxEncH264AppNotes1 Programming Sequence + + The following procedure requires that GFRmOpen() is called first to start GFSDK usage. The description is for a typical case + where encoding of video being captured from a camera is done and preview shown on the display. + + 1. Initialize the display panel by using GFRmIxInit().\n + + 2. Open the display component by calling GFDxOpen() to get the GFMxDecAPI Dxhandle.\n + + 3. Initialize the display start address, stride and bits per pixel using GFDxSetDisplay().\n + + 4. Get the various attributes of the display panel (width, height, etc) using GFDxGetAttribute().\n + + 5. For clearing the screen, open the graphics component using GFGxOpen() and use GFGxFillRect() for filling the screen with + some color (say, green).\n + + 6. Open the Vx component using GFVxOpen() and get the GFVxAPI VxHandle. \n + + 7. Setup the camera. \n + + 8. Initialize VIP. \n + + 9. Obtain the handle specific to H264 encoder by calling GFMxEncH264Open(). \n + + 10. Call GFMxEncH264GetProperty() to query properties. Check whether this version can support the desired H264 profile and level. \n + + 11. If supported, call GFRmSurfaceAlloc() to allocate one surface for encoding purposes. \n + + 12. Call GFMxEncH264SetAttribute() if specific features need to be set. \n + + 13. Call GFMxEncH264SetSequence() for configuring the characteristics of a new H264 video sequence. \n + + 14. Call GFMxEncH264SetPicture() for setting the characteristics of a new picture. \n + + 15. If the current source image is from the CPU, the application should call GFMxEncH264FeedImage() to feed the + image to the GFMxEncH264API. If the current source image is coming from the VIP (for example. camera input), the + application should skip the GFMxEncH264FeedImage() call. + + 16. If the application uses an interrupt scheme, it must implement a callback function and set it up using GFMxEncH264SetupInterrupt. + Inside of the callback function, the application should call GFMxEncH264FetchNALs() to retrieve the encoded NALs. \n + + 17. Start the encoding by calling GFMxEncH264Start(). \n + + 18. The application should periodically call the callback function to get the data from the encoder. \n + + 19. The encoder can be paused by calling GFMxEncH264Pause() and can be resumed by calling GFMxEncH264Pause() again. \n + + 20. Before exiting, call GFMxEncH264Stop() to stop the encoder. \n + + 21. Call the callback function after waiting for some time to get the data for the last frame encoded. \n + + 22. Free all relevent resources and call GFMxEncH264Close() to free the H264 encoder component. \n + + */ + +#ifdef __cplusplus +} // only need to export C interface if +// used by C++ source code +#endif + +#endif //#ifndef _GF_MPEG_ENC_H264__ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFOSx.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFOSx.h new file mode 100755 index 00000000..f3f48b0d --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFOSx.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFOSx.h + GFSDK OS Abstraction API header file. +*/ + +#ifndef __GFOSx_H__ +#define __GFOSx_H__ + +#include "GFRmOEM.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupOSx OSxAPI OS Abstraction API +*/ +/*@{*/ + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFOSxOpen(GFRmHandle hRm, GFOSxHandle *phOSx, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFOSxClose(GFOSxHandle *phOSx); + +/*@}*/ + +#ifdef __cplusplus +} +#endif + +#endif // _GFOSx_H_ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFOption.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFOption.h new file mode 100755 index 00000000..c54f0d7e --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFOption.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFOption.h + GFSDK (Compile-time) Option header file. + Contains user level options and selected compile-time options. +*/ + +#ifndef __GFOPTION_H__ +#define __GFOPTION_H__ + +#include "cpuopsys.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +/*************************************************************************** + * Hardware Dependent Options and Compile-time selections + ***************************************************************************/ + +/** @name Device ID options and compile-time selection + @anchor DeviceIDs + #GF_DEVICE_ID_DEFAULT option is for selecting any ID. +@{*/ + +#define GF_DEVICE_ID_DEFAULT 0x0000 +#define GF_DEVICE_ID_SC11 0x0011 +#define GF_DEVICE_ID_SC15 0x0015 +#define GF_DEVICE_ID_SC14 0x0014 + +#ifndef GF_DEVICE_ID +#define GF_DEVICE_ID GF_DEVICE_ID_SC15 + // Primary chip id +#endif /* GF_DEVICE_ID */ + +#define GF_DEVICE_ID_MASK 0x0000FFFF +#define GF_DEVICE_ID_SHIFT 0 +#define GF_DEVICE_ID_VALUE( val ) \ + (((val) >> GF_DEVICE_ID_SHIFT) & GF_DEVICE_ID_MASK) +/*@}*/ + +/** @name Device Revision options and compile-time selection + @anchor DeviceRevisions + #GF_DEVICE_REV_DEFAULT is for selecting any revision. + Always use 16bit when referring Device Revision only. +@{*/ +#define GF_REV_A1 0x00A1 +#define GF_REV_A2 0x00A2 +#define GF_REV_A3 0x00A3 +#define GF_REV_A4 0x00A4 + +#define GF_DEVICE_REV_DEFAULT 0x0000 +#ifndef GF_DEVICE_REV +#define GF_DEVICE_REV GF_DEVICE_REV_DEFAULT + //!< Primary chip revision +#endif /* GF_DEVICE_REV */ + +#define GF_DEVICE_REV_MASK 0x0000FFFF +#define GF_DEVICE_REV_SHIFT 16 +#define GF_DEVICE_REV_VALUE( val ) \ + (((val) >> GF_DEVICE_REV_SHIFT) & GF_DEVICE_REV_MASK) + +/*@}*/ + +#if defined(NVCPU_XTENSA) + +// On DSP, we always use direct addressing. +#define GF_DEVICE_ADDRESS_DEFAULT GF_DEVICE_ADDRESS_DIRECT +#define GF_DEVICE_ADDRESS GF_DEVICE_ADDRESS_DIRECT + +#else + +// On host CPU, direct & indirect addressing are available in runtime. Default +// is direct addressing. +#ifndef GF_DEVICE_ADDRESS_DEFAULT +#define GF_DEVICE_ADDRESS_DEFAULT GF_DEVICE_ADDRESS_DIRECT +#endif /* GF_DEVICE_ADDRESS_DEFAULT */ + +#ifndef GF_DEVICE_ADDRESS +#define GF_DEVICE_ADDRESS ( GF_DEVICE_ADDRESS_DIRECT \ + | GF_DEVICE_ADDRESS_INDIRECT16 \ + | GF_DEVICE_ADDRESS_INDIRECT8 \ + | GF_DEVICE_ADDRESS_INDIRECT32) +#endif /* GF_DEVICE_ADDRESS */ + +#endif + + + +/*************************************************************************** + * Operating system Dependent Options + ***************************************************************************/ + +/* The bootloader has already initialized the chip and display. To avoid + * writing the hardware again (which can cause screen flicker and other + * symptoms that the customer doesn't like), define this variable to 1. + */ +#ifndef GF_BOOTLOADER_PRESENT +#define GF_BOOTLOADER_PRESENT 0 +#endif + + + + +// If we're compiling for the bootloader right now, of course the +// bootloader cannot be present +#ifdef GF_BOOT_LIB +#undef GF_BOOTLOADER_PRESENT +#define GF_BOOTLOADER_PRESENT 0 +#endif + +/************************************************************************** + * GFSDK Library Auto Compiler Options + * Attempts to set up enough options if none is specified by Build Project. + **************************************************************************/ + +// XXX We should get rid of NV_DEBUG, so we don't have both DEBUG and NV_DEBUG +#if defined(NV_WINDOWS) && !defined(NV_WINDOWS_CE) +#ifdef _DEBUG +#ifndef NV_DEBUG +#define NV_DEBUG 1 +#endif +#endif +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFOPTION_H__ */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRm.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRm.h new file mode 100755 index 00000000..6669abcd --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRm.h @@ -0,0 +1,2039 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFRm.h + GFSDK Resource Manager API header file. +*/ + +#ifndef __GFRM_H__ +#define __GFRM_H__ + +#include "GF.h" +#include "GFRmError.h" + +/** @addtogroup groupRm RmAPI Resource Manager API +
        +
      • @ref pageRmAppNotes +
          +
        • @ref pageRmAppNotes1 +
        +
      +*/ +/*@{*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "GFRmScr.h" + +/** Hardware Module IDs. + List of all the modules in the SCXX chips. +*/ +typedef enum +{ +#define GFRM_MODULE(x,y) MODID_##x, +#include "gfrm_module_ids.h" +#undef GFRM_MODULE + GFNUMOFMODULEIDS +} eGFModuleIDs; + +/** @name Power Planes/Islands + List of all the power planes in the SCXX chips. +@{*/ + +/** Power Plane ID: Core Power Plane. */ +#define GFPPID_AOCVDD 0x00000001 + +/** Power Plane ID: Video Codec Power Plane. */ +#define GFPPID_VECVDD 0x00000002 + +/** Power Plane ID: SRAM Power Plane. */ +#define GFPPID_MMCVDD 0x00000004 + +/** Power Plane ID: 3D Power Plane. */ +#define GFPPID_TDCVDD 0x00000008 + +/** Power Plane ID: SRAM I/O Power Plane. */ +#define GFPPID_EMVDD 0x00000010 + +/** Power Plane ID: Mostly Bus Interface Power Plane. */ +#define GFPPID_HVDD 0x00000020 + +/** Power Plane ID: Video I/O Power Plane. */ +#define GFPPID_VVDD 0x00000040 + +/** Power Plane ID: LCD I/O Power Plane. */ +#define GFPPID_LVDD 0x00000080 + +/** Power Plane ID: Audio I/O Power Plane. */ +#define GFPPID_ACVDD 0x00000100 + +/** Power Plane ID: SD I/O Power Plane. */ +#define GFPPID_SDVDD 0x00000200 + +/** Power Plane ID: Oscillator Power Plane. */ +#define GFPPID_AVDDOSC 0x00000400 + +/** Power Plane ID: PLL1 Power Plane. */ +#define GFPPID_AVDDP1 0x00000800 + +/** Power Plane ID: PLL2 Power Plane. */ +#define GFPPID_AVDDP2 0x00001000 + +/** Power Plane ID: DRAM Power Plane. */ +#define GFPPID_DRAM 0x00002000 + +/** Number of power plane IDs. */ +#define GFNUMOFPPIDS 14 + +/*@}*/ + +/** @name States for Component Manager and general services +@{*/ + +/** State for registering Component. + @see GF_STATE_TYPE, GFRmComponentGet(). +*/ +#define GF_STATE_REGISTER 0x00000001 + +/** State for unregistering Component. + @see GF_STATE_TYPE, GFRmComponentRelease(). + */ +#define GF_STATE_UNREGISTER 0x00000002 + +/** State for unregistering all Components (internal used only). + @see GF_STATE_TYPE, GFRmComponentRelease(). + */ +#define GF_STATE_UNREGISTER_ALL 0x00000004 + +/** General Enable State. + @see GF_STATE_TYPE. +*/ +#define GF_STATE_ENABLE 0x00000008 + +/** General Disable State. + @see GF_STATE_TYPE. +*/ +#define GF_STATE_DISABLE 0x00000010 + +/** General Done State. + @see GF_STATE_TYPE. +*/ +#define GF_STATE_DONE 0x00000020 + +/** State for instantiating a new or share Component. + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_NEW_OR_SHARE 0x00000100 + +/** State for instantiating a new Component only. + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_NEW_ONLY 0x00000200 + +/** State for instantiating a share Component only. + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_SHARE_ONLY 0x00000400 + +/** State indicating special Block Device Component (internal use). + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_BLOCK_DEVICE 0x80000000 + +/** Default Component instantiation State. + @see GF_STATE_TYPE, GFRmComponentGet(). + */ +#define GF_STATE_DEFAULT GF_STATE_NEW_OR_SHARE + +/** Mask for the regular States. + @see GF_STATE_TYPE. +*/ +#define GF_STATE_MASK 0x000000FF + +/*@}*/ + + +/** Attributes ID/Values. + @see GFRmGetAttribute(), GFRmSetAttribute(). +*/ +typedef enum +{ + /** Attribute for changing device bus addressing (direct/indirect) mode. */ + GF_ATTRIB_DEVICE_ADDRESS, + + /** Attribute for mapped/virtual/usable I/O base address. */ + GF_ATTRIB_IO_MAP_BASE, + + /** Attribute for mapped/virtual/usable embedded memory base. */ + GF_ATTRIB_EMBEDDED_MEM_MAP_BASE, + + /** Attribute for initial embedded internal memory size. */ + GF_ATTRIB_INIT_EMBEDDED_MEM_TOTAL, + + /** Attribute for initial available embedded internal memory size. */ + GF_ATTRIB_INIT_EMBEDDED_MEM_AVAIL, + + /** Attribute for initial embedded extended memory size. */ + GF_ATTRIB_INIT_EXT_EMBEDDED_MEM_TOTAL, + + /** Attribute for user specific object 0. */ + GF_ATTRIB_USER_OBJECT_0, + + /** Attribute for user specific object 1. */ + GF_ATTRIB_USER_OBJECT_1, + + /** Attribute for user specific object 2. */ + GF_ATTRIB_USER_OBJECT_2, + + /** Attribute for user specific object 3. */ + GF_ATTRIB_USER_OBJECT_3, + + /** Attribute for swapping memory allocation with shared embedded memory + MAX CHUNK scheme. For advanced user only. */ + GF_ATTRIB_SWAP_SHARE_MEMORY_ALLOC_ON_MAX_CHUNK, + + /** Get device information structure. + GFRmGetAttribute() parameter \a AttribData is of type PGFRMDEVICEINFO. + */ + GF_ATTRIB_DEVICE_INFO_STRUCT, + + /** For internal use only. */ + GF_ATTRIB_RMC_FLAG, + + /** Enable/Disable Hardware Resource Constraint. */ + GF_ATTRIB_HW_RESOURCE_CONSTRAINT, + + /** Enable embedded extended memory. */ + GF_ATTRIB_ENABLE_EXTENDED_MEMORY, + + /** Disable RMC trace, closing any log files that might be opened */ + GF_ATTRIB_DISABLE_RMC_TRACE, + + /** Set/Clr surface with absolute rotation option. */ + GF_ATTRIB_SURFACE_ABSOLUTE_ROTATE, + + /** Primary surface freeing policy. */ + GF_ATTRIB_PRIMSURF_FREEING_POLICY, + + /** Primary surface allocation policy. */ + GF_ATTRIB_PRIMSURF_ALLOCATION_POLICY, + + /** Internal use. */ + GF_ATTRIB_EFUSE_PRODUCT_SKU_ID, + + /** Internal use. */ + GF_ATTRIB_MAIN_PANEL_INDEX, + + /** GFRm attribute: Set DSP2Host communication mode. + + This attribute can be used to control how components wait + for messages from the DSP. The following options for \a AttribData are available: + - #GF_ATTRIB_DSPCOMMODE_POLLING -- Register polling. + This mode is intended for debuging only, since it allows only one client + to use DSP2Host interrupts. + - #GF_ATTRIB_DSPCOMMODE_EVENT -- Receive DSP2Host messages via an interrupt framework. + This mode requires an ISR/IST to be setup, that handles DSP interrupts and calls + GFRmDispatchMessage(). + + The default setting is register polling. + + Attribute can be get and set. + + @see GFRmSetAttribute(), GFRmGetAttribute(), GFRmQueueSetHandler(), GFRmDispatchMessage() + */ + GF_ATTRIB_DSPCOMMODE, + + /** Set surface for DSP debug console output. + + This sets a surface which will be used to output text from the DSP debug console. + The DSP XRM must be initialized before this function can be called. + + GFRmSetAttribute() parameter \a AttribData is of type #PGFRMSURFACE and defines a pointer to a + surface descriptor. + + @retval GF_SUCCESS Successfully send message + @retval GF_WAIT_TIME_OUT Timeout sending message + @retval GFRM_ERROR_BAD_PARAMETER Bad parameters, e.g. surface color format is not supported + + @see GFRmSetAttribute() + + Attribute can be set only. + */ + GF_ATTRIB_DSPCONSOLE_SURFACE, + + /** Internal use. */ + GF_ATTRIB_USE_CAMERA_SCRIPT, + + /** Internal use. */ + GF_ATTRIB_DEVICE_TYPE, + + /** Timeout in ms for RM IST to wait for interrupts. + Set to 0 to disable timeout, default setting is 1000 ms. + GFRmSetAttribute() parameter \a AttribData is of type NvU32 and defines timout in ms. + */ + GF_ATTRIB_INTX_TIMEOUT, + + /** Enable debug printout for GPU memory allocations. + + GFRmSetAttribute() parameter \a AttribData is of type NvU32, + - 0 means disable log (default) + - !=0 means enable log + + This GFRmSetAttribute() call always succeeds. + + @see GFRmSetAttribute() + + Attribute can be set only. + */ + GF_ATTRIB_GPUMEM_ENABLELOG + +} GF_ATTRIBUTE_TYPE; + +/** DSP2Host communication modes, polling. + @see GF_ATTRIB_DSPCOMMODE +*/ +#define GF_ATTRIB_DSPCOMMODE_POLLING 0 +/** DSP2Host communication modes, OS event synchronization. + @see GF_ATTRIB_DSPCOMMODE +*/ +#define GF_ATTRIB_DSPCOMMODE_EVENT 1 + +/** GFSDK (low-level) device interface type. (Read Only) + * @see GF_ATTRIB_DEVICE_TYPE. + **/ +#define GF_ATTRIB_DEVICE_TYPE_HARDWARE 0x00000000 +#define GF_ATTRIB_DEVICE_TYPE_SIMULATOR 0x00001000 + + +/** @name Component Types + +@{*/ + +/** Component Type: EPP Component. + @anchor ComponentTypes +*/ +#define GF_EPPAPI 0x00000001L + +/** Component Type: Gx (2D) API Component. */ +#define GF_GXAPI 0x00000002L + +/** Component Type: Vx (general Video and Video Input Port) API Component. */ +#define GF_VXAPI 0x00000003L + +/** Component Type: JxE (JPEG Encode) API Component. */ +#define GF_JXEAPI 0x00000004L + +/** Component Type: JxE (JPEG Decode) API Component. */ +#define GF_JXDAPI 0x00000005L + +/** Component Type: MxE (MPEG Encode) API Component. */ +#define GF_MXEAPI 0x00000006L + +/** Component Type: MxD (MPEG Decode) API Component. */ +#define GF_MXDAPI 0x00000007L + +// 0x8 is unused + +/** Component Type: Dx (Display and Flat Panel) API Component. */ +#define GF_DXAPI 0x00000009L + +// 0xA is unused + +/** Component Type: ISP (Image Signal Processing) API Component. */ +#define GF_ISPAPI 0x0000000BL + +/** Component Type: FDev (Pseudo File System/Device) API Component. */ +#define GF_FDEVAPI 0x0000000CL + +/** Component Type: BDevSD (SD Block Device) Component. */ +#define GF_BDEVSDAPI 0x0000000DL + +// 0xE is unused +// 0xF is unused + +/** Component Type: OSx (Operating System) API COmponent */ +#define GF_OSXAPI 0x00000010L + +/** Component Type: I2C API Component */ +#define GF_I2CAPI 0x00000011L + +/** Component Type: I2S API COmponent */ +#define GF_I2SAPI 0x00000012L + +/** Component Type: MMProc (Audio) API COmponent */ +#define GF_MMPROCAPI 0x00000013L + +/** Component Type: CAM (Camera) API Component */ +#define GF_CAMAPI 0x00000014L + +/** Component Type: 3D API Component */ +#define GF_3DAPI 0x00000015L + +/** Component Type: INTx (Interrupt) API COmponent */ +#define GF_INTXAPI 0x00000016L + +/** Component Type: MXDH264 (H264 Decoder) API COmponent */ +#define GF_MXDH264API 0x00000017L + +/** Component Type: MXEH264 (H264 Encoder) API Component */ +#define GF_MXEH264API 0x00000018L + +/** Component Type: RM (Resource Manager) Services (listed only for return status). */ +#define GF_RMAPI 0x00000019L + +/** Component Type: GxFB (Gx/2D API with Frame Buffer rendering) API. Internal Use. */ +#define GF_GXFBAPI 0x0000001AL + +/** MXDRV9 (RV9 Decoder) API COmponent */ +#define GF_MXDRV9API 0x0000001BL + +/** Component Type: MXDVC1 (VC1 Decoder) API Component */ +#define GF_MXDVC1API 0x0000001CL + +/** Component Type: MXDEMTS (MPEG TS Demux) API Component */ +#define GF_MXDEMTSAPI 0x0000001DL + +/** Component Type: Minimal ISP API Component (NvIsp) */ +#define GF_MINIMALISPAPI 0x0000001EL + +/** Component Type: NvISP API Component ID -- only used for GF_TRACE */ +#define NV_ISPAPI 0x0000001FL + +/*@}*/ + +/** NULL driver related. Internal use. */ +#define GF_USE_NULL_DRIVER 0x1 + +/** NULL driver related. Internal use. */ +#define GF_USE_HW_DRIVER 0x2 + + +/** @name Hardware Resources + @anchor HardwareResources + Flags 'hwEngineReq' in GFRmHwResourceConstraint(). (not working yet). + @see GFRmHwResourceConstraint(). +@{*/ + +/** Hardware resource flag: MPEG Decoder Engine. */ +#define GF_HWR_MPEGD 0x00000001 + +/** Hardware resource flag: JPEG Decoder is same as MPEG Decoder Engine. */ +#define GF_HWR_JPEGD 0x00000001 + +/** Hardware resource flag: MPEG Encoder Engine. */ +#define GF_HWR_MPEGE 0x00000002 + +/** Hardware resource flag: JPEG Encoder shares FrontEnd and BackEnd with JPEG Enc Engine. */ +#define GF_HWR_JPEGE 0x00000002 + +/** Hardware resource flag: Video Input Port. */ +#define GF_HWR_VIP 0x00000004 + +/** Hardware resource flag: EPP */ +#define GF_HWR_EPP 0x00000008 + + + +/** Options for GFRmHwResourceConstraint(). + (not working yet!) + @see GFRmHwResourceConstraint(). +*/ +typedef enum +{ + /** check availability and allocate hardware resource. */ + GF_HRC_ALLOCATE, + + /** free hardware resource. */ + GF_HRC_FREE, + + /** check availability of hardware resource. */ + GF_HRC_CHECK +} GF_HRC_OPTIONS; + +/*@}*/ + +/** Component ID structure. */ +typedef struct _GFRMCOMPONENTID +{ + NvU32 ComponentType; /**< Component Type, see @ref ComponentTypes. */ + GFRmChHandle CxtHandle; +} GFRMCOMPONENTID, *PGFRMCOMPONENTID; + +/* Component */ + +/* forward declaration */ +typedef struct _GFRMCOMPONENT GFRMCOMPONENT, *PGFRMCOMPONENT; + +typedef GF_HANDLE (* GFOPENFUNCTIONTYPE)(GFRmHandle pRm, GFRmChHandle); +typedef GF_RETTYPE (* GFCLOSEFUNCTIONTYPE)(GF_HANDLE *); + +/** Component Registration structure. + Internal use. + @internal +*/ +struct _GFRMCOMPONENT +{ + GFRMCOMPONENTID id; /**< Structure defining component. */ + GFOPENFUNCTIONTYPE Open; /**< Component Open callback. Called from GFRmComponentGet(). */ + GFCLOSEFUNCTIONTYPE Close; /**< Component Close callback. Called from GFRmComponentRelease(). */ +}; + + +/** @name Surface Types + @anchor SurfaceTypes + @see GFRmSurfaceAlloc(). +@{*/ + +/** Surface Type: Surface rotation orientation at 0 degree. */ +#define GF_SURFACE_ROTATE_0 0x00000000 + +/** Surface Type: Surface rotation orientation at 90 degree (relative to _ROTATE_0). */ +#define GF_SURFACE_ROTATE_90 0x10000000 + +/** Surface Type: Surface rotation orientation at 180 degree (relative to _ROTATE_0). */ +#define GF_SURFACE_ROTATE_180 0x20000000 + +/** Surface Type: Surface rotation orientation at 270 degree (relative to _ROTATE_0). */ +#define GF_SURFACE_ROTATE_270 0x30000000 + +/* + * GF_SURFACE_H_FLIP and GF_SURFACE_V_FLIP can be ORed with above 4 rotation + * options to create 16 combinations but in reality there are only 8 unique + * combinations. + */ + +/** Surface Type: Horizontal Flip. You can or'ed this flag with _ROTATE_ flag above too. */ +#define GF_SURFACE_H_FLIP 0x40000000 + +/** Surface Type: Vertical Flip. You can or'ed this flag with _ROTATE_ flag above too. */ +#define GF_SURFACE_V_FLIP 0x80000000 + +/** Surface Type: internal use. */ +#define GF_SURFACE_ROTATE_MASK 0xF0000000 + +/** Surface Type: internal use. */ +#define GF_SURFACE_PLANAR_ROTATE_MASK 0x30000000 + +/** Surface Type: internal use. */ +#define GF_SURFACE_ROTATE_SHIFT 28 // bits[31:28] + +/** Surface Type: internal use. */ +#define GF_SURFACE_ROTATE_WRAP 8 + +/** Surface Type: Primary Surface (default rotate orientation). */ +#define GF_SURFACE_PRIMARY 0x00000001 //primary surface + +/** Surface Type: Primary Surface with 0 degree rotation. */ +#define GF_SURFACE_PRIMARY_0 (GF_SURFACE_PRIMARY| GF_SURFACE_ROTATE_0) + +/** Surface Type: Primary Surface with 90 degree rotation. */ +#define GF_SURFACE_PRIMARY_90 (GF_SURFACE_PRIMARY| GF_SURFACE_ROTATE_90) + +/** Surface Type: Primary Surface with 180 degree rotation. */ +#define GF_SURFACE_PRIMARY_180 (GF_SURFACE_PRIMARY| GF_SURFACE_ROTATE_180) + +/** Surface Type: Primary Surface with 180 degree rotation. */ +#define GF_SURFACE_PRIMARY_270 (GF_SURFACE_PRIMARY| GF_SURFACE_ROTATE_270) + +/** Surface Type: Overlay Surface. */ +#define GF_SURFACE_OVERLAY 0x00000002 + +/** Surface Type: Surface to reside in embedded (video) memory. */ +#define GF_SURFACE_VIDEO_MEMORY 0x00000004 + +/** Surface Type: Surface to reside in system memory. */ +#define GF_SURFACE_SYSTEM_MEMORY 0x00000008 + +/** Surface Type: Sub primary surface (for Sub LCD). */ +#define GF_SURFACE_PRIMARY_SUB 0x00000100 //Sub primary surface + +/** Surface Type: Surface to be allocated from "share" embedded memory for + advanced use only. + Cannot be used with #GF_SURFACE_PRIMARY. + No effect with #GF_SURFACE_SYSTEM_MEMORY. +*/ +#define GF_SURFACE_SHARE 0x00001000 + +/** Surface Type: Allocate surface with pre-allocated memory handle. */ +#define GF_SURFACE_PREALLOCATED_MEM 0x00002000 + +/** Request to use new API */ +#define GF_SURFACE_NEW_API 0x01000000 + +/* + * Note: GF_SURFACE_ROTATE_ refers to caller's view of current logical + * orientation relative to Primary Surface. And Primary surface is + * always set to GF_SURFACE_ROTATE_0 even though physical LCD Display + * panel may require different physical orientation. + */ + +/*@}*/ + +/** @name Surface Hints + @anchor SurfaceHints + @see GFRmSurfaceAlloc(). +@{*/ + +/** Surface Hint: Alloc from highest possible position. */ +#define GF_SURFACE_HINT_TOP_DOWN 0x1 + +/** Surface Hint: Alloc from lowest possible position. */ +#define GF_SURFACE_HINT_BOTTOM_UP 0x2 + +/** Surface Hint: Alloc max chunck of memory. */ +#define GF_SURFACE_HINT_MAX_CHUNK 0x4 + +/** Surface Hint: Try allocations from external memory first before internal memory */ +#define GF_SURFACE_HINT_EXT_MEMORY_PREFERRED 0x8 + +/** Surface Hint: Try allocations only from external memory. */ +#define GF_SURFACE_HINT_EXT_MEMORY_ONLY 0x10 + +/** Surface Hint: Try allocations only from internal memory. */ +#define GF_SURFACE_HINT_INT_MEMORY_ONLY 0x20 + +/** Surface Hint: Alloc from embedded memory, YUV in the same contiguous memory. + Valid only for GF_SURFACE_YUV420. +*/ +#define GF_SURFACE_HINT_CONTIGUOUS_MEMORY 0x40 + +/** Surface Hint: Try allocations from internal memory first before external memory */ +#define GF_SURFACE_HINT_INT_MEMORY_PREFERRED 0x80 + +/** Surface Hint: Hints to align stride to 4 bytes - default for YUV422 */ +#define GF_SURFACE_HINT_STRIDE_ALIGN4 0x100 + +/** Surface Hint: Hints to align stride to 8 bytes */ +#define GF_SURFACE_HINT_STRIDE_ALIGN8 0x200 + +/** Surface Hint: Hints to align stride to 16 bytes */ +#define GF_SURFACE_HINT_STRIDE_ALIGN16 0x400 + +/** Surface Hint: Hints to align stride to 32 bytes */ +#define GF_SURFACE_HINT_STRIDE_ALIGN32 0x800 + +/** Surface Hint: Surface will be used for direct read by the applications */ +#define GF_SURFACE_NEED_DIRECT_CPU_READ 0x1000 + +/** Surface Hint: Surface will be used for direct write by the applications */ +#define GF_SURFACE_NEED_DIRECT_CPU_WRITE 0x2000 + +/** Surface Hint: Surface will be used for direct access by the applications + both read and write actions are allowed + */ +#define GF_SURFACE_NEED_DIRECT_CPU_ACCESS \ + (GF_SURFACE_NEED_DIRECT_CPU_READ | GF_SURFACE_NEED_DIRECT_CPU_WRITE) +/*@}*/ + +/** @name Primary surface allocation and freeing policies + @see GFRmSetAttribute(). +@{*/ + +/** Any avaliable memory. Use with GF_ATTRIB_PRIMSURF_ALLOCATION_POLICY. */ +#define GF_ATTRIB_PRIMSURF_ALLOCP_NONE 0x0 + +/** Allocate Primary surface from embedded extended memory. + Use with GF_ATTRIB_PRIMSURF_ALLOCATION_POLICY. +*/ +#define GF_ATTRIB_PRIMSURF_ALLOCP_USE_EXT_MEM 0x1 + +/** Allocate Primary surface from internal memory (SRAM). + Use with GF_ATTRIB_PRIMSURF_ALLOCATION_POLICY. +*/ +#define GF_ATTRIB_PRIMSURF_ALLOCP_USE_INT_MEM 0x2 + +/** Use with GF_ATTRIB_PRIMSURF_FREEING_POLICY. */ +#define GF_ATTRIB_PRIMSURF_FREEP_NONE 0x0 + +/** Never free, Default policy. Use with GF_ATTRIB_PRIMSURF_FREEING_POLICY. */ +#define GF_ATTRIB_PRIMSURF_FREEP_NEVER_FREE 0x0 + +/** Free when the ref count is zero. Use with GF_ATTRIB_PRIMSURF_FREEING_POLICY. */ +#define GF_ATTRIB_PRIMSURF_FREEP_FREE_ON_EMPTY 0x1 + +/** Force free. Use with GF_ATTRIB_PRIMSURF_FREEING_POLICY. */ +#define GF_ATTRIB_PRIMSURF_FREEP_FORCE_FREE 0x2 + +/*@}*/ + +/** Surface structure. + @see GFRmSurfaceAlloc(), GFRmSurfaceFree(). +*/ +typedef struct _GFRMSURFACE +{ + NvU32 width; /**< Width in pixels. */ + NvU32 height; /**< Height in lines. */ + NvU32 SurfaceType; /**< Surface type, see @ref SurfaceTypes. */ + NvU32 ColorFormat; /**< Surface color format, see @ref SurfaceTypes. */ + + NvU32 YStride; /**< Stride for RGB, YUV422 surfaces, or Y plane. */ + NvU32 UStride; /**< U plane stride */ + NvU32 VStride; /**< V plane stride */ + + GFRmMemHandle YMemHandle; /**< Opaque handle for RGB, YUV422 surface, or Y plane memory. */ + GFRmMemHandle VMemHandle; /**< Opaque handle for V plane memory. */ + GFRmMemHandle UMemHandle; /**< Opaque handle for U plane memory. */ + + NvU32 YOffset; /**< Physical address of RGB, YUV422 surfae, or Y plane. */ + NvU32 UOffset; /**< Physical address of U plane. */ + NvU32 VOffset; /**< Physical address of U plane. */ + + /* Direct addressable pointer to the memory region. Don't + use these pointers, unless you want to run only in + "direct addressing mode". Instead, use handles for reading + or writing to the memory from the host, and offsets for + programming the hardware registers. */ + + NvU8 *pY; /**< Pointer to non-planar surface or Y plane of YUV420, valid only for direct addressing. */ + NvU8 *pU; /**< for YUV420 surface, valid only for direct addressing. */ + NvU8 *pV; /**< for YUV420 surface, valid only for direct addressing. */ + + NvU32 memUsed; /**< Total number of bytes used by surfaces. */ + + //void *reserved; // Reserved. Do not modify +} GFRMSURFACE, *PGFRMSURFACE; + +/** Surface Request + @see GFRmSurfaceAlloc(), GFRmSurfaceFree(). +*/ +typedef struct _GFRMSURFACEREQUEST +{ + NvU32 width; /**< Width in pixels. */ + NvU32 height; /**< Height in lines. */ + NvU32 SurfaceType;/**< Surface type, see @ref SurfaceTypes. */ + NvU32 ColorFormat;/**< Surface color format, see @ref SurfaceTypes. */ + NvU32 hint; /**< Allocation hint or 0, see @ref SurfaceHints. */ + NvU8 *pMem; /**< Pointer to pre-allocated memory from which + to allocate the surface planes. */ + NvU32 memSize; /**< Size of pre-allocated Y plane memory. */ + NvU32 id; /**< User defined ID to track allocated block, debugging use */ + + /* Reserved for future */ + /* GF_RETTYPE (* pSurfaceCallBack) + ( GFRmHandle RmHandle, PGFRMSURFACE pSurface); */ + /* Reserved for future */ + /* PGFRMSURFACE pSurfaceShare; */ +} GFRMSURFACEREQUEST, *PGFRMSURFACEREQUEST; + +/** Device Info */ +typedef struct _GFRMDEVICEINFO +{ + NvU32 MinorRev; + NvU32 MajorRev; + NvU32 ChipID; + NvU32 Family; +} GFRMDEVICEINFO, *PGFRMDEVICEINFO; + +/** @name Surface Update Flags + @anchor SurfaceUpdateFlags + @see GFRmSurfaceUpdate() +@{*/ + +/** GFRmSurfaceUpdate() attribute type: Update surface rotation. + + The following values are valid for parameter \a data of GFRmSurfaceUpdate(): +
      +    #GF_SURFACE_ROTATE_0
      +    #GF_SURFACE_ROTATE_90
      +    #GF_SURFACE_ROTATE_180
      +    #GF_SURFACE_ROTATE_270
      +    
      + + @see GFRmSurfaceUpdate() +*/ +#define GF_SURFACE_UPDATE_ROTATE 0x00000001 + +/** GFRmSurfaceUpdate() attribute type: Update surface width. + + Meaning of parameter \a data of GFRmSurfaceUpdate(): + New surface width in pixels. + + The number of bytes required for the new width must not exceed the + surface stride. It is the responsibility of the caller to ensure this. + + @see GFRmSurfaceUpdate() +*/ +#define GF_SURFACE_UPDATE_WIDTH 0x00000002 + +/** GFRmSurfaceUpdate() attribute type: Update surface height. + + Meaning of parameter \a data of GFRmSurfaceUpdate(): + New surface height in line. + + The set height * surface stride must not exceed the memory allocated + for the surface. It is the responsibility of the caller to ensure this. + + @see GFRmSurfaceUpdate() +*/ +#define GF_SURFACE_UPDATE_HEIGHT 0x00000003 + +/** GFRmSurfaceUpdate() attribute type: Update surface width and stride. + + Meaning of parameter \a data of GFRmSurfaceUpdate(): + New surface width in pixels. + + YStride, UStride, and VStride will be updated automatically according + to alignment requirements. Supported colour formats: + - GF_SURFACE_YUV420 + + @see GFRmSurfaceUpdate() +*/ +#define GF_SURFACE_UPDATE_WIDTH_STRIDE 0x00000004 + +/*@}*/ + + +/** @name Memory types + @anchor MemoryTypes + @see GFRMMEMORYREQUEST, GFRmMemHandleAlloc() +@{*/ + +/** Memory Type: Host system memory. */ +#define GF_MEMORY_SYSTEM 0x01 +/** Memory Type: Any GPU memory */ +#define GF_MEMORY_EMBEDDED 0x02 +/** Memory Type: Memory mapped memory. */ +#define GF_MEMORY_MEMMAPPED 0x04 +/** Memory Type: External GPU memory only. */ +#define GF_MEMORY_EMBEDDED_EXT_ONLY GF_MEMORY_EMBEDDED_EXT +#define GF_MEMORY_EMBEDDED_EXT 0x08 +/** Memory Type: Internal GPU memory only. */ +#define GF_MEMORY_EMBEDDED_INT_ONLY GF_MEMORY_EMBEDDED_INT +#define GF_MEMORY_EMBEDDED_INT 0x10 +/** Memory type: Internal or external memory with preference to internal memory. */ +#define GF_MEMORY_EMBEDDED_INT_PREFERRED 0x20 +/** Memory type: External or internal memory with preference to external memory. */ +#define GF_MEMORY_EMBEDDED_EXT_PREFERRED 0x40 +/** Memory type: Direct Read access */ +#define GF_MEMORY_DIRECT_CPU_READ_ACCESS 0x80 +/** Memory type: Direct Write access */ +#define GF_MEMORY_DIRECT_CPU_WRITE_ACCESS 0x100 + +/** Memory type: Direct Read/Write access */ +#define GF_MEMORY_DIRECT_CPU_ACCESS (GF_MEMORY_DIRECT_CPU_WRITE_ACCESS | GF_MEMORY_DIRECT_CPU_READ_ACCESS) + +/*@}*/ + +/** @name Memory Share Types + @anchor MemoryShare + @see GFRMMEMORYREQUEST, GFRmMemHandleAlloc() +@{*/ + +/** Memory Share Flag: Internal use, used in GFRmMemInfo only. */ +#define GF_MEMORY_SHARE 0x80 + +/*@}*/ + +/** @name Memory Alignment + @anchor MemoryAlignment + @see GFRMMEMORYREQUEST, GFRmMemHandleAlloc() +@{*/ + +/** Memory alignment types, must match log2 of alignment size. */ +enum +{ + GF_MEMORY_ALIGN_NONE = 0, /**< Memory Alignment: Don't care. */ + GF_MEMORY_ALIGN2, /**< Memory Alignment: Aligned to 2 byte boundary. */ + GF_MEMORY_ALIGN4, /**< Memory Alignment: Aligned to 4 byte boundary. */ + GF_MEMORY_ALIGN8, /**< Memory Alignment: Aligned to 8 byte boundary. */ + GF_MEMORY_ALIGN16, /**< Memory Alignment: Aligned to 16 byte boundary. */ + GF_MEMORY_ALIGN32, /**< Memory Alignment: Aligned to 32 byte boundary. */ + GF_MEMORY_ALIGN64, /**< Memory Alignment: Aligned to 64 byte boundary. */ + GF_MEMORY_ALIGN128, /**< Memory Alignment: Aligned to 128 byte boundary. */ + GF_MEMORY_ALIGN256, /**< Memory Alignment: Aligned to 256 byte boundary. */ + GF_MEMORY_ALIGN512, /**< Memory Alignment: Aligned to 512 byte boundary. */ + GF_MEMORY_ALIGN1024, /**< Memory Alignment: Aligned to 1024 byte boundary. */ + GF_MEMORY_ALIGN2048, /**< Memory Alignment: Aligned to 2048 byte boundary. */ + GF_MEMORY_ALIGN4096, /**< Memory Alignment: Aligned to 4096 byte boundary. */ + GF_MEMORY_ALIGN_DSP = 0xFF /**< Memory Alignment: Aligned properly for DSP cacheline size. */ +}; + +/*@}*/ + +/** @name Memory Allocation Hints + @anchor MemoryHints + @see GFRMMEMORYREQUEST, GFRmMemHandleAlloc() +@{*/ +/* Memory Hint - Follow Surface Hint */ +/** Memory Allocation Hint: Allocate from high to low addresses. */ +#define GF_MEMORY_HINT_TOP_DOWN GF_SURFACE_HINT_TOP_DOWN +/** Memory Allocation Hint: Allocate from low to high addresses. */ +#define GF_MEMORY_HINT_BOTTOM_UP GF_SURFACE_HINT_BOTTOM_UP +/** Memory Allocation Hint: Allocate from maximum available chunk. */ +#define GF_MEMORY_HINT_MAX_CHUNK GF_SURFACE_HINT_MAX_CHUNK +/** Memory Allocation Hint: Allocate at fixed address. */ +#define GF_MEMORY_HINT_FIXED (GF_MEMORY_HINT_MAX_CHUNK << 1) +/** Memory Allocation Hint: Allocate for 3D. */ +#define GF_MEMORY_HINT_3D (GF_MEMORY_HINT_MAX_CHUNK << 2) + +/* These options are for DRAM as extended memory. This option specifies + * bank the buffer should come from. This will avoid + * bank clobbering between two buffers that are accessed in lock + * step. + */ + +/** Memory Allocation Hint: Allocate from even banks in external memory. */ +#define GF_MEMORY_HINT_EVEN_BANK (GF_MEMORY_HINT_MAX_CHUNK << 3) +/** Memory Allocation Hint: Allocate from odd banks in external memory. */ +#define GF_MEMORY_HINT_ODD_BANK (GF_MEMORY_HINT_MAX_CHUNK << 4) +/*@}*/ + +/** Memory allocation request. + @see GFRmMemHandleAlloc() +*/ +typedef struct _GFRMMEMORYREQUEST +{ + NvU32 length; /**< Size in bytes. */ + NvU32 hint; /**< Allocation hint or 0, see @ref MemoryHints. */ + struct + { + NvU16 type; /**< Memory type, see @ref MemoryTypes. */ + NvU8 share; /**< Share flags or 0, see @ref MemoryShare. */ + NvU8 align; /**< Alignment flags, see @ref MemoryAlignment. */ + } + flag; + NvU32 id; /**< User defined ID to track allocated block, debugging use */ +} GFRMMEMORYREQUEST, *PGFRMMEMORYREQUEST; + +/** OS Critical Section bits 0-15 are general purpose use +bit 16-31 are for internal use */ +#define GF_CRITICAL_SECTION_HW 0x00000001 +/** RM internal use */ +#define GF_CRITICAL_SECTION_SW2 0x00000004 +/** RM internal use */ +#define GF_CRITICAL_SECTION_SW4 0x00000010 +/** I2C critical section */ +#define GF_CRITICAL_SECTION_I2C 0x00000020 +/** RM All channel lock, internal use */ +#define GF_CRITICAL_SECTION_ALL_CHANNELS 0x00000040 + +/** Ix internal use */ +#define GF_CRITICAL_SECTION_SW8 0x00000100 + +/** RM DSP to Host communication, internal use */ +#define GF_CRITICAL_SECTION_D2H 0x00000200 + +/** The SHUTDOWN_DSP lock protects the race between + * UpdateDSPFreq/DSPDisable and HandleInterrupt (IST). + * (Update and DSPDisable turn off the DSP, HandleInt reads + * DSP regs) + */ +#define GF_CRITICAL_SECTION_SHUTDOWN_DSP 0x00000400 +/** The DSP lock protects the race between + * AddTask and RemoveTask. + */ +#define GF_CRITICAL_SECTION_DSP 0x00000401 + +/** Define the ID for the kernel semaphore */ +#define GF_DSP_KERNEL_SEM_ID 0x0CAFEFAD + +/** Shared memory lock - used for internal purposes */ +#define GF_CRITICAL_SECTION_SHM 0x00000800 + +/** RM Host to DSP communication, internal use */ +#define GF_CRITICAL_SECTION_H2D 0x00001000 + +/** Rm internal use: lock for channel structures */ +#define GF_CRITICAL_SECTION_CHSTRUCT 0x00004000 + +/** Dx internal use */ +#define GF_CRITICAL_SECTION_DX 0x00008000 + +/** Vx internal use */ +#define GF_CRITICAL_SECTION_VX 0x00000080 + +#ifdef PROJECT_SEC_G1 +/** JxDec internal use */ +#define GF_CRITICAL_SECTION_JXDEC 0x00002000 +#endif + +/** Rm internal use: lock for DSP messages */ +#define GF_CRITICAL_SECTION_DSPMSG_MIN 0x00010000 +#define GF_CRITICAL_SECTION_DSPMSG_MAX 0x20000000 + +/** Audio Shared Memory lock - used for multiprocess OS */ +#define GF_CRITICAL_SECTION_SWAUDIO 0x10002000 + +/** Maximiun id */ +#define GF_CRITICAL_SECTION_SWMAX 0x00010000 + +/** OS IRQ Callback */ +typedef void (* GFRMOSIRQCALLBACK)( void *pData ); + +struct _GFRMCOMMONSTRUCT; +struct _GFRMENVIRONMENTVARIABLES; +struct _GFRMEXTDATASTRUCT; + +/** Definition of Ix powerplane operations + */ +typedef enum _GFIX_POWERPLANE_OP_TYPE + { + GFIX_POWERPLANE_OP_ENABLE = 0, + GFIX_POWERPLANE_OP_DISABLE, + GFIX_POWERPLANE_OP_QUERY +} GFIX_POWERPLANE_OP_TYPE; + +/** Configuration structure that may be passed to GFRmOpen(). + See GFRmOpen() for details. +*/ +typedef struct _GFRMOPENSTRUCT +{ + NvU32 isFirstProcess; + NvU32 isDeviceMapped; + GF_RETTYPE retStatus; //!< Return error reason code, in case GFRmOpen() fails + + /** Declare which driver HW or NULL driver to use. + This is for GFSDK compiled for NULL driver case. + */ + NvU32 useDriver; +} GFRMOPENSTRUCT; + +/** @name Interface Manager Returned Functions +@{*/ + +/** Write a 32-bit register in the device. + + @param base I/O base address + @param offset Offset of register + @param data Data to write + */ +typedef void (*GF_FUNC_WRITE_32BIT)(void * base, NvU32 offset, NvU32 data); + +/** Read a 32-bit register in the device. + + @param base I/O base address + @param offset Offset of register + + @retval #NvU32 register value + */ +typedef NvU32 (*GF_FUNC_READ_32BIT)(void * base, NvU32 offset); + +/*@}*/ + +/** Interface Options for Read/Write Embedded FIFO (for Jx/Mx APIs) */ +#define GF_EMBFIFO_SWAP_BYTE 0x00000001 +#define GF_EMBFIFO_SWAP_WORD 0x00000002 + +/** Interface FIFO flags */ +/** Front-End FIFO */ +#define GF_FIFO_FEND 0x00000001 +/** GE (2D/Primary) FIFO */ +#define GF_FIFO_SRC 0x00000002 + +/** Interface Helper macro to generate Address Pointer */ +#define GFMAKEADDR(base, offset) (void *)base, offset + +/** Utility Debug Flag */ +#define GF_DEBUG_DEFAULT 0 + +/** 4th argument for GFRmOSGetTickCount */ +#define GF_USEC_TICKS 0 +#define GF_MSEC_TICKS 1 +#define GF_SEC_TICKS 2 + +/** Flags for the Context manager GF_CTX_DEFAULT, GF_CTX_NEW */ +#define GF_CTX_DEFAULT 1 +#define GF_CTX_NEW 2 +#define GF_CTX_SHARED 3 + +/* + ######################################################################## + * Function Prototypes for GFSDK Resource Manager (RM) Services + ######################################################################## + */ + +/* Object Manager */ + +/** GFRmOpen - Starts Resource Manager and GFSDK. + + @param RmOpenHandle Must be NULL. + @return Resource manager handle, or NULL on failure. + + This must be called prior using any GFSDK component APIs and RM services. + This function can be called multiple times, for each successfull call + the application must also call GFRmClose(). + + If this function fails, and a pointer to an open structure is passed in + \a RmOpenHandle, the a failure reasoncode will be returned in GF_OPEN_RETTYPE::retStatus. +*/ +GFRmHandle GFRmOpen(GFRMOPENSTRUCT *RmOpenHandle); + +/** GFRmClose - Ends Resource Manager and GFSDK. + + @param pRmHandle Ptr to RmHandle to be closed. + @retval GF_RETTYPE #GF_SUCCESS if successful.
      + #GF_ERROR on error.
      + + All GFSDK resources will be freed related to this process. + Calls to GFRmOpen are reference counted, GFDSK will be closed only for + the last call to this function. + */ +void GFRmClose(GFRmHandle *pRmHandle); + +/** GFRmCleanUp - Frees resources allocated to a terminated Resource Manager session. + + @param RmProcessID RM Process ID to clean up after. + @retval GF_RETTYPE #GF_SUCCESS if successful.
      + #GF_ERROR on error.
      + + All GFSDK resources will be freed related to this + process. + */ +GF_RETTYPE +GFRmCleanUp( GFRmHandle RmHandle, NvU32 RmProcessID ); + +// FIXME: ripped off from the API doc. GFRmRecover is not implemented as of +// yet - there's null implementation in GFRmObj.c. +/** GFRmRecover - Handles ESD failures. + + @param RmHandle The handle to the Resource Manager. + @param option + @retval GF_RETTYPE #GF_SUCCESS if successful.
      + #GF_ERROR on error.
      + + This function is used to recover from an ESD (electrostatic discharge) + failure. If the system software finds that the GoForce processor is not + responding, the software uses the CPU GPIO to reset the GoForce processor + and then calls this function. GFRmRecover() only calls Recover() + functions of registered components. For example, the GFDxAPI and GFGxAPI + have registered Recover() functions that can bring the GoForce processor + back from the reset to normal working mode. + */ +GF_RETTYPE +GFRmRecover( GFRmHandle RmHandle, NvU32 option ); + +/** GFRmGetProperty - Returns properties of RM. + + @param pRmProp Caller passes ptr to GFPROPERTY that will be filled + upon return. + + @retval #GF_SUCCESS if successful. + */ +GF_RETTYPE +GFRmGetProperty( GFRmHandle RmHandle, + GFPROPERTY *pRmProp ); + +/** GFRmSetAttribute - Sets RM attribute. + + @param AttribType Attribute to get of type #GF_ATTRIBUTE_TYPE. + @param AttribData Data specific to AttribType. + + @retval #GF_SUCCESS if successful. + */ +GF_RETTYPE +GFRmSetAttribute(GFRmHandle RmHandle, + GF_ATTRIBUTE_TYPE AttribType, + NvU32 AttribData); + +/** GFRmGetAttribute - Gets RM attribute. + + @param AttribType Attribute to get of type #GF_ATTRIBUTE_TYPE. + @param AttribData Data specific to AttribType. + See GF_ATTRIBUTE_TYPE for interpretation. + May pass input and/or output parameters. + + @retval #GF_SUCCESS if successful. + */ +GF_RETTYPE +GFRmGetAttribute(GFRmHandle RmHandle, + GF_ATTRIBUTE_TYPE AttribType, + NvU32 *pAttribData); + +/** Claim or release a hardware resource. + + The GoForce GPU has a few hardware engines which are used by + different component API. If a component API is using that hardware + engine, then other API component should not be allowed to use that + engine. For example we have MPEG Decoder engine in the hardware which + is used by GFMxDecAPI and GFJxDecAPI components. If one of the API is + using MPEGD Engine and app/system software tries to use other engines, + it should not be allowed. + For SC4/SC5/SC10/SC12 GPU, we have following constraints: + GFMxDecAPI MPEGD, optional Auto Trigger SB + GFJxDecAPI MPEGD, optional Auto Trigger SB + Both of these component API share same engine so we should only allow + one component to be opened at a time. + + GFMxEncAPI MPEGE, EPP (planar converter) + GFJxEncAPI JPEGE, EPP (planar converter) + Both of these component API share same fron-end planar converter so we + should only allow one component to be opened. + + StetchBlt is represented by VxBlt(). SB has one context where auto + trigger SB can be set. Manual SB command uses same context for manual + command and then restores the auto context. + There is no need to check for manual VxBlt(). + Autotrigger need checking but it is difficult to check in the VxBlt() + function. + + This function only deals with Component level constraints. + Constraint checking can be enabled if GF_ATTRIB_HW_RESOURCE_CONSTRAINT. + + @param RmHandle Handle to the resource manager. + @param options Action code + @param hwEngineReq Flag bitmask specifying 0 or more HW engines, see @ref HardwareResources + + @retval GF_SUCCESS Hardware resource is available. + @retval GFRM_ERROR_HWRESOURCE_NOT_AVAILABLE Hardware resource is not available. + @retval GFRM_ERROR_BAD_PARAMETER Bad parameters passed +*/ +GF_RETTYPE +GFRmHwResourceConstraint( GFRmHandle RmHandle, + GF_HRC_OPTIONS options, + NvU32 hwEngineReq ); + +/* Context Manager */ + +/** GFRmContextGet - Retrieves either a default or new context. + + @param RmHandle Handle to the resource manager. + @param flags #GF_CTX_DEFAULT or #GF_CTX_NEW + @param pContext Pointer to the retreived context. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + */ +GF_RETTYPE +GFRmContextGet( GFRmHandle RmHandle, + NvU32 flags, + GFRmChHandle *pContext); + +/** GFRmChFree - Free a channel (same thing as a context). + + @param hRm Resource manager handle. + @param phCh Pointer to the channel handle. + + @see GFRmContextGet + */ +void GFRmChFree(GFRmHandle hRm, GFRmChHandle *phCh); + + +/* Component Manager */ + +/** GFRmComponentRegister - Register Component with Resource Manager + + @param pComponent Ptr to component to be registerd. + @param RegisterState Parameter of type GF_STATE_TYPE. + Usually, GF_STATE_REGISTER is passed. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + + */ +GF_RETTYPE +GFRmComponentRegister( GFRmHandle RmHandle, + GFRMCOMPONENT *pComponent, + GF_STATE_TYPE RegisterState ); + +/** GFRmComponentGet - Gets a registered component, associated with the passed + context. + + @param ComponentType Desired component type. + @param state Parameter of type #GF_STATE_TYPE. + @param pComponent Ptr to Handle to component available. + NULL if not available. + @param hCh Context Handle. Can be allocated by a call to + #GFRmContextGet function. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + + Depending on the requested state, a newly instantiated component or + a shared component is returned. GF_STATE_DEFAULT is the default option + for the state parameter. If the hCh passed is NULL, then a default + context is associalted with the component. + + */ +GF_RETTYPE +GFRmComponentGet(GFRmHandle hRm, + NvU32 ComponentType, + GF_HANDLE *pComponent, + GF_STATE_TYPE state, + GFRmChHandle hCh); + +/** GFRmComponentRelease - Releases the specified component handle. + + @param hRm Handle to the resource manager. + @param phComponent Pointer to component handle to be released. + + The handle pointed to by phComponent will be cleared to NULL as a side + effect of calling this function. Also, this function has no effect if + the handle pointed to by phComponent is already NULL, so it is not + necessary to check whether a component handle is NULL before releasing it. + */ +void GFRmComponentRelease(GFRmHandle hRm, GF_HANDLE *phComponent); + +/* Surface Manager */ + +/** GFRmSurfaceAlloc - Allocate a Surface without synchronization. + + @param pSurfaceReq Pointer to surface request structure #GFRMSURFACEREQUEST. + @param ppSurface Pointer to surface pointer. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + @retval #GF_OUT_OF_MEMORY when low on memory. + */ +GF_RETTYPE +GFRmSurfaceAlloc( GFRmHandle RmHandle, + GFRMSURFACEREQUEST *pSurfaceReq, + PGFRMSURFACE *ppSurface ); + +/** GFRmSurfaceFree - Frees an allocated surface. + + @param ppSurface Pointer to surface pointer. + + *ppSurface is cleared to NULL. + */ +void +GFRmSurfaceFree(GFRmHandle hRm, + PGFRMSURFACE *ppSurface); + +/** GFRmSurfaceQueryPrimaryInfo - Make a query on Primary Surface. + + @param ppSurface Pointer to Primary surface pointer. + @param pRotate Ptr to current Rotation orientation. + @retval GF_RETTYPE #GF_SUCCESS on success. + #GF_ERROR on error. + + Returned surface pointer is for quick reference only and is a + pointer to transient structure. In other words, this will not + increment the reference count as GFRmSurfaceAlloc does. + */ +GF_RETTYPE +GFRmSurfaceQueryPrimaryInfo( GFRmHandle RmHandle, + PGFRMSURFACE *ppSurface, + NvU32 *pRotate, + NvU32 subSurfaceType ); + +/** Update surface attributes. + + @param ppSurface Pointer to Primary surface pointer. + @param type Type of attribute to update: + + + + +
      #GF_SURFACE_UPDATE_ROTATESet surface rotation
      #GF_SURFACE_UPDATE_WIDTH Set surface width
      #GF_SURFACE_UPDATE_HEIGHTSet surface height
      + @param data Data specific to the type. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + + Currently only one update flag is defined #GF_SURFACE_UPDATE_ROTATE + + */ +GF_RETTYPE +GFRmSurfaceUpdate( GFRmHandle RmHandle, + PGFRMSURFACE pSurface, + NvU32 type, + NvU32 data ); + +/* Memory Manager */ + +/** Allocate a linear piece of internal memory block. + + @param pMemoryReq Pointer to Memory Request struct #GFRMMEMORYREQUEST. + @param pMemHandle A Pointer to the memory handle. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + */ +GF_RETTYPE +GFRmMemHandleAlloc(GFRmHandle RmHandle, + GFRMMEMORYREQUEST *pMemoryReq, + GFRmMemHandle *pMemHandle ); + +/** Frees an allocated internal memory block. + + @param phMem A Pointer to the memory handle. + */ +void +GFRmMemHandleFree(GFRmHandle hRm, + GFRmMemHandle *phMem); + +/** Current memory info. Only supports embedded memory. + + @param pTotalFree Pointer to NvU32 holding total free memoory available. + @param flag Type of memory. Can be one the + #GF_MEMORY_EMBEDDED + #GF_MEMORY_EMBEDDED_EXT + #GF_MEMORY_EMBEDDED_INT + @param pMaxChunk Size of the max chunk. + + @retval #GF_SUCCESS on success. + @retval #GF_ERROR on error. + + GF_MEMORY_EMBEDDED returns the free memory available in both internal + and external memory. + */ +GF_RETTYPE +GFRmMemInfo (GFRmHandle RmHandle, + NvU32 *pTotalFree, + NvU32 *pMaxChunk, + NvU32 flag ); + + +/** Get an handle for the entire internal memory. Used for debugging purposes + only. +*/ +GFRmMemHandle GFRmMemGetIntMemHandle(GFRmHandle RmHandle); + +/** Get an handle for the entire external memory. Used for debugging purposes + only. +*/ +GFRmMemHandle GFRmMemGetExtMemHandle(GFRmHandle RmHandle); + +/** Handle to offset(sc15 view of hw address) conversion. + */ +NvU32 GFRmMemGetOffset(GFRmMemHandle hMem); + +/** Handle to DSP offset(DSP address address map) conversion. + */ +NvU32 GFRmMemGetDSPOffset(GFRmMemHandle hMem); + +/** Handle to virtual address conversion. + + Returned pointer cannot be dereferenced excpet in direct + addressing mode. + */ +void *GFRmMemGetPointer(GFRmMemHandle hMem); + +/** Get the DSP address with a particular caching attribute for a given memory + handle. + */ +NvU32 GFRmMemGetUncachedDSPAddr(GFRmMemHandle hMem); +NvU32 GFRmMemGetWriteBackDSPAddr(GFRmMemHandle hMem); +NvU32 GFRmMemGetWriteThroughDSPAddr(GFRmMemHandle hMem); + +/** Memory Handle reverse lookup from offset. + + This can be used only for the embedded memory. + */ +GF_RETTYPE +GFRmMemOffsetToHandle(GFRmHandle RmHandle, NvU32 offset, GFRmMemHandle *MemHandle); + +/** Converts offset to virtual address. + + @param offset Hardware offset as seen by the SCxx chip. + @param ppMemory Pointer to Virtual address. + + */ +GF_RETTYPE +GFRmMemOffsetToVirt(GFRmHandle RmHandle, NvU32 offset, void **ppMemory); + +/** Converts virtual to offset (SCxx hw view) + + @param offset Hardware offset SCxx view. + @param ppMemory Virtual address. + */ +GF_RETTYPE +GFRmMemVirtToOffset(GFRmHandle RmHandle, void *ppMemory, NvU32 *offset); + +/** Test if the memory offset is from external memory. + + Returns NV_TRUE if the offset is comming from + external memory, otherwise NV_FALSE. + */ +NvBool +GFRmIsExternalMemoryOffset(GFRmHandle RmHandle, + NvU32 offset); + +/** Test if the memory handle is from external memory. + + Returns NV_TRUE if the handle is comming from + external memory, otherwise NV_FALSE. + */ +NvBool +GFRmIsExternalMemoryHandle(GFRmHandle RmHandle, + GFRmMemHandle memhandle); + +/** Test if the memory offset is valid. + @return NV_TRUE if valid, or NV_FALSE otherwise. + */ +NvBool GFRmIsMemoryOffsetValid(GFRmHandle hRm, NvU32 Offset); + +/** Test for bufferoverflows in allocated GPU memory. + This does nothing for release builds. In GFSDK debug build + each GPU memory block will be guarded by leading and trailing + 8 byte marker sequences: +
      +    Start of block: 0x0D,0xF0,0xAD,0xDE,0x0D,0xF0,0xAD,0xDE
      +    End   of block: 0xDE,0xAD,0xFO,0xOD,0xDE,0xAD,0xFO,0xOD
      +    
      + This call checks if these guard markers have been overwritten + @return Index of corrupted memory block, or -1 if all are ok. +*/ +int GFRmMemEmbVerify(GFRmHandle RmHandle); + +/* CPU bound memory fill functions: + These functions will use CPU cycles to write 16 to 32-bit fixed data + pattern into GPU memory. These API's will use user specified channel + apperture to access memory directly and are equipped with Lock and Unlock + routines to be thread safe. +*/ + +/** Fill memory with fixed data pattern on a particular channel. + Function locks and unlocks the channel automatically. + @param ChHandle User-specified channel to use. + @param memHandle GPU memory handle to write fixed 32-bit data. + @param offset Byte offset relative to memHandle block, + must be 32-bit aligned. + @param fill 32-bit fixed data pattern. + @param words Number of DWORDs to write. +*/ +void +GFRmChMemFill32(GFRmChHandle ChHandle, GFRmMemHandle memHandle, NvU32 offset, + NvU32 fill, NvU32 words); + +/** Fill memory with fixed data pattern on a particular channel. + Function locks and unlocks the channel automatically. + @param ChHandle User-specified channel to use. + @param memHandle GPU memory handle to write fixed 16-bit data. + @param offset Byte offset relative to memHandle block, + must be 32-bit aligned. + @param fill 16-bit fixed data pattern. + @param words Number of DWORDs to write. +*/ +void +GFRmChMemFill16(GFRmChHandle ChHandle, GFRmMemHandle memHandle, NvU32 offset, + NvU16 fill, NvU32 words); + +/** Save/Restore functions - These functions Save embedded memory to system memory. + * This memory can then be restored back to sys mem when required. These functions + * are used during DeepPowerDown. + */ +GF_RETTYPE GFRmSaveMemory(GFRmHandle pRm, + void *sysMemPtr, + NvU32 memSize); + +GF_RETTYPE GFRmRestoreMemory(GFRmHandle pRm, + void *sysMemPtr, + NvU32 memSize); + +/* Linear video memory functions: + + These functions are used for transferring system memory to video memory, + filling video memory, and video memory to video memory operations. These + set of functions use the "1d" engine in hardware. All operations use + channels and will be synchronized with other commands. Optionally each + operation can be passed a flag to insert a "clear/raise/wait" sequence + which will guarantee that the operation has completed before processing + more commands in the command stream. For example, if a texture is being + downloaded, it is useful that the download be complete prior to some other + engine (3d maybe) using this memory. + + Prior to using functions, the 1d engine must be enabled. Disabling + will cause the channel passed in to be idled. This is required by hardware + so that the command processors state can be updated when the 1d engine + has its clock disabled and put into reset. + +*/ + + +/** Callback prototype for GFRmChLinearSetDMACallback(). */ +typedef void (*GF_FUNC_DMA_CALLBACK)(void *dstAddr, void *srcAddr, NvU32 lengthInWords); + +/** Setup an DMA callback for downloading data to SRAM. + * + * This function allows for the user to to setup a DMA callback when + * downloading code to the frame buffer. + * + * The callback function should return AFTER all data has been transferred to + * the device. The downloader writes all data to the framebuffer through + * the registered frame buffer window. This window is 4KBytes in length, + * so there will be a callback once for each 4Kbytes (or less to handle alignment + * constraints). + * + * Also, it is possible for downloads to be occuring on multiple channels + * concurrently, which means that this Callback function must be able to + * handle calls from different threads, and do whatever arbitration is required. + * + * For indirect addressing modes, inside the GFSDK a semaphore will be taken + * and held for the duration of this transaction, as multiple threads cannot + * access the device concurrently when using an indirect addressing model. + * + * @param ChHandle The channel that will be used for the download (channel aperture is used) + * @param dmaCallback Pointer to the callback function that is called to do the download + */ +GF_RETTYPE +GFRmChLinearSetDMACallback(GFRmChHandle ChHandle, + GF_FUNC_DMA_CALLBACK dmaCallback); + +/** Flag for GFRmChLinearSysToVidMemcpy(): use a clear/raise/wait. */ +#define GF_RM_LINEAR_USE_CRW 0x01 + +/** Flag for GFRmChLinearSysToVidMemcpy(): don't synchronize with channel's pushbuffer. */ +#define GF_RM_LINEAR_NO_PB_SYNC 0x02 + +/** Enable 1D engine for GFRmChLinear* functions. + * + * Call before using any GFRmChLinear* function. This enables the hardware that is + * used for these functions. Internally there is a reference count, so it is safe + * to call this multiple times. + * + * @param ChHandle Any valid channel handle should work. + * @see GFRmChLinearDisable() + */ + +GF_RETTYPE +GFRmChLinearEnable(GFRmChHandle ChHandle); + + +/** Disable 1D engine for GFRmChLinear* functions. + * + * When the internal reference count reaches zero, the accelerator's clocks will be turned + * off to save power + * + * @param ChHandle Any valid channel should work. + * @see GFRmChLinearEnable() + */ + +GF_RETTYPE +GFRmChLinearDisable(GFRmChHandle ChHandle); + + + +/** Downloads a system memory buffer to the GPU memory buffer. + * + * The main reason for using this is that + * the copy to video memory is serialized with other operations. A typical use would be something + * like: 3d-driver issues draw commands that use a texture. 3d-driver issues a clear/raise/wait to + * know when draw is complete. 3d-driver issues a download to update the texture. + * + * @param pCtx : Current context (channel) + * @param memHandle : Handle returned from the memory allocator + * @param dstOffset : Offset from the beginning of the block referenced in memHandle + * @param pSrc : Source memory address in system memory + * @param len : Length in bytes to copy + * @param flags : Flags to optionally modify copy behavior + * + * flags can be one of: + * + * GF_RM_LINEAR_USE_CRW -- use a clear/raise/wait to make the operation finish prior to other command + * in the command stream being executed. + * GF_RM_LINEAR_NO_PB_SYNC -- This means the download does not need to be synchronous with the pushbuffer + * and the RM can optionally use different more efficient path + * than the pushbuffer. + * + * @return Returns GF_SUCCESS on success + */ +GF_RETTYPE +GFRmChLinearSysToVidMemcpy(GFRmChHandle pCtx, + GFRmMemHandle memHandle, + NvU32 dstOffset, + void *srcPtr, + NvU32 bytes, + NvU32 flags); + +/** Fills a region of GPU memory with a constant value, by memory handle. + * + * @param ctx Current context (or channel) + * @param memHandle Handle to the memory to fill + * @param dstOffset Offset inside the memory handle + * @param data32 The value being replicated in memory. This value is + * interpreted differently depending on the align parameter. + * if align==4 all of data32 is used + * if align==2 lower 16-bits of data32 is used + * if align==1 lower 8-bits of data32 is used + * + * @param bytes Number of bytes to fill + * @param align must 1,2,4 + * @param flags Can be 0 or GF_RM_LINEAR_USE_CRW + */ +GF_RETTYPE +GFRmChLinearVidMemFill(GFRmChHandle ctx, + GFRmMemHandle memHandle, + NvU32 dstOffset, + NvU32 data32, + NvU32 bytes, + NvU32 align, + NvU32 flags); + +/** Copies memory within GPU memory, by memory handle. + * + * @param ctx The channel handle + * @param dstMemHandle memory handle returned from memalloc + * @param dstOffset Offset from the beginning of dstMemHandle + * @param srcMemhandle memory handle of the src memory + * @param srcOffset Offset from the beginning of srcMemHandle + * @param bytes Number of bytes to be copied. + * @param flags Must be 0 or GF_RM_LINEAR_USE_CRW + * + */ +GF_RETTYPE +GFRmChLinearVidMemcpy(GFRmChHandle ctx, + GFRmMemHandle dstMemHandle, + NvU32 dstOffset, + GFRmMemHandle srcMemHandle, + NvU32 srcOffset, + NvU32 bytes, + NvU32 flags); + + +/** @name OS Manager +@{*/ + +/** Enter Critical section, extended version. + @param id GF_CRITICAL_SECTION_xxx + */ +void GFRmOSEnterCSExt(GFRmHandle hRm, NvU32 id); + +/** Exit Critical section, extended version. + @param id GF_CRITICAL_SECTION_xxx + */ +void GFRmOSExitCSExt(GFRmHandle hRm, NvU32 id); + +/** Enter Hardware Access Critical section. + */ +void GFRmOSEnterCS(GFRmHandle hRm); + +/** Exit Hardware Access Critical section. + */ +void GFRmOSExitCS(GFRmHandle hRm); + +/** Waits for some number of milliseconds. + @param msec Number of milliseconds to wait. + */ +void GFRmOSWaitMSec(NvU32 msec); + +/** Get the current OS tick counter. + @return Low 32 bits of millisecond counter. +*/ +NvU32 GFRmGetTickCountMSec(void); + +/** Get the current OS tick counter. + + NOTE: This function is NOT guaranteed to exist on all + platforms. Drivers should NOT call this function; it's + meant only for benchmarking. + + @return 64 bit microsecond counter. + */ +NvU64 GFRmGetTickCountUSec(void); + +/** Waits for a keypress with a timeout, and returns the key. + + @param timeOutMSec (NvU32) Milliseconds to wait for the keypress. + @retval (int) The code for the key, or zero if we timed out. + */ +int GFRmWaitKey(NvU32 timeOutMSec); + +/*@}*/ + +/** @name Read/Write functions + + We provide APIs to read and write GPU registers and memory, independent of + which bus addressing mode is in use (direct or indirect, 16 or 32). + + WARNING: These functions are not safe in all cases. + 1. They do not take into account handshake mode. With fixed timings it may + be unsafe, for example, to use GFRmMemRd/Wr32 to access external memory. + 2. They do not take into account limitations on the # of address bits. On + some direct addressing platforms, not all the address bits are wired up, + so it is impossible to directly access all of memory. For example, it + may be unsafe to use GFRmMemRd/Wr32 to access external memory. + 3. Some buses do not have full byte enable support. It is possible that + GFRmMemWr08, for example, may clobber the other byte in the word. + + It is believed that the first two pitfalls only apply to external memory. + You can probably use these APIs safely to access internal memory, subject to + caveat (3) (i.e. you should stick to 16-bit or 32-bit writes). For external + memory, "use at your own risk." + +@{*/ + +/** Read or write an 8-, 16-, or 32-bit register in the device. */ +NvU8 GFRmRegRd08(GFRmHandle hRm, NvU32 offset); +NvU16 GFRmRegRd16(GFRmHandle hRm, NvU32 offset); +NvU32 GFRmRegRd32(GFRmHandle hRm, NvU32 offset); +void GFRmRegWr08(GFRmHandle hRm, NvU32 offset, NvU8 data); +void GFRmRegWr16(GFRmHandle hRm, NvU32 offset, NvU16 data); +void GFRmRegWr32(GFRmHandle hRm, NvU32 offset, NvU32 data); + +/** Read or write 8, 16, or 32 bits of data to a given offset in a block of memory. + Offset is relative to the memory handle AND not the absolute one. + */ +NvU8 GFRmMemRd08(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset); +NvU16 GFRmMemRd16(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset); +NvU32 GFRmMemRd32(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset); +void GFRmMemWr08(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, NvU8 data); +void GFRmMemWr16(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, NvU16 data); +void GFRmMemWr32(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, NvU32 data); + +/** Read or write a region of a block of memory. Size is in bytes */ +void GFRmMemRead(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, + void *pDst, NvU32 size); +void GFRmMemWrite(GFRmHandle hRm, GFRmMemHandle hMem, NvU32 offset, + const void *pSrc, NvU32 size); + +/** Fill a block of memory with a given 8-, 16-, or 32-bit word. Size is in words, not bytes */ +void GFRmMemFill08(GFRmHandle hRm, GFRmMemHandle hMem, + NvU32 offset, NvU32 size, NvU8 data); +void GFRmMemFill16(GFRmHandle hRm, GFRmMemHandle hMem, + NvU32 offset, NvU32 size, NvU16 data); +void GFRmMemFill32(GFRmHandle hRm, GFRmMemHandle hMem, + NvU32 offset, NvU32 size, NvU32 data); + +/** Write to a FIFO in the chip. */ +void GFRmFifoWrite(GFRmHandle hRm, const void *srcPtr, + NvU32 dstOffset, NvU32 sizeIn32bits); + +/** Waits for the host to idle. + + @retval GF_SUCCESS on success + @retval GF_ERROR on error +*/ +GF_RETTYPE +GFRmWaitForHostIdle( GFRmHandle RmHandle ); + +/*@}*/ + +/** Dispatch DSP2Host messages. + + This function can be called from an IST in response to the DSP2Host + interrupt. It will perform the following sequence: + + - read the DSP2Host message from the DSP2Host registers, i.e. GFRmGetMessage() + - identify DSP task from the task ID in message parameter 0 + - add the message to that task's queue + - set an event registered with that task to notify it about the new message + - clear DSP2Host interrupt register, i.e. GFRmClearDspCommInterrupt() + + If the task ID from the message is unknown, the interrupt is still cleared, + but the message is ignored. + + @param ChHandle Channel to use, should be the protected channel (GF_PROTECTED_CHANNEL) + @return Returns the DSP task ID the received message belonged to, or 0 if unknown +*/ +NvU32 GFRmDispatchMessage(GFRmChHandle ChHandle); +NvU32 GFRmDispatchMessageDual(GFRmChHandle ChHandle, NvU32 dspModule); + +/** Descriptor for circular buffer in DSP memory. + This structure is intended for shared use between DSP tasks. + + If GF_RM_DSP_CBUFFER::wr == GF_RM_DSP_CBUFFER::rd, the circular buffer is empty. + If GF_RM_DSP_CBUFFER::wr != GF_RM_DSP_CBUFFER::rd, the buffer contains + (wr>=rd)?wr-rd:size+wr-rd bytes of data, starting at offset rd, wrapping on the buffer end. +*/ +typedef struct _GFRM_DSP_CIRCBUFFER +{ + NvU8* adr; //!< buffer address, DSP address space in GPU memory + NvU32 size; //!< Buffer size in bytes + NvU32 wr; //!< Current write offset relative to buffer address + NvU32 rd; //!< Current read offset relative to buffer address + NvU32 userData[4]; //!< User defined, specific depending on usage + +} GF_RM_DSP_CIRCBUFFER; + + +/* + * Pins that can be used as GPIOs once the corresponding module + * has been enabled + */ +typedef enum { + + /* SD PINS */ + GPIO_SD_PIN_DATA0 = 1, + GPIO_SD_PIN_DATA1, + GPIO_SD_PIN_DATA2, + GPIO_SD_PIN_DATA3, + GPIO_SD_PIN_CLK, + GPIO_SD_PIN_CMD, + GPIO_SD_PIN_SDGP0, + GPIO_SD_PIN_SDGP1, + + /* VI PINS */ + GPIO_VI_PIN_VD0, + GPIO_VI_PIN_VD1, + GPIO_VI_PIN_VD2, + GPIO_VI_PIN_VD3, + GPIO_VI_PIN_VD4, + GPIO_VI_PIN_VD5, + GPIO_VI_PIN_VD6, + GPIO_VI_PIN_VD7, + GPIO_VI_PIN_VD8, + GPIO_VI_PIN_VD9, + GPIO_VI_PIN_VD10, + GPIO_VI_PIN_VD11, + GPIO_VI_PIN_VSCK, + GPIO_VI_PIN_VHS, + GPIO_VI_PIN_VVS, + GPIO_VI_PIN_VGP0, + GPIO_VI_PIN_VGP1, + GPIO_VI_PIN_VGP2, + GPIO_VI_PIN_VGP3, + GPIO_VI_PIN_VGP4, + GPIO_VI_PIN_VGP5, + GPIO_VI_PIN_VGP6 + +} GFGPIOPin; + +/* + * I/O options for pins + */ +typedef enum { + GPIO_OPTION_DISABLE = 1, + GPIO_OPTION_INPUT, + GPIO_OPTION_OUTPUT +} GFGPIOOption; + +/* + * Enable/Disable I/O for GPIOS + */ +typedef enum { + GPIO_MODE_DISABLE = 1, + GPIO_MODE_ENABLE +} GFGPIOMode; + +/* + * Pin groups whose selects are tied together + */ +typedef enum { + GPIO_SD_PINGRP_D0_CLK_CMD = 1, + GPIO_SD_PINGRP_D1_D2 +} GFGPIOPinGrp; + +/* + * Pin select for GPIOS + */ +typedef enum { + GPIO_SELECT_GPIO = 1, + GPIO_SELECT_FUNC +} GFGPIOSelect; + +/** + * + * Sets all the pins of a specific module to GPIO mode + * + * @param RmHandle Handle specific to the GFRm + * @param modid Module + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIOEnable(GFRmHandle RmHandle, eGFModuleIDs modid); + +/** + * Initializes the GPIO API + * + * + * @param RmHandle Handle specific to the GFRm + * @param modid Module + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIODisable(GFRmHandle RmHandle, eGFModuleIDs modid); + +/** + * + * Modifies the pin's input/output modes + * + * @param ChHandle Channel to write to modules through + * @param pin Pin to set + * @param options One of GPIO_OPTION_DISABLE (ignores mode), + * GPIO_OPTION_INPUT, GPIO_OPTION_OUTPUT + * @param mode One of GPIO_MODE_ENABLE, GPIO_MODE_DISABLE + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIOSetPinMode(GFRmChHandle ChHandle, GFGPIOPin pin, GFGPIOOption option, GFGPIOMode mode); + +/** + * + * Sets a particular pin's output select + * + * @param ChHandle Channel to write to modules through + * @param pin Pin to set + * @param select One of GPIO_SELECT_GPIO, GPIO_SELECT_FUNC + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIOSetPinSelect(GFRmChHandle ChHandle, GFGPIOPin pin, GFGPIOSelect select); + +/** + * + * Sets a particular pin group's output select + * + * @param ChHandle Channel to write to modules through + * @param group Pin group to set + * @param select One of GPIO_SELECT_GPIO, GPIO_SELECT_FUNC + * + * @return GF_SUCCESS on success + * + */ +GF_RETTYPE +GFRmGPIOSetPinGrpSelect(GFRmChHandle ChHandle, GFGPIOPinGrp group, GFGPIOSelect select); + +/** + * + * Sets the status (high/low) of a pin + * + * @param ChHandle Channel to write to modules through + * @param pin Pin to set + * @param value Value to write to pin + * + */ +void +GFRmGPIOSetPin(GFRmChHandle ChHandle, GFGPIOPin pin, NvU8 value); + +/** + * Gets the status (high/low) of a pin + * + * @param ChHandle Channel to write to modules through + * @param pin Pin to set + * + * @return Status (high/low) of pin + * + */ +NvU32 +GFRmGPIOGetPin(GFRmChHandle ChHandle, GFGPIOPin pin); + +/** @ name Bootflags + List of flags inidicating all the devices which are booted +@{*/ + +/** Chip is initalized in other words IxInit is called */ +#define GFRM_BOOT_IXINIT 0x1 + +/** Display is initalized */ +#define GFRM_BOOT_DXINIT 0x2 + +/*@}*/ + +/** + * Writes to some scratch register with a log of all the components which are + * initalized. GFRM_BOOT_* are passed as bootflags. + */ +GF_RETTYPE GFRmBootPostInit(GFRmHandle hRm, NvU32 bootflags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*@}*/ + +/** @page pageRmAppNotes RmAPI Application Notes + + @section pageRmAppNotes1 Todo + +*/ + +#endif /* __GFRM_H__ */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmError.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmError.h new file mode 100755 index 00000000..7295b9f2 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmError.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFRmError.h + GFSDK Resource Manager API error code header file. +*/ + +#ifndef __GFRMERROR_H__ +#define __GFRMERROR_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** GFRM error code: Function not supported. */ +#define GFRM_ERROR_NO_SUPPORT (GFRM_ERROR | 0x02) +/** GFRM error code: Out of memory. */ +#define GFRM_ERROR_OUT_MEMORY (GFRM_ERROR | 0x03) +/** GFRM error code: Operation on primary surface, but primary surface not set. */ +#define GFRM_ERROR_NO_PRIMARY_SURFACE (GFRM_ERROR | 0x04) +/** GFRM error code: Bad parameters. */ +#define GFRM_ERROR_BAD_PARAMETER (GFRM_ERROR | 0x05) +/** GFRM error code: Out of memory in DSP XRM heap. */ +#define GFRM_ERROR_XRM_OUTMEMORY (GFRM_ERROR | 0x06) +/** GFRM error code: GFRM memory manager is not initialized. */ +#define GFRM_ERROR_MEM_MANAGER_NOT_INITIALIZED (GFRM_ERROR | 0x07) +/** GFRM error code: DSP2Host message queue overflow. */ +#define GFRM_ERROR_QUEUE_OVERFLOW (GFRM_ERROR | 0x08) +/** GFRM error code: DSP2Host message queue empty (not an error). */ +#define GFRM_ERROR_QUEUE_EMPTY (GFRM_ERROR | 0x09) +/** GFRM error code: DSP2Host message with unknown task ID received. */ +#define GFRM_ERROR_QUEUE_UNKNOWNTASK (GFRM_ERROR | 0x0A) +/** GFRM error code: Error getting GPU base address. */ +#define GFRM_ERROR_IXOPEN_GETADDRESS (GFRM_ERROR | 0x0C) +/** GFRM error code: Error opening file. */ +#define GFRM_ERROR_FILE_OPEN_FAILED (GFRM_ERROR | 0x0D) +/** GFRM error code: Cannot create XRM task. */ +#define GFRM_ERROR_XRM_CREATETASK (GFRM_ERROR | 0x0E) +/** GFRM error code: GFRmOSEventWait() failed. */ +#define GF_WAIT_ERROR (GFRM_ERROR | 0x0F) +/** GFRM error code: GFRmOSEventWait() timed out, the event was not set. */ +#define GF_WAIT_TIME_OUT (GFRM_ERROR | 0x10) +/** GFRM error code: RmEnableModule tried to enable a module that doesn't exist. */ +#define GFRM_ERROR_MODULE_NOT_EXIST (GFRM_ERROR | 0x11) +/** GFRM error code: HW Resource not available on GFRmHwResourceConstraint(). */ +#define GFRM_ERROR_HWRESOURCE_NOT_AVAILABLE (GFRM_ERROR | 0x12) +/** GFRM error code: Host2DSP task message queue overflow. */ +#define GFRM_ERROR_XRM_QUEUE_OVERFLOW (GFRM_ERROR | 0x13) +/** GFRM error code: Host2DSP task message queue empty. */ +#define GFRM_ERROR_XRM_QUEUE_EMPTY (GFRM_ERROR | 0x14) +/** GFRM error code: File not found */ +#define GFRM_ERROR_FILE_NOT_FOUND (GFRM_ERROR | 0x15) +/** GFRM error code: Create semaphore */ +#define GFRM_ERROR_CREATE_SEMAPHORE (GFRM_ERROR | 0x16) + +#ifdef __cplusplus +} +#endif + +#endif // __GFRMERROR_H__ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmHelp.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmHelp.h new file mode 100755 index 00000000..82c1fa5a --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmHelp.h @@ -0,0 +1,515 @@ +/* + * Copyright 2003 NVIDIA Corporation. All Rights Reserved. + * + * BY INSTALLING THE SOFTWARE THE USER AGREES TO THE TERMS BELOW. + * + * User agrees to use the software under carefully controlled conditions + * and to inform all employees and contractors who have access to the software + * that the source code of the software is confidential and proprietary + * information of NVIDIA and is licensed to user as such. User acknowledges + * and agrees that protection of the source code is essential and user shall + * retain the source code in strict confidence.User shall restrict access to + * the source code of the software to those employees and contractors of user + * who have agreed to be bound by a confidentiality obligation which + * incorporates the protections and restrictions substantially set forth + * herein, and who have a need to access the source code in order to carry out + * the business purpose between NVIDIA and user. The software provided + * herewith to user may only be used so long as the software is used solely + * with NVIDIA products and no other third party products (hardware or + * software). The software must carry the NVIDIA copyright notice shown + * above. User must not disclose, copy, duplicate, reproduce, modify, + * publicly display, create derivative works of the software other than as + * expressly authorized herein. User must not under any circumstances, + * distribute or in any way disseminate the information contained in the + * source code and/or the source code itself to third parties except as + * expressly agreed to by NVIDIA. In the event that user discovers any bugs + * in the software, such bugs must be reported to NVIDIA and any fixes may be + * inserted into the source code of the software by NVIDIA only. User shall + * not modify the source code of the software in any way. User shall be fully + * responsible for the conduct of all of its employees, contractors and + * representatives who may in any way violate these restrictions. + * + * NO WARRANTY + * THE ACCOMPANYING SOFTWARE (INCLUDING OBJECT AND SOURCE CODE) PROVIDED BY + * NVIDIA TO USER IS PROVIDED "AS IS." NVIDIA DISCLAIMS ALL WARRANTIES, + * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. + + * LIMITATION OF LIABILITY + * NVIDIA SHALL NOT BE LIABLE TO USER, USER’S CUSTOMERS, OR ANY OTHER PERSON + * OR ENTITY CLAIMING THROUGH OR UNDER USER FOR ANY LOSS OF PROFITS, INCOME, + * SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT + * OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A + * WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. IN NO EVENT SHALL NVIDIA’S + * AGGREGATE LIABILITY TO USER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH + * OR UNDER USER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY USER TO NVIDIA + * FOR THE SOFTWARE PROVIDED HEREWITH. + */ + +/* + * File: GFRmHelp.inl + * GFSDK Resource Manager Helper Manager inline header file. + * #### The helper functions are highly dependent on Operating System #### + * #### and Compiler. A number of these functions are macros that #### + * #### maps to corresonding operating system functions directly. #### + */ + +#ifndef __GFRMHelp_INL__ +#define __GFRMHelp_INL__ + +#include "nvtypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* Defined in GFRMHelp.c */ +extern int GFStricmp(char *, char *); +extern int GFStrincmp(char *, char *, int); + +extern void *GFMalloc(int); +extern void GFFree(void *ptr); + +#if NVOS_IS_WINDOWS_CE + +#ifndef __KERNEL__ +#include +#include +#endif // __KERNEL__ + +/* String Helper functions */ +#define GFStrcpy(p1, p2) strcpy(p1, p2) +#define GFStrncpy(p1, p2, p3) strncpy(p1, p2, p3) +#define GFStrcat(p1, p2) strcat(p1, p2) +#define GFStrncat(p1, p2, p3) strncat(p1, p2, p3) +#define GFStrlen(p1) strlen(p1) +#define GFStrchr(p1, p2) strchr(p1, p2) +#define GFStrcmp(p1, p2) strcmp(p1, p2) +#define GFStrncmp(p1, p2, p3) strncmp(p1, p2, p3) +#define GFStrtok(p1, p2) strtok(p1, p2) +#define GFStrstr(p1, p2) strstr(p1, p2) +#define GFSscanf(p1, p2, p3) sscanf(p1, p2, p3) +#define GFToupper(p1) toupper(p1) +#define GFTolower(p1) tolower(p1) +#define GFAtoi(p1) atoi(p1) + +// convert char string to wchar_t +// p1 = src string of type char +// p2 = dst string of type wchar_t +// p3 = size of dst string in wchar_t unit +#define GFStrConvert(p1, p2, p3) \ + MultiByteToWideChar(CP_ACP, 0, p1, -1, p2, p3); + +// convert wchar_t string to char +// p1 = src string of type wchar_t +// p2 = dst string of type char +// p3 = size of dst string in char unit +#define GFWStrConvert(p1, p2, p3) \ + WideCharToMultiByte(CP_ACP, 0, p1, -1, p2, p3, NULL, NULL) + +/* Standard Helper functions */ +#define GFStrtol(p1, p2, p3) strtol(p1, p2, p3) +#define GFStrtod(p1, p2) strtod(p1, p2) + +/* Memory Helper functions */ +#define GFMemcpy( p1, p2, p3 ) memcpy( p1, p2, p3 ) +#define GFMemmove( p1, p2, p3 ) memmove( p1, p2, p3 ) +#define GFMemcmp( p1, p2, p3 ) memcmp( p1, p2, p3 ) +#define GFMemset( p1, p2, p3 ) memset( p1, p2, p3 ) + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +/* Debug Helper functions */ +#if !defined(PROJECT_SEC_G1) || defined(DEBUG) +#define GFPrintf printf +#else +#define GFPrintf +#endif +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintfVAL vprintf + +#ifdef DEBUG +extern void RmDebugBreak(void); +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + RmDebugBreak(); \ + } +#endif + +#elif NVOS_IS_LINUX + +#ifndef __KERNEL__ +void RmDebugBreak(void); +#ifdef DEBUG +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + RmDebugBreak(); \ + } +#endif + +#include +#define GFToupper toupper +#define GFTolower tolower + +#include +#ifndef GF_XTENSA_RM_TASK +#include +#endif +#define GFMemcpy memcpy +#define GFMemmove memmove +#define GFMemset memset +#define GFMemcmp memcmp +#define GFStrchr strchr +#define GFStrcmp strcmp +#define GFStrcpy strcpy +#define GFStrncpy strncpy +#define GFStrlen strlen +#define GFStrcat strcat +#define GFStrncmp strncmp +#define GFStrtok strtok +#define GFStrstr strstr +#define GFSscanf sscanf + +#include +#define GFPrintf printf +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintf printf +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintfVAL vprintf + +#include +#define GFStrtol strtol +#define GFStrtod strtod +#define GFAtoi atoi +#include + +/* Add or overload RMCTrace function here */ +#if defined(GF_ENABLE_RMC_TRACE) +#include +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#else /* kernel mode */ + +#include +#include + +#include +#define GFToupper toupper +#define GFTolower tolower + +#include +#define GFMemcpy memcpy +#define GFMemmove memmove +#define GFMemset memset +#define GFStrcpy strcpy +#define GFStrncpy strncpy +#define GFStrlen strlen +#define GFMemcmp memcmp +#define GFStrcmp strcmp +#define GFStrncmp strncmp +#define GFStrcat strcat +#define GFStrncat strncat + +#define GFStrstr strstr +#define GFSscanf sscanf + +#define GFPrintf printk +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintfVAL vprintf +#define GFAtoi atoi + +#if defined(GF_ENABLE_RMC_TRACE) +#include +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#endif /* KERNEL */ + +#elif NVOS_IS_WINDOWS + +#include +#include +#include +#include + +/* String functions */ +#define GFStrcpy(p1, p2) strcpy(p1, p2) +#define GFStrncpy(p1, p2, p3) strncpy(p1, p2, p3) +#define GFStrcat(p1, p2) strcat(p1, p2) +#define GFStrncat(p1, p2, p3) strncat(p1, p2, p3) +#define GFStrstr(p1, p2) strstr(p1, p2) +#define GFSscanf(p1, p2, p3) sscanf(p1, p2, p3) +#define GFStrlen(p1) strlen(p1) +#define GFStrchr(p1, p2) strchr(p1, p2) +#define GFStrcmp(p1, p2) strcmp(p1, p2) +#define GFStrncmp(p1, p2, p3) strncmp(p1, p2, p3) +#define GFStrtok(p1, p2) strtok(p1, p2) +#define GFToupper(p1) toupper(p1) +#define GFTolower(p1) tolower(p1) +#define GFStrConvert(p1, p2, p3) \ + strcpy(p2,p1) +// MultiByteToWideChar( CP_ACP, 0, p1, -1, p2, p3 ); + // convert char string to Wide + // p1 = src string of type char + // p2 = dst string of type wchar_t + // p3 = size of dst string in wchar_t unit + +/* Standard Helper functions */ +#define GFStrtol(p1, p2, p3) strtol(p1, p2, p3) +#define GFStrtod(p1, p2) strtod(p1, p2) + +/* Memory Helper functions */ +#define GFMemcpy( p1, p2, p3 ) memcpy( p1, p2, p3 ) +#define GFMemmove( p1, p2, p3 ) memmove( p1, p2, p3 ) +#define GFMemcmp( p1, p2, p3 ) memcmp( p1, p2, p3 ) +#define GFMemset( p1, p2, p3 ) memset( p1, p2, p3 ) + +#define GFAtoi( p1 ) atoi( p1 ) +/* Debug Helper functions */ +#if !defined(PROJECT_SEC_G1) || defined(DEBUG) +#define GFPrintf printf +#else +#define GFPrintf +#endif +#define GFSprintf sprintf +#define GFSprintfVAL vsprintf +#define GFPrintfVAL vprintf + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +void RmDebugBreak(void); +#ifdef DEBUG +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + RmDebugBreak(); \ + } +#endif + +// Operating system running on the Xtensa +#elif NVCPU_IS_XTENSA + +#include + +/* Memory Helper functions */ +#define GFMemcpy( p1, p2, p3 ) memcpy(p1, p2, p3) +#define GFMemset( p1, p2, p3 ) memset(p1, p2, p3) + +#define GFRMCTrace(a) +#define GFRMCVTrace(a) + +#else + +#include +#include +#include +#include +#include + +/* String functions */ +extern char GFToupper(char); +extern char GFTolower(char); + +extern int GFAtoi(const char *); + +extern void *GFMemcpy(void *, const void *, int); +extern void *GFMemmove(void *, const void *, int); +extern void *GFMemset(void *, int, int); +extern int GFMemcmp(void *, void *, int); + +extern char *GFStrcpy(char *, const char *); +extern char *GFStrncpy(char *, const char *, int); + +extern char *GFStrcat(char *, const char *); +extern char *GFStrncat(char *, const char *, int); + +extern int GFStrlen(const char *); + +extern char *GFStrchr(const char *,int); +extern char *GFStrrchr(const char *,int); + +extern int GFStrcmp(const char *, const char *); +extern int GFStrncmp(const char *, const char *, int); + +extern char *GFStrstr(const char * string1, const char * string2); +extern int GFSscanf(char * string1, const char * string2, ...); + +extern char *GFStrtok(char *, const char *); + +extern long GFStrtol(const char *, char **, int); +extern double GFStrtod(const char *, char **); + +extern int GFPrintf(const char *, ... ); +extern int GFSprintf(char * , const char *, ... ); +extern int GFSprintfVAL(char *, const char *, va_list); +extern int GFPrintfVAL(const char *, va_list); + +#define GFStrConvert(p1, p2, p3) GFStrncpy(p1, p2, p3) + +#if defined(GF_ENABLE_RMC_TRACE) +#define GFRMCTrace(a) printf a +#define GFRMCVTrace(a) vprintf a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#ifdef DEBUG +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + } +#endif + +#endif /* GF_OS */ + +/* Virtual Key Mappings for Specific OS */ +#if NVOS_IS_LINUX +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 65 +#define GF_VKEY_LEFT 68 +#define GF_VKEY_RIGHT 67 +#define GF_VKEY_DOWN 66 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#elif NVOS_IS_WINDOWS_CE + +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 72 +#define GF_VKEY_LEFT 75 +#define GF_VKEY_RIGHT 77 +#define GF_VKEY_DOWN 80 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#elif NVOS_IS_WINDOWS +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 72 +#define GF_VKEY_LEFT 75 +#define GF_VKEY_RIGHT 77 +#define GF_VKEY_DOWN 80 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#else + +/* Virtual Keys */ +#define GF_VKEY_BACK 2 +#define GF_VKEY_FORWARD 3 +#define GF_VKEY_UP 4 +#define GF_VKEY_LEFT 5 +#define GF_VKEY_RIGHT 6 +#define GF_VKEY_DOWN 7 +#define GF_VKEY_SEND 8 +#define GF_VKEY_END 9 +#define GF_VKEY_0 10 +#define GF_VKEY_1 11 +#define GF_VKEY_2 12 +#define GF_VKEY_3 13 +#define GF_VKEY_4 14 +#define GF_VKEY_5 15 +#define GF_VKEY_6 16 +#define GF_VKEY_7 17 +#define GF_VKEY_8 18 +#define GF_VKEY_9 19 +#define GF_VKEY_STAR 20 +#define GF_VKEY_POUND 21 + +#endif /* GF_OS */ + +#ifndef GFDEBUG_ASSERT +#define GFDEBUG_ASSERT(x) do {} while (0) +#endif /* GFDEBUG_ASSERT */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFRMHelp_INL__ */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmHelp.inl b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmHelp.inl new file mode 100755 index 00000000..4612fce2 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmHelp.inl @@ -0,0 +1,626 @@ +/* + * Copyright 2003 NVIDIA Corporation. All Rights Reserved. + * + * BY INSTALLING THE SOFTWARE THE USER AGREES TO THE TERMS BELOW. + * + * User agrees to use the software under carefully controlled conditions + * and to inform all employees and contractors who have access to the software + * that the source code of the software is confidential and proprietary + * information of NVIDIA and is licensed to user as such. User acknowledges + * and agrees that protection of the source code is essential and user shall + * retain the source code in strict confidence. User shall restrict access to + * the source code of the software to those employees and contractors of user + * who have agreed to be bound by a confidentiality obligation which + * incorporates the protections and restrictions substantially set forth + * herein, and who have a need to access the source code in order to carry out + * the business purpose between NVIDIA and user. The software provided + * herewith to user may only be used so long as the software is used solely + * with NVIDIA products and no other third party products (hardware or + * software). The software must carry the NVIDIA copyright notice shown + * above. User must not disclose, copy, duplicate, reproduce, modify, + * publicly display, create derivative works of the software other than as + * expressly authorized herein. User must not under any circumstances, + * distribute or in any way disseminate the information contained in the + * source code and/or the source code itself to third parties except as + * expressly agreed to by NVIDIA. In the event that user discovers any bugs + * in the software, such bugs must be reported to NVIDIA and any fixes may be + * inserted into the source code of the software by NVIDIA only. User shall + * not modify the source code of the software in any way. User shall be fully + * responsible for the conduct of all of its employees, contractors and + * representatives who may in any way violate these restrictions. + * + * NO WARRANTY + * THE ACCOMPANYING SOFTWARE (INCLUDING OBJECT AND SOURCE CODE) PROVIDED BY + * NVIDIA TO USER IS PROVIDED "AS IS." NVIDIA DISCLAIMS ALL WARRANTIES, + * EXPRESS, IMPLIED OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. + + * LIMITATION OF LIABILITY + * NVIDIA SHALL NOT BE LIABLE TO USER, USER’S CUSTOMERS, OR ANY OTHER PERSON + * OR ENTITY CLAIMING THROUGH OR UNDER USER FOR ANY LOSS OF PROFITS, INCOME, + * SAVINGS, OR ANY OTHER CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE, DIRECT + * OR INDIRECT DAMAGES (WHETHER IN AN ACTION IN CONTRACT, TORT OR BASED ON A + * WARRANTY), EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGES. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF THE + * ESSENTIAL PURPOSE OF ANY LIMITED REMEDY. IN NO EVENT SHALL NVIDIA’S + * AGGREGATE LIABILITY TO USER OR ANY OTHER PERSON OR ENTITY CLAIMING THROUGH + * OR UNDER USER EXCEED THE AMOUNT OF MONEY ACTUALLY PAID BY USER TO NVIDIA + * FOR THE SOFTWARE PROVIDED HEREWITH. + */ + +/* + * File: GFRmHelp.inl + * GFSDK Resource Manager Helper Manager inline header file. + * #### The helper functions are highly dependent on Operating System #### + * #### and Compiler. A number of these functions are macros that #### + * #### maps to corresonding operating system functions directly. #### + */ + +#ifndef __GFRMHelp_INL__ +#define __GFRMHelp_INL__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Define the macro GFRMHELP_IMPORTFUNC to import the helper functions + * referenced in GFSDK. Typically Target OS provides definitions for these + * functions. Sample definitions are provided in file RMHelpGeneric.c. + */ + +#if defined(GFRMHELP_ABSTRACTION) +extern char GFAToupper(char); +extern char GFATolower(char); + +extern void *GFMalloc(int); +extern void GFFree(void *ptr); + +extern void *GFMemcpy(void *, const void *, int); +extern void *GFMemmove(void *, const void *, int); +extern void *GFMemset(void *, int, int); +extern int GFMemcmp(void *, void *, int); + +extern char *GFAStrcpy(char *, const char *); +extern char *GFAStrncpy(char *, const char *, int); + +extern char *GFAStrcat(char *, const char *); +extern char *GFAStrncat(char *, const char *, int); + +extern char *GFAStrstr(const char * string1, const char * string2); +extern int GFASscanf(char * string1, const char * string2, ...); + +extern int GFAStrlen(const char *); + +extern char *GFAStrchr(const char *,int); + +extern int GFAStrcmp(const char *, const char *); +extern int GFAStrncmp(const char *, const char *, int); + +extern char *GFAStrtok(char *, const char *); + +extern long GFAStrtol(const char *, char **, int); +extern double GFAStrtod(const char *, char **); + +extern int GFAPrintf(const char *, ... ); + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +#define GFRMCTrace(a) GFRmRMCTrace a +#else +#define GFRMCTrace(a) +#endif + +#else + +/* Defined in GFRMHelp.c */ +extern int GFAStricmp(char *, char *); +extern int GFAStrincmp(char *, char *, int); + + +#if defined(NV_WINDOWS_CE) + +#ifndef __KERNEL__ +#include +#include +#include +#endif // __KERNEL__ + +/* String Helper functions */ +#define GFAStrcpy(p1, p2) strcpy(p1, p2) +#define GFAStrncpy(p1, p2, p3) strncpy(p1, p2, p3) +#define GFAStrcat(p1, p2) strcat(p1, p2) +#define GFAStrncat(p1, p2, p3) strncat(p1, p2, p3) +#define GFAStrlen(p1) strlen(p1) +#define GFAStrchr(p1, p2) strchr(p1, p2) +#define GFAStrcmp(p1, p2) strcmp(p1, p2) +#define GFAStrncmp(p1, p2, p3) strncmp(p1, p2, p3) +#define GFAStrtok(p1, p2) strtok(p1, p2) +#define GFAStrstr(p1, p2) strstr(p1, p2) +#define GFASscanf(p1, p2, p3) sscanf(p1, p2, p3) +#define GFAToupper(p1) toupper(p1) +#define GFATolower(p1) tolower(p1) +#define GFAAtoi(p1) atoi(p1) + +// convert char string to wchar_t +// p1 = src string of type char +// p2 = dst string of type wchar_t +// p3 = size of dst string in wchar_t unit +#define GFAStrConvert(p1, p2, p3) \ + MultiByteToWideChar(CP_ACP, 0, p1, -1, p2, p3); + +// convert wchar_t string to char +// p1 = src string of type wchar_t +// p2 = dst string of type char +// p3 = size of dst string in char unit +#define GFWStrConvert(p1, p2, p3) \ + WideCharToMultiByte(CP_ACP, 0, p1, -1, p2, p3, NULL, NULL) + +/* Standard Helper functions */ +#define GFAStrtol(p1, p2, p3) strtol(p1, p2, p3) +#define GFAStrtod(p1, p2) strtod(p1, p2) + +/* Memory Helper functions */ +#define GFMalloc( p1 ) malloc( p1 ) +#define GFFree( p1 ) free( p1 ) +#define GFMemcpy( p1, p2, p3 ) memcpy( p1, p2, p3 ) +#define GFMemmove( p1, p2, p3 ) memmove( p1, p2, p3 ) +#define GFMemcmp( p1, p2, p3 ) memcmp( p1, p2, p3 ) +#define GFMemset( p1, p2, p3 ) memset( p1, p2, p3 ) + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +/* Debug Helper functions */ +#define GFAPrintf printf +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintfVAL vprintf + +#ifdef DEBUG +extern void RmDebugBreak(void); +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + RmDebugBreak(); \ + } +#endif + +#elif defined(NV_LINUX) + +#ifndef __KERNEL__ +#ifdef DEBUG +#include +#define GFDEBUG_ASSERT(x) assert(x) +#endif + + +#define __declspec(x) + +#include +#define GFMalloc malloc +#define GFFree free + +#include +#define GFAToupper toupper +#define GFATolower tolower + +#include +#ifndef GF_XTENSA_RM_TASK +#include +#endif +#define GFMemcpy memcpy +#define GFMemmove memmove +#define GFMemset memset +#define GFMemcmp memcmp +#define GFAStrcmp strcmp +#define GFAStrcpy strcpy +#define GFAStrncpy strncpy +#define GFAStrlen strlen +#define GFAStrcat strcat +#define GFAStrncmp strncmp +#define GFAStrtok strtok +#define GFAStrstr strstr +#define GFASscanf sscanf + +#include +#define GFAPrintf printf +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintf printf +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintfVAL vprintf + +#include +#define GFAStrtol strtol +#define GFAStrtod strtod +#define GFAAtoi atoi +#include + +/* Add or overload RMCTrace function here */ +#if defined(GF_ENABLE_RMC_TRACE) +#include +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#else /* kernel mode */ + +#include +#include +#define GFMalloc(x) kmalloc((x), GFP_KERNEL) +#define GFFree kfree + +#include +#define GFAToupper toupper +#define GFATolower tolower + +#include +#define GFMemcpy memcpy +#define GFMemmove memmove +#define GFMemset memset +#define GFAStrcpy strcpy +#define GFAStrncpy strncpy +#define GFAStrlen strlen +#define GFMemcmp memcmp +#define GFAStrcmp strcmp +#define GFAStrncmp strncmp +#define GFAStrcat strcat +#define GFAStrncat strncat + +#define GFAStrstr strstr +#define GFASscanf sscanf + +#define GFAPrintf printk +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintfVAL vprintf +#define GFAAtoi atoi + +#if defined(GF_ENABLE_RMC_TRACE) +#include +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#endif /* KERNEL */ + +#elif defined(NV_WINDOWS) + +#include +#include +#include +#include +#include +#include + +/* String functions */ +#define GFAStrcpy(p1, p2) strcpy(p1, p2) +#define GFAStrncpy(p1, p2, p3) strncpy(p1, p2, p3) +#define GFAStrcat(p1, p2) strcat(p1, p2) +#define GFAStrncat(p1, p2, p3) strncat(p1, p2, p3) +#define GFAStrstr(p1, p2) strstr(p1, p2) +#define GFASscanf(p1, p2, p3) sscanf(p1, p2, p3) +#define GFAStrlen(p1) strlen(p1) +#define GFAStrchr(p1, p2) strchr(p1, p2) +#define GFAStrcmp(p1, p2) strcmp(p1, p2) +#define GFAStrncmp(p1, p2, p3) strncmp(p1, p2, p3) +#define GFAStrtok(p1, p2) strtok(p1, p2) +#define GFAToupper(p1) toupper(p1) +#define GFATolower(p1) tolower(p1) +#define GFAStrConvert(p1, p2, p3) \ + strcpy(p2,p1) +// MultiByteToWideChar( CP_ACP, 0, p1, -1, p2, p3 ); + // convert char string to Wide + // p1 = src string of type char + // p2 = dst string of type wchar_t + // p3 = size of dst string in wchar_t unit + +/* Standard Helper functions */ +#define GFAStrtol(p1, p2, p3) strtol(p1, p2, p3) +#define GFAStrtod(p1, p2) strtod(p1, p2) + +/* Memory Helper functions */ +#define GFMalloc( p1 ) malloc( p1 ) +#define GFFree( p1 ) free( p1 ) +#define GFMemcpy( p1, p2, p3 ) memcpy( p1, p2, p3 ) +#define GFMemmove( p1, p2, p3 ) memmove( p1, p2, p3 ) +#define GFMemcmp( p1, p2, p3 ) memcmp( p1, p2, p3 ) +#define GFMemset( p1, p2, p3 ) memset( p1, p2, p3 ) + +#define GFAAtoi( p1 ) atoi( p1 ) +/* Debug Helper functions */ +#define GFAPrintf printf +#define GFASprintf sprintf +#define GFASprintfVAL vsprintf +#define GFAPrintfVAL vprintf + +#if defined(GF_ENABLE_RMC_TRACE) +void GFRmRMCTrace(const char *printf_format, ...); +void GFRmRMCVTrace(const char *printf_format, va_list ap); +#define GFRMCTrace(a) GFRmRMCTrace a +#define GFRMCVTrace(a) GFRmRMCVTrace a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#ifdef DEBUG +#include "assert.h" +#define GFDEBUG_ASSERT( x ) assert( x ) +#endif + +// Operating system running on the Xtensa +#elif defined(NVCPU_XTENSA) + +#include + +#define GFAAtoi(p1) +/* String functions */ +#define GFAStrcpy(p1, p2) strcpy(p1, p2) +#define GFAStrncpy(p1, p2, p3) +#define GFAStrcat(p1, p2) +#define GFAStrncat(p1, p2, p3) +#define GFAStrlen(p1) +#define GFAStrchr(p1, p2) +#define GFAStrcmp(p1, p2) +#define GFAStrncmp(p1, p2, p3) + +#define GFAStrstr(p1, p2) +#define GFASscanf(p1, p2, p3) + +#define GFAStrncmp(p1, p2, p3) +#define GFAStrtok(p1, p2) +#define GFAToupper(p1) +#define GFATolower(p1) +#define GFAStrConvert(p1, p2, p3) +#define GFAAtoi(p1) + +/* Standard Helper functions */ +#define GFAStrtol(p1, p2, p3) +#define GFAStrtod(p1, p2) + +/* Memory Helper functions */ +#define GFMalloc( p1 ) +#define GFFree( p1 ) +#define GFMemcpy( p1, p2, p3 ) memcpy(p1, p2, p3) +#define GFMemmove( p1, p2, p3 ) memmove(p1, p2, p3) +#define GFMemcmp( p1, p2, p3 ) memcmp(p1, p2, p3) +#define GFMemset( p1, p2, p3 ) memset(p1, p2, p3) + +/* Debug Helper functions */ +#define GFAPrintf +#define GFASprintf +#define GFASprintfVAL +#define GFAPrintfVAL + +#define GFRMCTrace(a) +#define GFRMCVTrace(a) + +#else + +#include +#include +#include +#include +#include + +/* String functions */ +extern char GFAToupper(char); +extern char GFATolower(char); + +extern int GFAAtoi(const char *); +//#define GFMalloc( p1 ) malloc( p1 ) +//#define GFFree( p1 ) free( p1 ) +extern void *GFMalloc(int); +extern void GFFree(void *); + +extern void *GFMemcpy(void *, const void *, int); +extern void *GFMemmove(void *, const void *, int); +extern void *GFMemset(void *, int, int); +extern int GFMemcmp(void *, void *, int); + +extern char *GFAStrcpy(char *, const char *); +extern char *GFAStrncpy(char *, const char *, int); + +extern char *GFAStrcat(char *, const char *); +extern char *GFAStrncat(char *, const char *, int); + +extern int GFAStrlen(const char *); + +extern char *GFAStrchr(const char *,int); +extern char *GFAStrrchr(const char *,int); + +extern int GFAStrcmp(const char *, const char *); +extern int GFAStrncmp(const char *, const char *, int); + +extern char *GFAStrstr(const char * string1, const char * string2); +extern int GFASscanf(char * string1, const char * string2, ...); + +extern char *GFAStrtok(char *, const char *); + +extern long GFAStrtol(const char *, char **, int); +extern double GFAStrtod(const char *, char **); + +extern int GFAPrintf(const char *, ... ); +extern int GFASprintf(char * , const char *, ... ); +extern int GFASprintfVAL(char *, const char *, va_list); +extern int GFAPrintfVAL(const char *, va_list); + +#define GFAStrConvert(p1, p2, p3) GFAStrncpy(p1, p2, p3) + +#if defined(GF_ENABLE_RMC_TRACE) +#define GFRMCTrace(a) printf a +#define GFRMCVTrace(a) vprintf a +#else +#define GFRMCTrace(a) +#define GFRMCVTrace(a) +#endif + +#ifdef DEBUG +#define GFDEBUG_ASSERT(x) if(!(x)) \ + { \ + GFPrintf(" Assert at Line no: %d in %s ", \ + __LINE__, __FILE__); \ + } +#endif + +#endif /* GF_OS */ + +#endif /* GFRMHELP_ABSTRACTION */ + + +#define GFStrcpy GFAStrcpy +#define GFStrncpy GFAStrncpy +#define GFStrcat GFAStrcat +#define GFStrncat GFAStrncat +#define GFStrlen GFAStrlen +#define GFStrchr GFAStrchr +#define GFStrrchr GFAStrrchr +#define GFStrstr GFAStrstr +#define GFStrcmp GFAStrcmp +#define GFStricmp GFAStricmp +#define GFStrincmp GFAStrincmp +#define GFStrncmp GFAStrncmp +#define GFStrtok GFAStrtok +#define GFToupper GFAToupper +#define GFTolower GFATolower +#define GFStrConvert GFAStrConvert +#define GFPrintf GFAPrintf +#define GFSprintf GFASprintf +#define GFSprintfVAL GFASprintfVAL +#define GFPrintfVAL GFAPrintfVAL +#define GFStrtol GFAStrtol +#define GFStrtod GFAStrtod +#define GFSscanf GFASscanf +#define GFAtoi GFAAtoi + + +/* Virtual Key Mappings for Specific OS */ +#if defined(NV_LINUX) +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 65 +#define GF_VKEY_LEFT 68 +#define GF_VKEY_RIGHT 67 +#define GF_VKEY_DOWN 66 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#elif defined(NV_WINDOWS_CE) + +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 72 +#define GF_VKEY_LEFT 75 +#define GF_VKEY_RIGHT 77 +#define GF_VKEY_DOWN 80 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#elif defined(NV_WINDOWS) +/* Virtual Keys */ +#define GF_VKEY_BACK 27 +#define GF_VKEY_FORWARD 13 +#define GF_VKEY_UP 72 +#define GF_VKEY_LEFT 75 +#define GF_VKEY_RIGHT 77 +#define GF_VKEY_DOWN 80 +#define GF_VKEY_SEND 46 +#define GF_VKEY_END 44 +#define GF_VKEY_0 48 +#define GF_VKEY_1 49 +#define GF_VKEY_2 50 +#define GF_VKEY_3 51 +#define GF_VKEY_4 52 +#define GF_VKEY_5 53 +#define GF_VKEY_6 54 +#define GF_VKEY_7 55 +#define GF_VKEY_8 56 +#define GF_VKEY_9 57 +#define GF_VKEY_STAR 42 +#define GF_VKEY_POUND 35 + +#else + +/* Virtual Keys */ +#define GF_VKEY_BACK 2 +#define GF_VKEY_FORWARD 3 +#define GF_VKEY_UP 4 +#define GF_VKEY_LEFT 5 +#define GF_VKEY_RIGHT 6 +#define GF_VKEY_DOWN 7 +#define GF_VKEY_SEND 8 +#define GF_VKEY_END 9 +#define GF_VKEY_0 10 +#define GF_VKEY_1 11 +#define GF_VKEY_2 12 +#define GF_VKEY_3 13 +#define GF_VKEY_4 14 +#define GF_VKEY_5 15 +#define GF_VKEY_6 16 +#define GF_VKEY_7 17 +#define GF_VKEY_8 18 +#define GF_VKEY_9 19 +#define GF_VKEY_STAR 20 +#define GF_VKEY_POUND 21 + +#endif /* GF_OS */ + +#ifndef GFDEBUG_ASSERT +#define GFDEBUG_ASSERT(x) do {} while (0) +#endif /* GFDEBUG_ASSERT */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFRMHelp_INL__ */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmIx.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmIx.h new file mode 100755 index 00000000..c2dddd0d --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmIx.h @@ -0,0 +1,654 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFRmIx.h + Chip Initialization API header file. +*/ + +#ifndef __GFRMIX_H__ +#define __GFRMIX_H__ + +#include "GFRm.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** @addtogroup groupRmIx Chip Initialization API +*/ +/*@{*/ + +/* GPIO configurations + * Host GPIO1~GPIO7 correspond to HGP0~HGP6, C32KHZ. + * When configured as output, it is necessay to select output as data or + * Clocks or interrupt. + * GFIX_GPIO_CFG_OUTPUT can Or with GFIX_GPIO_CFG_OUTPUT_SEL_* + */ + +/* Host GPIO type enum */ +typedef enum +{ + GFIX_GPIO0 = 0, + GFIX_GPIO1, + GFIX_GPIO2, + GFIX_GPIO3, + GFIX_GPIO4, + GFIX_GPIO5, + GFIX_GPIO6, + GFIX_GPIO7 +} GFIX_GPIO_TYPE; + +/* Host GPIO operations. */ +#define GFIX_GPIO_GET_INPUT_ENABLE 0x80000000UL +#define GFIX_GPIO_GET_OUT_PUT_ENABLE 0x40000000UL +#define GFIX_GPIO_SET_DATA 0x20000000UL +#define GFIX_GPIO_CLR_DATA 0x10000000UL +#define GFIX_GPIO_GET_DATA 0x08000000UL + +#define GFIX_GPIO_SET_INPUT_ENABLE 0x04000000UL +#define GFIX_GPIO_CLR_INPUT_ENABLE 0x02000000UL +#define GFIX_GPIO_SET_OUTPUT_ENABLE 0x01000000UL +#define GFIX_GPIO_CLR_OUTPUT_ENABLE 0x00800000UL + +/* + * GPIO output select data, configure the pin as data output. + * Meaningful for pin0~pin4(HGP0~HGP4) + */ + +#define GFIX_GPIO_CFG_OUTPUT_SEL_DATA 0x00000000 + +/* + * GPIO output select interrupt, configure the pin as interrupt output. + * Meaningful for pin3(HGP3) only + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_INTR 0x00000040 + +/* + * GPIO output select RDY signal + * Meaningful for pin4(HGP4) only + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_RDY 0x00000100 + +/* + * For pin5 and pin6(HGP5, HGP6), config output clock or data on HGP5 and HGP6. + * + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP56_CLK 0x00000800 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP56_DATA 0x00000000 + +/* + * For pin5(HGP5) + * select monitor clock to HGP5 + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP5_PLL1 0x00000000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP5_PLL2 0x00001000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP5_PLLCOSC 0x00002000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP5_PLLROSC 0x00003000 + +/* + * For pin6(HGP6) + * select monitor clock to HGP6 + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP6_PLL2 0x00000000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP6_DCFCLK 0x00004000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP6_MCCLK 0x00008000 +#define GFIX_GPIO_CFG_OUTPUT_SEL_HGP6_DSPCLK 0x0000C000 + +/* + * For pin7(C32KHZ) + */ +#define GFIX_GPIO_CFG_OUTPUT_SEL_C32KHZ 0x00000000 + +/* + * Definition of attribute ids for Set/GetAttributes() + */ +typedef enum _GFIX_ATTR_TYPE + { + GFIX_ATTR_NONE = 0, + GFIX_ATTR_DEVICE_INFO, + GFIX_ATTR_DEVICE_INFO_STRUCT, /* Get Device ID & Rev */ + GFIX_ATTR_EFUSE_PRODUCT_SKU_ID, + GFIX_ATTR_DRAM_SELF_REFRESH, + GFIX_ATTR_DRAM_DEEP_POWER_DOWN +} GFIX_ATTR_TYPE; + +/* + * Definition of module frequency types. + */ +typedef enum _GFIX_MODULEFREQ_TYPE + { + GFIX_MODULEFREQ_OPTIMAL = 0, + GFIX_MODULEFREQ_MINIMUM, + GFIX_MODULEFREQ_MAXIMUM, + GFIX_MODULEFREQ_REQUESTED, + GFIX_MODULEFREQ_ACTUAL +} GFIX_MODULEFREQ_TYPE; + +/* + * Definition of module operations. + */ +#define GFIX_DISABLECLOCK 0x00000001 +#define GFIX_ENABLECLOCK 0x00000002 +#define GFIX_SPECIAL 0x00000004 +#define GFIX_FORCEDISABLECLOCK 0x00000008 +#define GFIX_FORCEENABLECLOCK 0x00000010 +#define GFIX_DYNAMICSWITCH 0x00000020 + +#define GFIX_FORCEDISABLEMODULE 0x00010000 +#define GFIX_FORCEENABLEMODULE 0x00020000 + +/* + * Clock selections, profile and options + */ +enum +{ +#define GFRM_CLOCK(x, y) GFIX_##x, +#define GFRM_CLOCK_PLL(x, y) GFIX_##x, +#include "gfrm_clock_ids.h" +#undef GFRM_CLOCK +#undef GFRM_CLOCK_PLL + GFNUMOFCLOCKIDS +}; + +enum +{ +#define GFRM_CLOCK(x, y) (1 << GFIX_##x )| +#define GFRM_CLOCK_PLL(x, y) (1 << GFIX_##x )| + GFIX_ALL_CLOCKS = +#include "gfrm_clock_ids.h" + 0, // | 0 to GFIX_ALL_CLOCKS +#undef GFRM_CLOCK +#undef GFRM_CLOCK_PLL + +#define GFRM_CLOCK(x, y) (1 << GFIX_##x )| +#define GFRM_CLOCK_PLL(x, y) + GFIX_NO_PLLS = +#include "gfrm_clock_ids.h" + 0, // | 0 to GFIX_NO_PLLS +#undef GFRM_CLOCK +#undef GFRM_CLOCK_PLL + +#define GFRM_CLOCK(x, y) +#define GFRM_CLOCK_PLL(x, y) (1 << GFIX_##x )| + GFIX_ONLY_PLLS = +#include "gfrm_clock_ids.h" + 0, // | 0 to GFIX_NO_PLLS +#undef GFRM_CLOCK +#undef GFRM_CLOCK_PLL + + GFIX_N_CLOCKSOURCES = GFNUMOFCLOCKIDS, + GFIX_NO_CLOCK = 0xFFFFFFFF, + GFIX_PLL_QUERY = 0x80000000 +}; + +#define GFIX_POWER 0x00010000 +#define GFIX_PERFORMANCE 0x00020000 + +#define GFIX_DEFAULTSLK 0x00000000 +#define GFIX_HIGHESTSLK 0x00000001 + +/** Module clock profile */ +typedef struct _GFIXMODULECONFIG +{ + NvU8 clockSelection; /**< Selection mode */ + NvU32 minFrequency; /**< Lowest frequency allowed */ + NvU32 optimalFrequency; /**< Optimal frequency */ + NvU32 maxFrequency; /**< Max frequency */ + NvU32 sourceClocks; /**< Bitfield of valid source clocks */ +} GFIXMODULECONFIG, *PGFIXMODULECONFIG; + +/** Module state */ + typedef struct _GFIXMODULESTATE +{ + NvU32 clkRefCount; /**< Reference counter used in GFRmIxEnableModuleClock */ + NvU32 clkSelect; /**< Clock selected for module (only valid when clkRefCount is non-zero) */ + /**< If clkSelect==GFIX_NO_CLOCK no clock is selected by this module */ + NvU32 enableRefCount; /**< Reference counter used in GFRmIxEnableModule */ +} GFIXMODULESTATE, *PGFIXMODULESTATE; + + +/** typedef for callback when the module is disabled */ + +typedef GF_RETTYPE (*GF_FUNC_RMIX_CALLBACK)(void *handle); + +/** Initializes the chip + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFRmIxInit() is the first function which touches the hardware, there are no + hardware accesses before GFRmIxInit(). It initializes some module's clocks + and as well as taking some modules out of reset. It also initializes + device-control registers. + + @see GFRmIxDeInit() +*/ +GF_RETTYPE +GFRmIxInit( GFRmHandle RmHandle ); + +/** De-initializes the chip + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + GFRmIxDeInit() does the reverse of GFRmIxInit(), it shut downs the chip. + All modules are put back in reset and clocks turned off. + + @see GFRmIxInit() +*/ +GF_RETTYPE +GFRmIxDeInit( GFRmHandle RmHandle ); + +/** This function enables a module's clock + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param modid (#eGFModuleIDs) ID of the module + @param option (NvU32) Bit field of options, GFIX_ENABLECLOCK, + GFIX_DISABLECLOCK, GFIX_FORCEENABLECLOCK, + GFIX_FORCEDISABLECLOCK, GFIX_DYNAMICSWITCH, GFIX_SPECIAL + @param special (NvU32) Specifies a module specific setting, only used when + option contains GFIX_SPECIAL + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function enables and disables a module's clock as well as enables the + module's source clock. There are two types of enables, the normal enable + and the force enable. When doing a normal enable the module's clock enable + reference count is increased as well as a call to GFRmIxEnableClockSource() + which ensures the module's source clock is enabled. When doing a force + enable/disable the modules reference counter is not touched, + GFRmIxEnableClockSource() is called which increases/deceases the source's + reference count. If the operation is to enable and the clock is currently + disabled, for the both normal enable and force disable GFRmIxEnableModuleClock + will attempt to find the best clock source and divider for the module. + + Some modules support a dynamic clock divider, that is the clock doesn't have + to be turned off before reprogramming the divider. To switch a module's + frequency that supports dynamic dividers without first turning the module + off set option to GFIX_DYNAMICSWITCH. GFRmIxEnableModuleClock will attempt + to find the closest frequency to the desired without changing clock sources. + + Some modules have special clock configurations such as VI, GFIX_SPECIAL can + be specified along with GFIX_ENABLECLOCK or by itself to configure the special + option for the module. +*/ +GF_RETTYPE +GFRmIxEnableModuleClock( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 option, + NvU32 special ); + +/** Same as GFRmIxEnableModuleClock, but takes a callback + function which will be called when the refcount goes + to zero. + + @param func Callback funtion of type GFRmIxEnableModuleClock + @param arg used as an argument to when callback function is called. + + @see GFRmIxEnableModuleClock() +*/ +GF_RETTYPE +GFRmIxEnableModuleClockEx( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 option, + NvU32 special, + GF_FUNC_RMIX_CALLBACK func, + void *arg); + +/** Enables a module + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param modid (#eGFModuleIDs) ID of the module + @param option (NvU32) If option is nonzero the module will be enabled + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function takes a module out of reset. Each module has a reference + count which is used to keep track of how many outstanding enables the + module has. The module will not be disabled until the reference counter + is returned to zero. +*/ +GF_RETTYPE +GFRmIxEnableModule( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 option ); + +/** Same as GFRmIxEnableModule() but calls the passing in callback + function when the refcount of the module goes to zero. + + @param callback Callback function of type GF_FUNC_RMIX_CALLBACK + @param arg Argument passed to the callback function. + + @see GFRmIxEnableModule() +*/ +GF_RETTYPE +GFRmIxEnableModuleEx( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 option, + GF_FUNC_RMIX_CALLBACK callback, + void *arg + ); + +/** Changes frequency of a clock. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param option (NvU32) GFIX_PLL1, GFIX_PLL2, GFIX_ROSC, GFIX_OSC, + GFIX_REFCLK0, GFIX_REFCLK1 or GFIX_PLL_QUERY + @param pFrequency (NvU32*) Pointer to 32-bit value in KHz to get three + digit MHz precision. Returns with newly set + current frequency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GF_ERROR_BAD_PARAMETER Bad parameter passed + + This function sets a clock to a certain frequency. If the clock cannot meet + the requested frequency then the closest one will be chosen. For the PLLs + this function determines the closest dividers to arrive at the requested + frequency. To determine the frequency that will be chosen without actually + setting it GFIX_PLL_QUERY can be Or'ed along with the clock ID. + + Some clocks only have one frequency that never changes; this function must + still be called at least once to allow the internal logic to know what the + frequency of the clock is. To disable the selection of a clock by a module, + a clock can be disabled by setting its frequency to zero; this will remove + it from consideration for all modules. + + This function will fail if a module is already using the clock. + + @see GFRmIxGetFrequency() +*/ +GF_RETTYPE +GFRmIxSetFrequency( GFRmHandle RmHandle, + NvU32 option, + NvU32 *pFrequency ); + +/** Retrieves frequency of a clock. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param option (NvU32) GFIX_PLL1, GFIX_PLL2, GFIX_ROSC, GFIX_OSC, + GFIX_REFCLK0, GFIX_REFCLK1 + @param pFrequency (NvU32*) Pointer to 32-bit value in KHz to get three + digit MHz precision. Returns with currently + set frequency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GF_ERROR_BAD_PARAMETER Bad parameter passed + + @see GFRmIxSetFrequency() +*/ +GF_RETTYPE +GFRmIxGetFrequency( GFRmHandle RmHandle, + NvU32 option, + NvU32 *pFrequency ); + +/** Sets the requested frequency of the module. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param modid (#eGFModuleIDs) ID of the module + @param frequency (NvU32) 32-bit value in KHz to get three digit MHz + precision + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function sets the requested frequency of a module, this value must + lie between the minimum and maximum frequencies specified in + GFRmIxSetModuleConfig(). This value is cached and used when + GFRmIxEnableModuleClock() is called attempting to enable the clock to the + module. + + @see GFRmIxSetModuleConfig() +*/ +GF_RETTYPE +GFRmIxSetModuleFrequency( GFRmHandle RmHandle, + eGFModuleIDs modid, + NvU32 frequency ); + +/** This function is used to retrieve clock frequency information about a module. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param modid (#eGFModuleIDs) ID of the module + @param type (#GFIX_MODULEFREQ_TYPE) Type of frequency + @param pFrequency (NvU32*) Pointer to 32-bit value in KHz to get three digit + MHz precision. Returns with currently frequency. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +GF_RETTYPE +GFRmIxGetModuleFrequency( GFRmHandle RmHandle, + eGFModuleIDs modid, + GFIX_MODULEFREQ_TYPE type, + NvU32 *pFrequency ); + +/** This function enables and disables power plane(s). + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param ppID (NvU32) ID of power plane (More then one can be Or'ed to perform + operation in parallel) + @param operation (#GFIX_POWERPLANE_OP_TYPE) Operation to perform on the + power planes + @param states (NvU32*) Ptr to 32 bit value to store the resulting bit + field of a GFIX_POWERPLANE_OP_QUERY operation. + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GF_ERROR_BAD_PARAMETER Bad parameter passed + + This function enables and disables power plane(s), multiple power planes can + be disabled in one function call. There is two versions of this functions + specified with the compilation flag GF_EXTERNAL_POWERPLANE_LOGIC. If this + flag is set to 1 then all the power plane logic is done in the platform code, + if 0 then all the logic is done in Ix. + + When internal power plane logic is chosen, each power plane has a reference + count. If the power plane is to be enabled or disabled, GFRmIxPowerPlane() + will call out to RmPowerPlane(), which will perform platform specific enabling. +*/ +GF_RETTYPE +GFRmIxPowerPlane( GFRmHandle RmHandle, + NvU32 ppID, + GFIX_POWERPLANE_OP_TYPE operation, + NvU32 *states ); + +/** Enable and disables clock sources. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param clockid (NvU32) ID of the clock + @param state (NvU32) 0 for disable, 1 for enable + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function enables and disables a clock's source. A reference counter is + used to ensure the clock's source won't be disabled until there is a matching + number of enable and disable operations. If a clocks source is to be enabled + or disabled, GFRmIxEnableClockSource() will call out to RmEnableClockSource() + to do the platform specific enabling or disabling. +*/ +GF_RETTYPE +GFRmIxEnableClockSource( GFRmHandle RmHandle, + NvU32 clockid, + NvU32 state ); + +/** This function sets the list of reference clocks that a PLL may choose. + + @param RmHandle (#GFRmHandle) Handle specific to the GFRm + @param option (NvU32) GFIX_PLL1, GFIX_PLL2 + @param clocks (NvU32) Bitfield of clocks. (1< +
      +                                                      0    -> audio structs can be locate anywhere, dspcore will be allocated anywhere (default)
      +                                                      1    -> audio structs must be allocated in internal SRAM, dspcore will be allocated anywhere
      +                                                      0xMM -> MM is a 8 bit wide bitmask: b'10XXYYZZ (i.e. 0x80 | b'XXYYZZ)
      +
      +                                                      XX controls allocation of dspcore DSP image (about 100 kB)
      +                                                      YY to control allocation of GfSgl (about 90 kB, not required for encoding=ADTSINTERNAL)
      +                                                      ZZ controls allocation of GfGlobalParameters struct (about 36 kB)
      +
      +                                                      bitmask meaning:
      +                                                      b'00 no special requirement
      +                                                      b'01 force internal SRAM
      +                                                      b'10 force external SRAM
      +                                                      b'11 unused
      +                                                      
      + */ + + NvU32 AudioRecordEnable; //!< GFSDK_AUDIO_REC_ENABLE, Enable SC15 I2S Record, default : 0 + NvU32 AudioNoI2C; //!< Disable codec I2C access in GFAudioAPI + char I2SCodecInit[RM_ENV_MAXLEN]; //!< Codec init addr/data sequence comma delimited zero padded 32 bit hex values "xxxxxxxx,xxxxxxxx,..." up to 128 chars + char I2SCodecReset[RM_ENV_MAXLEN]; //!< Codec reset addr/data sequence comma delimited zero padded 32 bit hex values "xxxxxxxx,xxxxxxxx,..." up to 128 chars + //!< I2S "aaaaddrr" aaaa - i2s slave address, dd - 8 bit data, rr 7 bit i2s register + //!< AC97 "aaaadddd" aaaa - ac97 register address, dddd - 16 bit data value + NvU32 I2SCodecEnableSMCLK; + NvU32 SCInterfaceMode; + + NvU32 perfMode3D; // 3D perf mode. + NvU32 DxInitBypass; // This is used to tell DxSetDisplay() to initialize the + // software state without touching the hardware + NvU32 noDCPreLoadCtx; + NvU32 nulldriver2D; +#if NVOS_IS_WINDOWS_CE + NvU32 BackupMemory; +#endif + NvU32 IndirectAddrSet; +} GFRMENVIRONMENTVARIABLES, *PGFRMENVIRONMENTVARIABLES; + +/* Rm Public Services for platform only. May depend on GFPlat.h */ +enum +{ + RM_EXTDATA_INIT_TYPE = 0 +}; + +enum +{ + RM_EXTDATA_INIT_SCRIPT = 0, + RM_EXTDATA_RM_SCRIPT, + RM_EXTDATA_CAMERA_SCRIPT, + RM_EXTDATA_ENVVARS_SCRIPT, + RM_EXTDATA_DISPLAY_SCRIPT, + RM_EXTDATA_DISPLAY_SUB_SCRIPT, + RM_EXTDATA_AUTOCTRL_SCRIPT, + RM_EXTDATA_AVP_IMAGE_AUDIO_AVP1, + RM_EXTDATA_AVP_IMAGE_MP3_AVP1, + RM_EXTDATA_AVP_IMAGE_SBC_AVP1, + RM_EXTDATA_AVP_IMAGE_AAC_AVP1, + RM_EXTDATA_AVP_IMAGE_EAAC_AVP1, + RM_EXTDATA_AVP_IMAGE_AACLPSBR_AVP1, + RM_EXTDATA_AVP_IMAGE_AMRNB_AVP1, + RM_EXTDATA_AVP_IMAGE_AMRWB_AVP1, + RM_EXTDATA_AVP_IMAGE_WMA_AVP1, + RM_EXTDATA_AVP_IMAGE_AUDIO_AVP2, + RM_EXTDATA_AVP_IMAGE_MP3_AVP2, + RM_EXTDATA_AVP_IMAGE_SBC_AVP2, + RM_EXTDATA_AVP_IMAGE_AAC_AVP2, + RM_EXTDATA_AVP_IMAGE_EAAC_AVP2, + RM_EXTDATA_AVP_IMAGE_AACLPSBR_AVP2, + RM_EXTDATA_AVP_IMAGE_AMRNB_AVP2, + RM_EXTDATA_AVP_IMAGE_AMRWB_AVP2, + RM_EXTDATA_AVP_IMAGE_WMA_AVP2, + RM_EXTDATA_AVP_IMAGE_H264DEC_AVP1, + RM_EXTDATA_AVP_IMAGE_H264DEC_AVP2, + RM_EXTDATA_AVP_IMAGE_MP4DEC_AVP1, + RM_EXTDATA_AVP_IMAGE_MP4DEC_AVP2, + RM_EXTDATA_AVP_IMAGE_JPEGDEC_AVP1, + RM_EXTDATA_AVP_IMAGE_JPEGDEC_AVP2, + RM_EXTDATA_AVP_IMAGE_H264ENC_AVP1, + RM_EXTDATA_AVP_IMAGE_H264ENC_AVP2, + RM_EXTDATA_AVP_IMAGE_VC1DEC_AVP1, + RM_EXTDATA_AVP_IMAGE_VC1DEC_AVP2, + RM_EXTDATA_AVP_IMAGE_RV9DEC_AVP1, + RM_EXTDATA_AVP_IMAGE_RV9DEC_AVP2, + RM_EXTDATA_AVP_IMAGE_ISP3A_AE_AF_AVP1, + RM_EXTDATA_AVP_IMAGE_ISP3A_AWB_AVP1, + RM_EXTDATA_AVP_IMAGE_ISP3A_DVS_AVP1, + RM_EXTDATA_AVP_IMAGE_BEATNIK_AVP1, + RM_EXTDATA_AVP_IMAGE_BEATNIK_AVP2, + RM_EXTDATA_AVP_IMAGE_KERNEL_AVP1, + RM_EXTDATA_AVP_IMAGE_KERNEL_AVP2, + RM_EXTDATA_AVP_IMAGE_DSP_UNITTESTS, + RM_EXTDATA_AVP_IMAGE_TSDEM_AVP1, //!< SC15 version of GFMxDemTS DSP image + RM_EXTDATA_AVP_IMAGE_TSDEM_AVP2, //!< SC14 version of GFMxDemTS DSP image + RM_EXTDATA_AVP_IMAGE_ISP_AVP1 +}; + +enum +{ + RM_EXTDATA_FILE = 0, + RM_EXTDATA_FILE_WITH_SUBID, +}; + +#define DEFAULTSCRIPTNAME "default" + +#define RM_EXTDATA_READ 1 // Read in data +#define RM_EXTDATA_USEBUFFER 4 // RmAccessExternalData shouldn't handle + // allocation of buffer, the data is to + // be placed at the orginal buffer address +#define RM_EXTDATA_SIZE 8 // Query the size of the data +#define RM_EXTDATA_FILENAME 0x10 // return script file name +#define RM_EXTDATA_NAME 0x20 // return name of script without prefix and sub ID +#define RM_EXTDATA_IDLIST 0x40 // return array of script sub ID + +/* Fields in struct PGFRMEXTDATASTRUCT + * dataType : Type of the data + * dataID : ID of the data + * subID : Sub ID of script + * buffer : Pointer to pointer of the data address + * size : Address to store the resulting size. During a read operation if size + * is non-zero the amount of bytes read in will be stored there. If size + * or the value pointed to by size is zero all the data represented by + * dataID will be read in. + * option : flag that will change what is returned in buffer and size. + */ +typedef struct _GFRMEXTDATASTRUCT +{ + NvU32 dataType; // type of data + NvU32 dataID; // ID of data + NvU32 subID; // sub ID of data + void ** buffer; + NvU32 * size; + NvU32 option; +} GFRMEXTDATASTRUCT, *PGFRMEXTDATASTRUCT; + + + /** This function is called to get value from curent environment. + + @param envName environment name in env table + @param envType environment type + RM_ENV_DECIMAL // String should be parsed as a decimal + RM_ENV_HEX // String should be parsed as a hexadecimal + RM_ENV_CHAR // String should be parsed as a character + RM_ENV_STRING // String used as-is. + @param parsedval converted value. Only available while environment type is RM_ENV_DECIMAL or RM_ENV_HEX + @return a pointer to the environment table entry containing varname. + */ +// char * ReadEnvVars( const char *envName, int envType, NvU32 *parsedval); +GF_RETTYPE nvGetConfigUint32(const char *name, NvU32 *value); + +GF_RETTYPE nvGetConfigString( const char *envName, char **value); + +/** Retrieves the Process id of the current process. + + @param RmGetProcessID Pointer to NvU32 for returning the prcess id, + + @return GF_SUCCESS If the platforms support some sort of get process id API + @return GF_ERROR. if not support +*/ +GF_RETTYPE RmGetProcessID( NvU32 *RmProcessID ); + +/* Thread, Mutex, Event and Semaphore opaque handles */ +typedef struct GFMutex_t *GFMutex; +typedef struct GFSemaphore_t *GFSemaphore; +typedef struct GFEvent_t *GFEvent; +typedef struct GFThread_t *GFThread; + +/* Rm platform functions for OS abstraction */ + +/** Create Mutex object. + + @param id - Mutex identiifer. Used to cretate named objects. If the + id is 0, un named object is created. + + @return Handle to the event object, or 0 on failure. +*/ +GFMutex RmCreateMutex( NvU32 id ); + +/** Lock mutex object, blocks until mutex can be taken. Must always succeed if + given a valid mutex handle. + + @param mutex Mutex handle +*/ +void RmLockMutex(GFMutex mutex); + +/** Unlock mutex object. Must always succeed if given a valid mutex handle. + + @param mutex Mutex handle +*/ +void RmUnlockMutex(GFMutex mutex); + +/** Destroy mutex object. Must always succeed if given a valid mutex handle. + Must not crash (should do nothing) if given a NULL handle. + + @param mutex Mutex handle. +*/ +void RmDestroyMutex(GFMutex mutex ); + +/** Create semaphore object. + + @param id - Semaphore identifer. Used to create named objects. If the + id is 0, unnamed object is created. + + @param InitCount (NvU32) Initial count of semaphore. This value must be + greater than zero. + @param MaxCount (NvU32) Maximum count of semaphore. This value must be + greater than zero. + + @return Handle to semaphore object, or 0 on failure +*/ +GFSemaphore RmCreateSemaphore(NvU32 id, NvU32 InitCount, NvU32 MaxCount); + +/** Destroy semaphore object. Must always succeed if given a valid semaphore + handle. Must not crash (should do nothing) if given a NULL handle. + + @param sem Semaphore handle +*/ +void RmDestroySemaphore(GFSemaphore sem); + +/** Signal semaphore object. This function increments the semaphore's counter. + Must always succeed if given a valid semaphore handle. + + @param sem Semaphore handle +*/ +void RmSignalSemaphore(GFSemaphore sem); + +/** Wait on semaphore. + Function blocks while semaphore's count is 0. Once the count is non-zero, + the count is decremented by one and function returns. If timeout is passed + as 0, the function does not block. + + @param sem Semaphore handle + @param timeout Timeout in miliseconds, 0 for non-blocking, (NvU32)-1 for infinite wait. + @retutn GF_SUCCESS indicates that the semaphore was taken successfully, GF_WAIT_TIME_OUT + indicates timeout, any other return value indicates error. +*/ +GF_RETTYPE RmWaitOnSemaphore(GFSemaphore sem, NvU32 timeout); + + +/** Create event object. + + @return Handle to event object, or NULL on failure +*/ +GFEvent RmCreateEvent(void); + +/** Sets the event object to the signaled state. Must always succeed if given + a valid event handle. + + @param event Event handle +*/ +void RmSetEvent( GFEvent event ); + +/** Resets the event object to the nonsignaled state. Must always succeed if + given a valid event handle. + + @param event Event handle +*/ +void RmResetEvent( GFEvent event ); + +/** Function blocks until the event is signaled. + + @param event Event handle. + @param msec Milli seconds to wait. + + @retval GF_WAIT_GET_OBJECT Event was signaled, and the event object was acquired. + @retval GF_WAIT_TIME_OUT Timeout before event was signaled + @retval GF_WAIT_ERROR An error occured. +*/ +GF_RETTYPE RmWaitForEvent(GFEvent event, NvU32 msec ); + + +/** Destroys the event object. Must always succeed if given a valid event + handle. Must not crash (should do nothing) if given a NULL handle. + + @param event Event Handle. This is the handler returned by + the call to RmCreateEvent function. +*/ +void RmDestroyEvent( GFEvent event ); + +/** Creates a thread to execute within the calling process. + + @param func (NvU32 (*)(void *)) Pointer to a function to be executed + by the thread. + @param data (void *) Pointer to variable to be passed to the thread + + @return Handle to thread on success, otherwise 0 is returned. +*/ +GFThread RmCreateThread(NvU32 (*StartFunction)(void *), void *data); + +/** Blocks until the specified thread terminates, then frees system resources + associated with the thread. Must always succeed if given a valid thread + handle. Must not crash (should do nothing) if given a NULL handle. + + @param ThreadHandle Thread handle retruned by RmCreateThread call +*/ +void RmJoinThread(GFThread ThreadHandle); + +/** Yield execution to other threads. This will be called inside spin loops + that are waiting for the hardware to finish something. +*/ +void RmYield(void); + +/** Get full path of extended script data. Assume the script data is at same directory as bootload module. + @param modulename (char *)Bootloader module name. If the script data is not at same directory as module, could be NULL. + @param fullpath (char *)Pointer to extened script data path. + + @return GF_SUCCESS to signal success, or error code to signal failure +*/ +GF_RETTYPE + RmGetExtDataPath(char *modulename, char *fullpath ); + +/* File and File Search opaque handles */ +typedef struct GFFile_t *GFFile; +typedef struct GFFileSearch_t *GFFileSearch; + +/** Searches a directory for a file whose name matches the specified file name. + It examines subdirectory names as well as file names + @param filePath (char *) Pointer to a null-terminated string that specifies a valid directory or path and file name, + which can contain wildcard characters (* and ?) + @param filename (char *) pointer to the full path file/dir which match this search. + + @return If the function succeeds, the return value is a search handle used in a subsequent call to RmFindNextFile or RmFindClose, + NULL if the function failed. +*/ +GFFileSearch RmFindFirstFile(const char *filePath, char *fileName); + +/** Continues a file search from a previous call to the RmFindFirstFile function. + @param hFind (GFFileSearch ) Search handle returned by a previous call to the RmFindFirstFile function. + @param filename (char *) pointer to the filename with full path which match this search. + @return GF_SUCCESS to signal success, or error code to signal failure +*/ +GF_RETTYPE RmFindNextFile(GFFileSearch hFind, char *fileName); + +/** Closes the specified search handle. Must always succeed if given a valid + search handle. Must not crash (should do nothing) if given a NULL handle. + + @param hFind (GFFileSearch) Search handle returned by a previous call to the RmFindFirstFile function. +*/ +void RmFindClose(GFFileSearch hFind); + +/** Open file. + @param filename (const char *) Filename + @param fileSpec (const char *) Type of access permitted + @return Handle to the open file. A NULL pointer value indicates an error. +*/ +GFFile RmFileOpen(const char *fileName, const char *fileSpec); + +/** Close file. Must always succeed if given a valid file handle. Must not + crash (should do nothing) if given a NULL handle. + + @param fp Handle that RmFileOpen() returned +*/ +void RmFileClose(GFFile fp); + +/** Read data from file. + @param buffer (void *) Storage location for data + @param lSize (NvU32) Item size in bytes + @param lCount(NvU32) Maximum number of items to be read + @param fp (GFFile) Pointer that RmFileOpen() returned + @return Number of full items actually read, 0 if nothing is read out. +*/ +GF_RETTYPE RmFileRead(void *buffer, NvU32 lSize, NvU32 lCount, GFFile fp); + +/** Get file size. + @param fp(GFFile ) Pointer that RmFileOpen() returned + @return Current file size in bytes. +*/ +GF_RETTYPE RmFileSize(GFFile fp); + +/** Platform abstraction for millisecond sleep. + + @param msec Milliseconds to sleep. + */ +void RmWaitMSec(NvU32 msec); + +/** Waits for a keypress with a timeout, and returns the key. + + @param timeOutMSec Milliseconds to wait for the keypress. + @retval The code for the key, or zero if we timed out. + */ +int RmWaitKey(NvU32 timeOutMSec); + +/** Get the current OS tick counter. + @return Low 32 bits of millisecond counter. +*/ +NvU32 RmGetTickCountMSec(void); + +/** Get the current OS tick counter. + + NOTE: This function is NOT guaranteed to exist on all + platforms. Drivers should NOT call this function; it's + meant only for benchmarking. + + @return (NvU64) 64 bit microsecond counter. + */ +NvU64 RmGetTickCountUSec(void); + +/** SetupPlatform - It is called by RmSetupPlatform to setup any platform specific stuff. + + @param pOutput (PGFRMSETUPPLATFORM) output structure. Used to pass variables to high layer function RmSetupPlatform + @param penv (PGFRMENVIRONMENTVARIABLES) pass Environment Variable Configuration structure + + @return GF_SUCCESS to signal success, or error code to signal failure + +*/ +GF_RETTYPE SetupPlatform( PGFRMSETUPPLATFORM pOutput, PGFRMENVIRONMENTVARIABLES penv ); + +/** Called by RmExitPlatform to exit and clean-up any platform specific stuff, if any + + @param pUserObject0 (void *) Pointer to user specified object 0 from high layer function RmExitPlatform + + @return GF_SUCCESS to signal success, or error code to signal failure +*/ +GF_RETTYPE ExitPlatform( void *pUserObject0); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFRMOEM_H__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmRDMA.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmRDMA.h new file mode 100755 index 00000000..151ec65d --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmRDMA.h @@ -0,0 +1,411 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @File: GFRmRDMA.h + GFSDK Read DMA memmory manager. + + */ + +#ifndef __GFRMRDMA_H__ +#define __GFRMRDMA_H__ + +#include "GF.h" + +/** @addtogroup groupRDMA RDMA ReadDMA API +
        +
      • @ref pageRDMAAppNotes +
      +*/ + +/*@{*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + + +/** eGFRmRDMAClientID: Enumeration of client id's. SC15 has 4 + RDMA (Read DMA) FIFO's. Modules specified below can be + attached to the RDMA FIFO's. See @ + */ +typedef enum +{ + RDMA_CLID_CPU = 0, + RDMA_CLID_DSP, + RDMA_CLID_I2S, + RDMA_CLID_SD, + RDMA_CLID_MPEGE, + RDMA_CLID_JPEGE, + RDMA_CLID_EPP, + RDMA_CLID_VI, + RDMA_CLIDS +} eGFRmRDMAClientID; + +/** RDMA buffer header. + + For non-rectangular (or linear) reads + RDMA expects a header in the memory. The header formart is as specified + below. GFRmRDMAReadHeader function returns the header in this format. + + @See GFRmRDMAReadHeader() + */ + +typedef struct _RDMA_BUF_HEADER +{ + NvU32 bufferSize; + NvU32 raiseVector; + NvU32 channel; + NvU8 raiseEnable; + NvU8 frameStart; + NvU8 frameEnd; + NvU8 largeHdr; + NvU32 extHeader; + +} RDMA_BUFFER_HEADER, *pRDMA_BUFFER_HEADER; + + +/* RDMA flags */ + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + No byte swap. +*/ +#define GF_RDMA_FLAGS_SWAP_NONE 0x00000000 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + Swap bytes in a word. example: 0xaabbccdd to 0xbbaaddcc. +*/ +#define GF_RDMA_FLAGS_SWAP_BYTE_IN_WORD 0x00000001 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + Swap bytes in dword: 0xaabbccdd to 0xddccbbaa. +*/ +#define GF_RDMA_FLAGS_SWAP_BYTE_IN_DWORD 0x00000002 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + Swap word in dword example: 0xaabbccdd to 0xccddaabb. +*/ +#define GF_RDMA_FLAGS_SWAP_WORD_IN_DWORD 0x00000003 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags bitmask: + mask out byte swap options GF_RDMA_FLAGS_SWAP_*. +*/ +#define GF_RDMA_FLAGS_SWAP_MASK 0x00000003 + +/** RDMA_NONRECT::flags and RDMA_RECT::flags flagbit: + Tells the RDMA engine to output header. Will output a header into the data stream, + which has to be read with GFRmRDMAReadHeader() before calling GFRmRDMARead(). + This flag is relevant only in non-rectangular reads. + */ +#define GF_RDMA_FLAGS_STR_HEADER 0x00010000 + +/** RDMA_RECT + Setup information for the RDMA. + */ +typedef struct _RDMA_RECT +{ + /** physical addess of the buffer in the SC15 Memory view. 32-bit alignment + * required. */ + NvU32 baseOffset; + + /** client id. See @eGFRmRDMAClientID */ + eGFRmRDMAClientID clid; + + /** buffers/stride/width/lines of the rectangular buffer. + + Need to comply with the following constraints provided + by the hardware + - if width is not a multiple of 4 bytes (one word): + - stride equals width, stride should be the exact stride in bytes (eg. line_stride[1:0] not equal to 0) + - if stride is bigger than width, stride should be rounded down to the nearest word + (eg. line_stride[1:0] should be zero) + + For example: width = 42 bytes, stride = 82 -> stride should be programmed to 80 + width = 42 bytes, stride = 42 -> stride should be programmed to 42 + */ + NvU32 buffers; + NvU32 stride; + NvU32 width; + NvU32 lines; + + /* use the RDMA flags defined above as GF_RDMS_FLAGS_* */ + NvU32 flags; //!< Flagbits, see GF_RDMA_FLAGS_* + + /* Timeout in msec. If <=0, then no timeout */ + NvU32 timeout; + +} RDMA_RECT, *pRDMA_RECT; + +/** RDMA_NONRECT + + Setup structure for non-rectangular reads. + + */ +typedef struct _RDMA_NONRECT +{ + /** Physical addess of the buffer in the GPU address space. Needs to be + * 32-bit aligned. */ + NvU32 baseOffset; + + /** client id. See @eGFRmRDMAClientID */ + eGFRmRDMAClientID clid; + + NvU32 buffers; + NvU32 stride; + + /* use the RDMA flags defined above as GF_RDMS_FLAGS_* */ + NvU32 flags; //!< Flagbits, see GF_RDMA_FLAGS_* + + /* Timeout in msec. If =0, then no timeout */ + NvU32 timeout; + +} RDMA_NONRECT, *pRDMA_NONRECT; + + +/** There are four read dma channels, the RM manages the allocation/ + freeing of these channels. This function allocates a channel. + + @param RmHandle Handle to the Rm allocated via call to GFRmOpen. + @param DmaHandle Pointer to an allocated handle. + + @retval GF_SUCCESS if a RDMA channel is available, and returns + RDMA handle on allocation. + + The release function will return GF_ERROR + if the read dma is already released. + */ + +GF_RETTYPE +GFRmRDMAAlloc(GFRmHandle RmHandle, GFRmRdmaHandle *DmaHandle); + +/** There are four read dma channels, the RM manages the allocation/ + freeing of these channels. This function frees an allocated + channel. + + @param hRm Handle to the Rm allocated via call to GFRmOpen. + @param phDma Pointer to the DMA handle to be released. + */ +void +GFRmRDMARelease(GFRmHandle hRm, GFRmRdmaHandle *phDma); + +/** Setup non-rectangular RDMA. + + When the flag GF_RDMA_FLAGS_STR_HEADER is set, buffer header is written to the + memory by the RDMA client. So, when the cpu reads the data, buffer + header comes first and then the data. Buffer header has the information + of buffer, like its size etc. + + + So, an example sequence would be + - Call setup with GF_RDMA_FLAGS_STR_HEADER flag set. + - Read header with the GFRmRDMAReadHeader(...) + - Read buffer size of data with GFRmRDMARead() funtion. + Buffer size is in the buffer header. + + If this flag is not set, then the there is no buffer header. + In this case it is assumed that the the size of the buffer is prefixed + and known to the module API writers. + + So, an example sequence would be + - Call setup GF_RDMA_FLAGS_STR_HEADER flag not set. + - Read buffer size of data with GFRmRDMARead() funtion. + Buffer size is known to the callers. + + baseOffset of pReq structure needs to be 32-bit aligned. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param pReq Populated RDMA req structure. See @RDMA_NONRECT +*/ + +GF_RETTYPE +GFRmRDMASetupNONRect(GFRmRdmaHandle DmaHandle, pRDMA_NONRECT pReq); + +/** Setup RDMA for rectangular read. + + Requirement: + baseOffset of pReq structure needs to be 32-bit aligned. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param pReq Populated RDMA req structure. See @RDMA_RECT +*/ +GF_RETTYPE +GFRmRDMASetupRect(GFRmRdmaHandle DmaHandle, pRDMA_RECT pReq); + +/** Reads the RDMA FIFO status register and returns the + available number of FIFO slots. A slot is 32-bit. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + */ +NvU32 GFRmRDMAFIFOAvailIn32Bits(GFRmRdmaHandle DmaHandle); + +/** Reads memory from SC15 internal/external + memory to the system memory pointed by the dstAddr. Need + to pass the same rectangular attributes passed, when the + RDMA is setup. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param dstAddr aligned or non-aligned dest pointer. Aligned + pointer results in faster reads. + @param width Width in bytes to read. + @param height Height of the rectangular region. + + @retval Returns GF_SUCCESS or GF_ERROR. + */ + +GF_RETTYPE +GFRmRDMARectRead(GFRmRdmaHandle DmaHandle, void *dstAddr, NvU32 width, NvU32 height); + + +/** Reads memory from SC15 internal/external + memory to the system memory pointed by the dstAddr. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param dstAddr aligned or non-aligned dest pointer. Aligned + pointer results in faster reads. + @param sizeInBytes Number of bytes to read. + + @retval Returns GF_SUCCESS or GF_ERROR. + */ + +GF_RETTYPE +GFRmRDMARead(GFRmRdmaHandle DmaHandle, void *dstAddr, NvU32 sizeInBytes); + +/** Reads buffer header. Once this info is read + API's will know how much data to read or expect. + + @param DmaHandle Handle returned by @GFRmRDMAAlloc function. + @param header Pointer to RDMA header structure. See @RDMA_BUFFER_HEADER + */ +GF_RETTYPE +GFRmRDMAReadHeader(GFRmRdmaHandle DmaHandle, pRDMA_BUFFER_HEADER header); + + +/** Cleanup the RDMA FIFO, by reading out any extra DOWRDS + GFRmRDMARead might not have read. + + In general this function need not be used. + */ + +GF_RETTYPE +GFRmRDMACleanup(GFRmRdmaHandle DmaHandle); + + +/** Gets the actual RDMA channel number from the DMA handle. This is + usefull for DSP development. Host code allocates the DMAHandle + gets the DMA number from that and creates the DMA handle on the + DSP side using GFXRmRDMAAlloc function. GFXRmRDMAAlloc needs to + know what DMA channel to use. + + @param DmaHandle RDMA handle. + @param dmaNumber RDMA channel number used the handle. + +*/ + +void +GFRmRDMAGetPortNumber(GFRmRdmaHandle DmaHandle, NvU32 *portNumber); + +#if NVCPU_IS_XTENSA + +// In XRM, it is expected that the dma handle is allocated on +// the Host side, and just the dma number is passed into code +// running on the Xtensa. These functions will setup a +// DMA handle that can used in the XRM. + + +GF_RETTYPE +GFXRmRDMAAlloc(NvU32 dmaNumber, GFRmRdmaHandle *DmaHandle); + + +GF_RETTYPE +GFXRmRDMARelease(GFRmRdmaHandle *DmaHandle); + +#endif // NVCPU_IS_XTENSA + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/*@}*/ + +/** @page pageRDMAAppNotes RDMA Application Notes + + General information about RDMA - RDMA is read DMA hw block. Unlike + traditional DMA, sw reads the data from the FIFO to system memory. This is + becasuse SC15 cannot bus master and write directly to the system memory. + RDMA will be faster becasue the data is buffered by the HOST1x Block and sw + reads back data in a tight loop. + + SC15 RDMA supports 2 modes - Linear(AKA NON-Rect) and Rect mode. + In both modes the sequence of programming same - setup and then read the data. + + RDMA setup is 2 step process. + - RDMA need to know which client will trigger the RDMA. It also need to other + parameters like which varies for linear and RECT modes. + In rect reads software has to setup the stride/width/number of lines. + This information is needed to describe a buffer. In case of non-rect + read a buffer header is expected, which describes the buffer. In both + cases one need to specify the number of buffers. + + - Client module also need to be setup, as it notifies the RDMA hw block when + the data is ready. This step is not needed for CPU triggered case, as the + data is already available in the memory. + + Sample program sequence: + + Setup RDMA + Setup Client side register (example - vi, SD etc...). Not needed when + setup for CLID CPU. + + wait till the data is available () + { + Read the data(..) + } + + Amount of data to read is either known a-priori (RECT mode) or read from + the header (linear mode). + + + As described ealier RDMA supports 2 modes + + Linear RDMA - RDMA expects a header in the memory right before the data, when + it is triggered. That header describes the length and the attributes of the + buffer. + + Depending on how the RDMA is setup, buffer header will be/will not be + (i.e RDMA_BUFFER_HEADER struct) readout. see #GF_RDMA_FLAGS_STR_HEADER + + When the header is returned the usage looks like + + RDMA_BUFFER_HEADER header; + GFRmRDMAReadHeader(...,&header); + While (header->bufferSize) + { + ... + GFRmReadRDMA(...) + } + + In this mode, it is important is to note that RDMA expect the buffer header + in the memory. So, this is not good for CPU triggerd case, as in that case + CPU should somehow write the buffer header to read the data already present + in the embedded memory. + + Rect RDMA - In this mode, there is no concept of buffer header. Exact size + should be programmed in the RDMA registers when the Setup is done. So, sw + should know how much data to pull out. Requests for data more than available + will result in timeout errors. + + A guideline: if an engine already generated the buffer for you, then use + non-rectangular read. Otherwise, use rect read. + +*/ + +#endif /* __GFRMRDMA_H__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmScr.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmScr.h new file mode 100755 index 00000000..1678ba09 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFRmScr.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#if !defined (__GFRMSCR_INC__) +#define __GFRMSCR_INC__ + +/* Surface ColorFormat - Follow GFBITMAP type (GF_BITMAP_xxx) */ + +#define GF_SURFACE_YUV420 1 +#define GF_SURFACE_YUV422 2 +#define GF_SURFACE_YUV444 4 +#define GF_SURFACE_ROTATED_YUV422 8 + +#define GF_SURFACE_YUYV (GF_SURFACE_YUV422|0x00000004) +#define GF_SURFACE_YVYU (GF_SURFACE_YUV422|0x00000008) +#define GF_SURFACE_UYVY (GF_SURFACE_YUV422|0x00000010) +#define GF_SURFACE_VYUY (GF_SURFACE_YUV422|0x00000020) +#define GF_SURFACE_MPEGDEC (GF_SURFACE_YUV420|0x00000040) + + +/** Image is for encoding purpose. Must combine with particular YUV format. */ +#define GF_SURFACE_MPEGENC 0x00000080 +#define GF_SURFACE_JPEGDEC (GF_SURFACE_YUV420|0x00000100) + +/** Image is for encoding purpose. Must combine with particular YUV format. */ +#define GF_SURFACE_JPEGENC 0x00000200 +#define GF_SURFACE_PLANAR_YUV422 0x400 +#define GF_SURFACE_RGB565 0x00010000 + +/** Used for 18 bpp (MSB bits) (18bpp MSB bits) case. */ +#define GF_SURFACE_RGB888 0x00020000 +#define GF_SURFACE_ARGB8888 0x00030000 +#define GF_SURFACE_ARGB1555 0x00040000 +#define GF_SURFACE_ARGB4444 0x00050000 + +/** Used for 18 bpp (LSB bits). */ +#define GF_SURFACE_RGB666 0x00060000 + +/** 8bpp surface. */ +#define GF_SURFACE_RGB8 0x00070000 +#define GF_SURFACE_RGB_MASK 0x000F0000 + +/** Bayer 8bit ColorFormat. */ +#define GF_SURFACE_BAYER8 0x00100000 + +/** Bayer 16bit ColorFormat. */ +#define GF_SURFACE_BAYER16 0x00200000 +#define GF_SURFACE_ABGR8888 0x00400000 + +/** YUV422 rotated averaging. */ +#define GF_SURFACE_PLANAR_YUV422RA 0x00800000 + +#endif diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFTrace.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFTrace.h new file mode 100755 index 00000000..4d50b3bd --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFTrace.h @@ -0,0 +1,304 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* GFTrace.h: Tracing utility for GFSDK libraries. + * + * Features a suite of conditionally compilied tracing macros: + * + * GF_TRACE( a ): for "don't care" tracing - will be mapped + * to the DEBUG priority. + * + * And several others, each with a different priority. + * + * GF_TRACE_CRITICAL( a ) + * GF_TRACE_WARNING( a ) + * GF_TRACE_NORMAL( a ) + * GF_TRACE_VERBOSE( a ) + * GF_TRACE_DEBUG( a ) + * + * The trace macro parameter is treated as a printf style argument + * list, so it should be wrapped in double-parenthesis, such as: + * + * GF_TRACE(("Register value is: %x", reg)); + * + * Tracing is either handled via priorities (normal tracing). + * Tracing supports logging to a file (defaulting to "gfsdk.log") + */ + +#ifndef GF_RMTRACE_H +#define GF_RMTRACE_H + +/* Required for compilation: + * + * GF_TRACE_COMPONENTID [id] + * 'id' is a number 0 to GF_TRACE_COMPONENT_MAX. Tracing priorities + * and thresholds are set via the component id. + * + * Example usage of this header file: + * + * #define GF_TRACE_COMPONENTID GF_GXAPI + * #define GF_TRACE_ENABLE 1 + * #include "GFTrace.h" + * + * void + * foo( NvU32 x ) + * { + * GF_TRACE_DEBUG(("foo called with: %x", x )); + * } + * + */ + +#ifndef GF_TRACE_COMPONENTID +#error "GF_TRACE_COMPONENTID must be defined." +#endif + +#include +#include "GFRm.h" + +/* see GFRm.h for available component ids */ + +/* Compiliation options: + * + * GF_TRACE_ENABLE [0|1] + * If zero, will remove tracing for that file. + * + * GF_TRACE_GLOBAL_DISABLE + * If this is defined and set to 1 - tracing is force globally disabled. + * If not defined will be controlled by the GF_TRACE_ENABLE macro. + * + * GF_TRACE_GLOBAL_ENABLE + * If this is defined and set to 1 - tracing is force globally enabled. + * If not defined will be controlled by the GF_TRACE_ENABLE macro and + * GF_TRACE_GLOBAL_DISABLE macros. + * + * So, the precedence is GF_TRACE_GLOBAL_ENABLE > GF_TRACE_GLOBAL_DISABLE > + * GF_TRACE_ENABLE + * + * GF_TRACE_COMPONENTID_MAX [max] + * The maximum number of component ids that may exist for tracing. + * + * GF_TRACE_MESSAGESIZE_MAX [max] + * The maximum length of a tracing message, in bytes. + * + * GF_TRACE_DECORATE [0|1] + * Automatically add a newline, componentname and process ID to + * the output. + */ + +/* default for component id max */ +#ifndef GF_TRACE_COMPONENTID_MAX +#define GF_TRACE_COMPONENTID_MAX 32 +#endif + +/* default for message size max */ +#ifndef GF_TRACE_MESSAGESIZE_MAX +#define GF_TRACE_MESSAGESIZE_MAX 256 +#endif + +/* default for decoration is 1 */ +#ifndef GF_TRACE_DECORATE +#define GF_TRACE_DECORATE 1 +#endif + +#if defined(NV_MODS) + +/* By default enable everything for MODS */ +#undef GF_TRACE_ENABLE +#define GF_TRACE_ENABLE 1 + +#ifndef INCLUDED_GFMODS_H +#include "GFMods.h" +#endif + +#endif /* NV_MODS */ + +#if defined(GF_TRACE_GLOBAL_ENABLE) && defined(GF_TRACE_GLOBAL_DISABLE) +#error "Both GF_TRACE_GLOBAL_DISABLE and GF_TRACE_GLOBAL_ENABLE cannot be defined" +#endif + +/* global overrides */ +#ifdef GF_TRACE_GLOBAL_ENABLE + #undef GF_TRACE_ENABLE + #define GF_TRACE_ENABLE 1 +#endif + +#ifdef GF_TRACE_GLOBAL_DISABLE + #undef GF_TRACE_ENABLE + #define GF_TRACE_ENABLE 0 +#endif + +/* Several priorities from which to choose. Use the + * GFRmTrace*Threshold functions to limit tracing output. + * By deafult, all messages will be traced in a Debug build, + * only Warning, and Critical in a Release build. + * + * The priority numbers should exactly match the printing + * priorities in MODS. + */ +#define GF_TRACE_PRI_CRITICAL 5 +#define GF_TRACE_PRI_WARNING 4 +#define GF_TRACE_PRI_NORMAL 3 +#define GF_TRACE_PRI_VERBOSE 2 +#define GF_TRACE_PRI_DEBUG 1 + +/* Returns the current tracing threshold. + */ +NvU32 +GFRmTraceGetThreshold( NvU32 componentId ); + +/* Sets the current tracing threshold. All messages with an equal-to or + * greater-than priority will be traced. + */ +void +GFRmTraceSetThreshold( NvU32 componentId, NvU32 thresh ); + +/* Gets the current tracing priority. + */ +NvU32 +GFRmTraceGetPriority( NvU32 componentId ); + +/* Sets the current tracing priority for the given component. + */ +void +GFRmTraceSetPriority( NvU32 componentId, NvU32 pri ); + +/* Trace a message. Takes variable arguments that exactly match those + * of the libc printf family. Messages may or may not be controlled + * via a priority mechanism. + */ +void +GFRmTrace( NvU32 componentId, NvU32 priority, const char *msg, va_list args ); + +/* Tracing may be controlled via run-time as well as compile-time. + * The run-time options that are available (to be passed into + * GFRmTraceConfigure as the option flag) are: + * + * GF_TRACE_OPT_OUTPUT [ioname] + * The output device of normal tracing. Defaults to stdout. + * 'value' is a char *, max len is 256. Should be null-terminated. + * May be "default" or a filename. + * + * GF_TRACE_OPT_COMPONENT_ENABLE [id] [0|1] + * Component that have compiled in tracing can be turned off or + * back on. The configure value is a pointer to an array of two + * integers, the first is id, the second is the enable/disable. + * + * GF_TRACE_OPT_DECORATE [id] [0|1] + * Automatically add a newline and component id to the output. + * 1 for on, 0 for off. 'id' is the component id. + */ +#define GF_TRACE_OPT_OUTPUT 0 +#define GF_TRACE_OPT_COMPONENT_ENABLE 1 +#define GF_TRACE_OPT_DECORATE 2 + +/* Open the trace file. Called by GFRmOpen */ +GF_RETTYPE GFRmTraceOpen(void); + +/* Closes the trace file. Called by GFRmClose */ +void GFRmTraceClose(void); + +/* Run-time configuration for tracing. See the GF_TRACE_OPT + * flags for 'value' documentation. All configuration settings + * assigned via GFRmTraceConfigure() are global across all component + * ids, and should be synchronized if accessed by multiple threads. + * + * Returns 0 on failure, 1 otherwise. + */ +NvU32 +GFRmTraceConfigure( int option, void *value ); + +/* Returns a nice name for the component id. + * Note that this will always be defined (never compiled out). + */ +const char * +GFRmTraceGetComponentName( NvU32 componentId ); + +#if !GF_TRACE_ENABLE || NVCPU_IS_XTENSA + +#define GF_TRACE( a ) +#define GF_TRACE_CRITICAL( a ) +#define GF_TRACE_WARNING( a ) +#define GF_TRACE_NORMAL( a ) +#define GF_TRACE_VERBOSE( a ) +#define GF_TRACE_DEBUG( a ) + +#else /* tracing is enabled */ + +static NV_INLINE void GFRmTraceWithPriority(const char *msg, ...) +{ + va_list list; + NvU32 priority = 0; + + va_start( list, msg ); + + priority = GFRmTraceGetPriority( GF_TRACE_COMPONENTID ); + +#if !defined(NV_MODS) + GFRmTrace( GF_TRACE_COMPONENTID, priority, msg, list ); +#else + GFModsTrace( GF_TRACE_COMPONENTID, priority, msg, list ); +#endif + va_end( list ); +} + +/* component id will be defined to be -1 for the trace implementation. + * Each client must define component id before including this file. + * + * For a MODS build, GFRmTraceWithPriority() must call ModsDrvVPrintf(). + * See main/diag/mods/include/modsdrv.h for details. ModsDrvVPrintf() + * is called via GFModsTrace(). + */ +#if GF_TRACE_COMPONENTID >= 0 + +#define GF_TRACE( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_DEBUG ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_CRITICAL( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_CRITICAL ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_WARNING( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_WARNING ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_NORMAL( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_NORMAL ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_VERBOSE( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_VERBOSE ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) + +#define GF_TRACE_DEBUG( a ) \ + do \ + { \ + GFRmTraceSetPriority( GF_TRACE_COMPONENTID, GF_TRACE_PRI_DEBUG ); \ + GFRmTraceWithPriority a; \ + } while( 0 ) +#endif /* componentid check */ + +#endif /* enable trace */ + +#endif /* GFRMTRACE_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFTypes.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFTypes.h new file mode 100755 index 00000000..49145b10 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFTypes.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFTypes.h + * GFSDK standard data types. + */ + +#ifndef __GFTYPES_H__ +#define __GFTYPES_H__ + +#include "nvtypes.h" + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +/* Misc Helper macros on data types (deal with byte-endianness later ) */ +#ifndef MAKENvU32 +#define MAKENvU32(dataLo16, dataHi16) \ + (NvU32)(((NvU32)(dataHi16) << 16) | (NvU32)(dataLo16)) +#endif /* MAKENvU32 */ + +#ifndef MAKENvU16 +#define MAKENvU16(dataLo8, dataHi8) \ + (NvU16)(((NvU16)(dataHi8) << 8) | (NvU16)(dataLo8)) +#endif /* MAKENvU16 */ + +#if defined(__arm) +# define GFALIGN8 __align(1) +# define GFALIGN16 __align(2) +# define GFALIGN32 __align(4) +#elif defined(__IAR_SYSTEMS_ICC__) +# define GFALIGN8 +# define GFALIGN16 +# define GFALIGN32 +#elif defined(NV_LINUX) +# define GFALIGN8 +# define GFALIGN16 __attribute__ ((aligned (2))) +# define GFALIGN32 __attribute__ ((aligned (4))) +#elif defined(NVCPU_XTENSA) +# define GFALIGN8 +# define GFALIGN16 __attribute__ ((aligned (2))) +# define GFALIGN32 __attribute__ ((aligned (4))) +#elif defined(NV_WINDOWS) +# define GFALIGN8 +# define GFALIGN16 +# define GFALIGN32 +#else +# define GFALIGN8 +# define GFALIGN16 +# define GFALIGN32 +#endif + +#endif /* __GFTYPES_H__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVersion.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVersion.h new file mode 100755 index 00000000..399900be --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVersion.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * File: GFVersion.h + * GFSDK build version header file. + */ + +#ifndef __GFVERSION_H__ +#define __GFVERSION_H__ + +#define GF_MAJOR_VERSION 0x0017 +#define GF_MINOR_VERSION 0x0100 +#define GF_BUILD_NUMBER 1039 + + +#endif /* __GFVERSION_H__ */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVx.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVx.h new file mode 100755 index 00000000..5af9e634 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVx.h @@ -0,0 +1,3028 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFVx.h + GFSDK Video API header file. +*/ + +#ifndef __GFVX_H__ +#define __GFVX_H__ + +#include "GFRm.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#include "GFVxScr.h" + +/** @addtogroup groupVx VxAPI Video API +
        +
      • @ref pageVxOverview +
          +
        • @ref pageVxOverview1 +
        • @ref pageVxOverview2 +
        • @ref pageVxOverview3 +
        +
      • @ref pageVxAppNotes +
          +
        • @ref pageVxAppNotes1 +
        +
      +*/ +/*@{*/ + +/* GFVX Property Capability */ + +/** VxAPI property flag: Color space conversion supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_CSC 0x00000001 + +/** VxAPI property flag: VIP functions available. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_VIP 0x00000002 + +/** VxAPI property flag: Enlarge source image via VIP supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_ENLARGE 0x00000004 + +/** VxAPI property flag: Shrink source image via VIP supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_SHRINK 0x00000008 + +/** VxAPI property flag: Overlay supported. + The GoForce processor version supports overlay display. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_OVERLAY 0x00000020 + +/** VxAPI property flag: MPEG4 decoder supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_MPEGDEC 0x00000040 + +/** VxAPI property flag: MPEG4 encoder supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_MPEGENC 0x00000080 + +/** VxAPI property flag: JPEG decoder supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_JPEGDEC 0x00000100 + +/** VxAPI property flag: JPEG encoder supported. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_JPEGENC 0x00000200 + +/** VxAPI property flag: Alpha blending supported. + @version SC12 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_ALPHA_BLEND 0x00000400 + +/** VxAPI property flag: Extended RGB format 32 bpp supported. + @version SC12 above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_EXTEND_RGB 0x00000800 + +/** VxAPI property flag: Variable sized data camera interface (Type A/B/C) + supported. See section @ref pageVxOverview2 for information on Type A/B/C + camera interfaces. + @version SC12 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability, +*/ +#define GFVX_CAP_ENCODE_TYPE 0x00001000 + +/** VxAPI property flag: Bayer type camera interface supported. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability, +*/ +#define GFVX_CAP_BAYER_TYPE 0x00002000 // support bayer type input + +/** VxAPI property flag: YUV Overlay supported. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_OVERLAY_YUV 0x00004000 + +/** VxAPI property flag: Overlay with scaling supported. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_OVERLAY_SCALE 0x00008000 + +/** VxAPI property flag: Multiple Overlay supported. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_OVERLAY_MULTIPLE 0x00010000 + +/** VxAPI property flag: Per pixel alpha supported. + Used when application wants to use weight (overlay and blend) + defined in pixels alpha bits. + @version SC15 and above only. + @see GFVxGetProperty(), GFPROPERTY::Capability +*/ +#define GFVX_CAP_PER_PIXEL_ALPHA 0x00020000 + +/** VxAPI GFVXBLT::BltOption flagbit: Disable VSync wait. + Disable GFVxBlt() synchronization with VSync. The default behaviour of + GFVxBlt() is to wait for VSync to prevent display flicker. Note that + if the display is disabled there is no VSync signal and GFVxBlt() + would block. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_DISABLE_WAIT_VSYNC 0x00000080 + +/** VxAPI GFVXBLT::BltOption flagbit: Source color key. + GFVxBlt() compares each pixel of the source surface with the color key. + If the colors match, the pixel is not copied to the destination surface. + + The source color key option is not very useful when scaling is used. + + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_SRC_KEY 0x00000100 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-blit at end of VIP frame. + If this flag is set, GFVxBlt() configures blit parameters for + VIP auto-blit. VIP auto-blit can be used to fire stretch blit automatically + at the end of the video input frame from the video input port (VIP). This + requires double buffering of the input and output of stretch blit. The use + of this flag is to be combined with GFVxVIPUpdate() flag + #GFVX_VIP_AUTO_TRIGER_BLT. + @see GFVXBLT, GFVxBlt(), #GFVX_VIP_AUTO_TRIGER_BLT +*/ +#define GFVX_AUTO_BLT 0x00000400 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-blit at end of VIP frame. + This flag is the same as #GFVX_AUTO_BLT + @version SC15 and above only + @see GFVXBLT, GFVxBlt(), #GFVX_VIP_AUTO_TRIGER_BLT, #GFVX_AUTO_BLT +*/ +#define GFVX_BLT_AUTO_VI 0x00000400 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-display destination surface. + The application does not need call GFVxFlip() to show the surface. + With the auto-display option, the VI module triggers stretch blit which + in turn sends the destination surface's buffer address to the display + controller (GC). VI input data goes into double buffers which become the + stretch blit source, the output of stretch blit is also double buffered. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_AUTO_DISPLAY 0x00000800 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-display destination surface. + This flag is the same as #GFVX_AUTO_DISPLAY + @version SC15 and above only + @see GFVXBLT, GFVxBlt(), #GFVX_AUTO_DISPLAY +*/ +#define GFVX_BLT_AUTO_DISPLAY 0x00000800 + +/** VxAPI GFVXBLT::BltOption flagbit: Set up parameters for partial blit + If this flag is set, GFVxBlt() configures blit parameters for + partial blit. The partial blit works only with circular buffers and + source and destination format are not YUV planar format. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_PARTIAL 0x00001000 + +/** VxAPI GFVXBLT::BltOption flagbit: Trigger partial blit + If this flag is set, GFVxBlt() will blit buffer specified + in buffer index option of circular buffers to destination surface. + The use of this flag is to be combined with GFVxBlt() flag + #GFVX_BLT_PARTIAL. + @see GFVXBLT, GFVxBlt(), #GFVX_BLT_PARTIAL +*/ +#define GFVX_BLT_PARTIAL_TRIGGER 0x00002000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit without rotation + If this flag is set, GFVxBlt() blits without rotation + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ROTATE_0 0x00004000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with 90 degree rotation + If this flag is set, GFVxBlt() blits with 90 degree rotation + Currently, SC15 doesn't support this feature. However, this flag + can be combined with flag GFVX_BLT_H_FLIP to blit with XY swap + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ROTATE_90 0x00008000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with 180 degree rotation + If this flag is set, GFVxBlt() blits with 180 degree rotation + Currently, SC15 doesn't support this feature. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ROTATE_180 0x00010000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with 270 degree rotation + If this flag is set, GFVxBlt() blits with 270 degree rotation + Currently, SC15 doesn't support this feature. However, this flag + can be combined with flag GFVX_BLT_V_FLIP to blit with XY swap + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ROTATE_270 0x00020000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with horizontal flip + If this flag is set, GFVxBlt() blits with horizontal flip + Currently, SC15 doesn't support this feature. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_H_FLIP 0x00040000 + +/** VxAPI GFVXBLT::BltOption flagbit: Blit with vertical flip + If this flag is set, GFVxBlt() blits with vertical flip + Currently, SC15 doesn't support this feature + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_V_FLIP 0x00080000 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-display destination surface + using overlay window 2. This is exactly identical to #GFVX_AUTO_DISPLAY + except that it uses overlay window 2 instead of overlay window 1 (default). + + @version SC15 and above only + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_AUTO_DISPLAY_OVERLAY2 0x00100000 + +/** VxAPI GFVXBLT::BltOption flagbit: Auto-display destination surface + using overlay window 2. This flag is the same as #GFVX_AUTO_DISPLAY_OVERLAY2 + @version SC15 and above only + @see GFVXBLT, GFVxBlt(), #GFVX_AUTO_DISPLAY_OVERLAY2 +*/ +#define GFVX_BLT_AUTO_DISPLAY_OVERLAY2 0x00100000 + +/** VxAPI GFVXBLT::BltOption flagbit: Enables full range in color spce conversion + 0<= Y <=255, -128<= U <=127, -128<= V <=127 + YUV-->RGB conversion formula: + R = 1.000Y + 1.402V + G = 1.000Y - 0.344U - 0.714V + B = 1.000Y + 1.772U + This option is useful for decoded video from movies. + When this flag is not set, uses CCIR601 range (16-235) as follows: + 16<= Y <=235, 16<= U <=240, 16<= V <=240 + YUV-->RGB conversion formula: + R = 1.164(Y-16) + 1.596(Cr-128) + G = 1.164(Y-16) - 0.391(Cb-128) - 0.813(Cr-128) + B= 1.164(Y-16) + 2.018(Cb-128) + This option is useful for video from camera. + @version SC15 and above only + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_CSC_FULL_RANGE 0x00200000 + +/** VxAPI GFVXBLT::BltOption flagbit: Enable camera VSync wait. + Enable GFVxBlt() synchronization with camera VSync. Note that + if the camera is disabled there is no VSync signal and GFVxBlt() + would block. + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_ENABLE_WAIT_CAMERA_VSYNC 0x00400000 + +/** VxAPI GFVXBLT::BltOption flagbit: Disable vertical and horizontal filters + By default, the vertical and horizontal filters are enabled. If this flag + is set, GFVxBlt() blits with filters disabled + @see GFVXBLT, GFVxBlt() +*/ +#define GFVX_BLT_DISABLE_FILTERS 0x00800000 + +/** VxAPI option parameter of routines GFVxBltSetCSCCoefff() + and GFVxVIPSetCSCCoeff() to use CCIR601 range + + CSC_USE_CCIR601_RANGE (16-235) as follows: + 16<= Y <=235, 16<= U <=240, 16<= V <=240 + YUV-->RGB conversion formula: + + R = sat(KYRGB*(Y + YOF) + KUR*U + KVR*V) + G = sat(KYRGB*(Y + YOF) + KUG*U + KVG*V) + B = sat(KYRGB*(Y + YOF) + KUB*U + KVB*V) + + The CSC coefficients are: + + KYRGB, KUR, KVR 1.1644 0.0000 1.5960 + KYRGB, KUG, KVG = 1.1644 -0.3918 -0.8130 + KYRGB, KUB, KVB 1.1644 2.0172 0.0000 + + and YOF = -16.0000 + This option is useful for video from camera. + + @see GFVxBltSetCSCCoeff(), GFVxVIPSetCSCCoeff() +*/ +#define GFVX_SET_CSC_USE_CCIR601_RANGE 0x00800000 + +/** VxAPI option parameter of routines GFVxBltSetCSCCoefff() + and GFVxVIPSetCSCCoeff() to use full range in color space conversion + + CSC_USE_FULL_RANGE + 0<= Y <=255, -128<= U <=127, -128<= V <=127 + YUV-->RGB conversion formula: + + R = sat(KYRGB*(Y + YOF) + KUR*U + KVR*V) + G = sat(KYRGB*(Y + YOF) + KUG*U + KVG*V) + B = sat(KYRGB*(Y + YOF) + KUB*U + KVB*V) + + The CSC coefficients are: + + KYRGB, KUR, KVR 1.0000 0.0000 1.4020 + KYRGB, KUG, KVG = 1.0000 -0.3440 -0.7140 + KYRGB, KUB, KVB 1.0000 1.7720 0.0000 + + and YOF = 0.0000 + This option is useful for decoded video from movies. + @see GFVxBltSetCSCCoeff(), GFVxVIPSetCSCCoeff() +*/ +#define GFVX_SET_CSC_USE_FULL_RANGE 0x01000000 + +/** VxAPI option parameter of routines GFVxBltSetCSCCoefff() + and GFVxVIPSetCSCCoeff() to use user defined range + provided in option parameter pCoeff pointer to GFVXCSCCOEF struct + + @see GFVxBltSetCSCCoeff(), GFVxVIPSetCSCCoeff() +*/ +#define GFVX_SET_CSC_USE_USER_DEFINED_RANGE 0x02000000 +/** Structure to control GFVxBlt() behaviour. + @see GFVxBlt() +*/ + +typedef struct _GFVXBLT +{ + PGFRMSURFACE *ppDestSurf; /**< Pointer to an array of destination + surfaces of identical dimensions. + + For passing scaled YUV output data to + the planar block as input to the + JPEG/MPEG encoder, pass an array containing + one NULL pointer. + + Destination surface dimensions limitations: + + + + + + + +
      Minimum stride0 bytes
      Minimum width 1
      Minimum height1
      Maximum stride4095 bytes
      Maximum width 4064 (YUV) + (YUV data restricted by JPEG encoder),
      + 32767 (RGB) + (RGB data restricted by stride) +
      Maximum height32766, or unlimited + if \a pDestRect is specified
      + + If the destination color format is YUV (pass to + JPEG/MPEG EPP, and \a pDestRect is not specified, + the surface width must be a multiple of 2. + */ + PGFRMSURFACE *ppSrcSurf; /**< Pointer to an array of source surfaces + of identical dimensions. + Source surface dimensions limitations: + + + + + + + +
      Minimum stride0 bytes
      Minimum width 1
      Minimum height1
      Maximum stride4095 bytes
      Maximum width + 16383 (SC15), + 2032 (SC12), + 496 (SC5, RGB or YUV422), 512 (SC5), + 496 (SC10, SC4), + 312 (SC3 and below), + or unlimited if \a pSrcRect is specified +
      Maximum height32766, or unlimited + if \a pDestRect is specified
      + */ + PGFRECT pDestRect; /**< Destination rectangle, or NULL to blit + scaled to the size of the entire target + surface (size of first surface in + \a ppDestSurf is used). + Destination cropping rectangle limitations: + + + + + +
      Minimum width 1
      Minimum height1
      Maximum width 4064 (YUV), + 32767 (RGB) +
      Maximum height32766
      + + If the destination color format is YUV (pass to + JPEG/MPEG EPP), the destination cropping rectangle's + width must be a multiple of 2. + */ + PGFRECT pSrcRect; /**< Source cropping rectangle, or NULL for + no cropping and blit the entire source + surface (size of first surface in + \a ppSrcSurf is used). + Source cropping rectangle limitations: + + + + + +
      Minimum width 1
      Minimum height1
      Maximum width + 16383 (SC15), + 2032 (SC12), + 496 (SC5, RGB or YUV422), 512 (SC5), + 496 (SC10, SC4), + 312 (SC3 and below) +
      Maximum height32766
      + */ + NvU32 numofDestSurf;/**< Number of destination surfaces in array + \a ppDestSurf, used only if + #GFVX_AUTO_BLT flag set + */ + NvU32 numofSrcSurf; /**< Number of source surfaces in array + \a ppSrcSurf, used only if + #GFVX_AUTO_BLT flag or #GFVX_BLT_PARTIAL flag set + */ + NvU32 colorKey; /**< Color key value in RGB888 format */ + NvU32 BltOption; /**< Flag bitmask: + + + + + + + + + + + + + + + + +
      #GFVX_BLT_DISABLE_WAIT_VSYNCDisable VSync +
      #GFVX_BLT_SRC_KEYSource color key +
      #GFVX_AUTO_BLTAuto-blit at end of VIP frame +
      #GFVX_AUTO_DISPLAYAuto-show destination surface +
      #GFVX_AUTO_DISPLAY_OVERLAY2Auto-show destination surface from overlay window 2 +
      #GFVX_BLT_PARTIALConfigure partial blit parameters +
      #GFVX_BLT_PARTIAL_TRIGGERTrigger partial blit at end of circular buffer +
      #GFVX_BLT_ENABLE_WAIT_CAMERA_VSYNCEnable wait for camera VSYNC +
      + */ + // Fill The following fields if GFVX_BLT_PARTIAL_TRIGGER is set in BltOption + NvU32 FrameStart; /* @Notify start of frame. + Used only if #GFVX_BLT_PARTIAL_TRIGGER is set + in \a BltOption. + */ + NvU32 FrameEnd; /* @Notify end of frame. + Used only if #GFVX_BLT_PARTIAL_TRIGGER is set + in \a BltOption. + */ + NvU32 BufferIndex; /* @Specify which buffer of circular buffers is blitted. + Used only if #GFVX_BLT_PARTIAL_TRIGGER is set + in \a BltOption. + */ +} GFVXBLT, *PGFVXBLT; + +/** VxAPI GFVXFLIP::FlipOption flagbit: Flip uses second overlay window. + + By default, VxFlip associates foreground and background surfaces + to first overlay window and flips them. However, the application can override + the default behavior and use second overlay window by using this flag in FlipOption. + + This option should be used only if second overlay surface has been + previously set using UpdateOverlay(). . + + @version SC15 and above only + @see GFVXFLIP, GFVxFlip() +*/ +#define GFVX_FLIP_OVERLAY2 0x00000001 + +/** Structure to control GFVxFlip() behaviour. + @see GFVxFlip() +*/ +typedef struct _GFVXFLIP +{ + PGFRMSURFACE pBackGroundSurf; /**< Pointer to the surface to be flipped + to the background. This surface will + not be seen anymore after the + GFVxFlip() call. + */ + PGFRMSURFACE pForeGroundSurf; /**< Pointer to the surface to be flipped + to the foreground. This surface will + be seen after the GFVxFlip() call. + */ + NvU32 FlipOption; + /**< Flagbit mask controlling flip: + + + + + +
      0 Default. Flip uses first overlay window
      GFVX_FLIP_SECOND_OVERLAY Flip uses second overlay window
      + */ +} GFVXFLIP, *PGFVXFLIP; + + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay without rotation. + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_ROTATE_0 GF_SURFACE_ROTATE_0 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay with 180 degree rotation. + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_ROTATE_180 GF_SURFACE_ROTATE_180 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay with horizontal + flip. + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_H_FLIP 0x00000010 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay with vertical + flip. + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_V_FLIP 0x00000020 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Source color keying. + + A pixel from the source (overlay) surface is displayed only if pixel + color from the source surface matches the color key in + GFVXUPDATEOVERLAY::ColorKey. + + Source color keying is not useful for video overlay, because changing + video is the source. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay(), GFVX_UO_DEST_COLOR_KEY +*/ +#define GFVX_UO_SRC_COLOR_KEY 0x00010000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Destination color keying. + + A pixel from the source (overlay) surface is displayed only if pixel + color from the destination surface matches the color key in + GFVXUPDATEOVERLAY::ColorKey. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay(), GFVX_UO_SRC_COLOR_KEY +*/ +#define GFVX_UO_DEST_COLOR_KEY 0x00020000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Alpha blending. + Enable alpha blending. Alpha value is used from + GFVXUPDATEOVERLAY::AlphaValue. + + As AlphaVal increases, the weight of source (overlay) window increases + until the window reaches its maximum weight of 0xFF. + + Even though AlphaVal is a 32 bit number, alpha value can only be a 8 bit value. + Application should specify the same value in byte 1 (LSB), 2 and 3 else the API + will fail. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_ALPHA_BLENDING 0x00040000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay based on + destination alpha only. + + If destination is in 1-bit alpha format (eg ARGB1555), GFVXUPDATEOVERLAY::ColorKey bit[24] + contains the alpha value. GFVxUpdateOverlay() compares this value with + the target surface's alpha and ignores the RGB value. Overlay (source) surface + shows up in portions of the screen where the two match. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_COLOR_KEY_ALPHA_ONLY 0x00080000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay based on + destination alpha and color + + If destination is in 1-bit alpha format (eg ARGB1555), + GFVXUPDATEOVERLAY::ColorKey bit [24] contains alpha and + GFVXUPDATEOVERLAY::ColorKey bit [23:0] contains RGB color values. + GFVxUpdateOverlay() compares the key's alpha value and + color values with destination surface pixels. + + Overlay (source) surface shows up in portions of the screen where both + alpha and color values match. + + If neither #GFVX_UO_COLOR_KEY_ALPHA_ONLY nor #GFVX_UO_COLOR_KEY_ALPHA_COLOR are + set, GFVxUpdateOverlay() assumes the RGB values in + GFVXUPDATEOVERLAY::ColorKey to be valid and compares the RGB value with + surface's RGB value. Depending upon whether #GFVX_UO_SRC_COLOR_KEY or + #GFVX_UO_DEST_COLOR_KEY is defined, RGB value is compared with source or + destination pixels. If neither #GFVX_UO_SRC_COLOR_KEY nor #GFVX_UO_DEST_COLOR_KEY + is defined, overlay(source) surface is overlayed on top of destination surface + without any match. #GFVX_UO_COLOR_KEY_ALPHA_ONLY nor #GFVX_UO_COLOR_KEY_ALPHA_COLOR + if defined, are ignored. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_COLOR_KEY_ALPHA_COLOR 0x00100000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Alpha blending based on + destination alpha. + + If destination is in 1-bit alpha format (eg ARGB1555), + GFVXUPDATEOVERLAY::BlendingColorKey bit [24] contains an alpha value. + GFVxUpdateOverlay() compares this value with the destination surface's + alpha only and ignores the RGB value. + + If the two match, GFVXUPDATEOVERLAY::AlphaValue determines the weight + of source surface. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY 0x00200000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Alpha blending based on + destination alpha and color + + If destination is in 1-bit alpha format (eg ARGB1555), + GFVXUPDATEOVERLAY::BlendingColorKey bit [24] contains an alpha value and + GFVXUPDATEOVERLAY::BlendingColorKey bit [23:0] contains RGB values. + GFVxUpdateOverlay() compares alpha value and color value with the + destination surface's alpha and color value. + + Source and destination pixels appear blended in portions of the screen where both + alpha and color values match. GFVXUPDATEOVERLAY::AlphaValue determines the weight + of source surface. + + If neither #GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY nor #GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR + are set, GFVxUpdateOverlay() assumes the RGB portion in the key to be + valid and compares the RGB value with the surface's RGB value. + + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR 0x00400000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Enable Second overlay window + + SC15 supports two overlay windows. This flag is used to enable + the second overlay window. + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_OVERLAY2 0x00800000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Show this overlay window on top + + When more than one overlay windows are enabled and their destination rectangles + overlap, this flag can be defined to indicate which overlay window should appear + on top. + + By default, first overlay window will appear on top if destination + rectangles for the two windows overlap. However, application can override the + default behavior by specifying #GFVX_UO_ACTIVETOP flag in relevant windows's + UpdateOption. + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_ACTIVETOP 0x01000000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Overlay and Blend weight + comes from per-pixel alpha channel. + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_COLOR_KEY_PER_PIXEL_ALPHA 0x02000000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption flagbit: Enable digital vibrance for + overlay. + + If this bit is set in UpdateOption, then dvRed, dvGreen and dvBlue must be + set in UpdateOverlay structure for overlay window. + + If this bit is set in UpdateOption2, then dvRed2, dvGreen2 and dvBlue2 must be + set in UpdateOverlay structure for overlay2 window. + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_DIGITAL_VIBRANCE 0x04000000 + +/** VxAPI GFVXUPDATEOVERLAY::UpdateOption2 flagbit: Enable AlphaValue2 + + If this bit is set in UpdateOption2, then the alpha value is used + from GFVXUPDATEOVERLAY::AlphaValue2 + + @version SC15 and above only + @see GFVXUPDATEOVERLAY, GFVxUpdateOverlay() +*/ +#define GFVX_UO_USE_ALPHAVALUE2 0x08000000 + +/** Structure for controlling GFVxUpdateOverlay() behaviour. + @see GFVxUpdateOverlay() +*/ +typedef struct _GFVXUPDATEOVERLAY +{ + PGFRMSURFACE pDestSurf; /**< Destination surface pointer */ + PGFRMSURFACE pSrcSurf; /**< Source surface pointer, if this pointer + is NULL, disable overlay. + */ + PGFRECT pDestRect; /**< Destination rectangle */ + PGFRECT pSrcRect; /**< Source rectangle */ + NvU32 ColorKey; /**< Color key value in ARGB32 format. + Color keying takes effect only when + #GFVX_UO_SRC_COLOR_KEY or + #GFVX_UO_DEST_COLOR_KEY is set. + */ + NvU32 UpdateOption; + /**< Flagbit mask controlling rotation, color keying: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_UO_ROTATE_0 Overlay without rotation
      #GFVX_UO_ROTATE_180 Overlay with 180 degree rotation
      #GFVX_UO_H_FLIP Overlay with horizontal flip
      #GFVX_UO_V_FLIP Overlay with vertical flip
      #GFVX_UO_SRC_COLOR_KEY Source color keying
      #GFVX_UO_DEST_COLOR_KEY Destination color keying
      #GFVX_UO_ALPHA_BLENDING Alpha blending
      #GFVX_UO_COLOR_KEY_ALPHA_ONLY Overlay based on destination alpha
      #GFVX_UO_COLOR_KEY_ALPHA_COLOR Overlay based on destination alpha and color
      #GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY Alpha Blending based on destination alpha
      #GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR Alpha Blending based on destination alpha and color
      #GFVX_UO_OVERLAY2 Enable second overlay window
      #GFVX_UO_ACTIVETOP Show this overlay window on top
      #GFVX_UO_DIGITAL_VIBRANCE Enable digital vibrance for first overlay window
      + */ + NvU32 BlendingColorKey; + /**< Blending color key value in ARGB32 format. + Value takes effect only when #GFVX_UO_ALPHA_BLENDING and + (#GFVX_UO_SRC_COLOR_KEY or #GFVX_UO_DEST_COLOR_KEY) + are set. + */ + NvU32 AlphaValue; + /**< Alpha value for blending overlay. + Alpha value is used to do blending when + blending color key matches. Even though AlphaVal + is a 32 bit number, alpha value can only be a 8 bit value. + Application should specify the same value in byte 1 (LSB), + 2 and 3 else the API will fail. + */ + + PGFRMSURFACE pDestSurf2; /**< Destination surface pointer for second overlay */ + PGFRMSURFACE pSrcSurf2; /**< Source surface pointer for second overlay, + if this pointer is NULL, disable second overlay. + */ + PGFRECT pDestRect2; /**< Destination rectangle for second overlay */ + PGFRECT pSrcRect2; /**< Source rectangle for second overlay */ + NvU32 UpdateOption2; + /**< Flagbit mask controlling rotation, color keying for second overlay: + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_UO_ROTATE_0 Overlay without rotation
      #GFVX_UO_ROTATE_180 Overlay with 180 degree rotation
      #GFVX_UO_H_FLIP Overlay with horizontal flip
      #GFVX_UO_V_FLIP Overlay with vertical flip
      #GFVX_UO_SRC_COLOR_KEY Source color keying
      #GFVX_UO_DEST_COLOR_KEY Destination color keying
      #GFVX_UO_ALPHA_BLENDING Alpha blending
      #GFVX_UO_COLOR_KEY_ALPHA_ONLY Overlay based on destination alpha
      #GFVX_UO_COLOR_KEY_ALPHA_COLOR Overlay based on destination alpha and color
      #GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY Alpha Blending based on destination alpha
      #GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR Alpha Blending based on destination alpha and color
      #GFVX_UO_ACTIVETOP Show this overlay window on top
      #GFVX_UO_DIGITAL_VIBRANCE Enable digital vibrance for second overlay window
      + */ + NvU8 dvRed; /**< Digital vibrance amplification factor for R overlay. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvRed's valid value range + is 1 to 100. + */ + NvU8 dvGreen; /**< Digital vibrance amplification factor for G overlay. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvGreen's valid value range + is 1 to 100. + */ + NvU8 dvBlue; /**< Digital vibrance amplification factor for B overlay. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvBlue's valid value range + is 1 to 100. + */ + NvU8 dvRed2; /**< Digital vibrance amplification factor for R overlay2. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvRed2's valid value range + is 1 to 100. + */ + NvU8 dvGreen2; /**< Digital vibrance amplification factor for G overlay2. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvGreen2's valid value range + is 1 to 100. + */ + NvU8 dvBlue2; /**< Digital vibrance amplification factor for B overlay2. + It is configured via GFVxUpdateOverlay(), + GFVXUPDATEOVERLAY::dvBlue2's valid value range + is 1 to 100. + */ + NvU32 AlphaValue2; + /**< Alpha value for blending Window C overlay. + Same restriction as for GFVXUPDATEOVERLAY::AlphaValue apply. + */ + +} GFVXUPDATEOVERLAY, *PGFVXUPDATEOVERLAY; + + +/** Parameter structure for GFVxVIPFeedImage(). + This structure describes the image data that is to be fed to the VIP + via the CPU host. + @see GFVxVIPFeedImage() +*/ +typedef struct _GFVXVIPFEEDIMAGE +{ + PGFRMSURFACE pSurf; /**< Surface to feed data from, must be in a YUV + format and accessible by the host CPU + */ + PGFRECT pSrcRect; /**< Source clipping rectangle for data feeding, or + NULL for no clipping + */ +} GFVXVIPFEEDIMAGE, *PGFVXVIPFEEDIMAGE; + + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP supports image shrinking. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_SHRINK 0x00000001 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP supports image enlarging. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_ENLARGE 0x00000002 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: Parallel video input supported. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_PARALLEL 0x00000004 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: Serial video input supported. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_SERIAL 0x00000008 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: Vertical and horizontal flip supported + for VIP output RGB image. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_RGB_VH_FLIP 0x00000010 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can supply VClock and VHSync + signals to the camera chip. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_OUTPUT_VCLOCK_VHSYNC 0x00000020 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can supply a master clock to the + camera chip. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_OUTPUT_MASTER_CLOCK 0x00000040 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept a JPEG bitstream from + a camera with type A interface. + See section @ref pageVxOverview2 for description of type A, B, and C + interfaces. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_TYPE_A 0x00000080 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept a JPEG bitstream from + a camera with type B interface. + See section @ref pageVxOverview2 for description of type A, B, and C + interfaces. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_TYPE_B 0x00000100 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept a JPEG bitstream from + a camera with type C interface. + See section @ref pageVxOverview2 for description of type A, B, and C + interfaces. + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_TYPE_C 0x00000200 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept Bayer format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_BAYER 0x00000400 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept RGB565 format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_RGB565 0x00000800 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept RGB888 format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_RGB888 0x00001000 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept RGB444 format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_RGB444 0x00002000 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept YUV420NP format input. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_YUV420NP 0x00004000 + +/** VxAPI GFVXVIPPROPERTY::Flag flagbit: VIP can accept JPEG image from camera + through type C_RAW interface. See section @ref pageVxOverview2. + @version SC15 and above + @see GFVXVIPPROPERTY, GFVxVIPGetProperty(), GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CAP_TYPE_C_RAW 0x00008000 + +/** Structure used by GFVxVIPGetProperty() to describe VIP capabilities. + @see GFVxVIPGetProperty() +*/ +typedef struct _GFVXVIPPROPERTY +{ + NvU32 Flag; /**< Flag bitmask describing VIP capabilities: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_VIP_CAP_SHRINKVIP supports image shrinking
      #GFVX_VIP_CAP_ENLARGEVIP supports image enlarging
      #GFVX_VIP_CAP_PARALLELParallel video input supported
      #GFVX_VIP_CAP_SERIALSerial video input supported
      #GFVX_VIP_CAP_RGB_VH_FLIPVertical and horizontal flip supported for VIP + output RGB image
      #GFVX_VIP_CAP_OUTPUT_VCLOCK_VHSYNCVIP can supply VClock and VHSync signals to the + camera chip
      #GFVX_VIP_CAP_OUTPUT_MASTER_CLOCKVIP can supply a master clock to the + camera chip
      #GFVX_VIP_CAP_TYPE_AVIP can accept a JPEG bitstream from a camera with + type A interface
      #GFVX_VIP_CAP_TYPE_BVIP can accept a JPEG bitstream from a camera with + type B interface
      #GFVX_VIP_CAP_TYPE_CVIP can accept a JPEG bitstream from a camera with + type C interface
      #GFVX_VIP_CAP_BAYERVIP can accept Bayer format input
      #GFVX_VIP_CAP_RGB565VIP can accept RGB565 format input
      #GFVX_VIP_CAP_RGB888VIP can accept RGB888 format input
      #GFVX_VIP_CAP_RGB444VIP can accept RGB444 format input
      #GFVX_VIP_CAP_YUV420NPVIP can accept YUV420NP format input
      #GFVX_VIP_CAP_TYPE_C_RAWVIP can accept JPEG image from Camera through + type C_RAW interface
      + */ + NvU32 DestFormat;/**< Supported color formats at VIP output, the returned + value is a logically OR'ed combination of the + following surface identifiers: + + + + + + + + + + + + + + + +
      #GF_SURFACE_YUYVYUV422 in YUYV order
      #GF_SURFACE_YVYUYUV422 in YVYU order
      #GF_SURFACE_UYVYYUV422 in UYVY order
      #GF_SURFACE_VYUYYUV422 in VYUY order
      #GF_SURFACE_RGB565RGB565, 16 bpp
      #GF_SURFACE_RGB888RGB888, 24 bpp
      #GF_SURFACE_ARGB8888ARGB8888, 32 bpp
      + To check if a specific colour format is + supported, logically AND \a DestFormat against the + format identifier and compare it as below: +
      +    if ((DestFormat & GF_SURFACE_RGB565) == GF_SURFACE_RGB565)
      +    {
      +        // RGB565 is supported
      +    }
      +    
      + */ + NvU32 HMaxNumerator; /**< Maximum horizontal numerator for VI + decimation. VI decimation is configured via + GFVxVIPSetVIP(), GFVXVIPINFO::HNumerator's + valid value range is 1 to \a HMaxNumerator. + */ + NvU32 HMaxDenominator; /**< Maximum horizontal denominator for VI + decimation. VI decimation is configured via + GFVxVIPSetVIP(), GFVXVIPINFO::HDenominator's + valid value range is 1 to \a HMaxDenominator. + */ + NvU32 VMaxNumerator; /**< Maximum vertical numerator for VI decimation. + VI decimation is configured via + GFVxVIPSetVIP(), GFVXVIPINFO::VNumerator's + valid value range is 1 to \a VMaxNumerator. + */ + NvU32 VMaxDenominator; /**< Maximum vertical denominator for VI decimation. + VI decimation is configured via + GFVxVIPSetVIP(), GFVXVIPINFO::VDenominator's + valid value range is 1 to \a VMaxDenominator. + */ +} GFVXVIPPROPERTY, *PGFVXVIPPROPERTY; + + +/** Structure used to describe the input frame size if input data format is Bayer. + This structure is not used when input source is VIP. + @see +*/ +typedef struct _GFVXBAYERINPUTFRAME +{ + NvU16 Width; /**< Host Input source width. */ + NvU16 Height; /**< Host Input source height. */ +} GFVXBAYERINPUTFRAME, *PGFVXBAYERINPUTFRAME; + +/** Structure used to describe ISP scan size if input data format is Bayer. + Scan size is camera specific. + + The application should populate this structure with + values filled by GFCameraSetup() in GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo. + The application should also configure ISP with values in + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ScanWidth and + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ScanHeight. + + This structure is used only when input source is VIP and input data format is Bayer. + + @see GFISPIMGTIMING +*/ +typedef struct _GFVXBAYERSCANSIZE +{ + NvU16 HScan; /**< VIP input signal horizontal scan size. */ + NvU16 VScan; /**< VIP input signal vertical scan size. */ +} GFVXBAYERSCANSIZE, *PGFVXBAYERSCANSIZE; + +/** Structure used to describe ISP Active Area if input data format is Bayer. + Active Area is camera specific. + + The application should populate this structure with + values filled by GFCameraSetup() in GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo. + The application should also configure ISP with values in + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ActiveFrameStart, + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ActiveLineStart, + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ActiveFrameHeight and + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo::ActiveLineWidth. + + Active Area rectangle should fall inside the Scan Size. + This structure is used only when input source is VIP and input data format is Bayer. + + @see GFISPIMGTIMING +*/ +typedef struct _GFVXBAYERACTIVEAREA +{ + NvU16 LineStart; /**< VIP input signal horizontal active offset. */ + NvU16 FrameStart; /**< VIP input signal vertical active offset. */ + NvU16 LineWidth; /**< VIP input signal horizontal active width. */ + NvU16 FrameHeight; /**< VIP input signal vertical active height. */ +} GFVXBAYERACTIVEAREA, *PGFVXBAYERACTIVEAREA; + +/** Structure used to describe ISP Output Area if input data format is Bayer. + + This structure is not used by VI. It is used to configure ISP. + Output Area rectangle can be equal to or less than Active Area rectangle. + This structure is used only when input source is VIP and input data format is Bayer. + + @see GFISPIMGTIMING +*/ +typedef struct _GFVXBAYEROUTPUTAREA +{ + NvU16 LineStart; /**< VIP input signal horizontal output offset. */ + NvU16 FrameStart; /**< VIP input signal vertical output offset. */ + NvU16 LineWidth; /**< VIP input signal horizontal output width. */ + NvU16 FrameHeight; /**< VIP input signal vertical output height. */ +} GFVXBAYEROUTPUTAREA, *PGFVXBAYEROUTPUTAREA; + + +/** Structure used to describe the rectangles needed by ISP to properly process Bayer input from camera. + This structure is used only when input source is VIP and input data format is Bayer. + + @see GFVXBAYERINPUTFRAME, GFVXBAYERSCANSIZE, GFVXBAYERACTIVEAREA, GFVXBAYEROUTPUTAREA +*/ +typedef struct _GFVXBAYERINFO +{ + PGFVXBAYERINPUTFRAME pInputFrameSize; /**< For VIP input, this field is not used. + */ + PGFVXBAYERSCANSIZE pScanSize; /**< ISP Scan Size. + Scan size is camera specific. This field is set + by GFCameraAPI in GFCAMERARESOLUTIONTYPE::pBayerInfo. + */ + PGFVXBAYERACTIVEAREA pActiveArea; /**< ISP Active Area. + Active Area is camera specific. This field is set + by GFCameraAPI in + GFCAMERATABLETYPE::GFCAMERARESOLUTIONTYPE::pBayerInfo. + Active Area rectangle should fall inside the Scan Size. + */ + PGFVXBAYEROUTPUTAREA pOutputArea; /**< ISP Output Area. This field is not used by VI. + Output Area rectangle can be equal to or less than + Active Area rectangle. + */ + NvU8 DemosaicKernelSize; /**< For VIP input, this field is not used. + */ + NvU16 IspDownscaleUsed; /**< Use Isp downscale (Only for sc17 and above) + */ +} GFVXBAYERINFO, *PGFVXBAYERINFO; + + +///////////Cindy: Following is CSI defination. + +/* flags optoins */ + +/** Pixel Parser stream is from CSI A +*/ +#define GFVX_CSI_SOURCE_CSI_A 0x00000001 + +/** Pixel Parser stream is from CSI B +*/ +#define GFVX_CSI_SOURCE_CSI_B 0x00000002 + +/** Pixel Parser stream is from HOST +*/ +#define GFVX_CSI_SOURCE_HOST 0x00000004 + +/** Pixel Parser stream is from VIP +*/ +#define GFVX_CSI_SOURCE_VIP 0x00000008 + +/** Pixel Parser A enable +*/ +#define GFVX_CSI_PPA_ENABLE 0x00000010 + +/** Pixel Parser B enable +*/ +#define GFVX_CSI_PPA_DISABLE 0x00000020 + +//#define GFVX_CSI_PPA_MASK 0x00000030 + +/** Pixel Parser A enable +*/ +#define GFVX_CSI_PPB_ENABLE 0x00000040 + +/** Pixel Parser B enable +*/ +#define GFVX_CSI_PPB_DISABLE 0x00000080 + +//#define GFVX_CSI_PPB_MASK 0x000000C0 + +/** whether packet header is sent in the beginning of packet or not. payload only mode: no header +*/ +#define GFVX_CSI_PACKET_HEADER_ENABLE 0x00000100 + +/** Check data_type and Virtural_Channel_ID or not +*/ +#define GFVX_CSI_DATA_IDENTIFIER_ENABLE 0x00000200 + +/** check WordCount from header or register +*/ +#define GFVX_CSI_WORD_COUNT_SELECT_HEADER 0x00000400 + +/** check ECC from header +*/ +#define GFVX_CSI_HEADER_EC_DISABLE 0x00000800 + +/** pad short line with 0 +*/ +#define GFVX_CSI_LINE_PAD_NONE 0x00001000 + +/** pad short line with 1 +*/ +#define GFVX_CSI_LINE_PAD_1 0x00002000 + +/** pad short frame with 0 +*/ +#define GFVX_CSI_FRAME_PAD_NONE 0x00004000 + +/** pad short frame with 1 +*/ +#define GFVX_CSI_FRAME_PAD_1 0x00008000 + +/** 2 bytes CRC Check enable +*/ +#define GFVX_CSI_CRC_CHECK 0x00010000 + +/** Embedded data enable +*/ +#define GFVX_CSI_EMBEDDED_DATA_ENABLE 0x00020000 + +/** enable timeout checking +*/ +#define GFVX_CSI_LINE_TIMEOUT_ENABLE 0x00040000 + +#define GFVX_CSI_VSYNC_START_MARK_VSYNC 0x00080000 + +#define GFVX_CSI_VI_HSYNC_CONTROL 0x00100000 + +#define GFVX_CSI_VI_VSYNC_CONTROL 0x00200000 + + +typedef struct _GFVXCSISET +{ + NvU32 flags; /** flag options see above */ + NvU32 HOffset; /**< VIP input signal horizontal offset. */ + NvU32 HActive; /**< VIP input signal horizontal active width. */ + NvU32 VOffset; /**< VIP input signal vertical offset. */ + NvU32 VActive; /**< VIP input signal vertical active height.*/ + NvU32 ColorFormat; /** convert to data type*/ + +// PIXEL_STREAM_PPA_COMMAND: + NvU32 StartMarkerFrameMin; //CSI_PPA_START_MARKER_FRAME_MIN; /** comment */ + NvU32 StartMarkerFrameMax; //CSI_PPA_START_MARKER_FRAME_MAX; /** comment */ + +// PIXEL_STREAM_A_CONTROL0: + NvU32 VirtualChannelID; //CSI_PPA_VIRTUAL_CHANNEL_ID; /** stream virtual ID number */ + NvU32 OutputFormatOpt; //CSI_PPA_OUTPUT_FORMAT_OPTIONS; /** output format */ + +// PIXEL_STREAM_A_CONTROL1: + NvU32 TopFieldFrame; //CSI_PPA_TOP_FIELD_FRAME; /** camera spec */ + NvU32 TopFieldFrameMask; //CSI_PPA_TOP_FIELD_FRAME_MASK; /** camera sepc */ + +// PIXEL_STREAM_A_GAP: + NvU32 LineMinGap; //PPA_LINE_MIN_GAP; /** gap between lines */ + NvU32 FrameMinGap; //PPA_FRAME_MIN_GAP; /** gat between frames */ + +// PIXEL_STREAM_A_EXPECTED_FRAME: + NvU32 LineTimeOutMaxClock; //PPA_MAX_CLOCKS; /** line time out value */ + +} GFVXCSISET, *PGFVXCSISET; + +/* CSI data types + *` Set by camera script to match + * stream supplied by camera + */ + +#define GFVX_CSI_DATA_YUV420_8 (24UL) +#define GFVX_CSI_DATA_YUV420_10 (25UL) +#define GFVX_CSI_DATA_LEG_YUV420_8 (26UL) +#define GFVX_CSI_DATA_YUV420CSPS_8 (28UL) +#define GFVX_CSI_DATA_YUV420CSPS_10 (29UL) +#define GFVX_CSI_DATA_YUV422_8 (30UL) +#define GFVX_CSI_DATA_YUV422_10 (31UL) +#define GFVX_CSI_DATA_RGB444 (32UL) +#define GFVX_CSI_DATA_RGB555 (33UL) +#define GFVX_CSI_DATA_RGB565 (34UL) +#define GFVX_CSI_DATA_RGB666 (35UL) +#define GFVX_CSI_DATA_RGB888 (36UL) +#define GFVX_CSI_DATA_RAW6 (40UL) +#define GFVX_CSI_DATA_RAW7 (41UL) +#define GFVX_CSI_DATA_RAW8 (42UL) +#define GFVX_CSI_DATA_RAW10 (43UL) +#define GFVX_CSI_DATA_RAW12 (44UL) +#define GFVX_CSI_DATA_RAW14 (45UL) +#define GFVX_CSI_DATA_ARB_DT1 (48UL) +#define GFVX_CSI_DATA_ARB_DT2 (49UL) +#define GFVX_CSI_DATA_ARB_DT3 (50UL) +#define GFVX_CSI_DATA_ARB_DT4 (51UL) + + +/** OutputFormatOpt */ +#define GFVX_CSI_OUTPUT_FORMAT_OPTIONS_ARBITRARY (0UL) +#define GFVX_CSI_OUTPUT_FORMAT_OPTIONS_PIXEL (1UL) +#define GFVX_CSI_OUTPUT_FORMAT_OPTIONS_PIXEL_REP (2UL) +#define GFVX_CSI_OUTPUT_FORMAT_OPTIONS_STORE (3UL) + +#define GFVX_INTERNAL_DEBUG 0x10000000 + +// Below defines are used only when input source is HOST and input format is Bayer +// Since this is not a valid customer use case, we will not add Doxygen comments to these defines + +// Minimum padding requirement for ISP +#define MIN_SCANSIZE_WIDTH_DIFF 20 +#define MIN_SCANSIZE_HEIGHT_DIFF 10 + +// The actual minimum padding has not been determined; +// however, 30 padding on all sides is not enough for +// Demosaic mode 4 (5X5BPNR) with M3 statistics gathering. +// 35 on right + 15 on top/left/bottom seems to +// work fine. +#define MIN_ACTIVE_AREA_LEFT_PADDING 15 +#define MIN_ACTIVE_AREA_RIGHT_PADDING 35 +#define MIN_ACTIVE_AREA_TOP_PADDING 15 +#define MIN_ACTIVE_AREA_BOTTOM_PADDING 15 + +// Active Rect must be a few pixels larger than Output Rect to avoid +// a halo effect where the outer pixels are wrong. +#define MIN_OUTPUT_AREA_PADDING_3X3 2 +#define MIN_OUTPUT_AREA_PADDING_5X5 3 + + +/** Parameter structure passed to GFVxVIPSetVIP(). + @see GFVxVIPSetVIP() +*/ +typedef struct _GFVXVIPINFO +{ + NvU32 Flag; + /**< Flag bitmask, OR'ed combination of: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_VIP_PARALLEL_INPUT8-bit/clock video data
      #GFVX_VIP_SERIAL_INPUTSerial input
      #GFVX_VIP_HVSYNC_IN_STREAMVHSYNC and VVSYNC in the data stream
      #GFVX_VIP_EXTERNAL_VHSYNCCamera VHSYNC asserted by external signal
      #GFVX_VIP_INTERNAL_VHSYNCCamera VHSYNC generated by GoForce chip
      #GFVX_VIP_EXTERNAL_VCLKVCLK generated externally
      #GFVX_VIP_INTERNAL_VCLKVCLK generated by GoForce chip
      #GFVX_VIP_DETECT_FIELDDetect field 0 or 1, will not work for internal VHSYNC + (#GFVX_VIP_INTERNAL_VHSYNC) +
      #GFVX_VIP_RGB_H_FLIPHorizontal flip
      #GFVX_VIP_RGB_V_FLIPVertical flip
      #GFVX_VIP_HOST_IMAGECPU feeds image to VIP
      #GFVX_VIP_CHANGE_DEFAULT_TIMINGChange the default timing for VHSYNC and VCLK
      #GFVX_VIP_ASK_FOR_MCLOCKCamera master clock provided by GoForce chip
      #GFVX_VIP_TYPE_AVIP input type A interface
      #GFVX_VIP_TYPE_BVIP input type B interface
      #GFVX_VIP_TYPE_CVIP input type C interface
      #GFVX_VIP_DEST_BYTE_SWAPEnable destination byte swap for YUV/RGB data written to + preview surface +
      #GFVX_VIP_TYPE_C_RAWDo not remove the 0xFF, 0x02 sequence when camera is + running at type C interface +
      #GFVX_VIP_VIP_ROTATE_0VI output without rotation
      #GFVX_VIP_VIP_ROTATE_90VI output with 90 degree rotation
      #GFVX_VIP_VIP_ROTATE_180VI output with 180 degree rotation
      #GFVX_VIP_VIP_ROTATE_270VI output with 270 degree rotation
      #GFVX_VIP_RGB565RGB565 input to EPP
      #GFVX_VIP_RGB888RGB888 input to EPP
      #GFVX_VIP_RGB444RGB444 input to EPP
      #GFVX_VIP_BYPASS_MCLOCK_PINBypass any manipulation on internal master clock generation + output pin +
      #GFVX_VIP_BYPASS_NON_MCLOCK_PINSBypass any manipulation on VCLK, VHSYNC, and VID[7:0] pins +
      #GFVX_VIP_PRE_GENERATE_MCLOCKPre-generation of master clock
      + */ + NvU32 HOffset; /**< VIP input signal horizontal offset. */ + NvU32 HActive; /**< VIP input signal horizontal active width. */ + NvU32 VOffset; /**< VIP input signal vertical offset. */ + NvU32 VActive; /**< VIP input signal vertical active height. */ + NvU32 ColorFormat; /**< VIP input color format identifier, see + GFRMSURFACE::ColorFormat. + */ + NvU32 SerialDelay; /**< VIP serial input delay, reserved for future + use. + */ + NvU32 NewTiming; /**< Flag bitmask configuring VIP input timing, used + only if flag #GFVX_VIP_CHANGE_DEFAULT_TIMING + set, OR'ed combination of: + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_VIP_PDL_FALLING_VCLKParallel data latched at falling edge + of VCLK (default is rising edge) +
      #GFVX_VIP_SDL_RISING_VCLKSerial data lacthed at rising edge of + VCLK (default is falling edge) +
      #GFVX_VIP_VHSYNC_ACTIVE_LOWVHSYNC active low (default is active + high) +
      #GFVX_VIP_VVSYNC_ACTIVE_LOWVVSYNC active low (default is active + high) +
      #GFVX_VIP_VHSYNC_ACTIVE_EDGE_LEADVHSYNC active leading edge (default + is trailing edge) +
      #GFVX_VIP_VVSYNC_ACTIVE_EDGE_LEADVVSYNC active leading edge (default + is trailing edge) +
      #GFVX_VIP_SFRAME_ACTIVE_LOWSerial video frame sync active low, + falling edge indicates start of data + frame (default is active high, rising + edge indicates start of data frame) +
      #GFVX_VIP_SFRAME_SIZE_16Serial video input is 16 bit per frame + (default is 8 bit per frame) +
      #GFVX_VIP_FILED_0_BOTTOMField 0 is bottom/even field + (default is top/odd field) +
      #GFVX_VIP_VCLK_OUTPUT_ACTIVE_LOWVCLK output from GoForce chip active + low (default is active high) +
      + */ + NvU32 HNumerator; /**< VI decimation horizontal numerator, number of + pixels to keep from a group of incoming + pixels. + */ + NvU32 HDenominator;/**< VI decimation horizontal denominator, group + size. + */ + NvU32 VNumerator; /**< VI decimation vertical numerator, number of + lines to keep from a group of incoming lines. + */ + NvU32 VDenominator;/**< VI decimation vertical numerator, group + size. + */ + NvU32 MClockFreq; /**< Master clock frequency supplied to camera from + GoForce chip, used only if + #GFVX_VIP_ASK_FOR_MCLOCK set. + */ + NvU32 VClockFreq; /**< Clock frequency required for VIP input signal. + */ + + // Fill The following fields if GFVX_VIP_INTERNAL_VHSYNC is set in Flag + NvU32 VHPulseWidth; /**< VHSYNC pulse width in number of VCLK cycles, + valid range is 1 to 8. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + NvU32 VHPulsePeriod;/**< VHSYNC pulse period in number of VCLK cycles, + valid range 32 to 2048. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + NvU32 VVPulseWidth; /**< VVSYNC pulse width in number of VCLK cycles + valid range is 1 to 8. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + NvU32 VVPulsePeriod;/**< VVSYNC pulse period in number of VCLK + valid range 32 to 1024. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + NvU32 VVDelay; /**< Number of VCLK cycles from the leading edge + of VHSYNC to the leading edge of VVSYNC, + valid range is -2 to 13. Used only if + #GFVX_VIP_INTERNAL_VHSYNC is set. + */ + PGFVXBAYERINFO pBayerInfo; /**< Structure used to describe the rectangles needed by ISP + to properly process Bayer input from camera. This + structure is used only when input source is VIP and + input data format is Bayer. + */ + PGFVXCSISET pCSIInfo; /** Structure used to describe CSI stream info. Only used when input source is CSI stream + */ +} GFVXVIPINFO, *PGFVXVIPINFO; + + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Start VIP data feeding. + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_START 0x00000001 + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Stop VIP data feeding. + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_STOP 0x00000002 + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Start VIP data feeding with + synchronized auto-display surface after a frame is captured from VIP. + If no output surface is set (GFVXVIPUPDATE::ppSurf is NULL), this action + behaves in the same way as #GFVX_VIP_START. + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_AUTO_FLIP (0x00000004 | GFVX_VIP_START) + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Start VIP data feeding with + synchronized auto-blit from VIP output surface to another surface. + + Parameters for the blit have to be set up separately via GFVxBlt() with + flag #GFVX_AUTO_BLT. Auto-blit is triggered after a complete frame has + been captured from VIP. + + If no output surface is set (GFVXVIPUPDATE::ppSurf is NULL), this action + behaves in the same way as #GFVX_VIP_START. + + Once auto-blit has been enabled it can be disabled with GFVxVIPUpdate() + action identifier #GFVX_VIP_AUTO_TRIGER_BLT_OFF. + + @see GFVXVIPUPDATE, GFVxVIPUpdate(), #GFVX_VIP_AUTO_TRIGER_BLT_OFF, + #GFVX_AUTO_BLT +*/ +#define GFVX_VIP_AUTO_TRIGER_BLT (0x00000008 | GFVX_VIP_START) + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Stop auto-blit that has been + enabled earlier via #GFVX_VIP_AUTO_TRIGER_BLT. + + Note that this action only disables auto-blit. It does not disable the + VIP data feed. If also VIP is to be disabled, GFVxVIPUpdate() has to be + called again with action #GFVX_VIP_STOP. + + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_AUTO_TRIGER_BLT_OFF 0x00000010 + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Start VIP data feeding with + synchronized auto-display surface after a frame is captured from VIP. + Second Overlay Window is used instead of first. + If no output surface is set (GFVXVIPUPDATE::ppSurf is NULL), this action + behaves in the same way as #GFVX_VIP_START. + + @version SC15 and above only + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_AUTO_FLIP_OVERLAY2 (0x00000020 | GFVX_VIP_START) + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Capture one frame in VIP buffer + if it is combined with flag #GFVX_VIP_START + + @version SC15 and above only + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_CAPTURE_ONE_FRAME 0x00000040 + +/** VxAPI GFVXVIPUPDATE::UpdateOption action: Restart VIP without changes VI + state after stop VI + + @version SC15 and above only + @see GFVXVIPUPDATE, GFVxVIPUpdate() +*/ +#define GFVX_VIP_RESTART 0x00000080 + +/** Parameter structure for GFVxVIPUpdate(). + @see GFVxVIPUpdate() +*/ +typedef struct _GFVXVIPUPDATE +{ + PGFRMSURFACE *ppSurf; /**< Pointer to an array of VIP output surfaces + pointers, or NULL to feed to MPEG/JPEG without + display. + */ + NvU32 numofSurf; /**< Number of surface pointers in \a ppSurf, valid + range is 1 to 2. + */ + NvU16 XStart; /**< Destination surface X position for the output + from VIP + */ + NvU16 YStart; /**< Destination surface Y position for the output + from VIP + */ + NvU32 UpdateOption; + /**< Action identifier, one of: + + + + + + + + + + + +
      #GFVX_VIP_STARTStart VIP data feeding
      #GFVX_VIP_STOPStop VIP data feeding
      #GFVX_VIP_AUTO_FLIPStart VIP data feeding and enable + auto-display of the last VIP target + surface +
      #GFVX_VIP_AUTO_TRIGER_BLTStart VIP data feeding and enable + auto-blit from the last target surface + to additional surfaces +
      #GFVX_VIP_AUTO_TRIGER_BLT_OFFDisable auto-blit
      + */ +} GFVXVIPUPDATE, *PGFVXVIPUPDATE; + +/** VxAPI VxBlt operation modes. + Constants to specify SB mode for a call to GFVxBltSetCSCCoeff(). + @see GFVxBltSetCSCCoeff(), GFVxBltGetCSCCoeff() +*/ +typedef enum +{ + /** Host full frame stretchblt trigger */ + GFVX_BLT_FULL_MODE, + + /** Host partial frame stretchblt trigger */ + GFVX_BLT_PARTIAL_MODE, + + /** Auto stretchblt trigger from VI */ + GFVX_BLT_AUTO_VI_MODE +} GFVXBLTMODE; + +/** VxAPI component level interrupt operation types. + Constants to specify operation for a call to GFVxInterruptControl(). + @see GFVX_INTERRUPT_TYPE, GFVxInterruptControl() +*/ +typedef enum +{ + /** Enable interrupt/status assertion for an interrupt type. */ + GFVX_INTERRUPT_ENABLE, + + /** Disable interrupt/status assertion for an interrupt type. */ + GFVX_INTERRUPT_DISABLE, + + /** Clear interrupt/status assertion for an interrupt type. */ + GFVX_INTERRUPT_CLEAR, + + /** Query for interrupt/status assertion for an interrupt type. */ + GFVX_INTERRUPT_QUERY_STATUS, + + /** Set Y-FIFO threshold. */ + GFVX_INTERRUPT_SET_Y_FIFO_THRESHOLD, + + /** Get Y-FIFO threshold. */ + GFVX_INTERRUPT_GET_Y_FIFO_THRESHOLD, + + /** Set V-counter threshold. */ + GFVX_INTERRUPT_SET_V_COUNTER_THRESHOLD, + + /** Get V-counter threshold. */ + GFVX_INTERRUPT_GET_V_COUNTER_THRESHOLD, + + /** Get all bits of VI interrupt status register. */ + GFVX_INTERRUPT_GET_ALL_STATUS, + + /** Clear all VI interrupt status bits. */ + GFVX_INTERRUPT_CLEAR_ON_ALL_STATUS + +} GFVX_INTERRUPT_OPERATION_TYPE; + +/** VxAPI interrupt types. + @see GFVX_INTERRUPT_OPERATION_TYPE, GFVxInterruptControl() +*/ +typedef enum +{ + /** VID[8] pin rising edge interrupt. */ + GFVX_VD8PIN_RISING_EDGE_INTR = 0x0100001, + /** VID[9] pin rising edge interrupt. */ + GFVX_VD9PIN_RISING_EDGE_INTR = 0x0100002, + /** VID[10] pin rising edge interrupt. */ + GFVX_VD10PIN_RISING_EDGE_INTR = 0x0100004, + /** VID[11] pin rising edge interrupt. */ + GFVX_VD11PIN_RISING_EDGE_INTR = 0x0100008, + /** VGP[4] pin rising edge interrupt. */ + GFVX_VGP4PIN_RISING_EDGE_INTR = 0x0100010, + /** VGP[5] pin rising edge interrupt. */ + GFVX_VGP5PIN_RISING_EDGE_INTR = 0x0100020, + /** VGP[6] pin rising edge interrupt. */ + GFVX_VGP6PIN_RISING_EDGE_INTR = 0x0100040, + /** VHSYNC pin rising edge interrupt. */ + GFVX_VHSYNC_RISING_EDGE_INTR = 0x0100080, + /** VVSYNC pin rising edge interrupt. */ + GFVX_VVSYNC_RISING_EDGE_INTR = 0x0100100, + + /** Vertical counter threshold interrupt. */ + GFVX_VERTICAL_COUNTER_THRESHOLD_INTR = 0x0000200, + /** Y-FIFO threshold int. */ + GFVX_Y_FIFO_THRESHOLD_INTR = 0x0000400, + /** Buffer done first output interrupt. */ + GFVX_BUFFER_FIRST_OUTPUT_INTR = 0x0000800, + /** Frame done first output interr upt. */ + GFVX_FRAME_FIRST_OUTPUT_INTR = 0x0001000, + /** Buffer done second output interrupt. */ + GFVX_BUFFER_SECOND_OUTPUT_INTR = 0x0002000, + /** Frame done second output interrupt. */ + GFVX_FRAME_SECOND_OUTPUT_INTR = 0x0004000, + /** VI to EPP error interrupt. */ + GFVX_EPP_ERROR_INTR = 0x0008000, + /** YUV420PA error interrupt. */ + GFVX_YUV420PA_ERROR_INTR = 0x0010000, + /** First output peer stall interrupt. */ + GFVX_FIRST_OUTPUT_PEER_STALL_INTR = 0x0020000, + /** Second output peer stall interrupt. */ + GFVX_SECOND_OUTPUT_PEER_STALL_INTR = 0x0040000, + /** DMA stall interrupt. */ + GFVX_DMA_STALL_INTR = 0x0080000, + + + /** VD[8] pin falling edge interrupt. */ + GFVX_VD8PIN_FALLING_EDGE_INTR = 0x0000001, + /** VD[9] pin falling edge interrupt. */ + GFVX_VD9PIN_FALLING_EDGE_INTR = 0x0000002, + /** VD[10] pin falling edge interrupt. */ + GFVX_VD10PIN_FALLING_EDGE_INTR = 0x0000004, + /** VD[11] pin falling edge interrupt. */ + GFVX_VD11PIN_FALLING_EDGE_INTR = 0x0000008, + /** VGP[4] pin falling edge interrupt. */ + GFVX_VGP4PIN_FALLING_EDGE_INTR = 0x0000010, + /** VGP[5] pin falling edge interrupt. */ + GFVX_VGP5PIN_FALLING_EDGE_INTR = 0x0000020, + /** VGP[6] pin falling edge interrupt. */ + GFVX_VGP6PIN_FALLING_EDGE_INTR = 0x0000040, + /** VHSYNC pin falling edge interrupt. */ + GFVX_VHSYNC_FALLING_EDGE_INTR = 0x0000080, + /** VVSYNC pin falling edge interrupt. */ + GFVX_VVSYNC_FALLING_EDGE_INTR = 0x0000100, + + /** VD[8] pin rising edge interrupt. */ + GFVX_VD8PIN_RISING_LEVEL_INTR = 0x1100001, + /** VD[9] pin rising edge interrupt. */ + GFVX_VD9PIN_RISING_LEVEL_INTR = 0x1100002, + /** VD[10] pin rising edge interrupt. */ + GFVX_VD10PIN_RISING_LEVEL_INTR = 0x1100004, + /** VD[11] pin rising edge interrupt. */ + GFVX_VD11PIN_RISING_LEVEL_INTR = 0x1100008, + /** VGP[4] pin rising edge interrupt. */ + GFVX_VGP4PIN_RISING_LEVEL_INTR = 0x1100010, + /** VGP[5] pin rising edge interrupt. */ + GFVX_VGP5PIN_RISING_LEVEL_INTR = 0x1100020, + /** VGP[6] pin rising edge interrupt. */ + GFVX_VGP6PIN_RISING_LEVEL_INTR = 0x1100040, + /** VHSYNC pin rising edge interrupt. */ + GFVX_VHSYNC_RISING_LEVEL_INTR = 0x1100080, + /** VVSYNC pin rising edge interrupt. */ + GFVX_VVSYNC_RISING_LEVEL_INTR = 0x1100100, + + /** VD[8] pin falling level interrupt. */ + GFVX_VD8PIN_FALLING_LEVEL_INTR = 0x1000001, + /** VD[9] pin falling level interrupt. */ + GFVX_VD9PIN_FALLING_LEVEL_INTR = 0x1000002, + /** VD[10] pin falling level interrupt. */ + GFVX_VD10PIN_FALLING_LEVEL_INTR = 0x1000004, + /** VD[11] pin falling level interrupt. */ + GFVX_VD11PIN_FALLING_LEVEL_INTR = 0x1000008, + /** VGP[4] pin falling level interrupt. */ + GFVX_VGP4PIN_FALLING_LEVEL_INTR = 0x1000010, + /** VGP[5] pin falling level interrupt. */ + GFVX_VGP5PIN_FALLING_LEVEL_INTR = 0x1000020, + /** VGP[6] pin falling level interrupt. */ + GFVX_VGP6PIN_FALLING_LEVEL_INTR = 0x1000040, + /** VHSYNC pin falling level interrupt. */ + GFVX_VHSYNC_FALLING_LEVEL_INTR = 0x1000080, + /** VVSYNC pin falling level interrupt. */ + GFVX_VVSYNC_FALLING_LEVEL_INTR = 0x1000100 + +} GFVX_INTERRUPT_TYPE; + +/** VxAPI related attributes. + @see GFVxGetAttribute() +*/ +typedef enum _GFVXATTRIBUTES +{ + /** VxAPI attribute: Video input interrupt status. + Use this attribute with GFVxGetAttribute() to read the current video + input interrupt status. + + Interpretation of associated attribute value: +
      +        NvU32 Bitmask with interrupt status
      +              For bitpositions see the VI status register in the GoForce
      +              technical manual (Register VI11 on SC12)
      +        
      + + Attribute is get only. + + @see GFVxGetAttribute() + */ + GFVX_ATTR_VIDEO_BUF, + + /** VxAPI attribute: Video VIP input status. + Use this attribute with GFVxGetAttribute() to read the current number + of frames received + */ + + GFVX_ATTR_VIP_INPUT_FRAME_COUNT, + + /** VxAPI attribute: Video VIP input status. + Use this attribute with GFVxGetAttribute() to read the current number + of lines received + */ + + GFVX_ATTR_VIP_INPUT_LINE_COUNT, + +} GFVXATTRIBUTES; + +/** YUV Color Space Conversion (CSC) coefficients. + Parameter structure for GFVxVIPSetCSCCoeff(), GFVxBltSetCSCCoeff(), + GFVxVIPGetCSCCoeff(), and GFVxBltGetCSCCoeff() + + YUV color space conversion is used when converting from a YUV formatted + surface to RGB formatted surface. The YUV color space conversion formular + appears as follows: + + R = sat(KYRGB*(Y + YOF) + KUR*U + KVR*V) + G = sat(KYRGB*(Y + YOF) + KUG*U + KVG*V) + B = sat(KYRGB*(Y + YOF) + KUB*U + KVB*V) + + By default, the YUV color space conversion coefficients are: + + KYRGB, KUR, KVR 1.1644 0.0000 1.5960 + KYRGB, KUG, KVG = 1.1644 -0.3918 -0.8130 + KYRGB, KUB, KVB 1.1644 2.0172 0.0000 + + and YOF = -16.0000 + + The value corresponding to each of these YUV color space conversion + coefficients is a Q16 (signed 15.16 fixed point value). + + For examples: + YOF = -16.0000, the value corresponding is 0xFFF00000 + KYRGB = 1.1644, the value corresponding is 0x00012A16 + KVR = 1.5960, the value corresponding is 0x00019893 + KUG = -0.3918, the value corresponding is 0xFFFF9BB3 + KVG = -0.8130, the value corresponding is 0xFFFF2FE0 + KUB = 2.0172, the value corresponding is 0x00020467 +*/ +typedef struct _GFVXCSCCOEF +{ + NvU32 YOF; + NvU32 KYRGB; + NvU32 KUR; + NvU32 KVR; + NvU32 KUG; + NvU32 KVG; + NvU32 KUB; + NvU32 KVB; +} GFVXCSCCOEF; + + +// Typesafe functions for opening and closing this component +GF_RETTYPE GFVxOpen(GFRmHandle hRm, GFVxHandle *phVx, + GF_STATE_TYPE state, GFRmChHandle hCh); +void GFVxClose(GFVxHandle *phVx); + +/** @name Functions +@{*/ + +/** This function returns version and capabilities of API and hardware. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pVXProp (#PGFPROPERTY) Pointer to property structure to be + filled in + + @retval #GF_SUCCESS \a pJXProp filled in successfully + @retval #GF_ERROR Some error occured + + This function returns information about the VxAPI, including the following: + - VxAPI module version + - VIP support + - Overlay support + - MPEG decoding and encoding + - JPEG decoding and encoding + + The #GFPROPERTY structure passed with parameter \a pVXProp will be + filled in on successfull return. The #GFPROPERTY::Capability field + will hold a combination of flagbits indicating capabilities specific + to the VxAPI: + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_CAP_CSCColor space conversion supported
      #GFVX_CAP_VIPVIP functions available
      #GFVX_CAP_ENLARGEEnlarge source image supported
      #GFVX_CAP_SHRINKShrink source image supported
      #GFVX_CAP_COLOR_CONTROLColor control supported
      #GFVX_CAP_OVERLAYOverlay supported
      #GFVX_CAP_MPEGDECMPEG4 decoder supported
      #GFVX_CAP_MPEGENCMPEG4 encoder supported
      #GFVX_CAP_JPEGDECJPEG decoder supported
      #GFVX_CAP_JPEGENCJPEG encoder supported
      #GFVX_CAP_ALPHA_BLENDAlpha blending supported
      #GFVX_CAP_EXTEND_RGBExtended RGB format 32 bpp supported
      #GFVX_CAP_OVERLAY_YUVYUV overlay supported
      #GFVX_CAP_OVERLAY_SCALEOverlay with scaling supported
      #GFVX_CAP_OVERLAY_MULTIPLEMultiple overlay supported
      #GFVX_CAP_ENCODE_TYPEVariable sized data camera interface (Type A/B/C) supported
      + + It is a good practice to call this function to query for the API version + and its capabilities before using the rest of the JxDecAPI functions. + + @see GFPROPERTY +*/ +GF_RETTYPE GFVxGetProperty(GFVxHandle VxHandle, PGFPROPERTY pVvProp); + +/** Stretch-blit rectangular area from source to destination surface. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pBlt (#PGFVXBLT) Pointer to #GFVXBLT structure + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function copies a rectangular area from a source surface to a + rectangle in the destination surface. If source and destination + rectangles differ in size, the GPU's stretch blit (SB) unit scales the + source data to fit the destination rectangle. If the source and destination + surfaces have different color formats, GFVxBlt() provides limited color + format conversions. + + Source and Destination surfaces have to be in GPU memory. Source surfaces + can be in YUV420, YUV422, or RGB565 format. Destination surfaces can be + in RGB565, RGB888 (SC12), or ARGB8888 (SC12 SC15) format. YUV output can also + be routed to EPP for encoding. + + Color format conversions from a YUV420 or YUV422 source are supported for these + destination formats: + - RGB565 + - ARGB8888 (SC12 SC15) + - RGB888 (SC12) + + A #GFVXBLT control structure is passed with parameter \a pBlt. + GFVXBLT::ppDestSurf points to an array of destination surface pointers, + with the number of pointers in this array specified by + GFVXBLT::numofDestSurf. GFVXBLT::ppSrcSurf points to an array of source + surface pointers, with the size of this array specified by + GFVXBLT::numofSrcSurf. + + When the destination surface pointer is NULL, output of SB goes + to EPP for encoding. + + See #GFVXBLT for minimum and maximum specifications of source and destination + rectangle sizes. + + Instant Blit Mode + + In this mode of operation, the blit is executed immediately via the command + FIFO. It is always performed from the first surface in GFVXBLT::ppSrcSurf + to the first surface in GFVXBLT::ppDestSurf. Other pointers in these + arrays are ignored. + + Auto Blit Mode + + VxBlt() can be used to enable auto-blit mode (flag #GFVX_AUTO_BLT + in GFVXBLT::BltOption). Whenever the end of a frame coming from VIP is + reached, SB will be fired automatically with the parameters set in GFVXBLT. + Auto-blit mode remains set until it is reset by another auto-blit command. + During auto-blit mode, manual SB commands should save and restore SB + registers (SC12 and below). This is not required for SC15 and above because + they have three hardware contexts: one for auto-blit, one for host trigger + (manual SB commands) and one for host partial trigger. + + The first time auto-blit is fired, the first surface in GFVXBLT::ppSrcSurf + is copied to the first surface in GFVXBLT::ppDestSurf. In subsequent blits, + the source and destination arrays are walked through subsequently. If + there is only one surface in the GFVXBLT::ppSrcSurf or GFVXBLT::ppDestSurf + arrays, only this one is used. + + Note that VxBlt() only sets auto-blit parameters. It is actually enabled by + GFVxVIPUpdate() using action #GFVX_VIP_AUTO_TRIGER_BLT, or GFMxDecSetMBs(). + + Auto Display + + If auto-display (#GFVX_AUTO_DISPLAY or #GFVX_AUTO_DISPLAY_OVERLAY2) is on, + GFVxBlt() automatically shows the destination surface on the screen. + The application does not need to call GFVxFlip() to show the surface. + Auto-display can be combined with both auto-blit and instant-blit modes. + + Color Keying + + If source color keying (#GFVX_BLT_SRC_KEY) is set, all pixels from the + source surface matching GFVXBLT::colorKey are transparent (not copied). + + VSync Synchronisation + + By default all blits are synchronized to display VSync. Note that blits + may block, if the display is disabled. Flag #GFVX_BLT_DISABLE_WAIT_VSYNC + can be used to disable VSync synchronisation. + + @see GFVXBLT +*/ +GF_RETTYPE GFVxBlt(GFVxHandle VxHandle, PGFVXBLT pBlt); + +/** Activate surface for display. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pFlip (#PGFVXFLIP) Pointer to #GFVXFLIP structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If ColorFormat is unsupported + + This function changes the display buffer address from one surface to + another. + + This function displays #GFVXFLIP::pForeGroundSurf. If + GFVXFLIP::pForeGroundSurf is an overlay surface, this function displays + that surface to the destination rectangle that has been set by + GFVxUpdateOverlay(). + + If GFVXFLIP::pForeGroundSurf is not an overlay surface, this function + displays the entire surface. In this case GFVxFlip() can show either the + primary surface or an offscreen surface on the display screen. + + If there is only one surface for primary or overlay, GFVxFlip() should not + be called. + + @see GFVXFLIP +*/ +GF_RETTYPE GFVxFlip(GFVxHandle VxHandle, PGFVXFLIP pFlip); + +/** Configure properties of overlay (WinB) display. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pOverlay (#PGFVXUPDATEOVERLAY) Pointer to #GFVXUPDATEOVERLAY structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_SURFACETYPE_NOT_SUPPORTED If Source SurfaceType is unsupported + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If Source ColorFormat is unsupported + @retval GFVX_ERROR_ILLEGAL_ALPHA_VALUE If Alpha Value is incorrect + + This function controls overlay (WinB) display, setting the following + features: + - Destination and source rectangle areas + - Rotation for overlay surface + - Color keying + - Alphablending Color Key (GoForce 4800 and above) + - Foreground and Background alpha values. (GoForce 4800 and above) + - Destination surface color format (RGB888, ARGB8888 for GoForce 4800 and + above) + + SC15 supports the following overlay surface orientations - 0 degree rotated, + 180 degree rotated, horizont flip, vertical flip. Overlay surface orientation + is always relative to the orientaton of primary surface. For eg. if primary + surface is 180 degree rotated and requested overlay surface orientation is + 0 degree rotated, then overlay surface will be 180 degree rotated. + + This function supports the following source surface type - GF_SURFACE_OVERLAY. + It supports the following source surface colorformats - RGB565, ARGB8888, ARGB1555, + ARGB4444. + + In order to work around a hardware bug in SC12, in which the GC displays + pixels at the end of the line that are 64 pixels back from the end of + the line, the overlay window width will be aligned to 4-pixels. + + If GFVXUPDATEOVERLAY::pSrcSurf is NULL then overlay display is disabled. + + This function will have no effect, if the GoForce media processor version + does not support overlays. This can be checked via the #GFVX_CAP_OVERLAY + attribute with GFVxGetProperty(). + + Color Keying + + With color keying pixels from the overlay surface can be masked (made + transparent). It can be enabled in different modes of operation by setting + one of the following flags in GFVXUPDATEOVERLAY::UpdateOption: + - #GFVX_UO_SRC_COLOR_KEY + - #GFVX_UO_DEST_COLOR_KEY + + The color key is passed in GFVXUPDATEOVERLAY::ColorKey. Refer to the flags' + documentation for details on modes of operation. + + An exotic color which does not conflict with other colors of a use-case + should be selected as the color key. Color keying for overlay display is + processed on the fly, no pixels in the surfaces are overwritten. + + If destination is in 1-bit alpha format (eg ARGB1555), application can + use two additional flags - #GFVX_UO_COLOR_KEY_ALPHA_ONLY and + #GFVX_UO_COLOR_KEY_ALPHA_COLOR. Refer to the flags' + documentation for details on modes of operation. + + Alpha Blending + + Overlay display with alpha blending can be enabled by setting + flag #GFVX_UO_ALPHA_BLENDING. + + Setting flag #GFVX_UO_ALPHA_BLENDING lets the overlay surface to appear + blended with the destination surface using the alpha value passed in + GFVXUPDATEOVERLAY::AlphaValue. Refer to the flags' documentation for details + on how to define AlphaVal. + + If destination is in 1-bit alpha format (eg ARGB1555), application can + use two additional flags - #GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY and + #GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR. Refer to the flags' + documentation for details on modes of operation. + + Just like overlay colorkey, an exotic color which does not conflict with + other colors of a use-case should be selected as the blending color key. + Blending is processed on the fly, no pixels in the surfaces are overwritten. + + If #GFVX_UO_DEST_COLOR_KEY is set, alpha blending enabled, and the + destination pixel color matches BlendingColorKey, the following equation + is used to generate the final pixel: +
      +    src * AlphaValue + dest * (1-AlphaValue)
      +    
      + Otherwise, the original pixel is not updated. + + Alpha blending is supported only on GoForce 4800 and above. + + SC15 supports alphablending with the following restriction - You cannot alpha-match + (alpha-blend) in non-key-match areas, at the same time you alpha-blend in key-match areas. + In other words, the following flag combinations will not work - + + #GFVX_UO_DEST_COLOR_KEY|#GFVX_UO_ALPHA_BLENDING|#GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY + #GFVX_UO_DEST_COLOR_KEY|#GFVX_UO_COLOR_KEY_ALPHA_COLOR|#GFVX_UO_ALPHA_BLENDING|#GFVX_UO_BLD_COLOR_KEY_ALPHA_ONLY + #GFVX_UO_DEST_COLOR_KEY|#GFVX_UO_COLOR_KEY_ALPHA_ONLY|#GFVX_UO_ALPHA_BLENDING + #GFVX_UO_DEST_COLOR_KEY|#GFVX_UO_COLOR_KEY_ALPHA_ONLY|#GFVX_UO_ALPHA_BLENDING|#GFVX_UO_BLD_COLOR_KEY_ALPHA_COLOR + + @see GFVXUPDATEOVERLAY +*/ +GF_RETTYPE GFVxUpdateOverlay(GFVxHandle VxHandle, + PGFVXUPDATEOVERLAY pOverlay); + +/** Feed image data from host to VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pImage (#PGFVXVIPFEEDIMAGE) Pointer to #GFVXVIPFEEDIMAGE parameter + structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If Source ColorFormat is unsupported + + This function feeds an image from the CPU host via the VI source FIFO to + the VIP. It supports YUV420, YUV422 (YUYV, YVYU, UYVY, VYUY), YUV422 planar and + Bayer (8, 12) formats. + + For an YUV420 image, it feeds Y-Fifo, U-Fifo, V-Fifo interleaved at 32 bit. + For an YUV422 image, it feeds the Y-Fifo only. + + This function is intended to be used for feeding YUV data to the JPEG + encoder, or for feeding input for VIP preview display (GFVxVIPSetVIP() + and GFVxVIPUpdate()). YUV data for MPEG encoding is fed with + GFMxEncFeedImage(). + + Parameter \a pImage passes a surface containing source image data and an + optional source clipping rectangle. Surface data has to reside in memory + accessible by the host CPU, e.g. a surface allocated as type + #GF_SURFACE_SYSTEM_MEMORY. + + @see GFVXVIPFEEDIMAGE, GFVX_VIP_HOST_IMAGE +*/ +GF_RETTYPE GFVxVIPFeedImage(GFVxHandle VxHandle, + PGFVXVIPFEEDIMAGE pImage); + +/** Setup partial feed image data from host to VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param colorFormat Color format of feed image surface + @param width Width of feed image + @param height Height of feed image + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_ILLEGAL_PARAMETER If width and height values are incorrect + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If color format of feed image surface is unsupported + + This function setups partial feed image from the CPU host via the VI source FIFO to + the VIP. It supports YUV420, YUV422 (YUYV, YVYU, UYVY, VYUY), YUV422 planar formats. + The partial image data is fed with + GFVxVIPPartialFeedImage(). + + @see GFVxVIPPartialFeedImage, GFVX_VIP_HOST_IMAGE +*/ +GF_RETTYPE GFVxVIPPartialFeedImageSetup(GFVxHandle VxHandle, + NvU32 colorFormat, + NvU32 width, + NvU32 height); + +/** Feed partial image data from host to VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pSrcSurf Pointer to source feed image surface + @param pSrcRect Pointer to a clip rectangle from source feed image surface + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_ILLEGAL_PARAMETER If pSrcSurf is NULL + + This function feeds a partial image from the CPU host via the VI source FIFO to + the VIP. It supports YUV420, YUV422 (YUYV, YVYU, UYVY, VYUY), YUV422 planar formats. + + For an YUV420 image, it feeds Y-Fifo, U-Fifo, V-Fifo interleaved at 32 bit. + For an YUV422 image, it feeds the Y-Fifo only. + + This function is intended to be used for feeding partial YUV data to the JPEG + encoder, or for feeding partial input for VIP preview display (GFVxVIPSetVIP() + and GFVxVIPUpdate()). YUV data for MPEG encoding is fed with + GFMxEncFeedImage(). + + Parameter \a pSrcRect is an optional source clipping rectangle. + Surface data has to reside in memory accessible by the host CPU, + e.g. a surface allocated as type + #GF_SURFACE_SYSTEM_MEMORY. +*/ +GF_RETTYPE GFVxVIPPartialFeedImage(GFVxHandle VxHandle, + PGFRMSURFACE pSrcSurf, + PGFRECT pSrcRect); + +/** Put video unit into sleep mode. + @param VxHandle (#GFVxHandle) Handle to VxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @note Not implemented by default, this function is intended to be + implemented only in GFSDK ports to platforms that are in need of + this feature. + + @see GFVxWakeup() +*/ +GF_RETTYPE GFVxSleep(GFVxHandle VxHandle); + +/** Wake up video unit from sleep mode. + @param VxHandle (#GFVxHandle) Handle to VxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + @note Not implemented by default, this function is intended to be + implemented only in GFSDK ports to platforms that are in need of + this feature. + + @see GFVxSleep() +*/ +GF_RETTYPE GFVxWakeup(GFVxHandle VxHandle); + +/** This function enumerates capabilities of the Video Input Port (VIP). + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pVIPProp (#PGFVXVIPPROPERTY) Pointer to #GFVXVIPPROPERTY structure + to be filled in + + @retval #GF_SUCCESS \a pVIPProp filled in successfully + @retval #GF_ERROR Some error occured + + The #GFPROPERTY structure passed with parameter \a pVIPProp will be + filled in on successfull return. + + The following GoForce VIP features are described by this function: + - Image decimation (scaling) limits + - Image flipping + - Video input interface type + + Parameters that are passed with a #GFVXVIPINFO structure to GFVxVIPSetVIP() + must be within the limits returned by this function. + + @see GFVXVIPPROPERTY, GFVxVIPSetVIP(), GFVXVIPINFO +*/ +GF_RETTYPE GFVxVIPGetProperty(GFVxHandle VxHandle, + PGFVXVIPPROPERTY pVIPProp); + +/** Configure video input to VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pVIPInfo (#PGFVXVIPINFO) Pointer to GFVXVIPINFO parameter structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_ILLEGAL_BAYER_VALUES If values in BayerInfo structure are incorrect + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If Source ColorFormat is unsupported + + The following VIP properties can be configured using this function, see + #GFVXVIPINFO for details: + - Data source and format (CPU host or video input) + - VIP input cropping rectangle + - Image decimation + - Input (camera) color format + + After configuring video input, the flow of data has to be explicitly + enabled with GFVxVIPUpdate(). + + See GFVxVIPGetProperty() for how to test for VIP capabilities at runtime. + + This function returns GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED error if color format + is not supported. Supported color formats for HOST input are - YUV422, YUV422 Planar, + YUV420 and Bayer (8 and 12). YUV420 is not supported if input source is VIP. + + @see GFVXVIPINFO, GFVxVIPUpdate(), GFVxVIPGetProperty() +*/ +GF_RETTYPE GFVxVIPSetVIP(GFVxHandle VxHandle, + PGFVXVIPINFO pVIPInfo); + +/** Enable or disable video feeding through VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param pUpdate (#GFVXVIPUPDATE) Pointer to a #GFVXVIPUPDATE structure + + @retval #GF_SUCCESS Success + @retval GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED If Source ColorFormat is unsupported + + This function enables or disables data feeding through VIP after it has + been configured with GFVxVIPSetVIP(). + + The action to be performed by this function is defined by the action + identifier passed in GFVXVIPUPDATE::UpdateOption of parameter \a pUpdate. + + + + + + + + + + + + + + + + + + +
      #GFVX_VIP_START + Enable VIP data feeding + + The structure passed via \a pUpdate controls the output of the VIP, setting + the following parameters: + - Destination surface(s) (single or double buffered) + - Top-left corner the output video is written to the destination surfaces + + GFVXVIPUPDATE::ppSurf passes an array of 1 or 2 destination surfaces to + capture the incoming video stream. If 2 surfaces are passed, the VIP target + surface is flipped after each frame of VIP input if #GFVX_VIP_AUTO_FLIP or + #GFVX_VIP_AUTO_FLIP_OVERLAY2 flag is specified. + + Color space conversion (CSC) is performed depending on the output surface + color formats: + - #GF_SURFACE_RGB565 (16 bpp): VI CSC is used. + - #GF_SURFACE_ARGB8888 (32 bpp): VI CSC is used, only available for SC12 + and above + - #GF_SURFACE_YUV422: (32 bits per two pixels): No CSC is used, data from + the VIP is stored as is in memory + - any other format is considered to be YUV422, and the data is stored as is + + If GFVXVIPUPDATE::ppSurf is NULL, data flow through the VIP is still enabled. + Data from the VIP is not written to target surfaces, but is is fed to the + MPEG or JPEG encoder pre-processor. This mode of operation is useful for the + following two cases: + - There is not enough memory for JPEG encoding. The application could turn + off the screen, enable this mode, and let the JPEG encoder utilize screen + memory (the primary surface). + - In single-shot mode, the application does not want to display the video + image on the screen after enabling the JPEG encoder, thus allowing faster + captures and power savings, and freeing bandwidth. After the image is + captured, the application enables the JPEG decoder to decode the captured + image and shows it on the screen. +
      #GFVX_VIP_AUTO_FLIP + Enable VIP data feeding with auto-display + + Behaviour is identical to #GFVX_VIP_START, additionally auto-display of the + last captured VIP frame is enabled. It is recommended to use this feature + in double buffer mode, passing 2 surfaces in GFVXVIPUPDATE::ppSurf. +
      #GFVX_VIP_AUTO_FLIP_OVERLAY2 + Enable VIP data feeding with auto-display from overlay window2 + + If surfaces to be flipped are overlay surfaces, they are associated with + first overlay surface unless #GFVX_VIP_AUTO_FLIP_OVERLAY2 flag is defined. + This flag should be used only if UpdateOverlay has been previously called + with #GFVX_UO_OVERLAY2 UpdateOption and VxFlip has been called with + #GFVX_FLIP_OVERLAY2 FlipOption. + +
      #GFVX_VIP_AUTO_TRIGER_BLT + Enable VIP data feeding with auto-blit + + Behaviour is identical to #GFVX_VIP_START, additionally auto-blit of the + last captured VIP frame is enabled. It is recommended to use this feature + in double buffer mode, passing 2 surfaces in GFVXVIPUPDATE::ppSurf. + + If #GFVX_VIP_AUTO_FLIP and #GFVX_VIP_AUTO_TRIGER_BLT are required at the + same time, these two action identifiers can be logically OR'ed and passed + in GFVXVIPUPDATE::UpdateOption. +
      #GFVX_VIP_STOP + Disable VIP data feeding + + Stop data feeding through VIP. All other flags and parameters passed in + \a pUpdate are ignored. +
      #GFVX_VIP_AUTO_TRIGER_BLT_OFF + Disable VIP auto-blit + + Stop auto-blit that has been enabled earlier with this function via + #GFVX_VIP_AUTO_TRIGER_BLT. This does not disable VIP data feed. +
      + + This function returns GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED error if destination + surface color format is not supported. Supported destination color formats are - + RGB565, ARGB8888, YUV422, YUV422P, YUV420P and YUV420PA. + + @see GFVXVIPUPDATE, GFVxVIPSetVIP() +*/ +GF_RETTYPE GFVxVIPUpdate(GFVxHandle VxHandle, + PGFVXVIPUPDATE pUpdate); + +/** Manipulate GPIO signals on VIP. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param gpio (#GFVX_VIP_GPIO_TYPE) Signal (pin) to manipulate + @param operation (NvU32) Operation type, one of: + + + + + + + + + + + + + + + + + + Get output data. +
      #GF_GPIO_SET_INPUT_ENABLEInput enable set to 1
      #GF_GPIO_CLR_INPUT_ENABLEInput enable clr to 0.
      #GF_GPIO_GET_INPUT_ENABLEGet input enable.
      #GF_GPIO_SET_OUTPUT_ENABLEOutput enable set to 1.
      #GF_GPIO_CLR_OUTPUT_ENABLEOutput enable clr to 0.
      #GF_GPIO_GET_OUTPUT_ENABLEGet output enable.
      #GF_GPIO_SET_DATAOutput data set to 1.
      #GF_GPIO_CLR_DATAOutput data clr to 0.
      #GF_GPIO_GET_DATA
      + @param pGPIOStatus (#PGFGPIOSTATUS) Pointer to #GFGPIOSTATUS structure + returning pin status + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + This function manipulates the GPIO signals on the video input port (VIP). + The supported operations are clearing to 0, setting to 1, and getting the + status of the input enable, output enable, and data bits. + + @see GFGPIOSTATUS, GFVX_VIP_GPIO_TYPE +*/ +GF_RETTYPE GFVxVIPGPIO(GFVxHandle VxHandle, + GFGPIOPin gpio, + NvU32 operation, + PGFGPIOSTATUS pGPIOStatus); + +/** VxAPI component-level interrupt control. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param IntType (#GFVX_INTERRUPT_TYPE) VxAPI interrupt type + @param op (#GFVX_INTERRUPT_OPERATION_TYPE) VxAPI interrupt operation + @param pData (void*) Pointer to input or output data block, depending + on interrupt type and operation + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + @retval #GFVX_ERROR_NO_SUPPORT Operation not supported + + Interpretation of the datablock passed with \a pData depends on the + interrupt operation. The following operations (parameter op) + are defined for this call, + + + + + + + + + + + + + + + + + + + + + + + + + + +
      #GFVX_INTERRUPT_ENABLEEnable interrupt/status assertion for interrupt type \a IntType. + \a pData is ignored. +
      #GFVX_INTERRUPT_DISABLEDisable interrupt/status assertion for interrupt type \a IntType. + \a pData is ignored. +
      #GFVX_INTERRUPT_DISABLEClear interrupt/status assertion for interrupt type \a IntType. + \a pData is ignored. +
      #GFVX_INTERRUPT_QUERY_STATUSQuery for interrupt/status assertion for interrupt type \a IntType. + + Interpretation of associated data block \a pData: +
      +        NvU32 Interrupt/status assertion state, one of:
      +              GF_INTERRUPT_ON_STATUS_TRUE = asserted
      +              GF_INTERRUPT_ON_STATUS_FALSE = not asserted
      +        
      +
      #GFVX_INTERRUPT_SET_Y_FIFO_THRESHOLD,
      + #GFVX_INTERRUPT_GET_Y_FIFO_THRESHOLD +
      Set or get DMA FIFO threshold value that controls interrupt/status + assertion for interrupt type #GFVX_Y_FIFO_THRESHOLD_INTR. If the + number of filled locations in the Y-FIFO is greater or equal + than the programmed value, #GFVX_Y_FIFO_THRESHOLD_INTR is asserted. + Note that the threshold value must not be changed within a frame. + + Parameter \a IntType is ignored. + + Interpretation of associated data block \a pData: +
      +        NvU32 Y-FIFO threshold value in range 0..31
      +        
      +
      #GFVX_INTERRUPT_SET_V_COUNTER_THRESHOLD,
      + #GFVX_INTERRUPT_GET_V_COUNTER_THRESHOLD +
      Set or get threshold value that controls interrupt/status assertion + for interrupt type #GFVX_VERTICAL_COUNTER_THRESHOLD_INTR. If the + vertical scanline position for data from parallel video input is + greater or equal than the programmed value, + #GFVX_VERTICAL_COUNTER_THRESHOLD_INTRis asserted. + + Parameter \a IntType is ignored. + + Interpretation of associated data block \a pData: +
      +        NvU32 Vertical counter threshold value in range 0..4095
      +        
      +
      #GFVX_INTERRUPT_GET_ALL_STATUSGet VI interrupt status bitmask. + + Parameter \a IntType is ignored. + + Interpretation of associated data block \a pData: +
      +        NvU32 Interrupt status bitmask,
      +              Logically OR'ed combination of:
      +              #GFVX_VID0PIN_RISING_EDGE_INTR
      +              #GFVX_VID1PIN_RISING_EDGE_INTR
      +              #GFVX_VID2PIN_RISING_EDGE_INTR
      +              #GFVX_VID3PIN_RISING_EDGE_INTR
      +              #GFVX_VID4PIN_RISING_EDGE_INTR
      +              #GFVX_VID5PIN_RISING_EDGE_INTR
      +              #GFVX_VID6PIN_RISING_EDGE_INTR
      +              #GFVX_VID7PIN_RISING_EDGE_INTR
      +              #GFVX_VERTICAL_COUNTER_THRESHOLD_INTR
      +              #GFVX_VHSYNC_RISING_INTR
      +              #GFVX_VVSYNC_RISING_INTR
      +              #GFVX_VIDEO_IN_FIELD_DATA_RECV_INTR
      +              #GFVX_EARLY_VIDEO_INTR
      +              #GFVX_Y_FIFO_THRESHOLD_INTR
      +        
      +
      #GFVX_INTERRUPT_CLEAR_ON_ALL_STATUSClear VI interrupt assertions. + + Parameter \a IntType is ignored. + + Interpretation of associated data block \a pData: +
      +        NvU32 Interrupt status bitmask,
      +              set bit   = clear this interrupt assertion
      +              unset bit = leave unchanged
      +
      +              Valid bits which can be logically OR'ed:
      +              #GFVX_VID0PIN_RISING_EDGE_INTR
      +              #GFVX_VID1PIN_RISING_EDGE_INTR
      +              #GFVX_VID2PIN_RISING_EDGE_INTR
      +              #GFVX_VID3PIN_RISING_EDGE_INTR
      +              #GFVX_VID4PIN_RISING_EDGE_INTR
      +              #GFVX_VID5PIN_RISING_EDGE_INTR
      +              #GFVX_VID6PIN_RISING_EDGE_INTR
      +              #GFVX_VID7PIN_RISING_EDGE_INTR
      +              #GFVX_VERTICAL_COUNTER_THRESHOLD_INTR
      +              #GFVX_VHSYNC_RISING_INTR
      +              #GFVX_VVSYNC_RISING_INTR
      +              #GFVX_VIDEO_IN_FIELD_DATA_RECV_INTR
      +              #GFVX_EARLY_VIDEO_INTR
      +              #GFVX_Y_FIFO_THRESHOLD_INTR
      +        
      +
      + + @see GFVX_INTERRUPT_TYPE, GFVX_INTERRUPT_OPERATION_TYPE, + GFVxInterruptHandler() +*/ +GF_RETTYPE GFVxInterruptControl(GFVxHandle VxHandle, + GFVX_INTERRUPT_TYPE IntType, GFVX_INTERRUPT_OPERATION_TYPE op, + void * pData); + +/** Get information about a feature of the VxAPI. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + @param aid (NvU32) Attribute type identifier, see table. + @param pAttr (NvU32*) Returns 32 bit attribute value, see attribute + type documentation for interpretation + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + + + + + + + + +
      \b Attribute \b Direction \b Synopsis
      #GFVX_ATTR_VIDEO_BUFgetVideo input interrupt status
      + + @see GFVxSetAttribute() +*/ +GF_RETTYPE GFVxGetAttribute(GFVxHandle VxHandle, NvU32 aid, NvU32 *attr); + +/** Reset VI to a reset state. + + @param VxHandle (#GFVxHandle) Handle to VxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +GF_RETTYPE GFVxReset(GFVxHandle); + +/** This function waits until the next camera vsync has occurred. + It is implemented with interrupt mode. Therefore, it assumes that + interrupt platform has already supported or taken care, + otherwise it will wait forever for interrupt event + + @param VxHandle (#GFVxHandle) Handle to VxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured +*/ +GF_RETTYPE GFVxWaitCameraVSync(GFVxHandle); + +/** This function ensures synchronization between StretchBlt operations and others + modules operations. + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + When several modules share the same channel (like SB,JxDec,MxDec), + it may be necessary to synchronize the command flow with the StretchBlt (SB) + module execution. Putting a GFVxBltNotBusy() call after a SB operation ensures + that commands which follow the SB command are executed after full completion + of the SB command. + + As opposed to GFVxBltWaitNotBusy(), this function doesn't block the CPU thread. + stretchblt engine may not be idle when returning from the function. Control returns + to the CPU right after a wait command is placed in the stretchblt engine command FIFO. + The GoForce hardware begins executing the commands following the StretchBlt engine idle + command only after the stretchblt engine becomes idle. + + @see GFVxBltWaitNotBusy() +*/ +GF_RETTYPE GFVxBltNotBusy(GFVxHandle VxHandle); + +/** This function checks whether the stretchblt engine is busy or idle. + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + + The function will wait until the stretchblt engine is idle. For example, if you want + to stretchblt to the frame buffer but the stretchblt engine is busy the function can + be used to wait until it is idle. + + As opposed to GFVxBltNotBusy(), this function blocks the CPU thread while waiting for + the stretchblt engine to become idle. + + @see GFVxBltNotBusy() + +*/ +GF_RETTYPE GFVxBltWaitNotBusy(GFVxHandle VxHandle); + +/** This function sets the current state stretchblt color space converion (CSC) + coefficients that will be programmed to GPU after calling GFVxBlt to do + YUV color space conversion to RGB. + How to use this routine: + - GFVxBltGetCSCCoeff() to get default YUV CSC coefficients, save them + - GFVxBltSetCSCCoeff() to change to new YUV CSC coefficients + - GFVxBlt() to stretchblt image with your new YUV CSC coefficients to RGB, + then done whatever + - GFVxBltSetCSCCoeff() to restore back default YUV CSC coefficients + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + @param pCoef (GFVXCSCCOEF*) Pointer to #GFVXCSCCOEF structure + @param option (NvU32) Option type, one of: +
      +                - #GFVX_SET_CSC_USE_CCIR601_RANGE -- Use CCIR601 range.
      +                  This option will ignore parameter pCoef. It will use
      +                  pre-defined CSC CCIR601 coefficients values.
      +                - #GFVX_SET_CSC_USE_FULL_RANGE -- Use color full range.
      +                  This option will ignore parameter pCoef. It will use
      +                  pre-defined CSC full range coefficients values.
      +                - #GFVX_SET_CSC_USE_USER_DEFINED_RANGE -- Use user defined range.
      +                  This option will require parameter pCoef. It will use
      +                  CSC coefficients values provided from pCoef.
      +                
      + @param sbMode (#GFVXBLTMODE) StretchBlt mode, one of: +
      +                - GFVX_BLT_FULL_MODE: Host full frame stretchblt trigger
      +                - GFVX_BLT_PARTIAL_MODE: Host partial frame stretchblt trigger
      +                - GFVX_BLT_AUTO_VI_MODE: Auto stretchblt trigger from VI
      +                
      + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFVxBltSetCSCCoeff(GFVxHandle VxHandle, + GFVXCSCCOEF *pCoef, + NvU32 option, + GFVXBLTMODE sbMode); + +/** This function sets the current state VI color space converion (CSC) + coefficients that will be programmed to GPU after calling GFVxVIPUpdate + to do YUV color space conversion to RGB. + How to use this routine: + - GFVxVIPGetCSCCoeff() to get default YUV CSC coefficients, save them + - GFVxVIPSetCSCCoeff() to change to new YUV CSC coefficients + - GFVxVIPUpdate() to preview image with your new YUV CSC coefficients to RGB + - GFVxVIPSetCSCCoeff() to restore back default YUV CSC coefficients + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + @param pCoef (#GFVXCSCCOEF*) Pointer to #GFVXCSCCOEF structure + @param option (NvU32) Option type, one of: +
      +                - #GFVX_SET_CSC_USE_CCIR601_RANGE -- Use CCIR601 range.
      +                  This option will ignore parameter pCoef. It will use
      +                  pre-defined CSC CCIR601 coefficients values.
      +                - #GFVX_SET_CSC_USE_FULL_RANGE -- Use color full range.
      +                  This option will ignore parameter pCoef. It will use
      +                  pre-defined CSC full range coefficients values.
      +                - #GFVX_SET_CSC_USE_USER_DEFINED_RANGE -- Use user defined range.
      +                  This option will require parameter pCoef. It will use
      +                  CSC coefficients values provided from pCoef.
      +                
      + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFVxVIPSetCSCCoeff(GFVxHandle VxHandle, GFVXCSCCOEF *pCoef, NvU32 option); + +/** This function gets the current state stretchblt color space conversion (CSC) + coefficients + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + @param pCoef (#GFVXCSCCOEF*) Pointer to #GFVXCSCCOEF structure + @param sbMode (#GFVXBLTMODE) StretchBlt mode, one of: + - GFVX_BLT_FULL_MODE: Host full frame stretchblt trigger + - GFVX_BLT_PARTIAL_MODE: Host partial frame stretchblt trigger + - GFVX_BLT_AUTO_VI_MODE: Auto stretchblt trigger from VI + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFVxBltGetCSCCoeff(GFVxHandle VxHandle, GFVXCSCCOEF *pCoef, GFVXBLTMODE sbMode); + +/** This function gets the current state VI color space conversion (CSC) coefficients + + @param VxHandle (#GFVxHandle) Handle to GFVxAPI + @param pCoef (#GFVXCSCCOEF*) Pointer to #GFVXCSCCOEF structure + + @retval #GF_SUCCESS Success + @retval #GF_ERROR Some error occured + +*/ +GF_RETTYPE GFVxVIPGetCSCCoeff(GFVxHandle VxHandle, GFVXCSCCOEF *pCoef); + +/** @page pageVxOverview VxAPI Overview + + The GFVxAPI is an abstraction layer for both the Video Scalar (StretchBlt) + and the Video Input (VI) module. The Video Scalar provides color space + conversion (CSC) and smooth scaling of video. The VI module, which connects + to the Video Input Port (VIP), accepts data from the VIP or the host CPU + through a FIFO mechanism. + + Video data, either decimated or not, can be sent from the VI to JPEG or + MPEG encoder, and at the same time can go to memory through CSC for previewing, + again either decimated or not. If a decimator is used in both the preview and + the encoder paths, it has to have same decimation factor. + + Video data can also be sent to EPP. RGB565, RGB444 and RGB888 data goes directly + and YUV422 data, pre or post decimated, is first converted to YUV444 by VI + before sending to EPP. + + If data coming from VIP is in Bayer format, VI first sends this data to ISP. + After processing, ISP returns YUV444 data to VI. VI converts output of ISP to + YUV422 before sending it to core for decimation or to memory or both. + + There are also options to crop, mirror and/or flip video data. + + The Video Scalar and the VI module accept YUV (4:2:2 or 4:2:0) and + RGB (565) data as input. YUV data can be converted to YUV planar data or + RGB data (RGB:565 for all processors, and RGB:888 or ARGB:8888 for GoForce + 3D 4800). RGB data can be scaled, but cannot be converted to YUV, for all + processors up to the GoForce 3D 4800. + + @section pageVxOverview1 Video Sources + + The video source for the VI module can be the host CPU or a camera + connected to the VIP. The video source for the Video Scalar can be the + video memory surface or the output of the JPEG or MPEG decoder through a + circular buffer. The GFVxAPI functions that deal only with the VIP have VIP + in their function names. + + @section pageVxOverview2 Video Camera Interface + + Usually a video camera connected through the VIP generates YUV 422 data + (CCIR656 format) which can be encoded by the NVIDIA GPU. Some cameras + generate JPEG-encoded images directly, and the GFSDK can be configured to + accept those JPEG-encoded bit streams. + + To control the JPEG input stream, VIP of newer NVIDIA GPUs supports the + following camera interface protocols for variably sized bitstream data: + - Type A interface: VHSync and VVSync length can be variable, and + VVClk should be kept running. (SC12 only) + - Type B interface: VHSync and VVSync length can be variable, and + VVClk can be stopped during the image transfer period. (SC12 only) + - Type C interface: VHSync and VVSync length are fixed, and VVClk + should be kept running. The camera can insert 0xff in the image as + padding. + + @section pageVxOverview3 Video Coordinate Systems (Regular and Rotated) + + A destination coordinate is always the same as a screen coordinate. The + source coordinate stays the same, even if there is rotation. +*/ + +/** @page pageVxAppNotes VxAPI Application Notes + + @section pageVxAppNotes1 Programming Sequence + + The easiest way to learn the VxAPI is by referring to the demonstration + application source code that come with the GFSDK package. A new application + can be started by creating a project at the same directory level as the + demo application source directory. This way the same directory tree + structure can be maintained. The general sequence for programming the + VxAPI is as follows: + + -# Make sure that the build project or file has the right paths to the + library and header files. Use relative directory addressing if possible. + The GFSDK/Inc directory must be included. + -# Include GFVx.h in the source file. This header is all that is needed to + access the exposed API functions. + -# Call GFRmOpen() before any other GFSDK functions (including the VxAPI). + -# Use the handle returned from the Resource Manager in the previous step + to call GFRmComponentGet() with #GF_VXAPI as the ComponentType in the + #GFRMCOMPONENT structure. The returned handle is the one to use + throughout all VxAPI calls. + -# To better utilize VxAPI functions, it is a good idea to call + GFVxGetProperty() to determine the version that you are using and the + available video memory. + -# Make calls to the appropriate VxAPI functions. Always remember to pass + the same #GFVxHandle returned from GFRmComponentGet(). + -# When all the VxAPI calls are completed, call GFRmComponentRelease(). + -# When exiting the application, call RmClose() to release everything + associated with the GFSDK. +*/ + +//////////////////Raw Capture Defination ////////////////////////// +/** Descriptor for raw data fetch buffers. + This structure describes a buffer and its fill status for Raw YUV transfered + from RDMA to the application. + It is used with GFVxRawCapture() and GFVxRawCaptureFetchImage() + in either polling or callback data fetch mode. + + @see GFVxCapture(), GFVxRawCaptureFetchImage() +*/ +typedef struct _GFVX_BUF { + NvU8 *pBuf; /**< Pointer to the buffer */ + NvU32 bufSize; /**< Size of the buffer in bytes */ + NvU32 nBytesCaptured; /**< Number of bytes captured, + app initializes to 0 + */ +} GFVX_BUF, *PGFVX_BUF; + + +/** Image source/target dimensions and data source for Raw data capturing. + + This structure is passed as parameter to GFVxRawCaptureStart() and describes + data source, source cropping rectangle and destination image size. + + @see GFVxRawCaptureStart() +*/ +typedef struct _GFVXRAWINFO +{ + PGFRMSURFACE pSrcSurf;/**< Surface to encode, + NULL for camera. + */ + PGFRECT pSrcRect; /**< Source image area need to capture */ + NvU32 DestWidth; /**< Final output data width */ + NvU32 DestHeight; /**< Final output data height */ + NvU32 uiOptions; /**< Bitmask of flags to control capturing + +
      + */ + NvU32 Error; /**< Returns detailed error code on GFVxRawCaptureStart() failure + + + + + + + +
      #GF_CAPT_ERROR_VIDEO_MEMORY_NOT_BIG_ENOUGHNot enough free video memory, try to release + unnecessary video surfaces
      #GF_CAPT_ERROR_WRONG_CONFIGWrong input parameters, for example srcRect + size greater than pSrcSurf dimensions
      #GF_CAPT_ERROR_NO_CALLBACKNo callback function available
      + */ + NvU32 colorFormat; +} GFVXRAWINFO, *PGFVXRAWINFO; + +/** GFVXRAWINFO uiOptions: +*/ +#define RAWCAPTURE_ATTR_RAW_DATA 0x00000010 +#define RAWCAPTURE_ATTR_RAW_JPEG_CAPTURE 0x00000020 +#define RAWCAPTURE_ATTR_RAW_DATA_STREAM 0x00000030 + +/** Raw data capture APIs +*/ +GF_RETTYPE GFVxRawCaptureStart( GFVxHandle VxHandle, + PGFVXRAWINFO pStart); + +GF_RETTYPE GFVxRawCaptureSetupInterrupt(GFVxHandle VxHandle, + void (*Inter)(void *), void *IPara); + +GF_RETTYPE GFVxRawCapture (GFVxHandle VxHandle, + PGFVX_BUF aBuf, NvU32 nBuf, NvU32 *pStatus ); + +GF_RETTYPE GFVxRawCaptureFetchImage (GFVxHandle pVx, + PGFVX_BUF aBuf, NvU32 nBuf, NvU32 *pStatus ); + +GF_RETTYPE GFVxRawCaptureEnd( GFVxHandle pVx ); + +//uiFrameStatus; + +/** Raw Capture data fetch status code: All data of the current frame was fetched. + @see GFVxRawCaptureFetchImage(), GFVxRawCapture() +*/ +#define RAWCAPTURE_DATA_COMPLETE 0x1 + +/** Raw Capture data fetch status code: Data was fetched only partially. + The application should make more calls to GFVxRawCaptureFetchImage() to fetch + the rest. + @see GFVxRawCaptureFetchImage(), GFVxRawCapture() +*/ +#define RAWCAPTURE_MORE_FETCH 0x2 + +/** Raw Capture data fetch status code: New frame was captured and is ready to + fetch. + @see GFVxRawCaptureFetchImage(), GFVxRawCapture() +*/ +#define RAWCAPTURE_NEW_FRAME 0x8 + +/** Raw Capture data fetch status code: Time out error occured while output data is fetching. + fetch. + @see GFVxRawCaptureFetchImage(), GFVxRawCapture() +*/ +#define RAWCAPTURE_TIME_OUT 0x10 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GFVX_H__ */ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVxError.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVxError.h new file mode 100755 index 00000000..7f81f255 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVxError.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file GFVxError.h + GFVxAPI error codes +*/ + +#ifndef __GFVXERROR_H__ +#define __GFVXERROR_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define GFVX_ERROR_GET_COMPONENT (GFVX_ERROR | 0x00000001L) +/** GFVxAPI error code: Function not supported. */ +#define GFVX_ERROR_NO_SUPPORT (GFVX_ERROR | 0x00000002L) +#define GFVX_ERROR_COLORFORMAT_NOT_SUPPORTED (GFVX_ERROR | 0x00000003L) +#define GFVX_ERROR_SURFACETYPE_NOT_SUPPORTED (GFVX_ERROR | 0x00000004L) +#define GFVX_ERROR_ILLEGAL_ALPHA_VALUE (GFVX_ERROR | 0x00000005L) +#define GFVX_ERROR_ILLEGAL_BAYER_VALUES (GFVX_ERROR | 0x00000006L) +#define GFVX_ERROR_ILLEGAL_PARAMETER (GFVX_ERROR | 0x00000007L) +#define GFVX_ERROR_DRIVER_NOT_SUPPORTED (GFVX_ERROR | 0x00000008L) +#define GFVX_ERROR_FLAG_NOT_SUPPORTED (GFVX_ERROR | 0x00000009L) +#define GFVX_ERROR_FAIL_ALLOCATE_MEMORY (GFVX_ERROR | 0x0000000AL) +#define GFVX_ERROR_ILLEGAL_VALUE (GFVX_ERROR | 0x0000000BL) + +#ifdef __cplusplus +} +#endif + +#endif // __GFVXERROR_H__ + + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVxScr.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVxScr.h new file mode 100755 index 00000000..394a33ef --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/GFVxScr.h @@ -0,0 +1,311 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#if !defined (__GFVXSCR_INC__) +#define __GFVXSCR_INC__ + +/** VxAPI GFVXVIPINFO::Flag flagbit: 8-bit/clock video data. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_PARALLEL_INPUT 0x00000001 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Serial input. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_SERIAL_INPUT 0x00000002 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VHSYNC and VVSYNC in the data stream. + If this flag is set, vertical and horizontal sync for the camera picture + is contained in the data stream going into the data port of the VIP. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_HVSYNC_IN_STREAM 0x00000004 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Camera VHSYNC asserted by external signal. + If this flag is set, vertical and horizontal sync for the camera picture + is asserted to the GoForce chip by external signals, usually coming from + the camera chip. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_EXTERNAL_VHSYNC 0x00000008 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Camera VHSYNC generated by GoForce chip. + If this flag is set, vertical and horizontal sync is generated by the + GoForce chip, and not contained in the data stream. The following members + of GFVXVIPINFO have to be set to define the timing: + - GFVXVIPINFO::VHPulseWidth + - GFVXVIPINFO::VHPulsePeriod + - GFVXVIPINFO::VVPulseWidth + - GFVXVIPINFO::VVPulsePeriod + - GFVXVIPINFO::VVDelay + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_INTERNAL_VHSYNC 0x00000010 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VCLK generated externally. + If this flag is set, camera VCLK is provided from an external source, + and VLCK will be selected as clock source for VI module. + @see GFVXVIPINFO, GFVxVIPSetVIP(), GFVX_VIP_EXTERNAL_VCLK_PRESERVE_CLKSEL +*/ +#define GFVX_VIP_EXTERNAL_VCLK 0x00000020 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VCLK generated by GoForce chip. + If this flag is set, camera VCLK is provided by the GoForce chip. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_INTERNAL_VCLK 0x00000040 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Detect field 0 or 1, will not work for + internal VHSYNC (#GFVX_VIP_INTERNAL_VHSYNC). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_DETECT_FIELD 0x00000080 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Horizontal flip. + Flip VIP image horizontally. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB_H_FLIP 0x00000100 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Vertical flip. + Flip VIP image vertically. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB_V_FLIP 0x00000200 + +/** VxAPI GFVXVIPINFO::Flag flagbit: CPU feeds image to VIP. + This flag indicates to the VIP, that image data is fed from the + host interface. + @see GFVXVIPINFO, GFVxVIPSetVIP(), GFVxVIPFeedImage() +*/ +#define GFVX_VIP_HOST_IMAGE 0x00000400 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Change the default timing for VHSYNC and + VCLK. If this flag is set, VHSYNC and VCLK timing characteristics such as + polarity, active edge, serial frame polarity, size, field info are + overridden with GFVxVIPSetVIP() by the parameters passed in + GFVXVIPINFO::NewTiming. + + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_CHANGE_DEFAULT_TIMING 0x00000800 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Camera master clock provided by GoForce + chip. When this flag is set, GFVXVIPINFO::MClockFreq must be set to the + ideal clock which the camera wants. Internally the best matching frequency + is provided to the camera. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ASK_FOR_MCLOCK 0x00001000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VIP input type A interface. + @see GFVXVIPINFO, GFVxVIPSetVIP(), pageVxOverview2 +*/ +#define GFVX_VIP_TYPE_A 0x00002000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VIP input type B interface. + @see GFVXVIPINFO, GFVxVIPSetVIP(), pageVxOverview2 +*/ +#define GFVX_VIP_TYPE_B 0x00004000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VIP input type C interface. + @see GFVXVIPINFO, GFVxVIPSetVIP(), pageVxOverview2 +*/ +#define GFVX_VIP_TYPE_C 0x00008000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Camera is running at type C interface + and do not remove the 0xFF, 0x02 sequence. + @see GFVXVIPINFO, GFVxVIPSetVIP(), pageVxOverview2 +*/ +#define GFVX_VIP_TYPE_C_RAW 0x00010000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Enable destination byte swap for YUV/RGB + data written to preview surface. + + This flag enables byte swap for 32 bit words of data coming from VIP and + going to a target RGB or YUV422 surface. The sequence of 4 byte groups in + (LSB)b0 b1 b2 b3(MSB) order is swapped to + (LSB)b1 b0 b3 b2(MSB). + + This flag only affects data written to a preview surface, i.e. VIP image + capture enabled with GFVxVIPSetVIP() and GFVxVIPUpdate(). It does not + affect raw data going to the JPEG/MPEG encoder. + + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_DEST_BYTE_SWAP 0x00020000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VI output without rotation + Rotate VIP image 0 degree + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ROTATE_0 0x00040000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VI output with 90 degree rotation + Rotate VIP image 90 degree + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ROTATE_90 0x00080000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VI output with 180 degree rotation + Rotate VIP image 180 degree + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ROTATE_180 0x00100000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VI output with 270 degree rotation + Rotate VIP image 270 degree + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_ROTATE_270 0x00200000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: RGB565 input to EPP. + @todo clarify + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB565 0x00400000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: RGB888 input to EPP. + @todo clarify + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB888 0x00800000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: RGB444 input to EPP. + @todo clarify + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_RGB444 0x01000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Preserve VI clock source but enable external VLCK pad. + This flag can be used in combination with GFVX_VIP_EXTERNAL_VCLK to enable + an external clock on VLCK, but keep the VI module clocksource. + @version SC15 and above + @see GFVXVIPINFO, GFVxVIPSetVIP(), GFVX_VIP_EXTERNAL_VCLK +*/ +#define GFVX_VIP_EXTERNAL_VCLK_PRESERVE_CLKSEL 0x02000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: VIP input type D interface. + @version SC17 and above + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_TYPE_D 0x04000000 + +#define GFVX_VIP_CSI_ENABLE 0x08000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Bypass any manipulation on internal master + clock generation output pin. + + This flag is mutually exclusive to #GFVX_VIP_PRE_GENERATE_MCLOCK and + #GFVX_VIP_ASK_FOR_MCLOCK. + + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_BYPASS_MCLOCK_PIN 0x20000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Bypass any manipulation on VCLK, VHSYNC, + and VID[7:0] pins. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_BYPASS_NON_MCLOCK_PINS 0x40000000 + +/** VxAPI GFVXVIPINFO::Flag flagbit: Pre-generation of master clock. + Useful for scanning the I2C bus for a camera. + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_PRE_GENERATE_MCLOCK 0x80000000 + +/** + Bypass ISP mode. +*/ +#define GFVX_VIP_BYPASS_ISP 0x10000000 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Parallel data latched at falling edge + of VCLK (default is rising edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_PDL_FALLING_VCLK 0x00000001 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Serial data lacthed at rising edge of + VCLK (default is falling edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_SDL_RISING_VCLK 0x00000001 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VHSYNC active low (default is active + high). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VHSYNC_ACTIVE_LOW 0x00000002 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VVSYNC active low (default is active + high). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VVSYNC_ACTIVE_LOW 0x00000004 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VHSYNC active leading edge (default + is trailing edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VHSYNC_ACTIVE_EDGE_LEAD 0x00000008 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VVSYNC active leading edge (default + is trailing edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VVSYNC_ACTIVE_EDGE_LEAD 0x00000010 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Serial video frame sync active low, + falling edge indicates start of data frame (default is active high, rising + edge indicates start of data frame). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_SFRAME_ACTIVE_LOW 0x00000020 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Serial video input is 16 bit per + frame (default is 8 bit per frame). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_SFRAME_SIZE_16 0x00000040 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: Field 0 is bottom/even field + (default is top/odd field). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_FILED_0_BOTTOM 0x00000080 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VCLK output from GoForce chip active + low (default is active high). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VCLK_OUTPUT_ACTIVE_LOW 0x00000100 + +#define GFVX_VIP_VHSYNC_ACTIVE_LOW_RESET 0x00000200 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VVSYNC reset active low (default is active + high). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ +#define GFVX_VIP_VVSYNC_ACTIVE_LOW_RESET 0x00000400 + +/** VxAPI GFVXVIPINFO::NewTiming flagbit: VHSYNC reset active leading edge (default + is trailing edge). + @see GFVXVIPINFO, GFVxVIPSetVIP() +*/ + + +#endif diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/cpuopsys.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/cpuopsys.h new file mode 100755 index 00000000..daa89a73 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/cpuopsys.h @@ -0,0 +1,309 @@ + +/*! \brief + * Define compile time symbols for CPU type and operating system type. + * This file should only contain preprocessor commands so that + * there are no dependencies on other files. + * + * cpuopsys.h + * + * Copyright (c) 2001, Nvidia Corporation. All rights reserved. + */ + +/*! + * Uniform names are defined for compile time options to distinguish + * CPU types and Operating systems. + * Distinctions between CPU and OpSys should be orthogonal. + * + * These uniform names have initially been defined by keying off the + * makefile/build names defined for builds in the OpenGL group. + * Getting the uniform names defined for other builds may require + * different qualifications. + * + * The file is placed here to allow for the possibility of all driver + * components using the same naming convention for conditional compilation. + */ + +#ifndef __cpuopsys_h_ +#define __cpuopsys_h_ + +/*****************************************************************************/ +// Define all OS/CPU-Chip related symbols + +// ***** DOS variations +#if defined(__DJGPP__) +# define NV_DOS +#endif + +// ***** WINDOWS variations +#if defined(_WIN32) || defined(_WIN16) +# define NV_WINDOWS + +# if defined(_WIN32_WINNT) +# define NV_WINDOWS_NT +# elif defined(_WIN32_WCE) +# define NV_WINDOWS_CE +# elif !defined(NV_MODS) +# define NV_WINDOWS_9X +# endif +#endif // _WIN32 || defined(_WIN16) + +// ***** Unix variations +#if defined(__linux__) && !defined(NV_LINUX) +# define NV_LINUX +#endif // defined(__linux__) + +// SunOS + gcc +#if defined(__sun__) && defined(__svr4__) +# define NV_SUNOS +#endif // defined(__sun__) && defined(__svr4__) + +// SunOS + Sun Compiler (named SunPro, Studio or Forte) +#if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# define NV_SUNPRO_C +# define NV_SUNOS +# define __FUNCTION__ __func__ +# define NV_OPENGL_THREAD_UNSAFE // XXX To start with +#endif // defined(_SUNPRO_C) || defined(__SUNPRO_CC) + +#if defined(__FreeBSD__) +# define NV_BSD +#endif // defined(__FreeBSD__) + +// XXXar don't define NV_UNIX on MacOSX or vxworks or dos or QNX +#if (defined(__unix__) || defined(__unix) ) && !defined(macosx) && !defined(vxworks) && !defined(__DJGPP__) && !defined(NV_UNIX) && !defined(__QNX__) && !defined(__QNXNTO__)// XXX until removed from Makefiles +# define NV_UNIX +#endif // defined(__unix__) + +#if (defined(__QNX__) || defined(__QNXNTO__)) && !defined(NV_QNX) +# define NV_QNX +#endif + +// ***** Apple variations +#if defined(macintosh) || defined(__APPLE__) +# define NV_MACINTOSH +# if defined(__MACH__) +# define NV_MACINTOSH_OSX +# if !defined(NV_MODS) +# define NV_MACOSX_OPENGL +# endif +# else +# define NV_MACINTOSH_OS9 +# endif +# if defined(__LP64__) +# define NV_MACINTOSH_64 +# endif +#endif // defined(macintosh) + +// ***** VxWorks +// Tornado 2.21 is gcc 2.96 and #defines __vxworks. +// Tornado 2.02 is gcc 2.7.2 and doesn't define any OS symbol, so we rely on +// the build system #defining vxworks. +#if defined(__vxworks) || defined(vxworks) +# define NV_VXWORKS +# if (CPU==PENTIUM) +# define NV_VXWORKS_PENTIUM +# elif (CPU==PPC604) +# define NV_VXWORKS_PPC604 +# endif +#endif + +// ***** Integrity OS +#if defined(__INTEGRITY) +# if !defined(NV_INTEGRITY) +# define NV_INTEGRITY +# endif +#endif + +// ***** Processor type variations +// Note: The prefix NV_CPU_* is taken by \\sw\main\sdk\nvidia\inc\Nvcm.h + +#if ((defined(_M_IX86) || defined(__i386__) || defined(__i386)) && !defined(NVCPU_X86)) // XXX until removed from Makefiles + // _M_IX86 for windows, __i386__ for Linux (or any x86 using gcc) + // __i386 for Studio compiler on Solaris x86 +# define NVCPU_X86 // any IA32 machine (not x86-64) +#endif + +#if defined(_WIN32) && defined(_M_IA64) +# define NVCPU_IA64_WINDOWS // any IA64 for Windows opsys +#endif +#if defined(NV_LINUX) && defined(__ia64__) +# define NVCPU_IA64_LINUX // any IA64 for Linux opsys +#endif +#if defined(NVCPU_IA64_WINDOWS) || defined(NVCPU_IA64_LINUX) || defined(IA64) +# define NVCPU_IA64 // any IA64 for any opsys +#endif + +#if (defined(NV_MACINTOSH) && !(defined(__i386__) || defined(__x86_64__))) || defined(__PPC__) || defined(__ppc) +# ifndef NVCPU_PPC +# define NVCPU_PPC // any PowerPC architecture +# endif +# ifndef NV_BIG_ENDIAN +# define NV_BIG_ENDIAN +# endif +#endif + +#if defined(__x86_64) || defined(AMD64) || defined(_M_AMD64) +# define NVCPU_X86_64 // any x86-64 for any opsys +#endif + +#if defined(__arm__) && !defined(NVCPU_ARM) +# define NVCPU_ARM +#endif + +#if defined(__XSCALE__) +#define NVCPU_XSCALE // for XSCALE ARM processors +#endif + +#if defined(__SH4__) +# ifndef NVCPU_SH4 +# define NVCPU_SH4 // Renesas (formerly Hitachi) SH4 +# endif +#endif + +// For Xtensa processors +#if defined(__XTENSA__) +# define NVCPU_XTENSA +# if defined(__XTENSA_EB__) +# define NV_BIG_ENDIAN +# endif +#endif + + +// Other flavors of CPU type should be determined at run-time. +// For example, an x86 architecture with/without SSE. +// If it can compile, then there's no need for a compile time option. +// For some current GCC limitations, these may be fixed by using the Intel +// compiler for certain files in a Linux build. + + +#if defined(NVCPU_IA64) || defined(NVCPU_X86_64) +# define NV_64_BITS // all architectures where pointers are 64 bits +#else + // we assume 32 bits. I don't see a need for NV_16_BITS. +#endif + +// NOTE: NV_INT64_OK is not needed in the OpenGL driver for any platform +// we care about these days. The only consideration is that Linux does not +// have a 64-bit divide on the server. To get around this, we convert the +// expression to (double) for the division. +#if (!(defined(macintosh) || defined(vxworks) || defined(__INTEL_COMPILER)) || defined(NV_LINUX)) && !defined(NV_INT64_OK) +#define NV_INT64_OK +#endif + +// For verification-only features not intended to be included in normal drivers +#if defined(NV_MODS) && defined(DEBUG) && !defined(NV_DOS) +#define NV_VERIF_FEATURES +#endif + + +/* + * New, safer family of #define's -- these ones use 0 vs. 1 rather than + * defined/!defined. This is advantageous because if you make a typo, say: + * + * #if NVCPU_IS_BIG_ENDAIN // Oops! Endian is misspelled + * + * ...some compilers can give you a warning telling you that you screwed up. + * The compiler can also give you a warning if you forget to #include + * "cpuopsys.h" in your code before the point where you try to use these + * conditionals. + * + * Also, the names have been prefixed in more cases with "CPU" or "OS" for + * increased clarity. You can tell the names apart from the old ones because + * they all use "_IS_" in the name. + * + * Finally, these can be used in "if" statements and not just in #if's. For + * example: + * + * if (NVCPU_IS_BIG_ENDIAN) x = Swap32(x); + * + * Maybe some day in the far-off future these can replace the old #define's. + */ +#if defined(NV_WINDOWS) +#define NVOS_IS_WINDOWS 1 +#else +#define NVOS_IS_WINDOWS 0 +#endif +#if defined(NV_WINDOWS_CE) +#define NVOS_IS_WINDOWS_CE 1 +#else +#define NVOS_IS_WINDOWS_CE 0 +#endif +#if defined(NV_LINUX) +#define NVOS_IS_LINUX 1 +#else +#define NVOS_IS_LINUX 0 +#endif +#if defined(NV_UNIX) +#define NVOS_IS_UNIX 1 +#else +#define NVOS_IS_UNIX 0 +#endif +#if defined(NV_QNX) +#define NVOS_IS_QNX 1 +#else +#define NVOS_IS_QNX 0 +#endif +#if defined(NV_MACINTOSH) +#define NVOS_IS_MACINTOSH 1 +#else +#define NVOS_IS_MACINTOSH 0 +#endif +#if defined(NV_VXWORKS) +#define NVOS_IS_VXWORKS 1 +#else +#define NVOS_IS_VXWORKS 0 +#endif +#if defined(NV_INTEGRITY) +#define NVOS_IS_INTEGRITY 1 +#else +#define NVOS_IS_INTEGRITY 0 +#endif +#if defined(NVCPU_X86) +#define NVCPU_IS_X86 1 +#else +#define NVCPU_IS_X86 0 +#endif +#if defined(NVCPU_IA64) +#define NVCPU_IS_IA64 1 +#else +#define NVCPU_IS_IA64 0 +#endif +#if defined(NVCPU_X86_64) +#define NVCPU_IS_X86_64 1 +#else +#define NVCPU_IS_X86_64 0 +#endif +#if defined(NVCPU_PPC) +#define NVCPU_IS_PPC 1 +#else +#define NVCPU_IS_PPC 0 +#endif +#if defined(NVCPU_ARM) +#define NVCPU_IS_ARM 1 +#else +#define NVCPU_IS_ARM 0 +#endif +#if defined(NVCPU_SH4) +#define NVCPU_IS_SH4 1 +#else +#define NVCPU_IS_SH4 0 +#endif +#if defined(NVCPU_XTENSA) +#define NVCPU_IS_XTENSA 1 +#else +#define NVCPU_IS_XTENSA 0 +#endif +#if defined(NV_BIG_ENDIAN) +#define NVCPU_IS_BIG_ENDIAN 1 +#else +#define NVCPU_IS_BIG_ENDIAN 0 +#endif +#if defined(NV_64_BITS) +#define NVCPU_IS_64_BITS 1 +#else +#define NVCPU_IS_64_BITS 0 +#endif + +/*****************************************************************************/ + +#endif /* __cpuopsys_h_ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/gfrm_clock_ids.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/gfrm_clock_ids.h new file mode 100755 index 00000000..bd0d1209 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/gfrm_clock_ids.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file clock_ids.h + Clock List & string names +*/ + +GFRM_CLOCK(OSC,"osc") +GFRM_CLOCK(ROSC,"rosc") +GFRM_CLOCK_PLL(PLL1,"pll1") +GFRM_CLOCK_PLL(PLL2,"pll2") +GFRM_CLOCK(REFCLK0,"refclk0") +GFRM_CLOCK(REFCLK1,"refclk1") +GFRM_CLOCK(REFCLK2,"refclk2") +GFRM_CLOCK_PLL(PLL3,"pll3") + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/gfrm_module_ids.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/gfrm_module_ids.h new file mode 100755 index 00000000..fb644b13 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/gfrm_module_ids.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an + * express license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/** @file module_ids.h + Module List & string names +*/ + + +GFRM_MODULE(HOST1X, "host1x") +GFRM_MODULE(MPD,"mpd") +GFRM_MODULE(ME,"me") +GFRM_MODULE(JPEGE,"jpege") +GFRM_MODULE(VI,"vi") +GFRM_MODULE(EPP,"epp") +GFRM_MODULE(ISP,"isp") +GFRM_MODULE(DSPCORE,"dspcore") +GFRM_MODULE(GR2D,"gr2d") +GFRM_MODULE(GR3D,"gr3d") +GFRM_MODULE(DISPLAY,"display") +GFRM_MODULE(I2S,"i2s") +GFRM_MODULE(IC,"ic") +GFRM_MODULE(SD,"sd") +GFRM_MODULE(MC,"mc") +GFRM_MODULE(EMC,"emc") +GFRM_MODULE(DSP,"dsp") +GFRM_MODULE(EFUSE,"efuse") +GFRM_MODULE(AUDIO,"audio") +GFRM_MODULE(TVO,"tvo") +GFRM_MODULE(DISPLAYB,"displayb") +GFRM_MODULE(I2SB,"i2sb") +GFRM_MODULE(DSPB,"dspb") +GFRM_MODULE(CVE,"cve") +GFRM_MODULE(DSPBCORE,"dspbcore") +GFRM_MODULE(CSI,"csi") +GFRM_MODULE(TVDAC,"tvdac") +GFRM_MODULE(APB,"apb") +GFRM_MODULE(RESET, "reset") +GFRM_MODULE(SPROM, "sprom") +GFRM_MODULE(GPIO, "gpio") +GFRM_MODULE(CLK, "clk") +GFRM_MODULE(UART, "uart") +GFRM_MODULE(UART2, "uart2") +GFRM_MODULE(UART3, "uart3") +GFRM_MODULE(TIMER, "timer") +GFRM_MODULE(KBC, "kbc") +GFRM_MODULE(DMA, "dma") +GFRM_MODULE(USB, "usb") +GFRM_MODULE(CEATA, "ceata") +GFRM_MODULE(FLASH, "flash") +GFRM_MODULE(XHOST, "xhost") diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvboard.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvboard.h new file mode 100755 index 00000000..9277a904 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvboard.h @@ -0,0 +1,619 @@ +/* + * Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef NVBOARD_H +#define NVBOARD_H + +#include "nvcommon.h" +#include "nverror.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** NvBoard - Board Support Package + + NvBoard is designed to decouple customer platform specifics from generic + binary only drivers. + + The interface must be thread-safe. + */ + +typedef struct NvBoardAperture_t +{ + /* Physical Address */ + NvPhysAddr address; + + /* Size of Aperture */ + NvU32 size; +} NvBoardAperture; + +typedef struct NvBoardApertureIO_t +{ + void ( *Write8 )( void *pAddress, NvU8 data ); + void ( *Write16 )( void *pAddress, NvU16 data ); + void ( *Write32 )( void *pAddress, NvU32 data ); + void ( *Write64 )( void *pAddress, NvU64 data ); + NvU8 ( *Read8 )( void *pAddress ); + NvU16 ( *Read16 )( void *pAddress ); + NvU32 ( *Read32 )( void *pAddress ); + NvU64 ( *Read64 )( void *pAddress ); +} NvBoardApertureIO; + +typedef struct NvBoardApertures_t +{ + NvBoardAperture hostInterface; + + /* pIO is null unless the apertures cannot be dereferenced */ + NvBoardApertureIO *pIO; +} NvBoardApertures; + +typedef enum +{ + /* Bus type A */ + NvBoardBusType_A, + + /* Bus type C */ + NvBoardBusType_C, + + NvBoardBusType_Forceword = 0x7fffffff, +} NvBoardBusType; + +typedef enum +{ + /* Direct Addressing */ + NvBoardBusAddressing_Direct, + + /* Indirect Addressing */ + NvBoardBusAddressing_Indirect, + + NvBoardBusAddressing_Forceword = 0x7fffffff, +} NvBoardBusAddressing; + +typedef enum +{ + /* 16-bit bus */ + NvBoardBusWidth_16, + + /* 32-bit bus */ + NvBoardBusWidth_32, + + NvBoardBusWidth_Forceword = 0x7fffffff, +} NvBoardBusWidth; + +typedef enum +{ + /* Handshake mode. */ + NvBoardBusMode_Handshake, + + /* Fixed cycle mode. */ + NvBoardBusMode_FixedCycle, + + NvBoardBusMode_Forceword = 0x7fffffff, +} NvBoardBusMode; + +typedef enum +{ + /* Asynchronous. */ + NvBoardBusSynchronization_Asynchronous, + + /* Synchronous. */ + NvBoardBusSynchronization_Synchronous, + + NvBoardBusSynchronization_Forceword = 0x7fffffff, +} NvBoardBusSynchronization; + +typedef enum +{ + /* Active low. */ + NvBoardBusReadyPolarity_ActiveLow, + + /* Active high. */ + NvBoardBusReadyPolarity_ActiveHigh, + + NvBoardBusReadyPolarity_Forceword = 0x7fffffff, +} NvBoardBusReadyPolarity; + +typedef struct NvBoardMode_t +{ + NvBoardBusAddressing GPUaddressing; // Bus perspective from GPU + NvBoardBusWidth GPUwidth; + NvBoardBusAddressing CPUaddressing; // Bus perspective from CPU + NvBoardBusWidth CPUwidth; + NvBoardBusType type; + NvBoardBusMode mode; + NvBoardBusSynchronization synchronization; + NvBoardBusReadyPolarity readyPolarity; +} NvBoardMode; + +/** Stateless methods. Methods can be called before NvBoardInit */ + +/** NvBoardListSupportedModes - Method to enumerate the modes of the board + + Two calls should be made to this method. + + On the first call, the method populates the number of modes, for the + display. When this call is issued pMode should be NULL. + + On the second call, the length of the pMode array is indicated by + the value of *pNum. When pNum is less than the number of modes the + method populates the pMode array with only the first pNum modes. + When is more than the number of modes, the method populates the + pMode array with the number of modes and writes the number of modes + into pNum. + + The first mode enumerated by this method is the recommended / default mode + for the display. + + @param pNum unsigned integer value indicating the number of modes in + the array pMode. + + @param pMode pointer to an array of mode structures, where the size of + the array is determined by the value in pNum. + + @retval NvSuccess - on success + NvErrorBadParameter - when at least one parameter is incorrect + */ +NvError +NvBoardListSupportedModes( NvU32 *pNum, NvBoardMode *pMode ); + +/** Library Initialization */ + +/** NvBoardInit - platform initialization. Typically chip select is configured here. + + NvBoardInit uses a reference counter. The first invocation performs the + initialization, all future calls increment the counter. The counter is + decremented by NvBoardDeInit. + + This method is to be called before any other NvBoard methods can be used. + + @param pMode pointer to structure containing a mode to set on the board. + If mode is null, the recommended mode will be chosen. + */ +NvError +NvBoardInit( const NvBoardMode *pMode ); + +/** NvBoardDeInit - platform deinitialization. + */ +void +NvBoardDeInit( void ); + +/** Wince platform resume control */ +NvError +NvBoardResume( void ); + +/** Wince platform suspend control */ +NvError +NvBoardSuspend( void ); + +/** SD card detect status when card detect pin is connected to CPU GPIO pin */ +NvError +nvBoardSDCardDetectStatus(NvU32 *bCardInserted); + +/** SD card detect sysintr number if card detect pin is connected to CPU GPIO pin*/ +NvError +nvBoardSDCardDetectSysintr(NvU32 *dwSysintr); + +/** SD card socket power pin configuration + In general, this pin is connected to CPU GPIO pin, and we need to configure + GPIO input/output mode and setup default value +*/ +NvError +nvBoardSDSocketPowerInit(void); + +/** SD card socket power control*/ +NvError +nvBoardSDSocketPowerOnOff(NvU32 SDPowerOn); + +/** Camera(VI) interface power plane control*/ +NvError +nvBoardVIPowerOnOff(NvU32 VIPowerOn); + +/** OEM specific powerOn related calls after NV backlight ON. + + @retval ERROR_SUCCESS on success or appropriate wince error + codes. +*/ +NvError +nvBoard_PostOEMBacklightOn(void); + +/** OEM specific powerOff related calls after NV backlight Off. + + @retval ERROR_SUCCESS on success or appropriate wince error + codes. +*/ +NvError +nvBoard_PostOEMBacklightOff(void); + +/** NvBoardGetApertures - get apertures + */ +NvError +NvBoardGetApertures( NvBoardApertures *pApertures ); + +/** NvBoardGetMode - get current mode + */ +NvError +NvBoardGetMode( NvBoardMode *pMode ); + +/** Device Events -- Abstraction for interrupts */ + +/* NvDeviceEvent enumerates the types of events. NvBoard implementors should not + hardcode event names. The only enumerated value that should be used in the + implementation of NvBoard is NvDeviceEvent_Num. + */ +typedef enum NvDeviceEvent_t +{ + /* NOTE: Currently using unabstracted events until INTx is removed. */ + NvDeviceEvent_HOST = 0, + NvDeviceEvent_GRMPD, + NvDeviceEvent_ME, + NvDeviceEvent_JPEGE, + NvDeviceEvent_VI, + NvDeviceEvent_EPP, + NvDeviceEvent_ISP, + NvDeviceEvent_DSP, + NvDeviceEvent_GR2D, + NvDeviceEvent_GR3D, + NvDeviceEvent_DISPLAY, + NvDeviceEvent_I2S, + NvDeviceEvent_IC, + NvDeviceEvent_SD, + NvDeviceEvent_MC, + NvDeviceEvent_EMC, + + /* NUM should always be the 2nd last enumerated value */ + NvDeviceEvent_Num, + + NvDeviceEvent_Forceword = 0x7fffffff, +} NvDeviceEvent; + +/** NvBoardEnableEvent - Method to enable an event + + If the event is fired before a client is waiting, the event will be remembered + for the next NvBoardWaitForEvent invocation. + */ +NvError +NvBoardEnableEvent( NvDeviceEvent event ); + +/** NvBoardDisableEvent - Method to disable an event + */ +void +NvBoardDisableEvent( NvDeviceEvent event ); + +/** NvBoardWaitForEvent - This method blocks until the event is fired + + Each event may only have one client waiting on it. If more than one client + needs to be notified of an event, a broadcast layer will need to be + developed on top of this API. + + Once an event is fired, it is disabled. To reenable the event use + NvBoardEnableEvent. +*/ +NvError +NvBoardWaitForEvent( NvDeviceEvent event ); + +/** NvBoardWaitForEventWithTimeOut - NvBoardWaitForEvent with a timeout + + @param timeOut Unit is milliseconds + */ +NvError +NvBoardWaitForEventWithTimeOut( NvDeviceEvent event, NvU32 timeOut ); + +/** I2C I/O */ + +/** NvBoardI2CWrite - I2C write operation. Implementing this function is optional. + */ +NvError +NvBoardI2CWrite( NvU32 addr, const void *ptr, NvU32 size ); + +/** NvBoardI2CRead - I2C read operation. Implementing this function is optional. + */ +NvError +NvBoardI2CRead( NvU32 addr, void *ptr, NvU32 size ); + +/** Voltage and power control */ + +typedef enum NvBoardPowerPlane_t +{ + NvBoardPowerPlane_AOCVDD = 0, + NvBoardPowerPlane_VECVDD, + NvBoardPowerPlane_MMCVDD, + NvBoardPowerPlane_TDCVDD, + NvBoardPowerPlane_VVDD, + NvBoardPowerPlane_EMVDD, + NvBoardPowerPlane_ACVDD, + NvBoardPowerPlane_LVDD, + NvBoardPowerPlane_HVDD, + NvBoardPowerPlane_AUXVDD, + NvBoardPowerPlane_R1CVDD, + NvBoardPowerPlane_SDVDD, + NvBoardPowerPlane_DRAM, + + NvBoardPowerPlane_Forceword = 0x7fffffff, +} NvBoardPowerPlane; + +typedef enum NvBoardClock_t +{ + NvBoardClock_PLL1 = 0, + NvBoardClock_PLL2, + NvBoardClock_COSC, + NvBoardClock_ROSC, + NvBoardClock_REF1, + NvBoardClock_REF2, + + NvBoardClock_Forceword = 0x7fffffff, +} NvBoardClock; + +/** NvBoardSetVoltage - change voltage of hardware block + + @param voltage Unit is millivolts + */ +NvError +NvBoardSetVoltage( NvBoardPowerPlane block, NvU32 voltage ); + +/** NvBoardGetVoltage - get voltage of hardware block + + @param voltage Unit is millivolts + */ +NvError +NvBoardGetVoltage( NvBoardPowerPlane plane, NvU32 *voltage ); + +/** NvBoardPowerOn - enable power to block + */ +NvError +NvBoardPowerOn( NvBoardPowerPlane plane ); + +/** NvBoardPowerOff - disable power to block + */ +NvError +NvBoardPowerOff( NvBoardPowerPlane plane ); + +/** NvBoardClockOn - enable clock + */ +NvError +NvBoardClockOn( NvBoardClock clock ); + +/** NvBoardClockOff - disable clock + */ +NvError +NvBoardClockOff( NvBoardClock clock ); + +/** NvBoardSetFrequency - set frequency of clock + + @param frequency unit is KHz + */ +NvError +NvBoardSetFrequency( NvBoardClock clock, NvU32 frequency ); + + +/** Platfrom specific debug function. This like an ioctl to the platfrom + sepcific code. + */ +void NvBoardDebug(void *p, NvU32 op, NvU32 arg); + +/** Event notification */ + +typedef enum +{ + NvBoardDeviceType_Silicon, + NvBoardDeviceType_Emulator, + NvBoardDeviceType_Forceword = 0x7fffffff, +} NvBoardDeviceType; + +typedef struct NvBoardDeviceInfo_t +{ + NvU32 MinorRev; + NvU32 MajorRev; + NvU32 ChipID; + NvU32 Family; + NvBoardDeviceType Type; +} NvBoardDeviceInfo; + +/** NvBoardPostChipInit - Called after the chip is intialized. + + Chip specific timings can be programmed at this point. + + NvIrqPostChipInit should be called here. + */ +NvError +NvBoardPostChipInit( NvBoardDeviceInfo *deviceInfo ); + +/** NvBoardPreChipDeInit - Called before chip is shutdown. + + NvIrqPreChipDeInit should be called here. + */ +NvError +NvBoardPreChipDeInit( void ); + +/** NvBoardClockSwitch - Clock switch handling + + @param frequency Unit is kHz + */ +NvError +NvBoardClockSwitch( NvU32 frequency ); + +typedef enum NvBoardStateEvent_t +{ +#ifdef NV_WINDOWS_CE + NvBoardStateEvent_PreDeviceInit, + NvBoardStateEvent_PostDeviceInit, + NvBoardStateEvent_PrePanelInit, + NvBoardStateEvent_PostPanelInit, + NvBoardStateEvent_PreSetMode, + NvBoardStateEvent_PostSetMode, + NvBoardStateEvent_PreDisplayInit, + NvBoardStateEvent_PostDisplayInit, + NvBoardStateEvent_PreOEMPowerHandlerVideoPowerOff, + NvBoardStateEvent_PostOEMPowerHandlerVideoPowerOff, + NvBoardStateEvent_PreOEMPowerHandlerVideoPowerOn, + NvBoardStateEvent_PostOEMPowerHandlerVideoPowerOn, +#endif + + NvBoardStateEvent_Forceword = 0x7fffffff, +} NvBoardStateEvent; + +/** NvBoardGlobalStateNotification - Called during global state transitions + + Only used on Windows CE at the moment. + */ +NvError +NvBoardGlobalStateNotification( NvBoardStateEvent event ); + +void +NvBoardOsWaitUS( NvU32 usec ); + +void +NvBoardOsSleepMS( NvU32 msec ); + +typedef struct NvBoardOsMutex_t *NvBoardOsMutex; +typedef struct NvBoardOsSemaphore_t *NvBoardOsSemaphore; +typedef struct NvBoardOsThread_t *NvBoardOsThread; + +NvError +NvBoardOsMutexCreate( const char *key, NvBoardOsMutex *mutex ); + +void +NvBoardOsMutexLock( NvBoardOsMutex mutex ); + +void +NvBoardOsMutexUnlock( NvBoardOsMutex mutex ); + +void +NvBoardOsMutexDestroy( NvBoardOsMutex mutex ); + +typedef struct NvBoardOsSharedMemDescriptor_t *NvBoardOsSharedMemDescriptor; + +NvError +NvBoardOsSharedMemAlloc( const char *key, size_t size, + NvBoardOsSharedMemDescriptor *descriptor ); + +NvError +NvBoardOsSharedMemMap( NvBoardOsSharedMemDescriptor descriptor, size_t offset, + size_t size, void **ptr ); + +void +NvBoardOsSharedMemUnmap( void *ptr, size_t size ); + +void +NvBoardOsSharedMemFree( NvBoardOsSharedMemDescriptor descriptor ); + +void +NvBoardOsMemset( void *s, NvU8 c, size_t size ); + +int +NvBoardOsMemcmp( const void *s1, const void *s2, size_t size ); + +#define NVBOARDOS_KEY_MAX 128 + +#define NVBOARDOS_MEM_NONE 0x0 +#define NVBOARDOS_MEM_READ 0x1 +#define NVBOARDOS_MEM_WRITE 0x2 +#define NVBOARDOS_MEM_EXECUTE 0x4 +#define NVBOARDOS_MEM_READ_WRITE ( NVBOARDOS_MEM_READ | NVBOARDOS_MEM_WRITE ) + +typedef enum +{ + NvBoardOsMemAttribute_Uncached = 0, + NvBoardOsMemAttribute_WriteBack = 1, + NvBoardOsMemAttribute_WriteCombined = 2, + + NvBoardOsMemAttribute_Force32 = 0x7FFFFFFF +} NvBoardOsMemAttribute; + +NvError +NvBoardOsPhysicalMemMap( NvPhysAddr phys, size_t size, + NvBoardOsMemAttribute attrib, NvU32 flags, void **ptr ); + + +void +NvBoardOsPhysicalMemUnmap( void *ptr, size_t size ); + +NvError +NvBoardOsMemoryAlloc(void **ptr, size_t size); + +void +NvBoardOsMemoryFree(void *ptr, size_t size); + +NvError +NvBoardOsGetConfigU32( const char *name, NvU32 *value ); + +void * +NvBoardOsAlloc( size_t size ); + +void +NvBoardOsFree( void *ptr ); + +typedef void (*NvBoardOsThreadFunction)( void *args ); + +NvError +NvBoardOsThreadCreate( const char *name, NvBoardOsThreadFunction function, + void *args, NvBoardOsThread *thread ); + +void +NvBoardOsThreadJoin( NvBoardOsThread thread ); + +void +NvBoardOsThreadYield( void ); + +NvError +NvBoardOsSemaphoreCreate( const char *key, NvBoardOsSemaphore *semaphore, + NvU32 value ); + +void +NvBoardOsSemaphoreWait( NvBoardOsSemaphore semaphore ); + +void +NvBoardOsSemaphoreSignal( NvBoardOsSemaphore semaphore ); + +void +NvBoardOsSemaphoreDestroy( NvBoardOsSemaphore semaphore ); + +NvError +nvBoard_PreDisplayInit(void); + +NvError +nvBoard_PostDisplayInit(void); + +NvError +nvBoard_PrePanelInit(void); + +NvError +nvBoard_PostPanelInit(void); + +NvError +nvBoard_PreDeviceInit(void); + +NvError +nvBoard_PostDeviceInit(void); + +NvError +nvBoard_PreSetMode(void); + +NvError +nvBoard_PostSetMode(void); + +NvError +nvBoard_PreOEMPowerHandlerVideoPowerOff(void); + +NvError +nvBoard_PostOEMPowerHandlerVideoPowerOff(void); + +NvError +nvBoard_PreOEMPowerHandlerVideoPowerOn(void); + +NvError +nvBoard_PostOEMPowerHandlerVideoPowerOn(void); + +#ifdef __cplusplus +} +#endif + +#endif // NVBOARD_H diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvcommon.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvcommon.h new file mode 100755 index 00000000..ab79088f --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvcommon.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2006 - 2007 NVIDIA Corporation. All Rights Reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef NVCOMMON_H +#define NVCOMMON_H + +#include "nvtypes.h" + +// Include headers that provide NULL, size_t, offsetof, and [u]intptr_t. In the +// event that the toolchain doesn't provide these, provide them ourselves. +#include +#if NVOS_IS_WINDOWS_CE +typedef int intptr_t; +typedef unsigned int uintptr_t; +#elif (NVOS_IS_LINUX && !defined(__KERNEL__)) || defined(__arm) +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/** nvcommon.h contains standard definitions used by various interfaces + */ + +/** A physical address */ +#if NVOS_IS_WINDOWS +typedef NvU64 NvPhysAddr; +#else +typedef NvU32 NvPhysAddr; +#endif + +// For historical reasons that are hard to fix, nvtypes.h has an incorrect +// definition of NV_ALIGN_BYTES for Windows and Macintosh, and for other +// unsupported compilers like IAR. Provide a correct macro, which we call +// NV_ALIGN. This can be removed if and when nvtypes.h is fixed. +// Alternatively, we could use NV_DECLARE_ALIGNED... +#if NVOS_IS_WINDOWS +#define NV_ALIGN(size) __declspec(align(size)) +#elif defined(__GNUC__) || NVOS_IS_QNX +#define NV_ALIGN(size) __attribute__ ((aligned (size))) +#elif defined(__arm) +#define NV_ALIGN(size) __align(size) +#endif + +/** + * This macro wraps its argument with the equivalent of "#ifdef DEBUG", but also + * can be used where #ifdef's can't, like inside a macro. + */ +#if defined(DEBUG) +#define NV_DEBUG_CODE(x) x +#else +#define NV_DEBUG_CODE(x) +#endif + +/** Macro for determining the size of an array */ +#define NV_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +/** Macro for taking min or max of a pair of numbers */ +#define NV_MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define NV_MAX(a,b) (((a) > (b)) ? (a) : (b)) + +/** + * By convention, we use this value to represent an infinite wait interval in + * APIs that expect a timeout argument. A value of zero should not be + * interpreted as infinite -- it should be interpreted as "time out immediately + * and simply check whether the event has already happened." + */ +enum { NV_WAIT_INFINITE = 0xFFFFFFFF }; + +/** + * Union that can be used to view a 32-bit word as your choice of a 32-bit + * unsigned integer, a 32-bit signed integer, or an IEEE single-precision float. + * Here is an example of how you might use it to extract the (integer) bitwise + * representation of a floating-point number: + * NvData32 data; + * data.f = 1.0f; + * printf("%x", data.u); + */ +typedef union NvData32Rec +{ + NvU32 u; + NvS32 i; + NvF32 f; +} NvData32; + +/** NvPoint structure is used to determine a location on a 2-dimensional + object, where the coordinate (0,0) is located at the top-left of the + object. The values of x and y are in pixels. + */ +typedef struct _NvPoint_t +{ + /** horizontal location of the point */ + NvS32 x; + + /** vertical location of the point */ + NvS32 y; + +} NvPoint; + + +/** NvRect structure is used to define a 2-dimensional rectangle + where the rectangle is bottom right exclusive (i.e. the right most + column, and the bottom row of the rectangle is not included) + */ +typedef struct _NvRect_t +{ + /** left column of a rectangle */ + NvS32 left; + + /** top row of a rectangle*/ + NvS32 top; + + /** right column of a rectangle */ + NvS32 right; + + /** bottom row of a rectangle */ + NvS32 bottom; + +} NvRect; + + +/** NvSize structure is used to define a 2-dimensional surface + where the surface is determined by it's height and width in + pixels + */ +typedef struct _NvSize_t +{ + /* width of the surface in pixels */ + NvS32 width; + + /* height of the surface in pixels */ + NvS32 height; + +} NvSize; + + +/** NvDeviceHandle is an opaque handle to a device + */ +typedef struct NvDeviceStruct_t *NvDeviceHandle; +#ifdef __cplusplus +} +#endif + +#endif /* NVCOMMON_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nverror.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nverror.h new file mode 100755 index 00000000..6ef69080 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nverror.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2006 NVIDIA Corporation. All Rights Reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef NVERROR_H +#define NVERROR_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* NvError_t enumeration contains ALL return / error codes. Error codes + are specifically explicit to make it easy to identify where an error + came from. + + All error codes are derived from the macros in NvErrVal.h + */ +typedef enum _NvError_t +{ + +#ifdef NVERROR +#undef NVERROR +#endif /* NVERROR */ + +#define NVERROR(_name_, _value_, _desc_) _name_ = _value_, + + /* header included for macro expansion of error codes */ + #include "nverrval.h" + + /* bogus error code used to padd the enum to 32bits */ + NvErrorMax = 0x7FFFFFFF + +#undef NVERROR + +} NvError; + + +#ifdef __cplusplus +} +#endif + +#endif /* NVERROR_H */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nverrval.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nverrval.h new file mode 100755 index 00000000..2045dd83 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nverrval.h @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2006 NVIDIA Corporation. All Rights Reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* NvErrVal.h is a header used for macro expansion of the errors defined for + the Nv methods & interfaces. + + This header is NOT protected from being included multiple times, as it is + used for C pre-processor macro expansion of error codes, and the + descriptions of those error codes. + + Each error code has a unique name, description and value to make it easier + for developers to identify the source of a failure. Thus there are no + generic or unknown error codes. +*/ + +/* common error codes */ +NVERROR(NvSuccess, 0x00000000, "success") +NVERROR(NvError_NotImplemented, 0x00000001, "method or interface is not implemented") +NVERROR(NvError_NotSupported, 0x00000002, "requested operation is not supported") +NVERROR(NvError_NotInitialized, 0x00000003, "method or interface is not initialized") +NVERROR(NvError_BadParameter, 0x00000004, "bad parameter to method or interface") +NVERROR(NvError_Timeout, 0x00000005, "not completed in the expected time") +NVERROR(NvError_InsufficientMemory, 0x00000006, "insufficient system memory") +NVERROR(NvError_ReadOnlyAttribute, 0x00000007, "cannot write a read-only attribute") +NVERROR(NvError_InvalidState, 0x00000008, "module is in invalid state to perform the requested operation") +NVERROR(NvError_InvalidAddress, 0x00000009, "invalid address") +NVERROR(NvError_InvalidSize, 0x0000000A, "invalid size") +NVERROR(NvError_BadValue, 0x0000000B, "illegal value specified for parameter") + +/* surface specific error codes */ +NVERROR(NvError_InsufficientVideoMemory, 0x00010000, "insufficient video memory") +NVERROR(NvError_BadSurfaceColorScheme, 0x00010001, "this surface scheme is not supported in the current controller") + +/* display specific error codes */ +NVERROR(NvError_DisplayIncompatible, 0x00020000, "display incompatible with method or interface") +NVERROR(NvError_NoCompatibleMode, 0x00020001, "no compatible mode exists for the attached displays") +NVERROR(NvError_ModeNotSupported, 0x00020002, "the mode is not supported by the display or controller") +NVERROR(NvError_ControllerActive, 0x00020003, "the controller is active and cannot perform the operation") +NVERROR(NvError_DisplayAlreadyAttached, 0x00020004, "the display is already attached to the controller") +NVERROR(NvError_DetachDisplayFirst, 0x00020005, "the display is already attached to another controller") +NVERROR(NvError_TooManyDisplays, 0x00020006, "the controller has not enough free display slots") +NVERROR(NvError_NoDisplaysAttached, 0x00020007, "there are no displays attached to this controller") +NVERROR(NvError_AlreadySuspended, 0x00020008, "the controller is already suspended") +NVERROR(NvError_NotSuspended, 0x00020009, "the controller is not suspended, so cannot resume it") +NVERROR(NvError_EmptyColorKeyRange, 0x00020010, "color key range that was set is empty") +NVERROR(NvError_NoMode, 0x00020011, "controller is not driving a mode, cannot perform the selected action") +NVERROR(NvError_NotInVerticalBlank, 0x00020012, "controller is not in vertical blank") + +/* DMA specific error codes */ +NVERROR(NvError_DmaTargetNotLocked, 0x00030000, "client does not have a lock for this target DMA controller") +NVERROR(NvError_DmaCommunicationError, 0x00030001, "the DMA controller had failed to communicate with the target") +NVERROR(NvError_DmaOpNotFinished, 0x00030002, "the DMA operation has not completed") +NVERROR(NvError_DmaChannelNotAvailable, 0x00030003, "the requested DMA channel is not available") +NVERROR(NvError_InvalidSourceId, 0x00030004, "invalid source ID") +NVERROR(NvError_InvalidDestinationId, 0x00030005, "invalid destination ID") + +/* NvOs error codes */ +NVERROR(NvError_FileWriteFailed, 0x00040000, "the file write operation failed") +NVERROR(NvError_FileReadFailed, 0x00040001, "the file read operation failed") +NVERROR(NvError_EndOfFile, 0x00040002, "the end of file has been reached") +NVERROR(NvError_FileOperationFailed, 0x00040003, "the file operation has failed") +NVERROR(NvError_DirOperationFailed, 0x00040004, "the directory operation has failed") +NVERROR(NvError_EndOfDirList, 0x00040005, "there are no more entries in the directory") +NVERROR(NvError_ConfigVarNotFound, 0x00040006, "the configuration variable is not present") +NVERROR(NvError_InvalidConfigVar, 0x00040007, "the configuration variable is corrupted") +NVERROR(NvError_LibraryNotFound, 0x00040008, "the dynamic library was not found for open") +NVERROR(NvError_SymbolNotFound, 0x00040009, "the symbol in a dyanmic library was not found") +NVERROR(NvError_MemoryMapFailed, 0x0004000a, "the memory mapping operation failed") +NVERROR(NvError_MutexCreateFailed, 0x0004000b, "the mutex create operation failed") +NVERROR(NvError_SemaphoreCreateFailed, 0x0004000c, "the semaphore create operation failed") +NVERROR(NvError_ThreadCreateFailed, 0x0004000d, "the thread create operation failed") +NVERROR(NvError_SharedMemAllocFailed, 0x0004000e, "the shared memory allocation operation failed") + +/* NvBoard error codes */ +NVERROR(NvError_I2CNotAcknowledged, 0x00050000, "I2C acknowledge was not received") +NVERROR(NvError_KernelDriverNotFound, 0x00050001, "unable to find kernel driver") +NVERROR(NvError_KernelDriverBadVersion, 0x00050002, "the kernel driver is out of date") +NVERROR(NvError_KernelDriverIOFailed, 0x00050003, "the driver operation failed") +NVERROR(NvError_ModeMismatched, 0x00050004, "conflicting board mode") +NVERROR(NvError_VoltageOutsideRange, 0x00050005, "requested voltage is outside valid range") +NVERROR(NvError_EventNotEnabled, 0x00050006, "the event is not enabled") +NVERROR(NvError_EventBusy, 0x00050007, "the event is busy") +NVERROR(NvError_InterruptInitFailed, 0x00050008, "error initializing interrupts") + +/* NvIrq error codes */ +NVERROR(NvError_EventNotFound, 0x00060000, "no event found") + +/* Nv2D error codes */ +NVERROR(NvError_InvalidSurface, 0x00070000, "invalid surface") +NVERROR(NvError_RopNotSupported, 0x00070001, "rop not supported") +NVERROR(NvError_SurfaceNotSupported, 0x00070002, "surface is not supported") +NVERROR(NvError_BitmapNotSupported, 0x00070003, "bitmap is not supported") + +/* NvPower error codes */ +NVERROR(NvError_ResourceAlreadyInUse, 0x00080000, "resource already in use") +NVERROR(NvError_ResourceNotInUse, 0x00080001, "resource not in use") +NVERROR(NvError_ResourceInUse, 0x00080002, "resource is in use") + +/* UART error codes */ +NVERROR(NvError_UartOverrun, 0x00090000, "overrun occurred when receiving the data") +NVERROR(NvError_UartFraming, 0x00090001, "data received had framing error") +NVERROR(NvError_UartParity, 0x00090002, "data received had parity error") +NVERROR(NvError_UartFifoError, 0x00090003, "FIFO error occurred during receive/transmit") +NVERROR(NvError_UartBreakReceived, 0x00090004, "received break signal") +NVERROR(NvError_UartTransmit, 0x00090005, "UART transmit error") + +/* NvRm error code */ +NVERROR(NvError_RmInitFailed, 0x000a0000, "rm failed to initialize") +NVERROR(NvError_RmChannelInitFailure, 0x000a0001, "channel init failed") +NVERROR(NvError_RmStreamInitFailure, 0x000a0002, "stream init failed") +NVERROR(NvError_RmSyncPointAllocFailure, 0x000a0003, "sync point alloc failed") +NVERROR(NvError_RmStreamFlushFailure, 0x000a0004, "stream flush failed") + +/* NvIsp error codes */ +NVERROR(NvError_ChannelAllocFailed, 0x000B0000, "channel allocation failed") +NVERROR(NvError_NoConnectedImager, 0x000B0001, "no imager connected") +NVERROR(NvError_UnsupportedResolution, 0x000B0002, "unsupported resolution") +NVERROR(NvError_I2CCommunicationError, 0x000B0003, "i2c communication failed") +NVERROR(NvError_IspConfigFileParseError, 0x000B0004, "isp config file parse error") +NVERROR(NvError_IspBusy, 0x000B0005, "isp 3A algorithm busy") +NVERROR(NvError_TooDark, 0x000B0006, "image too dark for 3A operation") + +/* NvTest error codes */ +NVERROR(NvError_TestApplicationFailed, 0x000c0000, "the test application failed") +NVERROR(NvError_TestNoUserInput, 0x000c0001, "no user input available") +NVERROR(NvError_TestCommandLineError, 0x000c0002, "command line parsing error") + +/* NvCam error codes */ +NVERROR(NvError_VmAllocFailed, 0x000D0000, "virtual machine allocation failed") +NVERROR(NvError_ScriptAccessFailed, 0x000D0001, "unable to access script") +NVERROR(NvError_GettingComponentFailed, 0x000D0002, "getting component failed") +NVERROR(NvError_VmBufferAllocFailed, 0x000D0003, "vm buffer allocation failed") +NVERROR(NvError_CameraScriptNotPresent, 0x000D0004, "camera script not present") +NVERROR(NvError_IllegalBayerValues, 0x000D0005, "illegal bayer values") +NVERROR(NvError_ColorFormatNotSupported, 0x000D0006, "color format not supported") + +/* USBF error codes */ +NVERROR(NvError_UsbfTxfrActive, 0x000E0000, "The endpoint has an active transfer in progress.") +NVERROR(NvError_UsbfTxfrComplete, 0x000E0001, "The endpoint has a completed transfer that has not been cleared.") +NVERROR(NvError_UsbfEpStalled, 0x000E0002, "The endpoint has been placed in a halted or stalled state.") +NVERROR(NvError_UsbfEpError, 0x000E0003, "The last transfer started on this endpoint failed to complete.") + +/* ^^^ ADD ALL NEW ERRORS RIGHT ABOVE HERE ^^^ */ + +NVERROR(NvErrorNotImplemented, 0x00000001, "remove me later!") +NVERROR(NvErrorNotSupported, 0x00000002, "remove me later!") +NVERROR(NvErrorNotInitialized, 0x00000003, "remove me later!") +NVERROR(NvErrorBadParameter, 0x00000004, "remove me later!") +NVERROR(NvErrorTimeout, 0x00000005, "remove me later!") +NVERROR(NvErrorInsufficientMemory, 0x00000006, "remove me later!") +NVERROR(NvErrorReadOnlyAttribute, 0x00000007, "remove me later!") +NVERROR(NvErrorInvalidState, 0x00000008, "remove me later!") +NVERROR(NvErrorInvalidAddress, 0x00000009, "remove me later!") +NVERROR(NvErrorInvalidSize, 0x0000000A, "remove me later!") +NVERROR(NvErrorBadValue, 0x0000000B, "remove me later!") + +/* surface specific error codes */ +NVERROR(NvErrorInsufficientVideoMemory, 0x00010000, "remove me later!") +NVERROR(NvErrorBadSurfaceColorScheme, 0x00010001, "remove me later!") + +/* display specific error codes */ +NVERROR(NvErrorDisplayIncompatible, 0x00020000, "remove me later!") +NVERROR(NvErrorNoCompatibleMode, 0x00020001, "remove me later!") +NVERROR(NvErrorModeNotSupported, 0x00020002, "remove me later!") +NVERROR(NvErrorControllerActive, 0x00020003, "remove me later!") +NVERROR(NvErrorDisplayAlreadyAttached, 0x00020004, "remove me later!") +NVERROR(NvErrorDetachDisplayFirst, 0x00020005, "remove me later!") +NVERROR(NvErrorTooManyDisplays, 0x00020006, "remove me later!") +NVERROR(NvErrorNoDisplaysAttached, 0x00020007, "remove me later!") +NVERROR(NvErrorAlreadySuspended, 0x00020008, "remove me later!") +NVERROR(NvErrorNotSuspended, 0x00020009, "remove me later!") +NVERROR(NvErrorEmptyColorKeyRange, 0x00020010, "remove me later!") +NVERROR(NvErrorNoMode, 0x00020011, "remove me later!") +NVERROR(NvErrorNotInVerticalBlank, 0x00020012, "remove me later!") + +/* DMA specific error codes */ +NVERROR(NvErrorDmaTargetNotLocked, 0x00030000, "remove me later!") +NVERROR(NvErrorDmaCommunicationError, 0x00030001, "remove me later!") +NVERROR(NvErrorDmaOpNotFinished, 0x00030002, "remove me later!") +NVERROR(NvErrorDmaChannelNotAvailable, 0x00030003, "remove me later!") +NVERROR(NvErrorInvalidSourceId, 0x00030004, "remove me later!") +NVERROR(NvErrorInvalidDestinationId, 0x00030005, "remove me later!") + +/* NvOs error codes */ +NVERROR(NvErrorFileWriteFailed, 0x00040000, "remove me later!") +NVERROR(NvErrorFileReadFailed, 0x00040001, "remove me later!") +NVERROR(NvErrorEndOfFile, 0x00040002, "remove me later!") +NVERROR(NvErrorFileOperationFailed, 0x00040003, "remove me later!") +NVERROR(NvErrorDirOperationFailed, 0x00040004, "remove me later!") +NVERROR(NvErrorEndOfDirList, 0x00040005, "remove me later!") +NVERROR(NvErrorConfigVarNotFound, 0x00040006, "remove me later!") +NVERROR(NvErrorInvalidConfigVar, 0x00040007, "remove me later!") +NVERROR(NvErrorLibraryNotFound, 0x00040008, "remove me later!") +NVERROR(NvErrorSymbolNotFound, 0x00040009, "remove me later!") +NVERROR(NvErrorMemoryMapFailed, 0x0004000a, "remove me later!") +NVERROR(NvErrorMutexCreateFailed, 0x0004000b, "remove me later!") +NVERROR(NvErrorSemaphoreCreateFailed, 0x0004000c, "remove me later!") +NVERROR(NvErrorThreadCreateFailed, 0x0004000d, "remove me later!") +NVERROR(NvErrorSharedMemAllocFailed, 0x0004000e, "remove me later!") + +/* NvBoard error codes */ +NVERROR(NvErrorI2CNotAcknowledged, 0x00050000, "remove me later!") +NVERROR(NvErrorKernelDriverNotFound, 0x00050001, "remove me later!") +NVERROR(NvErrorKernelDriverBadVersion, 0x00050002, "remove me later!") +NVERROR(NvErrorKernelDriverIOFailed, 0x00050003, "remove me later!") +NVERROR(NvErrorModeMismatched, 0x00050004, "remove me later!") +NVERROR(NvErrorVoltageOutsideRange, 0x00050005, "remove me later!") +NVERROR(NvErrorEventNotEnabled, 0x00050006, "remove me later!") +NVERROR(NvErrorEventBusy, 0x00050007, "remove me later!") +NVERROR(NvErrorInterruptInitFailed, 0x00050008, "remove me later!") + +/* NvIrq error codes */ +NVERROR(NvErrorEventNotFound, 0x00060000, "remove me later!") + +/* Nv2D error codes */ +NVERROR(NvErrorInvalidSurface, 0x00070000, "remove me later!") +NVERROR(NvErrorRopNotSupported, 0x00070001, "remove me later!") +NVERROR(NvErrorSurfaceNotSupported, 0x00070002, "remove me later!") +NVERROR(NvErrorBitmapNotSupported, 0x00070003, "remove me later!") + +/* NvPower error codes */ +NVERROR(NvErrorResourceAlreadyInUse, 0x00080000, "remove me later!") +NVERROR(NvErrorResourceNotInUse, 0x00080001, "remove me later!") +NVERROR(NvErrorResourceInUse, 0x00080002, "remove me later!") + +/* UART error codes */ +NVERROR(NvErrorUartOverrun, 0x00090000, "remove me later!") +NVERROR(NvErrorUartFraming, 0x00090001, "remove me later!") +NVERROR(NvErrorUartParity, 0x00090002, "remove me later!") +NVERROR(NvErrorUartFifoError, 0x00090003, "remove me later!") +NVERROR(NvErrorUartBreakReceived, 0x00090004, "remove me later!") +NVERROR(NvErrorUartTransmit, 0x00090005, "remove me later!") + +/* NvRm error code */ +NVERROR(NvErrorRmInitFailed, 0x000a0000, "remove me later!") +NVERROR(NvErrorRmChannelInitFailure, 0x000a0001, "remove me later!") +NVERROR(NvErrorRmStreamInitFailure, 0x000a0002, "remove me later!") +NVERROR(NvErrorRmSyncPointAllocFailure, 0x000a0003, "remove me later!") +NVERROR(NvErrorRmStreamFlushFailure, 0x000a0004, "remove me later!") + +/* NvIsp error codes */ +NVERROR(NvErrorChannelAllocFailed, 0x000B0000, "remove me later!") +NVERROR(NvErrorNoConnectedImager, 0x000B0001, "remove me later!") +NVERROR(NvErrorUnsupportedResolution, 0x000B0002, "remove me later!") +NVERROR(NvErrorI2CCommunicationError, 0x000B0003, "remove me later!") +NVERROR(NvErrorIspConfigFileParseError, 0x000B0004, "remove me later!") +NVERROR(NvErrorIspBusy, 0x000B0005, "remove me later!") +NVERROR(NvErrorTooDark, 0x000B0006, "remove me later!") + +/* NvTest error codes */ +NVERROR(NvErrorTestApplicationFailed, 0x000c0000, "remove me later!") +NVERROR(NvErrorTestNoUserInput, 0x000c0001, "remove me later!") +NVERROR(NvErrorTestCommandLineError, 0x000c0002, "remove me later!") + +/* NvCam error codes */ +NVERROR(NvErrorVmAllocFailed, 0x000D0000, "remove me later!") +NVERROR(NvErrorScriptAccessFailed, 0x000D0001, "remove me later!") +NVERROR(NvErrorGettingComponentFailed, 0x000D0002, "remove me later!") +NVERROR(NvErrorVmBufferAllocFailed, 0x000D0003, "remove me later!") +NVERROR(NvErrorCameraScriptNotPresent, 0x000D0004, "remove me later!") +NVERROR(NvErrorIllegalBayerValues, 0x000D0005, "remove me later!") +NVERROR(NvErrorColorFormatNotSupported, 0x000D0006, "remove me later!") + +/* USBF error codes */ +NVERROR(NvErrorUsbfTxfrActive, 0x000E0000, "remove me later!") +NVERROR(NvErrorUsbfTxfrComplete, 0x000E0001, "remove me later!") +NVERROR(NvErrorUsbfEpStalled, 0x000E0002, "remove me later!") +NVERROR(NvErrorUsbfEpError, 0x000E0003, "remove me later!") + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvime.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvime.h new file mode 100755 index 00000000..e533f47f --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvime.h @@ -0,0 +1,849 @@ +/* + * Copyright (c) 2006 - 2007 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software and related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +/* + * nvime.h + * + * A collection of image enhancing functions that utilize the GoForce + * h/w. This file contains the common routines that are used by all + * image enhancing functions, as well as the APIs/enums/defines that are + * specific to all image enhancing functions. + * + * PLEASE NOTE: NvIme is not thread-safe. All API calls must be made in + * a single thread, or the application must explicitly protect each NvIme + * call with its own mutex. Any other usage is not guaranteed to work. + */ + +#ifndef NVIME +#define NVIME + +#include "nvtypes.h" +#include "GFRm.h" +#include "GFGx.h" +#include "GFVx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NvImeStruct_t *NvImeHandle; + +typedef enum { + NVIME_OK=0, + NVIME_OUT_OF_MEMORY=1, + NVIME_INIT_FAILED=2, + NVIME_INVALID_HANDLE=3, + NVIME_SURFACE_INDEX_OUT_OF_RANGE=4, + NVIME_INVALID_SURFACE=5, + NVIME_ILLEGAL_SURFACE_BASE=6, + NVIME_ILLEGAL_SURFACE_STRIDE=7, + NVIME_INVALID_ROTATION=8, + NVIME_INVALID_COORD=9, + NVIME_MISSING_SURFACE=10, + NVIME_INVALID_KERNEL=11, + NVIME_INVALID_KERNEL_SIZE=12, + NVIME_INVALID_PIXFMT=13, + NVIME_INVALID_LUT=14, + NVIME_UNSPECIFIED_OPERATION=15, + NVIME_UNSUPPORTED_OPERATION=16, + NVIME_OPERATION_FAILED=17, + NVIME_INVALID_FLAG=18, + NVIME_INVALID_GET=19, + NVIME_INVALID_SCALE=20, + NVIME_INVALID_BIAS=21, + NVIME_ILLEGAL_CSC_VALUES=22, + NVIME_ILLEGAL_COEFF=23, + NVIME_ILLEGAL_COEFF_ARRAY_SIZE=24, +} NvImeStatus; + + +// NvImeOpen() +// +// Initialize the library and return a handle to pass into all future +// API calls into this library. + +NvImeStatus NvImeOpen(GFRmHandle hRm, NvImeHandle *phIme); + + +// NvImeClose() +// +// Close down the library and relinquish all held resources. + +void NvImeClose(NvImeHandle *phIme); + + +// NvImeSetSourceSurface() +// +// Set a source surface. "index" can be in 0..NVIME_MAX_SOURCE_SURFACES-1. +// Because each source surface will be read as a texture by the 3D unit, +// each must abide by 3D's texture alignment restrictions. These +// restrictions are: +// +// SB1) Base of surface must begin at an aligned memory address. Use +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_ALIGNMENT_BYTES) +// to get this value. +// +// SB2) Stride must be a multiple of +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_STRIDE_BYTES) +// +// SB3) Stride must be a power of two +// +// SB4) Width must be between +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_MIN_WIDTH_PIXELS) and +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_MAX_WIDTH_PIXELS) +// +// SB5) Height must be between +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_MIN_HEIGHT_PIXELS) and +// NvIme_GetIntegerv(NVIME__GET_SRC_SURF_MAX_HEIGHT_PIXELS) +// +// Even though the 3D unit only understands textures that are powers of +// two in width and height, the width and height of the data contained +// within the source surfaces do NOT need to actually be a powers of two +// in size. Likewise, the height of the surface does not need to be a +// power of two (although the width always must be). +// +// If the width of the source data is not a power of two, then in addition +// to the above texture alignment restrictions, the following must be true: +// +// SBW1) Memory between the end of the data in a row and the end of the +// row must be allowed to be overwritten by this library. Because +// the 3D texture unit does bilinear interpolation, this library +// will need to replicate the last column of data out to the next +// (M/2) columns over, where M is the width of the kernel used. +// If width + (M/2) crosses over a power of two boundary, the +// adjusted width need only be as large as the power of two +// boundary. +// +// If the height of the source data is not a power of two, then in addition +// to the above texture alignment restrictions, the following must be true: +// +// SBH1) The height of the source surface does *not* need to be a power +// of two. +// +// SBH2) The height of the source surface needs to be large enough for the +// library to replicate the last row to the next (N/2) rows down, +// where N is the height of the kernel used. This area must be +// allowed to be overwritten by this library. If height + (N/2) +// crosses over a power of two boundary, the adjusted height need +// only be as large as the power of two boundary. +// +// Note that some image enhancing operations will only work on certain +// source pixel formats. The NvImeProcessRect() call will return an +// error code on a source pixel format mismatch. + +#define NVIME_MAX_SOURCE_SURFACES 5 +NvImeStatus NvImeSetSourceSurface(NvImeHandle hIme, + NvU32 index, + GFRMSURFACE *sourceSurface); + + +// NvImeSetDestSurface() +// +// Set the destination surface. Because the destination surface will be +// written by the 3D unit, each surface must abide by 3D's surface +// alignment restrictions. These restrictions are: +// +// DB1) Base of surface must begin at an aligned memory address. Use +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_ALIGNMENT_BYTES) +// to get this value. +// +// DB2) Stride must be a multiple of +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_STRIDE_BYTES) +// +// DB3) Width must be between +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_MIN_WIDTH_PIXELS) and +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_MAX_WIDTH_PIXELS) +// +// DB4) Height must be between +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_MIN_HEIGHT_PIXELS) and +// NvIme_GetIntegerv(NVIME__GET_DST_SURF_MAX_HEIGHT_PIXELS) +// +// "rotation" specifies how to rotate the source surfaces onto the +// destination surface as part of the rendering process. "rotation" +// must be one of GFGx's fast rotation modes. Specifically these are: +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_IDENTITY | 0 | 1 | | 0 | 1 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 2 | 3 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_ROT_90 | 0 | 1 | | 1 | 3 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 0 | 2 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_ROT_180 | 0 | 1 | | 3 | 2 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 1 | 0 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_ROT_270 | 0 | 1 | | 2 | 0 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 3 | 1 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_FLIP_X | 0 | 1 | | 1 | 0 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 3 | 2 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_FLIP_Y | 0 | 1 | | 2 | 3 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 0 | 1 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_TRANS_LR | 0 | 1 | | 0 | 2 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 1 | 3 | +// +---+---+ +---+---+ +// +// +---+---+ +---+---+ +// GFGXEX2_FAST_ROTATE_TRANS_RL | 0 | 1 | | 3 | 1 | +// +---+---+ --> +---+---+ +// | 2 | 3 | | 2 | 0 | +// +---+---+ +---+---+ +// +// Note that some image enhancing operations will only work on certain +// destination pixel formats. The NvImeProcessRect() call will return an +// error code on a destination pixel format mismatch. + +NvImeStatus NvImeSetDestSurface(NvImeHandle hIme, + GFRMSURFACE *destSurface, + NvU32 rotation); + + +// NvImeSetVxBltCSCCoeff() +// +// Set the Vx's color space conversion coefficients in the channel that +// NvIme is using. This API is nothing more than a pass-through to +// GFVxBltSetCSCCoeff(). However, it does need to be called if CSCCoeffs +// are desired to be changed. If GFVxBltSetCSCCoeff() is called directly +// by the application, the Vx issued commands in that channel will pick +// up the CSCCoeffs, but NvIme will not see them. +NvImeStatus NvImeSetVxBltCSCCoeff(NvImeHandle hIme, + GFVXCSCCOEF *pCoef, + NvU32 option); + + +// NvImeProcessRect() +// +// Render using the current algorithm. Application must call an NvIme +// API not contained within this header file that registers the algorithm +// to render with. +// +// "srcCoords" points to "numSrcCoords" GFRECTs. "srcCoords[i]" describes +// the region to use from the i'th sourceSurface. "dstCoord" points to a +// single GFRECT. If a coord extends beyond the size of the surface it +// refers to, it will be clamped to the surface boundaries. +// +// The range of pixels referred to in "dstCoord" and each "srcCoords[i]" +// do not have to match. Scaling up and down is supported. The quality +// of scaling up and down can vary with the particular image enhancing +// algorithm used. +// +// flags is used to pass down optional parameters to the renderer. +// +// NVIME_PR_FLAGS_DITHER_OUTPUT: dither color output to destination +// surface. This flag has no effect if destSurface->ColorFormat +// is GF_SURFACE_ARGB8888. + +#define NVIME_PR_FLAGS_DITHER_OUTPUT (1<<0) + +NvImeStatus NvImeProcessRect(NvImeHandle hIme, + NvU32 numSrcCoords, + GFRECT *srcCoords, + GFRECT *dstCoord, + NvU32 flags); + +// NvImeFinish() +// +// A blocking call that does not return until all previously called +// NvIme commands are complete. + +void NvImeFinish(NvImeHandle hIme); + + +// +// Kernel sizes +// +// When kernels are specified, they use row major order. For example a +// 3x3 kernel with weights arranged like so: +// +// w00 w01 w02 +// w10 w11 w12 +// w20 w21 w22 +// +// would be specified in memory in the following order: +// +// w00 w01 w02 w10 w11 w12 w20 w21 w22 + +typedef enum { + NVIME_KERNEL_SIZE_1x1=0, + NVIME_KERNEL_SIZE_3x1=1, + NVIME_KERNEL_SIZE_5x1=2, +} NvImeKernelSize; + + +// +// Pixel formats +// + +#define NVIME_COMPONENT_MASK(a) \ + (((1U << NVIME_PIXFMT_##a##_BITS) - 1) << NVIME_PIXFMT_##a##_SHIFT) + +#define NVIME_PIXFMT_L8_LUMINANCE_BITS 8 +#define NVIME_PIXFMT_L8_LUMINANCE_SHIFT 0 +#define NVIME_PIXFMT_L8_LUMINANCE_MASK NVIME_COMPONENT_MASK(L8_LUMINANCE) + +#define NVIME_PIXFMT_RGB565_BLUE_BITS 5 +#define NVIME_PIXFMT_RGB565_BLUE_SHIFT 0 +#define NVIME_PIXFMT_RGB565_BLUE_MASK NVIME_COMPONENT_MASK(RGB565_BLUE) +#define NVIME_PIXFMT_RGB565_GREEN_BITS 6 +#define NVIME_PIXFMT_RGB565_GREEN_SHIFT 5 +#define NVIME_PIXFMT_RGB565_GREEN_MASK NVIME_COMPONENT_MASK(RGB565_GREEN) +#define NVIME_PIXFMT_RGB565_RED_BITS 5 +#define NVIME_PIXFMT_RGB565_RED_SHIFT 11 +#define NVIME_PIXFMT_RGB565_RED_MASK NVIME_COMPONENT_MASK(RGB565_RED) + +#define NVIME_PIXFMT_RGB888_BLUE_BITS 8 +#define NVIME_PIXFMT_RGB888_BLUE_SHIFT 0 +#define NVIME_PIXFMT_RGB888_BLUE_MASK NVIME_COMPONENT_MASK(RGB888_BLUE) +#define NVIME_PIXFMT_RGB888_GREEN_BITS 8 +#define NVIME_PIXFMT_RGB888_GREEN_SHIFT 8 +#define NVIME_PIXFMT_RGB888_GREEN_MASK NVIME_COMPONENT_MASK(RGB888_GREEN) +#define NVIME_PIXFMT_RGB888_RED_BITS 8 +#define NVIME_PIXFMT_RGB888_RED_SHIFT 16 +#define NVIME_PIXFMT_RGB888_RED_MASK NVIME_COMPONENT_MASK(RGB888_RED) + +#define NVIME_PIXFMT_ARGB8888_BLUE_BITS 8 +#define NVIME_PIXFMT_ARGB8888_BLUE_SHIFT 0 +#define NVIME_PIXFMT_ARGB8888_BLUE_MASK NVIME_COMPONENT_MASK(ARGB8888_BLUE) +#define NVIME_PIXFMT_ARGB8888_GREEN_BITS 8 +#define NVIME_PIXFMT_ARGB8888_GREEN_SHIFT 8 +#define NVIME_PIXFMT_ARGB8888_GREEN_MASK NVIME_COMPONENT_MASK(ARGB8888_GREEN) +#define NVIME_PIXFMT_ARGB8888_RED_BITS 8 +#define NVIME_PIXFMT_ARGB8888_RED_SHIFT 16 +#define NVIME_PIXFMT_ARGB8888_RED_MASK NVIME_COMPONENT_MASK(ARGB8888_RED) +#define NVIME_PIXFMT_ARGB8888_ALPHA_SHIFT 24 +#define NVIME_PIXFMT_ARGB8888_ALPHA_MASK NVIME_COMPONENT_MASK(ARGB8888_ALPHA) + +#define NVIME_PIXFMT_BAYER10_BITS 10 +#define NVIME_PIXFMT_BAYER10_SHIFT 0 +#define NVIME_PIXFMT_BAYER10_MASK NVIME_COMPONENT_MASK(BAYER10) + +#define NVIME_PIXFMT_BAYER12_BITS 12 +#define NVIME_PIXFMT_BAYER12_SHIFT 0 +#define NVIME_PIXFMT_BAYER12_MASK NVIME_COMPONENT_MASK(BAYER12) + +#define NVIME_PIXFMT_BAYER14_BITS 14 +#define NVIME_PIXFMT_BAYER14_SHIFT 0 +#define NVIME_PIXFMT_BAYER14_MASK NVIME_COMPONENT_MASK(BAYER14) + +#define NVIME_PIXFMT_BAYER3D_LO_BITS 7 +#define NVIME_PIXFMT_BAYER3D_LO_SHIFT 0 +#define NVIME_PIXFMT_BAYER3D_LO_MASK NVIME_COMPONENT_MASK(BAYER3D_LO) +#define NVIME_PIXFMT_BAYER3D_HI_BITS 7 +#define NVIME_PIXFMT_BAYER3D_HI_SHIFT 8 +#define NVIME_PIXFMT_BAYER3D_HI_MASK NVIME_COMPONENT_MASK(BAYER3D_HI) + +typedef enum { + NVIME_PIXFMT_L8=0, // L=Luminance (R8=L8, G8=L8, B8=L8) + NVIME_PIXFMT_RGB565=1, + NVIME_PIXFMT_RGB888=2, + NVIME_PIXFMT_ARGB8888=3, + NVIME_PIXFMT_BAYER10=4, + NVIME_PIXFMT_BAYER12=5, + NVIME_PIXFMT_BAYER14=6, + NVIME_PIXFMT_BAYER3D=7, +} NvImePixelFormat; + + +// +// LUT values +// + +#define NVIME_LUT_ENTRIES 256 + + +// +// Scale factors +// + +typedef enum { + NVIME_SCALE_1_0=0, + NVIME_SCALE_2_0=1, + NVIME_SCALE_4_0=2, +} NvImeScaleFactor; + + +/* + * Below are APIs used to control the sharpening image enhancement + * operation. Sharpening takes in a YUV420p source surface and outputs + * to a destination surface of type RGB565, ARGB8888 or YUV420p. + * ==================================================================== + */ + +// NvImeSharpenGetIntegerv() +// +// Return the value or values of a selected parameter that apply to +// the YUV420p sharpen image enhancing operation. +// +// NVIME_SHARPEN_GET_SRC_SURF_ALIGNMENT_BYTES +// NVIME_SHARPEN_GET_DST_SURF_ALIGNMENT_BYTES +// +// "params" returns 1 value, the SOURCE/DEST surface's starting +// address must be aligned to this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_STRIDE_BYTES +// NVIME_SHARPEN_GET_DST_SURF_STRIDE_BYTES +// +// "params" returns 1 value, the SOURCE/DEST surface's stride must +// be a multiple of this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_MIN_WIDTH_PIXELS +// NVIME_SHARPEN_GET_DST_SURF_MIN_WIDTH_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's width in +// pixels must be greater than or equal to this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_MAX_WIDTH_PIXELS +// NVIME_SHARPEN_GET_DST_SURF_MAX_WIDTH_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's width in +// pixels must be less than or equal to this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_MIN_HEIGHT_PIXELS +// NVIME_SHARPEN_GET_DST_SURF_MIN_HEIGHT_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's height in +// pixels must be greater than or equal to this value. +// +// NVIME_SHARPEN_GET_SRC_SURF_MAX_HEIGHT_PIXELS +// NVIME_SHARPEN_GET_DST_SURF_MAX_HEIGHT_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's height in +// pixels must be less than or equal to this value. + +typedef enum { + NVIME_SHARPEN_GET_SRC_SURF_ALIGNMENT_BYTES=0, + NVIME_SHARPEN_GET_SRC_SURF_STRIDE_BYTES=1, + NVIME_SHARPEN_GET_SRC_SURF_MIN_WIDTH_PIXELS=2, + NVIME_SHARPEN_GET_SRC_SURF_MAX_WIDTH_PIXELS=3, + NVIME_SHARPEN_GET_SRC_SURF_MIN_HEIGHT_PIXELS=4, + NVIME_SHARPEN_GET_SRC_SURF_MAX_HEIGHT_PIXELS=5, + NVIME_SHARPEN_GET_DST_SURF_ALIGNMENT_BYTES=6, + NVIME_SHARPEN_GET_DST_SURF_STRIDE_BYTES=7, + NVIME_SHARPEN_GET_DST_SURF_MIN_WIDTH_PIXELS=8, + NVIME_SHARPEN_GET_DST_SURF_MAX_WIDTH_PIXELS=9, + NVIME_SHARPEN_GET_DST_SURF_MIN_HEIGHT_PIXELS=10, + NVIME_SHARPEN_GET_DST_SURF_MAX_HEIGHT_PIXELS=11, +} NvImeSharpenGet; + +NvImeStatus NvImeSharpenGetIntegerv(NvImeHandle hIme, + NvImeSharpenGet name, + int *params); + + +// NvImeSharpenParams() +// +// Specify sharpen parameters to use during subsequent call to +// NvImeProcessRect(). +// +// When NvImeProcessRect() is called with sharpening in effect, there +// are additional restrictions are applied: +// +// 1) Only sourceSurfaces[0] is used. Which means that numSrcCoords +// must be 1. Stretching sub-regions of a surface is not +// supported. Because pixels will be replicated as needed to +// provide a buffer for the filter kernel, if one were to use +// a sub-region of a surface, valid data would be over-written. +// dstCoord can have arbitrary values that allow scaling within +// destSurface. +// +// 2) sourceSurfaces[0]->ColorFormat must be one of: +// +// GF_SURFACE_YUV420 +// GF_SURFACE_JPEGDEC +// GF_SURFACE_MPEGDEC +// +// 3) destSurface->ColorFormat must be one of: +// +// GF_SURFACE_RGB565 +// GF_SURFACE_ARGB8888 +// GF_SURFACE_YUV420 +// GF_SURFACE_JPEGDEC +// GF_SURFACE_MPEGDEC +// +// 4) The rotation value must be GFGXEX2_FAST_ROTATE_IDENTITY (any +// desired rotation must be performed after this library has +// finished its processing). +// +// The sharpening algorithm is described as follows: +// +// 1) The Y data in sourceSurfaces[0] is replicated as needed. The +// number of pixels replicated at the end of each row will be: +// +// MAX( (M/2), distance to next power-of-two ) +// +// where M is the width of the kernel. Note that if +// sourceSurfaces[0]'s width is a power-of-two, then the distance +// to the next power-of-two will be zero, and no pixels will be +// replicated. +// +// The number of pixels replicated at the bottom of each column +// will be: +// +// MAX( (N/2), distance to next power-of-two ) +// +// where N is the height of the kernel. Note that if +// sourceSurfaces[0]'s height is a power-of-two, then the distance +// to the next power-of-two will be zero, and no pixels will be +// replicated. +// +// 2) If destSurface->ColorFormat is GF_SURFACE_RGB565 or +// GF_SURFACE_ARGB8888, then a 2D StretchBlit is performed on +// sourceSurfaces[0] to destSurface. The full range of +// sourceSurfaces[0] will be scaled to the region indicated by +// dstCoord within destSurface. +// +// If destSurface->ColorFormat is GF_SURFACE_YUV420, +// GF_SURFACE_JPEGDEC or GF_SURFACE_MPEGDEC then no StretchBlit +// will be performed. The 3D stage of the algorithm will write +// the destination directly without blending to an RGB surface. +// +// 3) For each pixel in the region within destSurface specified by +// dstCoord, the 3D unit will perform a number of texture reads from +// sourceSurfaces[0] that matches the size of the kernel. Each +// texture read will be bilinearly filtered. The texture reads will +// be multiplied times the S1.8 kernel weights, summed together, +// scaled by one of 1.0, 2.0 or 4.0, a bias is added, and the result +// is clamped to the 0.0 to 1.0 range (note that intermediate values +// that exceed the h/w's S1.8 numeric range will be clamped to S1.8). +// The final clamped value will index into the provided LUT, which +// contains biased color values. +// +// When destSurface->ColorFormat is GF_SURFACE_RGB565 or ARGB8888: +// +// Each color channel from the LUT value will be multiplied by +// 2.0 and then have 1.0 subtracted from it. These unbiased +// colors will be added to the pixel in destSurface. +// +// When destSurface->ColorFormat is GF_SURFACE_YUV420, +// GF_SURFACE_JPEGDEC or GF_SURFACE_MPEGDEC: +// +// The red color channel from the LUT value will be multiplied +// by 2.0 and then have 1.0 subtracted from it. This unbiased +// color will be added to the Y value from sourceSurfaces[0] +// and be written to the Y pixel in destSurface. The U and V +// pixels in destSurface will be scaled by the 3D h/w using a +// 2x2 filter. No sharpening is applied to the U and V pixels. +// +// Below is a psuedo-code approximation for this part of the algorithm: +// +// // for each pixel +// for ( y=dstCoord->top ; x<=dstCoord->bottom ; y++ ) { +// for ( x=dstCoord->left ; x<=dstCoord->right ; x++ ) { +// +// // get proper indices for sourceSurfaces[0] +// srcX = sourcesSurfaces[0].width * x/destSurface.width; +// srcY = sourcesSurfaces[0].height * y/destSurface.height; +// +// // for each kernel entry +// idx = 0; +// for ( ky=0 ; ky 1.0) idx = 1.0; +// +// if ((destSurface->ColorFormat == GF_SURFACE_YUV420) || +// (destSurface->ColorFormat == GF_SURFACE_JPEGDEC) || +// (destSurface->ColorFormat == GF_SURFACE_MPEGDEC)) { +// // write the color value +// dstColor[x,y] = srcColor[srcX, srcY] + +// 2.0 * lut[NVIME_LUT_ENTRIES * idx] - 1.0; +// } else { +// // update color value +// dstColor[x,y] += 2.0 * lut[NVIME_LUT_ENTRIES * idx] - 1.0; +// } +// } +// } +// +// The supported kernel sizes are: +// +// NVIME_KERNEL_SIZE_1x1 +// NVIME_KERNEL_SIZE_3x1 +// NVIME_KERNEL_SIZE_5x1 +// +// Each value in the kernel must be in S1.8 format, which means values +// between -2 inclusive and +2 exclusive in increments of 1/256 are +// representable. +// +// The LUT must contain NVIME_LUT_ENTRIES entries, each of size NvU32. +// The supported LUT formats are: +// +// NVIME_PIXFMT_L8 +// NVIME_PIXFMT_RGB888 +// +// Refer to the NVIME_PIXFMT_* macros for appropriate color channel bit +// positions. When destSurface->ColorFormat is GF_SURFACE_YUV420, +// GF_SURFACE_JPEGDEC or GF_SURFACE_MPEGDEC the Y buffer is processed +// directly without going through an RGB space. Because the Y buffer is +// monochrome, only the red channel of an RGB888 LUT will be used when +// the destSurface->ColorFormat is GF_SURFACE_YUV420, GF_SURFACE_JPEGDEC +// or GF_SURFACE_MPEGDEC. +// +// The finalScale parameter can be any of NVIME_SCALE_1_0, NVIME_SCALE_2_0, +// or NVIME_SCALE_4_0. +// +// The finalBias parameter must be in S1.8 format. + +NvImeStatus +NvImeSharpenParams(NvImeHandle hIme, + NvImeKernelSize kernelSize, + NvU32 *kernel, + NvImePixelFormat lutFormat, + NvU32 *lut, + NvImeScaleFactor finalScale, + NvU32 finalBias); + + +/* + * Below are APIs used to control the anti-vignetting (also known as + * lens correction) image enhancement operation. Anti-vignetting takes + * in a BAYER3D source surface and outputs either BAYER10, BAYER12 or + * BAYER14 data to the same source surface. BAYER3D is format that has + * 14bits of data like BAYER14, but has unused bits at positions 8 and 16. + * So if your 16bits of data looked like --dcba9876543210, these would + * be stored in BAYER3D as -dcba987-6543210. + * ==================================================================== + */ + +// NvImeAntivigGetIntegerv() +// +// Return the value or values of a selected parameter that apply to +// the BAYER3D anti-vignetting image operation. +// +// NVIME_ANTIVIG_GET_SURF_ALIGNMENT_BYTES +// +// "params" returns 1 value, the SOURCE/DEST surface's starting +// address must be aligned to this value. +// +// NVIME_ANTIVIG_GET_SURF_STRIDE_BYTES +// +// "params" returns 1 value, the SOURCE/DEST surface's stride must +// be a multiple of this value. +// +// NVIME_ANTIVIG_GET_SURF_MIN_WIDTH_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's width in +// pixels must be greater than or equal to this value. +// +// NVIME_ANTIVIG_GET_SURF_MAX_WIDTH_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's width in +// pixels must be less than or equal to this value. +// +// NVIME_ANTIVIG_GET_SURF_MIN_HEIGHT_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's height in +// pixels must be greater than or equal to this value. +// +// NVIME_ANTIVIG_GET_SURF_MAX_HEIGHT_PIXELS +// +// "params" returns 1 value, the SOURCE/DEST surface's height in +// pixels must be less than or equal to this value. +// +// NVIME_ANTIVIG_GET_COEFF_ARRAY_MIN_WIDTH +// +// "params" returns 1 value, the minimum "widthCoeffArrays" that +// can be passed into NvImeAntivigParams. +// +// NVIME_ANTIVIG_GET_COEFF_ARRAY_MAX_WIDTH +// +// "params" returns 1 value, the maximum "widthCoeffArrays" that +// can be passed into NvImeAntivigParams. +// +// NVIME_ANTIVIG_GET_COEFF_ARRAY_MIN_HEIGHT +// +// "params" returns 1 value, the minimum "heightCoeffArrays" that +// can be passed into NvImeAntivigParams. +// +// NVIME_ANTIVIG_GET_COEFF_ARRAY_MAX_HEIGHT +// +// "params" returns 1 value, the maximum "heightCoeffArrays" that +// can be passed into NvImeAntivigParams. + +typedef enum { + NVIME_ANTIVIG_GET_SURF_ALIGNMENT_BYTES=0, + NVIME_ANTIVIG_GET_SURF_STRIDE_BYTES=1, + NVIME_ANTIVIG_GET_SURF_MIN_WIDTH_PIXELS=2, + NVIME_ANTIVIG_GET_SURF_MAX_WIDTH_PIXELS=3, + NVIME_ANTIVIG_GET_SURF_MIN_HEIGHT_PIXELS=4, + NVIME_ANTIVIG_GET_SURF_MAX_HEIGHT_PIXELS=5, + NVIME_ANTIVIG_GET_COEFF_ARRAY_MIN_WIDTH=6, + NVIME_ANTIVIG_GET_COEFF_ARRAY_MAX_WIDTH=7, + NVIME_ANTIVIG_GET_COEFF_ARRAY_MIN_HEIGHT=8, + NVIME_ANTIVIG_GET_COEFF_ARRAY_MAX_HEIGHT=9, +} NvImeAntivigGet; + +NvImeStatus NvImeAntivigGetIntegerv(NvImeHandle hIme, + NvImeAntivigGet name, + int *params); + + +// NvImeAntivigParams() +// +// Specify anti-vignetting parameters to use during subsequent call to +// NvImeProcessRect(). +// +// When NvImeProcessRect() is called with anti-vignetting in effect, +// there are additional restrictions that are applied: +// +// 1) Only sourceSurfaces[0] is used. Which means that numSrcCoords +// must be 1. +// +// 2) sourceSurfaces[0]->ColorFormat must be GF_SURFACE_BAYER16. +// The actual data contained in the surface must be in the +// BAYER3D format. BAYER3D has 14 bits of data, where bits 13 +// and 7 are ignored. So if your data value is --dcba9876543210, +// that would be stored in BAYER3D format as -dcba987-6543210. +// +// 3) The contents of the structure pointed to by destSurface must +// be equal to the contents of the structure pointed to by +// sourceSurfaces[0]. +// +// 4) The contents of the structure pointed to by dstCoord must be +// equal to the contents of the structure pointed to by +// srcCoords[0]. +// +// 5) The rotation value must be GFGXEX2_FAST_ROTATE_IDENTITY (any +// desired rotation must be performed after this library has +// finished its processing). +// +// The anti-vignetting algorithm is described below: +// +// 1) The 4 passed in coefficient arrays are scanned looking for the +// largest gain value. The largest gain is used to determine +// whether the overall coefficient range is in [0.0 .. 2.0], +// [0.0 .. 4.0], [0.0 .. 8.0] or [0.0 .. 16.0]. The lower the +// maximum gain, the more precise the output will be. Here is +// a table showing the output format as a function of the maximum +// gain value: +// +// Maximum gain Output pixel format +// ------------- ------------------- +// [0.0 .. 2.0] BAYER14 +// [0.0 .. 4.0] BAYER12 +// [0.0 .. 8.0] BAYER12 +// [0.0 .. 16.0] BAYER10 +// +// 2) After the maximum gain has been determined, the coefficient +// arrays are divided by their maximum value rounded up to a power +// of 2, and stored in an 8bit value. +// +// 3) When NvImeProcessRect is called, the 8bit gain values for the +// appropriate 00, 01, 10, 11 pixel are bilinearly interpolated. +// The result is multiplied times the BAYER3D pixel value from +// the source surface and then written back in place in a +// BAYER10/12/14 format. +// +// 4) NvImeProcessRect can process an entire BAYER3D buffer at a time, +// or a horizontal swath of the buffer. This is to support large +// buffers (like 5Mpixel) where it may not be practical (or even +// possible) to have multiple buffers residing in memory at the same +// time. +// +// NvImeAntivigAdjustScanline() modifies the access pattern of the +// 8bit gain values as if srcCoords[0].top were scanlineBias larger. +// This shifts the accesses down. +// +// For example, suppose you had a 2048x64 BAYER3D surface which is +// used to hold 32 pixel high swaths of a 2048x2048 surface in +// a double buffered manner. You would process the buffer like so: +// +// srcCoordsLow.top = 0; +// srcCoordsLow.left = 0; +// srcCoordsLow.right = 2047; +// srcCoordsLow.bottom = 31; +// +// srcCoordsHigh.top = 32; +// srcCoordsHigh.left = 0; +// srcCoordsHigh.right = 2047; +// srcCoordsHigh.bottom = 63; +// +// // Fill SourceSurface[0] rows [0..31] with camera rows [0..31] +// NvImeAntivigAdjustScanline(hIme, 0); +// NvImeProcessRects(hIme, 1, &srcCoordsLow, &srcCoordsLow, 0); +// +// // Fill SourceSurface[0] rows [32..63] with camera rows [32..63] +// NvImeProcessRects(hIme, 1, &srcCoordsHigh, &srcCoordsHigh, 0); +// +// // Fill SourceSurface[0] rows [0..31] with camera rows [64..95] +// NvImeAntivigAdjustScanline(hIme, 32); +// NvImeProcessRects(hIme, 1, &srcCoordsLow, &srcCoordsLow, 0); +// +// // Fill SourceSurface[0] rows [32..63] with camera rows [96..127] +// NvImeProcessRects(hIme, 1, &srcCoordsHigh, &srcCoordsHigh, 0); +// +// // Fill SourceSurface[0] rows [0..31] with camera rows [128..159] +// NvImeAntivigAdjustScanline(hIme, 64); +// NvImeProcessRects(hIme, 1, &srcCoordsLow, &srcCoordsLow, 0); +// +// // Fill SourceSurface[0] rows [32..63] with camera rows [160..191] +// NvImeProcessRects(hIme, 1, &srcCoordsHigh, &srcCoordsHigh, 0); +// +// // and so on... + +NvImeStatus +NvImeAntivigParams(NvImeHandle hIme, + NvU32 widthCoeffArrays, + NvU32 heightCoeffArrays, + float *coeffsPix00, + float *coeffsPix01, + float *coeffsPix10, + float *coeffsPix11, + NvU32 totalSurfaceWidth, + NvU32 totalSurfaceHeight, + NvImePixelFormat *outFormat); + +NvImeStatus +NvImeAntivigAdjustScanline(NvImeHandle hIme, NvU32 scanlineBias); + +#ifdef __cplusplus +} +#endif + +#endif /* NVIME */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvirq.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvirq.h new file mode 100755 index 00000000..d3bf5d8b --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvirq.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2006 NVIDIA Corporation. All rights reserved. + * + * NVIDIA Corporation and its licensors retain all intellectual property + * and proprietary rights in and to this software, related documentation + * and any modifications thereto. Any use, reproduction, disclosure or + * distribution of this software and related documentation without an express + * license agreement from NVIDIA Corporation is strictly prohibited. + */ + +#ifndef NVIRQ_H +#define NVIRQ_H + +/** NvIrq - Interrupt abstraction layer: + + This provides a simple interface for querying and masking abstract interrupt + events. The interface is designed to be used inside of the OEM's ISR or IST. + + NvIrq needs NvOsPhysicalMemMap and NvOsPhysicalMemUnmap (Only uncached + write-through functionality is used). NvOsSharedMem* is needed if NvIrq + isn't initialized as a singleton. + + NvIrq is not thread-safe. + */ + +#include "nvcommon.h" +#include "nverror.h" +#include "nvboard.h" + +/** NvIrqChannel enum defines available I/O channels. No two I/O operations can + safely occur at the same time on a channel. (This is only important in + indirect addressing. In direct address I/O operators are atomic and there + is no concept of channels). + */ +typedef enum +{ + /* Channel used while not in ISR. This channel is used by all user-mode code. */ + NvIrqChannel_Normal, + + /* Channel used in ISR context */ + NvIrqChannel_Isr +} NvIrqChannel; + +/* NvIrqInterruptPortInfo struct describes the MMIO layout of the interrupt + status registers */ +typedef struct NvIrqInterruptPortInfo_t +{ + /* Offset of status register */ + NvU32 statusOffset; + + /* Offset of mask register */ + NvU32 maskOffset; +} NvIrqInterruptPortInfo; + +/** NvIrqInit - Method to initialize the NvIrq API. + + This method is to be called before any other NvIrq methods can be used. + + If NvIrq is not initialized as a singleton, NvIrq will put its state in + shared memory. + */ +NvError +NvIrqInit( const NvBoardMode *pMode, const NvBoardApertures *pApertures, + NvBool singleton ); + +/** NvIrqDeInit - Method to deinitialize the NvIrq API. + */ +void +NvIrqDeInit( void ); + +/** NvIrqPostChipInit - To be called after the chip is intialized. + + This method should be called during NvBoardPostChipInit. If NvIrqInit succeeds + NvIrqEnableInterrupt() should be used to unmask the global interrupt line. + */ +NvError +NvIrqPostChipInit( NvIrqChannel channel ); + +/** NvIrqPreChipDeInit - To be called before chip is shutdown. + + This method should be called during NvBoardPreChipDeInit. NvIrqDisableInterrupt() + should be called before invoking this method. + */ +void +NvIrqPreChipDeInit( NvIrqChannel channel ); + +/** NvIrqFastScan - Method to quickly check if interrupt is pending + + This method is faster than NvIrqScanForEvent. It only checks whether an + interrupt is pending or not. NvIrqScanForEvent should be called from an + IST to do the actual decoding. This is useful when ISR latency is + important. + + If an interrupt is pending the global SCxx interrupt line is masked + and should reenabled using NvIrqEnableInterrupt after NvIrqScanForEvent + is called. + */ +NvBool +NvIrqFastScan( NvIrqChannel channel ); + +/** NvIrqScanForEvent - Method to check SCxx for pending events. + + This method should be called from an ISR or IST. If a pending event is + found, the event is masked. Once an upper layer clears the source of + the event in hardware, the event can be reenabled. + + @retval NvSuccess - on success + NvErrorEventNotFound - no event found + */ +NvError +NvIrqScanForEvent( NvIrqChannel channel, NvDeviceEvent *event ); + +/** NvIrqIsEventPending - Check whether the event is pending + */ +NvBool +NvIrqIsEventPending( NvIrqChannel channel, NvDeviceEvent event ); + +/** NvIrqEnableInterrupt - Method to unmask global interrupt line + */ +void +NvIrqEnableInterrupt( NvIrqChannel channel ); + +/** NvIrqDisableInterrupt - Method to mask global interrupt line + */ +void +NvIrqDisableInterrupt( NvIrqChannel channel ); + +/** NvIrqEnableEvent - Method to unmask an event + */ +void +NvIrqEnableEvent( NvIrqChannel channel, NvDeviceEvent event ); + +/** NvIrqDisableEvent - Method to mask an event + */ +void +NvIrqDisableEvent( NvIrqChannel channel, NvDeviceEvent event ); + +/** NvIrqQueryInterruptPortInfo - Method to query interrupt port info. Calling + this method should be strongly avoided. + */ +NvError +NvIrqQueryInterruptPortInfo( NvIrqInterruptPortInfo *pPortInfo ); + +#endif // NVIRQ_H diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvtypes.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvtypes.h new file mode 100755 index 00000000..ba01db2d --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/nvtypes.h @@ -0,0 +1,258 @@ + /***************************************************************************\ +|* *| +|* Copyright 1993-1998 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NOTICE TO USER: The source code is copyrighted under U.S. and *| +|* international laws. Users and possessors of this source code are *| +|* hereby granted a nonexclusive, royalty-free copyright license to *| +|* use this code in individual and commercial software. *| +|* *| +|* Any use of this source code must include, in the user documenta- *| +|* tion and internal comments to the code, notices to the end user *| +|* as follows: *| +|* *| +|* Copyright 1993-1998 NVIDIA, Corporation. All rights reserved. *| +|* *| +|* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *| +|* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *| +|* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *| +|* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *| +|* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *| +|* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *| +|* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *| +|* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *| +|* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *| +|* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *| +|* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *| +|* *| +|* U.S. Government End Users. This source code is a "commercial *| +|* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *| +|* consisting of "commercial computer software" and "commercial *| +|* computer software documentation," as such terms are used in *| +|* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *| +|* ment only as a commercial end item. Consistent with 48 C.F.R. *| +|* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *| +|* all U.S. Government End Users acquire the source code with only *| +|* those rights set forth herein. *| +|* *| + \***************************************************************************/ + + + /***************************************************************************\ +|* *| +|* NV Architecture Interface *| +|* *| +|* defines common widths used to access hardware in of NVIDIA's *| +|* Unified Media Architecture (TM). *| +|* *| + \***************************************************************************/ + + +#ifndef NVTYPES_INCLUDED +#define NVTYPES_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + +#include "cpuopsys.h" + +#define NVRM_64 1 +#if defined(NV_64_BITS) +#define NVRM_TRUE64 1 +#endif + + /***************************************************************************\ +|* Typedefs *| + \***************************************************************************/ + +typedef unsigned char NvV8; /* "void": enumerated or multiple fields */ +typedef unsigned short NvV16; /* "void": enumerated or multiple fields */ +typedef unsigned char NvU8; /* 0 to 255 */ +typedef unsigned short NvU16; /* 0 to 65535 */ +typedef signed char NvS8; /* -128 to 127 */ +typedef signed short NvS16; /* -32768 to 32767 */ +typedef signed int NvS32; /* -2147483648 to 2147483647 */ +typedef float NvF32; /* IEEE Single Precision (S1E8M23) */ +typedef double NvF64; /* IEEE Double Precision (S1E11M52) */ + +/* mainly for 64-bit linux, where long is 64 bits + * and win9x, where int is 16 bit. + */ +#if (defined(NV_UNIX) || defined(vxworks) || defined(NV_WINDOWS_CE) || \ + defined(__arm) || defined(__IAR_SYSTEMS_ICC__) || defined(NV_QNX) || \ + defined(NV_INTEGRITY) || defined(NV_MODS) || defined(__GNUC__) ) && \ + !defined(NV_MACINTOSH) +typedef unsigned int NvV32; /* "void": enumerated or multiple fields */ +typedef unsigned int NvU32; /* 0 to 4294967295 */ +#else +typedef unsigned long NvV32; /* "void": enumerated or multiple fields */ +typedef unsigned long NvU32; /* 0 to 4294967295 */ +#endif + +/* 64-bit types for compilers that support them, plus some obsolete variants */ +#if defined(__GNUC__) || defined(__arm) || defined(__IAR_SYSTEMS_ICC__) || defined(__ghs__) || defined(_WIN64) +typedef unsigned long long NvU64; /* 0 to 18446744073709551615 */ +typedef long long NvS64; /* 2^-63 to 2^63-1 */ +#else +typedef unsigned __int64 NvU64; /* 0 to 18446744073709551615 */ +typedef __int64 NvS64; /* 2^-63 to 2^63-1 */ +#endif + +/* Boolean type */ +enum { NV_FALSE = 0, NV_TRUE = 1 }; +typedef NvU8 NvBool; + +/* Macros to extract the low and high parts of a 64-bit unsigned integer */ +/* Also designed to work if someone happens to pass in a 32-bit integer */ +#define NvU64_HI32(n) ((NvU32)(((NvU64)(n)) >> 32)) +#define NvU64_LO32(n) ((NvU32)((NvU64)(n))) +#define NvU40_HI32(n) ((NvU32)((((NvU64)(n))>>8)&0xffffffff)) +#define NvU40_HI24of32(n) ((NvU32)((((NvU64)(n)& 0xffffffff))&0xffffff00)) + + /***************************************************************************\ +|* *| +|* 64 bit type definitions for use in interface structures. *| +|* *| + \***************************************************************************/ + +#if defined(NV_64_BITS) + +typedef void* NvP64; /* 64 bit void pointer */ +typedef NvU64 NvUPtr; /* pointer sized unsigned int */ + +#define NvP64_VALUE(n) (n) + +#else + +typedef NvU64 NvP64; /* 64 bit void pointer */ +typedef NvU32 NvUPtr; /* pointer sized unsigned int */ + +#define NvP64_VALUE(n) ((void *)(NvUPtr)(n)) + +#endif + +// XXX Obsolete -- get rid of me... +typedef NvP64 NvP64_VALUE_T; +typedef NvUPtr NV_UINTPTR_T; +#define NvP64_LVALUE(n) (n) +#define NvP64_SELECTOR(n) (0) + +/* Useful macro to hide required double cast */ +#define NV_PTR_TO_NvP64(n) (NvP64)(NV_UINTPTR_T)(n) + +/* obsolete stuff */ +/* MODS needs to be able to build without these definitions because they collide + with some definitions used in mdiag. */ +#ifndef DONT_DEFINE_U032 +typedef NvV8 V008; +typedef NvV16 V016; +typedef NvV32 V032; +typedef NvU8 U008; +typedef NvU16 U016; +typedef NvU32 U032; +typedef NvS8 S008; +typedef NvS16 S016; +typedef NvS32 S032; +#endif +#if defined(MACOS) || defined(macintosh) || defined(__APPLE_CC__) || defined(NV_MODS) || defined(MINIRM) || defined(NV_UNIX) || defined (NV_QNX) +/* more obsolete stuff */ +/* need to provide these on macos9 and macosX */ +#if defined(__APPLE_CC__) /* gross but Apple osX already claims ULONG */ +#undef ULONG // just in case +#define ULONG unsigned long +#else +typedef unsigned long ULONG; +#endif +typedef unsigned char *PUCHAR; +#endif + +#if !defined(NV_PTR) + /* Supports 32bit libraries on Win64 + See drivers\opengl\include\nvFirst.h for explanation */ +#define NV_PTR +#define CAST_NV_PTR(p) p +#endif + +/* Aligns fields in structs so they match up between 32 and 64 bit builds */ +/* XXX Mac still uses structures without alignment -- needs to be fixed */ +#if (defined(__GNUC__) || defined(NV_QNX)) && !defined(NV_MACINTOSH) +#define NV_ALIGN_BYTES(size) __attribute__ ((aligned (size))) +#elif defined(__arm) +#define NV_ALIGN_BYTES(size) __align(ALIGN) +#else +// XXX This is dangerously nonportable! We really shouldn't provide a default +// version of this that doesn't do anything. +#define NV_ALIGN_BYTES(size) +#endif + +// NV_DECLARE_ALIGNED() can be used on all platforms. +// This macro form accounts for the fact that __declspec on Windows is required +// before the variable type, +// and NV_ALIGN_BYTES is required after the variable name. +#if defined(NV_WINDOWS) +#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) __declspec(align(ALIGN)) TYPE_VAR +#elif defined(__GNUC__) || defined(NV_QNX) +#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) TYPE_VAR __attribute__ ((aligned (ALIGN))) +#elif defined(__arm) +#define NV_DECLARE_ALIGNED(TYPE_VAR, ALIGN) __align(ALIGN) TYPE_VAR +#endif + + +/***************************************************************************\ +|* Function Declaration Types *| + \***************************************************************************/ + +// stretching the meaning of "nvtypes", but this seems to least offensive +// place to re-locate these from nvos.h which cannot be included by a number +// of builds that need them + +#if defined(NV_WINDOWS) + + #define NV_INLINE __inline + + #if _MSC_VER >= 1200 + #define NV_FORCEINLINE __forceinline + #else + #define NV_FORCEINLINE __inline + #endif + + #define NV_APIENTRY __stdcall + #define NV_FASTCALL __fastcall + #define NV_CDECLCALL __cdecl + #define NV_STDCALL __stdcall + +#else // defined(NV_WINDOWS) + + #if defined(__GNUC__) || defined(__INTEL_COMPILER) + #define NV_INLINE __inline__ + #elif defined (macintosh) + #define NV_INLINE inline + #elif defined(__arm) + #define NV_INLINE __inline + #else + #define NV_INLINE + #endif + + #if defined(__GNUC__) + // GCC 3.1 and beyond support the always_inline function attribute. + #if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) + #define NV_FORCEINLINE __inline__ __attribute__((always_inline)) + #else + #define NV_FORCEINLINE __inline__ + #endif + #else /* defined(__GNUC__) */ + #define NV_FORCEINLINE NV_INLINE + #endif + + #define NV_APIENTRY + #define NV_FASTCALL + #define NV_CDECLCALL + #define NV_STDCALL + +#endif // defined(NV_WINDOWS) + +#ifdef __cplusplus +}; +#endif + +#endif /* NVTYPES_INCLUDED */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/vssver2.scc b/kernel-2.6.33/arch/arm/mach-pxa/g900/gf5500/inc/vssver2.scc new file mode 100755 index 0000000000000000000000000000000000000000..aaf2f3863685f3f430796c71bfeea422f9c199b3 GIT binary patch literal 1261 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%0AgIXXU9pljrhTjK}Iek_OU5+DU)}N~GjUU&)iv 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 + Copyright (C) + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile new file mode 100755 index 00000000..3cae3177 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile @@ -0,0 +1,31 @@ +# +# DOC driver Makefile for Linux 2.6. +# Copyright (C) 2006, msystems Ltd. All rights reserved. +# +# Use this Makefile if you want to build DOC driver as loadable +# kernel module. +# + +obj-m += tffs.o + +tffs-objs := trace32.o +tffs-objs += defs.o +tffs-objs += docdrv.o +tffs-objs += doch_api.o +tffs-objs += doch_ata.o +tffs-objs += dochstub.o +tffs-objs += dochtl.o +tffs-objs += docsys.o +tffs-objs += extfiltr.o +tffs-objs += fatfilt.o +tffs-objs += flbase.o +tffs-objs += flcustom.o +tffs-objs += flioctl.o +tffs-objs += flsystem.o +tffs-objs += hal_nor.o +tffs-objs += tffs2lnx.o +tffs-objs += tffs_api.o +tffs-objs += tffsarch.o +tffs-objs += tffs-pm26.o +tffs-objs += tffsdrv26.o + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-m b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-m new file mode 100755 index 00000000..3cae3177 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-m @@ -0,0 +1,31 @@ +# +# DOC driver Makefile for Linux 2.6. +# Copyright (C) 2006, msystems Ltd. All rights reserved. +# +# Use this Makefile if you want to build DOC driver as loadable +# kernel module. +# + +obj-m += tffs.o + +tffs-objs := trace32.o +tffs-objs += defs.o +tffs-objs += docdrv.o +tffs-objs += doch_api.o +tffs-objs += doch_ata.o +tffs-objs += dochstub.o +tffs-objs += dochtl.o +tffs-objs += docsys.o +tffs-objs += extfiltr.o +tffs-objs += fatfilt.o +tffs-objs += flbase.o +tffs-objs += flcustom.o +tffs-objs += flioctl.o +tffs-objs += flsystem.o +tffs-objs += hal_nor.o +tffs-objs += tffs2lnx.o +tffs-objs += tffs_api.o +tffs-objs += tffsarch.o +tffs-objs += tffs-pm26.o +tffs-objs += tffsdrv26.o + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-omap2420 b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-omap2420 new file mode 100755 index 00000000..f42dfefb --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-omap2420 @@ -0,0 +1,137 @@ +############################################################################### +# +# DOC driver Makefile for Linux 2.6. +# Copyright (C) 2006, msystems Ltd. All rights reserved. +# +# Use this Makefile if you want to build DOC driver outside of Linux +# kernel's source code tree. You will need to change the following +# macros in this Makefile as appropriate for your project: +# KERNEL_DIR +# CC +# CFLAGS +# LD +# LDFLAGS +# +############################################################################### + +# +# Specify name of this kernel module +# +MODULE_NAME = tffs + +# +# Specify root directory of kernel's source tree as appropriate +# for your installation. +# +KERNEL_DIR = /opt/ti/omap2420/kernel/269 + +# +# Specify which compiler to use (default is ARM/GCC compiler) +# +CC = arm-unknown-linux-gnu-gcc + +# +# Specify compiler flags in the same fashion as 'make modules' does. +# Flags below are appropriate for ARM compilation. +# +CFLAGS += -nostdinc +CFLAGS += -iwithprefix include +CFLAGS += -D__KERNEL__ +CFLAGS += -I$(KERNEL_DIR)/include +CFLAGS += -Wall +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wno-trigraphs +CFLAGS += -fno-strict-aliasing +CFLAGS += -fno-common + +# Uncomment line below if you want compiler to optimize for speed +# CFLAGS += -O2 +# Uncomment line below if you want compiler to optimize for space +# CFLAGS += -Os +# Uncomment line below if you are going to debug DOC driver +# CFLAGS += -g + +CFLAGS += -Wdeclaration-after-statement +CFLAGS += -fno-omit-frame-pointer +CFLAGS += -mapcs +CFLAGS += -mno-sched-prolog +CFLAGS += -mlittle-endian +CFLAGS += -mapcs-32 +CFLAGS += -D__LINUX_ARM_ARCH__=6 +CFLAGS += -march=armv5t +CFLAGS += -Wa,-march=armv6 +CFLAGS += -mtune=strongarm +CFLAGS += -malignment-traps +CFLAGS += -msoft-float +CFLAGS += -Uarm +CFLAGS += -DMODULE +CFLAGS += -DKBUILD_BASENAME=$(MODULE_NAME) +CFLAGS += -DKBUILD_MODNAME=$(MODULE_NAME) +# CFLAGS += -DTRACE32 +CFLAGS += -c + +# +# Uncomment line below only if you are using multiple cascaded +# mDOC devices +# +# CFLAGS += -DATA_MAX_NUM_OF_DEVICES=2 +# + +# +# Specify which linker to use (default is ARM linker) +# +LD = arm-unknown-linux-gnu-ld + +# +# Specify linker flags in the same fashion as 'make modules' does. +# Flags below are appropriate for ARM compilation. +# +LDFLAGS = -EL +LDFLAGS += -r + +# +# Module's objects: +# - trace32.o (if used) must be first in the link order ! +# - $(MODULE_NAME).mod.o must be last in the link order ! +# +OBJS = trace32.o +OBJS += defs.o +OBJS += docdrv.o +OBJS += doch_api.o +OBJS += doch_ata.o +OBJS += dochstub.o +OBJS += dochtl.o +OBJS += docsys.o +OBJS += extfiltr.o +OBJS += fatfilt.o +OBJS += flbase.o +OBJS += flcustom.o +OBJS += flioctl.o +OBJS += flsystem.o +OBJS += hal_nor.o +OBJS += tffs2lnx.o +OBJS += tffs_api.o +OBJS += tffsarch.o +OBJS += tffs-pm26.o +OBJS += tffsdrv26.o +OBJS += $(MODULE_NAME).mod.o + +# +# rule for building loadable kernel module +# +$(MODULE_NAME).ko : $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) + +# +# C compilation rules +# +%.o: %.c + $(CC) $(CFLAGS) -o $@ $< + +# +# 'make clean' rule +# +clean : + rm *.o *.ko + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-pxa27x b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-pxa27x new file mode 100755 index 00000000..20d4981c --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-pxa27x @@ -0,0 +1,177 @@ +#============================================================== +# +# Makefile for building DiskOnChip driver loadable module +# for Linux 2.6.x kernels +# +# Version 1.0 +# +#============================================================== + + +# +# Specify name of this kernel module +# +MODULE_NAME = tffs + + +# +# Specify root directory of Linux kernel's source tree as appropriate +# for your installation. +# +KERNEL_DIR = /opt/mobilinux41/pxa27x/andrayk/kernel/2.6.10 + + +# +# Specify which compiler to use (default is XScale compiler) +# +CC = iwmmxt_le-gcc + + +# +# Specify compiler flags in the same fashion as 'make modules' does. +# Flags below are appropriate for XScale compilation. +# +CFLAGS += -nostdinc +CFLAGS += -iwithprefix include +CFLAGS += -D__KERNEL__ +CFLAGS += -I$(KERNEL_DIR)/include +CFLAGS += -Wall +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wno-trigraphs +CFLAGS += -fno-strict-aliasing +CFLAGS += -fno-common +# CFLAGS += -Os +CFLAGS += -fno-omit-frame-pointer +CFLAGS += -g +CFLAGS += -marm +CFLAGS += -fno-omit-frame-pointer +CFLAGS += -mapcs +CFLAGS += -mno-sched-prolog +CFLAGS += -mlittle-endian +CFLAGS += -mabi=aapcs +CFLAGS += -mno-thumb-interwork +CFLAGS += -D__LINUX_ARM_ARCH__=5 +CFLAGS += -march=armv5te +CFLAGS += -mtune=xscale +CFLAGS += -Wa,-mcpu=xscale +CFLAGS += -msoft-float +CFLAGS += -Uarm +CFLAGS += -Wdeclaration-after-statement +CFLAGS += -DMODULE +CFLAGS += -DKBUILD_BASENAME=$(MODULE_NAME) +CFLAGS += -DKBUILD_MODNAME=$(MODULE_NAME) +# CFLAGS += -DTRACE32 +CFLAGS += -c + +# +# Uncomment line below only if you are using multiple cascaded +# mDOC devices +# +# CFLAGS += -DATA_MAX_NUM_OF_DEVICES=2 +# + +# +# Specify which linker to use (default is XScale linker) +# +LD = iwmmxt_le-ld + + +# +# Specify linker flags in the same fashion as 'make modules' does. +# Flags below are appropriate for XScale compilation. +# +LDFLAGS = -EL +LDFLAGS += -r + + +# +# Module's headers +# +H_FILES = flcustom.h +H_FILES += flsystem.h +H_FILES += extfiltr.h +H_FILES += tffs2lnx.h +H_FILES += tffsarch.h +H_FILES += tffsdrv.h +H_FILES += _tffsioct.h +H_FILES += tffsioct.h +H_FILES += bddefs.h +H_FILES += blockdev.h +H_FILES += _common.h +H_FILES += defs.h +H_FILES += docbdk.h +H_FILES += _docsys.h +H_FILES += docsys.h +H_FILES += dosformt.h +H_FILES += fatfilt.h +H_FILES += flbase.h +H_FILES += flbuffer.h +H_FILES += flchkdef.h +H_FILES += flcommon.h +H_FILES += flioctl.h +H_FILES += flstdcmp.h +H_FILES += flstruct.h +H_FILES += flsysfun.h +H_FILES += flsystyp.h +H_FILES += _fltl.h +H_FILES += fltl.h +H_FILES += part_inf.h +H_FILES += bdkemul.h +H_FILES += _dochapi.h +H_FILES += doch_api.h +H_FILES += doch_ata.h +H_FILES += doch_func.h +H_FILES += doch_sys.h +H_FILES += dochstub.h +H_FILES += dochtl.h +H_FILES += hal_nor.h +H_FILES += hib.h +H_FILES += tffs_api.h + +# +# Module's objects: +# - trace32.o (if used) must be first in the link order ! +# - $(MODULE_NAME).mod.o must be last in the link order ! +# +OBJS = trace32.o +OBJS += defs.o +OBJS += docdrv.o +OBJS += doch_api.o +OBJS += doch_ata.o +OBJS += dochstub.o +OBJS += dochtl.o +OBJS += docsys.o +OBJS += extfiltr.o +OBJS += fatfilt.o +OBJS += flbase.o +OBJS += flcustom.o +OBJS += flioctl.o +OBJS += flsystem.o +OBJS += hal_nor.o +OBJS += tffs2lnx.o +OBJS += tffs_api.o +OBJS += tffsarch.o +OBJS += tffs-pm26.o +OBJS += tffsdrv26.o +OBJS += $(MODULE_NAME).mod.o + + +# +# rule for building loadable kernel module +# +$(MODULE_NAME).ko : $(OBJS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) + +# +# C compilation rules +# +%.o: %.c + $(CC) $(CFLAGS) -o $@ $< + +# +# 'make clean' rule +# +clean : + rm *.o *.ko + +################ Thank you for using M-Systems' products. #################### diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-y b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-y new file mode 100755 index 00000000..9e7c5dce --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/Makefile-y @@ -0,0 +1,31 @@ +# +# DOC driver Makefile for Linux 2.6. +# Copyright (C) 2006, msystems Ltd. All rights reserved. +# +# Use this Makefile if you want to link DOC driver statically +# with the Linux kernel. +# + +obj-y += tffs.o + +tffs-objs := trace32.o +tffs-objs += defs.o +tffs-objs += docdrv.o +tffs-objs += doch_api.o +tffs-objs += doch_ata.o +tffs-objs += dochstub.o +tffs-objs += dochtl.o +tffs-objs += docsys.o +tffs-objs += extfiltr.o +tffs-objs += fatfilt.o +tffs-objs += flbase.o +tffs-objs += flcustom.o +tffs-objs += flioctl.o +tffs-objs += flsystem.o +tffs-objs += hal_nor.o +tffs-objs += tffs2lnx.o +tffs-objs += tffs_api.o +tffs-objs += tffsarch.o +tffs-objs += tffs-pm26.o +tffs-objs += tffsdrv26.o + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/README.TXT b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/README.TXT new file mode 100755 index 00000000..e2d0e290 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/README.TXT @@ -0,0 +1,1109 @@ + + ******************************************************************************* + * * + * DOC Driver for Linux 2.6 * + * Source Code Edition * + * * + * * + * INSTALLATION MANUAL * + * * + * * + * Version 1.0.85-beta, released on February 06 2008 * + * Based on DOC Driver Block Device SDK version 1.1.0 EQA9 * + * * + * Copyright SanDisk IL Ltd. (C) 2008 * + * Please note that effective January 1, 2007, the name msystems Ltd. was * + * changed to SanDisk IL Ltd. * + * * + * Email questions to: oemsupport@sandisk.com * + * * + ******************************************************************************* + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program, * + * except for the rights expressly granted in this License. * + * * + ******************************************************************************* + + + Contents + ======== + + 1. Introduction + 2. Supported types of mDOC devices + 3. Conventions used in this document + 4. DOC driver's general configuration options + 5. Board specific configuration options + 6. Configuring DOC driver to use Direct Memory Access (DMA) + 7. Configuring DOC driver to use mDOC READY interrupt + 8. Compiling DOC driver + 9. Installing DOC driver + 10. Using DOC driver + 11. Configuring DOC driver to reduce power consumption + 12. Improving DOC driver's I/O performance + 13. Reducing DOC driver's load on CPU + 14. Access to DOC driver's Extended Functions + 15. Formatting mDOC + 16. Updating firmware in mDOC devices + 17. Memory footprint + 18. Known limitations + 19. Disclaimer of Liability + 20. Contact information + + + 1. Introduction + =============== + + 1.1. This document explains how to install DOC driver, and use mDOC device + with Linux operating system. The information in this document applies + to 2.6.x versions of the Linux kernel. + + 1.2. The mDOC devices are high performance, low cost data storage products + based on the latest flash technology. The mDOC devices serve two + purposes under Linux: + + (1) Main data storage device + + In this role, mDOC devices serve the same purpose that + conventional hard disks serve in Linux servers or workstations - + they store various Linux kernel componenets (such as device + drivers, Linux libraries and configuration files), user + applications etc. + + (2) System's boot device + + All mDOC devices feature ROM area which can be programmed via + IOCTL calls to DOC driver. Boards developers usually arrange + for this ROM area to appear at CPU's reset vector, and software + developers program board-specific bootstrap code into it. When + CPU is reset, it executes this bootstrap code, and boots Linux + system entirely from mDOC device. Dedicated boot devices such as + separate ROM or NOR flash chips are no longer needed. + + This document describes only the data storage function of mDOC devices. + + 1.3. Although mDOC devices use multi-level cell NAND flash technology + internally, DOC driver completely hides this fact from the user, and + implements traditional block device interface. This allow mDOC devices + to works with all standard disk-oriented Linux file systems (such as + EXT2, EXT3 etc.). In that respect DOC driver is similar to ATA hard + disks and CompactFlash cards, and is different from other NAND or NOR + flash devices (which must be managed by flash-specific file systems such + as JFFS2). All standard disk oriented Linux utilities (such as 'fdisk', + 'du' etc.) work with mDOC devices. + + 1.4. DOC driver is distributed in the source code form, and is expected to + be compiled at customer's site. Instructions on how to configure and + compile DOC driver are provided in later chapters in this document. + + + + 2. Supported types of mDOC devices + ================================== + + 2.1. This version of DOC driver supports the following types of mDOC + devices: + + - mDOC H3 family + + ===> NOTE. This version of DOC driver will NOT work with the + following types of mDOC devices: + + G3/P3 family + G4 family + H1 family + + You will need to use TrueFFS driver version 7.1.0 (or higher) + with these types of mDOC devices. + + + + 3. Conventions used in this document + ==================================== + + 3.1. Term "host" is used in this document to refer to computer where DOC + driver's source code is located, and where DOC driver is compiled and + linked. Typically "hosts" are engineering workstations running RedHat + or SUSE Linux, or Windows operating systems. + + Term "target" is used in this document to refer to computer where DOC + driver's executable runs, and where mDOC devices are installed. Typical + targets are mobile devices powered by ARM or XScale microprocessors, + specialized communication equipment powered by PowerPC microprocessors, + and various other embedded systems. + + ===> NOTE. Although usually host and target are different systems, in + some cases "host" and "target" could actually refer to the + same system. For example, it is possible to plug mDOC into + the PCI slot of PC workstation running Linux. If this + workstation contains kernel's source tree installed on it, + then it is possible to compile DOC driver, and run it on + this workstation. In this case PC workstation serves both + as host and target system. + + All instructions provided by this document refer to the case when + "host" and "target" are separate systems. + + 3.2. Installation instructions in this document assume that user is logged + into the system as "root". + + + + 4. DOC driver's general configuration options + ============================================= + + 4.1. Linux kernel requires that every device driver use unique major device + number. By default, DOC driver uses major device number '100'. If + you would like DOC driver to use different major device number, you + can do so by passing "tffs_major=" command line option when + starting the driver. For example, to tell DOC driver to use major + device number '120': + + insmod tffs.ko tffs_major=120 + + ==> NOTE. File Documentation/devices.txt in Linux kernel's directory + list all major device numbers that had been reserved for the + various types of block devices. When specifying major device + number for DOC driver, it is essential to pick the number that + isn't listed in that file as already reserved for some other + block device. Consider using block device numbers that are + allocated for "local/experimental use" (for example, major + block device numbers in 120..127 range). + + + + 5. Board specific configuration options + ======================================= + + 5.1. As shipped, the DOC driver should work with the following boards: + + - Texas Instruments OMAP 2420 ("H4") + - Intel PXA27x Development Platform ("Mainstone") + + If you are using one of these boards, you can skip remaining Sections + in Chapter 5. For all other boards, you will need to configure DOC + driver as appropriate for your system. Instructions below explain how + to do this. + + 5.2. User must tell DOC driver where to look for mDOC. This can be + accomplished by using "tffs_addr=" command line + option, where specifies physical address of the mDOC. + For example, if in your particular board mDOC resides at physical + address 0xc0000000, you would start DOC driver as follows: + + insmod tffs.ko tffs_addr=0x00000000 + + Alternatively, you can set macro TFFS_PHYS_ADDR in DOC driver's header + tffsarch.h to the physical address of the mDOC, and recompile the + driver. For example, if mDOC device resides at physical address + 0xc0000000, macro TFFS_PHYS_ADDR should be #defined as follows: + + #define TFFS_PHYS_ADDR 0xc0000000 + + In this case you DOC driver by default would look for mDOC at the + specified address, so you can omit "tffs_addr=" + command line parameter, and start DOC driver simply as: + + insmod tffs.ko + + 5.3. When DOC driver starts up, it calls routine tffsarch_init() to do any + board-specific hardware initialization (such as configuring Chip Select + that mDOC is connected to, allocating and configuring DMA channels and + interrupt request lines to be used by DOC driver etc.). The DOC + driver's file tffsarch.c contains example implementations of this + routine for a number of reference boards. + + Users are required to implement this routine as appropriate for their + particular boards. + + 5.4. When DOC driver shuts down, it calls routine TffsHWRelease() to do any + board-specific hardware cleanup (such as releasing previously allocated + DMA channels and interrupt request lines etc.). The DOC driver's file + tffsarch.c contains example implementations of this routine for number + of reference boards. + + Users are required to implement this routine as appropriate for their + particular boards. + + + + 6. Configuring DOC driver to use Direct Memory Access (DMA) + =========================================================== + + 6.1. By default, DOC driver uses software loops to transfer blocks of data + to and from mDOC. In many cases it is possible to substantially improve + mDOC's 'read' performance by using DMA controler to do these data + transfers. + + Current version of DOC driver includes example implementations of DMA + support for the following reference boards: + + - Texas Instruments OMAP2420 ("H4") + - Intel PXA27x ("Mainstone") + + These example implementations are found in DOC driver's files + tffsarch.h and tffsarch.c, and consists of the following items: + + macro flReadEvenNumberOfBytes defined in tffsarch.h + macro flWriteEvenNumberOfBytes defined in tffsarch.h + + routine tffs_dma_init() defined in tffsarch.c + routine tffs_dma_release() defined in tffsarch.c + routine __dmasw_bread() defined in tffsarch.c + routine __dmasw_bwrite() defined in tffsarch.c + + You can use these example implementation as the starting point for DMA + implementation for your own system. + + ===> NOTE. Most likely you will be able to use the definitions of all + macros in file tffsarch.h "as is". You do have to implement + routines in file tffsarch.c as appropriate for your own + system. + + 6.2. To instruct DOC driver to use DMA during 'read' and/or 'write + operations, use 'tffs_dma_mode=' command line option. Possible + values are described below: + + tffs_dma_mode Description + + 1 DMA is used during 'read' operations. + Data is transferred in two steps: first, it is + read (using DMA) from mDOC device into driver's + internal non-cachable DMA buffer; secondly, data + is copied (using memcpy()) from the internal DMA + buffer to destination buffer. + + 2 DMA is used during 'write' operations. + Data is transferred in two steps: first, it is + copied (using memcpy()) from source buffer into + driver's internal non-cacheable DMA buffer; + secondly, data is written (using DMA) from DMA + buffer to mDOC device. + + 3 This is the combination of modes '1' and '2'. + + 5 DMA is used during 'read' operations. + Data is transferred (using DMA) directly from mDOC + device to the destination buffer, without using + intermediate non-cachable DMA buffer. + + 6 DMA is used during 'write' operations. + Data is transferred (using DMA) directly from + the source buffer to mDOC device, without using + intermediate non-cachable DMA buffer. + + 7 This is the combination of modes '5' and '6'. + + ===> NOTE. Systems with fast CPU-to-external-RAM interfaces would benefit + most from the DMA modes 1..3. Systems with slow + CPU-to-external-RAM interfaces (such as PXA27x Mainstone) + would benefit most from the DMA modes 5..7. We advice that you + try various DMA modes with your particular system, and pick + the one with the best I/O performance. + + For example, to instruct DOC driver to use DMA mode '1' during + 'read' operations only, and don't use it during 'write' operations, you + would start the driver as follows: + + insmod tffs.ko tffs_dma_mode=1 + + + + 7. Configuring DOC driver to use mDOC READY interrupt + ===================================================== + + 7.1. The 'write' operations in modern flash devices (such as mDOC) might + take hundreeds of microseconds. Often it is possible to improve overall + system's responsiveness and throughput by configuring DOC driver to + yield CPU during these periods of time. + + ===> NOTE. This option could negatively impact mDOC's "write" + performance, especially when workload on the system + increases. + + 7.2. By default, DOC driver enables mDOC READY interrupt for Intel PXA27x + board ("Mainstone"), and disables it for all other boards. + + To override this default, use 'tffs_irq=' command line option. + The argument specifies board's interrupt request line that mDOC's + IREQ signal is connected to. + + Current version of DOC driver support mDOC interrupts for the following + reference boards: + + +------------------------------------+--------------------+ + | Board | Interrupt | + +------------------------------------+--------------------+ + | Texas Instruments OMAP2420 ("H4") | 190 | + +------------------------------------+--------------------+ + | Intel PXA27x ("Mainstone") | 167 | + +------------------------------------+--------------------+ + + For example, in case of Texas Instruments's OMAP2420 board ("H4"), + mDOC's IRQ signal is connected to board's GPIO_94 line (which generates + interrupt 190), so you would start DOC driver as follows: + + insmod tffs.ko tffs_irq=190 + + To disable mDOC's READY interrupt, specify as '-1'. For example: + + insmod tffs.ko tffs_irq=-1 + + + + 8. Compiling DOC driver + ======================= + + 8.1. This Chapter contains instructions for compiling DOC driver. + + The DOC driver can be placed into the Linux kernel's source code tree, + and compiled as part of the Linux kernel compilation. Section 8.2 + provides instructions of how to do that. + + The DOC driver can also be placed in the separate directory outside of + Linux kernel's source code tree, and compiled separately from the Linux + kernel. Section 8.3 explains how to do that. + + Instructions below refer to the top directory of Linux kernel's source + code tree (where .config kernel configuration file resides) as . + + 8.2. Sections 8.2.1 - 8.2.5 describe how to add DOC driver to Linux kernel's + source code tree, and build it as part of Linux kernel compilation. + + 8.2.1. Create new directory /drivers/tffs, copy DOC driver's archive + to this directory, and unpack it there. + + 8.2.2. If you are using multiple cascaded mDOC devices, edit + /drivers/tffs/flcustom.h file, and uncomment the following + line there: + + #define ATA_MAX_NUM_OF_DEVICES 2 /* only when using casacded devices */ + + 8.2.3. Edit /drivers/Makefile, and add the following statement at the + end of this file: + + obj-y += tffs/ + + This will cause 'make' utility to descend into /drivers/tffs + directory during Linux kernel compilation, build DOC driver, and + statically link it into Linux kernel. + + If you don't want to statically link DOC driver into Linux kernel, + and instead prefer to build it as dynamically loadable kernel module, + you should change this statement as shown below: + + obj-m += tffs/ + + This will cause 'make' utility to descend into /drivers/tffs + directory when building Linux kernel modules, and compile DOC driver + as dynamically loadble Linux kernel. + + 8.2.4. Create /drivers/tffs/Makefile with the following contents: + + obj-y += tffs.o + + tffs-objs := trace32.o + tffs-objs += defs.o + tffs-objs += docdrv.o + tffs-objs += doch_api.o + tffs-objs += doch_ata.o + tffs-objs += dochstub.o + tffs-objs += dochtl.o + tffs-objs += docsys.o + tffs-objs += extfiltr.o + tffs-objs += fatfilt.o + tffs-objs += flbase.o + tffs-objs += flcustom.o + tffs-objs += flioctl.o + tffs-objs += flsystem.o + tffs-objs += hal_nor.o + tffs-objs += tffs2lnx.o + tffs-objs += tffs_api.o + tffs-objs += tffsarch.o + tffs-objs += tffs-pm26.o + tffs-objs += tffsdrv26.o + + This Makefile instructs 'make' utility to build DOC driver, and + statically link it into Linux kernel. + + If you don't want to statically link DOC driver into Linux kernel, + and instead prefer to build it as dynamically loadable kernel module, + you should change the first line of this Makefile as shown below: + + obj-m += tffs.o + + 8.2.5. If you now build Linux kernel (if you have choosen to statically link + DOC driver into Linux kernel) or kernel modules (if you have choosen + to build DOC driver as loadable kernel module), you should see DOC + driver being built as part of this process. + + You are done; skip the rest of Chapter 8. + + 8.3. Sections 8.3.1 - 8.3.5 describe how to build DOC driver in the separate + directory outside of Linux kernel's source code tree, separately from + the Linux kernel. In this case DOC driver will be built as loadable + kernel module tffs.ko. + + 8.3.1. Place DOC driver's archive into the private directory outside of + kernel's source tree, and unpack it there. + + 8.3.2. If you are using multiple cascaded mDOC devices, edit + /drivers/tffs/flcustom.h file, and uncomment the following + line there: + + #define ATA_MAX_NUM_OF_DEVICES 2 /* only when using casacded devices */ + + 8.3.3. DOC driver directory includes example Makefiles for the following + reference boards: + + +------------------------------------+--------------------+ + | Board | Makefile- | + +------------------------------------+--------------------+ + | Texas Instruments OMAP2420 ("H4") | Makefile-omap2420 | + +------------------------------------+--------------------+ + | Intel PXA27x ("Mainstone") | Makefile-pxa27x | + +------------------------------------+--------------------+ + + If you are using one of these boards, then copy the respective file + Makefile- to Makefile. For example, if you are using Texas + Instruments' OMAP2420 board: + + cp Makefile-omap2420 Makefile + + If you are using board other then listed above, you will need to write + your own Makefile. The simplest way to do this is to take any of the + provided reference Makefile-, and change the following macros + as appropriate to your development setup: + + KERNEL_DIR + CC + CFLAGS + LD + LDFLAGS + + The KERNEL_DIR macro should be set to point to top directory of your + kernel's source code tree. + + Macros CC and CFLAGS specify which compiler to use to build DOC driver, + and which compiler flags to use for that. Similarly, macros LD and + LDFLAGS specify which linker to use to link DOC driver's binary, and + which linker flags to use for that. + + ===> NOTE. The easy way to figure out appropriate settings for CC, + CFLAGS, LD and LDFLAGS macros is to execute: + + make V=1 modules + + in the kernel's top directory, and observe the values that + this this command is using to compile and link all Linux + loadable kernel modules. + + The 'V=1' command line option instructs 'make' utility to + issue verbose output (which includes compiler's command line + parameters) rather then terse messages that it produces by + default. + + 8.3.4. Make sure that compiler (as specified by macro CC in Section 8.3.3) + is in the PATH, and build DOC driver by executing: + + make + + in DOC driver's directory. This command should generate tffs.ko + loadable kernel module. + + 8.3.5. You will need to create directory + + lib/modules//kernel/drivers/tffs + + on your target system's root file system, and copy loadable kernel + module tffs.ko to that directory. + + + + 9. Installing DOC driver + ======================== + + 9.1. Add the following line to /lib/modules//modules.dep + file on target's root file system: + + /lib/modules//kernel/drivers/tffs/tffs.ko: + + 9.2. Create mDOC entries for mDOC devices under /dev directory. + + Since current version of DOC driver supports up to 12 "disks" on mDOC + device, with up to 15 file system partition on each of such "disks", + you will need to create up to 192 mDOC entries under /dev (one "raw + disk" entry is required for each of 16 "disk"). You can use script + make_tffs_nodes.sh to create all these /dev entries, or you can do + that manually using Linux 'mknod' utility. For example: + + # mknod /dev/tffsa b 100 0 + # mknod /dev/tffsa1 b 100 1 + # mknod /dev/tffsa2 b 100 2 + # mknod /dev/tffsa3 b 100 3 + # mknod /dev/tffsa4 b 100 4 + + ===> NOTE. If you have configured DOC driver to use different major + device number (see Section 4.1), you will need to replace + '100' in the commands above accordingly. + + These /dev entries refer to: + + /dev/tffsa is the "raw disk" entry for the first mDOC "disk" + /dev/tffsa1 refers to 1-st file system partitions on this disk + /dev/tffsa2 refers to 2-nd file system partitions on this disk + /dev/tffsa3 refers to 3-rd file system partitions on this disk + /dev/tffsa4 refers to 4-th file system partitions on this disk + + ===> NOTE. While there is rarely a need to have more then four file + system partitions on mDOC, DOC driver actually supports + up to 15 of such partitions. If you opted to have more then + four file system partitions, simply add more 'mknod' commands + to the script above to create device entries for additional + partitions. + + ===> NOTE. Current version of mDOC driver doesn't take advantage of + devFs ability to allocate major driver numbers and create + device entries under /dev dynamically. + + + + 10. Using DOC driver + ==================== + + 10.1. The DOC driver can be loaded in the same way that other kernel modules + are loaded: + + insmod tffs.ko [params] + + The following command line parameters are currently supported by DOC + driver: + + tffs_major major device number to use (default is '100') + tffs_addr physical address of mDOC + tffs_sg_read "gather" data during read operations + tffs_sg_write "scatter" data during write operations + tffs_irq IRQ (interrupt request line) to use; '-1' for none + tffs_dma_mode DMA mode (default is don't use DMA) + tffs_pio polled I/O mode + prio controls priority of driver's I/O processing thread + hardsect size of the hardware sector in bytes + rahead read-ahead parameter + fl_debug controls verbosity level of driver's debug messages + tffs_dpd_timeout delay before mDOC automatically enters powerdown mode + + 10.2. To create disk partition table on mDOC: + + fdisk /dev/tffsa + + When 'fdisk' utility presents you with command prompt, you can choose + 'p' to print existing disk partition table, 'd' to delete existing disk + partitions (if exists), or 'n' to create new disk partitions. + + 10.3. If you created new disk partitions in Section 10.2, you will need to + initialize file systems on these disk partition(s). For example, + to initialize EXT2 file system on the first partition (/dev/tffsa1), + use: + + mke2fs /dev/tffsa1 + + When initializing file system on mDOC disk partition, 'mke2fs' utility + calculated file system's block size based on the size of this disk + partition. Currently EXT2 and EXT3 file systems supports file system + blocks of 1024, 2048 and 4096 bytes. Smaller file system blocks (1024 + bytes) allow more efficient use of disk space, at the expense of DOC + driver's 'write' performance. Larger file system blocks (4096 bytes) + noticably increase 'write' performance, at the expense of some disk + space. You can pass '-b ' parameter to 'mke2fs' utility to + explicitely specify size of file system blocks. + + For example, if you want to maximize 'write' performance of DOC driver, + you can do so by telling 'mke2fs' to use largest possible (4096 bytes) + file system blocks: + + mke2fs -b 4096 /dev/tffsa1 + + 10.4. Create mount point for mDOC partition(s), and mount them: + + mkdir -p /mnt/tffsa1 + mount /dev/tffsa1 /mnt/tffsa1 + + 10.5. You can now create files and directories on mDOC. For example: + + echo have a nice day > /mnt/tffsa1/greetings.txt + + To see if the above command worked as expected, execute: + + cat /mnt/tffsa1/greetings.txt + + 10.6. Before shutting the system down, unmount all previously mounted mDOC + partition(s): + + umount /dev/tffsa1 + + + + 11. Configuring DOC driver to reduce power consumption + ====================================================== + + 11.1. This Chapter is only relevant to devices where power conservation is of + major concern. Various battery powered systems (such as mobile phones + and PDAs) fall into this category. + + 11.2. The mDOC device automatically switches from the normal power state into + the low-power state after certain amount of time passes from the + completion of the last read/write access to mDOC device. By default, + this power-down timeout is set to 100 milliseconds; it can be changed + via driver's command line option "tffs_dpd_timeout=". The argument + specifies duration of power-down timeout in milliseconds, for + example: + + insmod tffs.ko tffs_dpd_timeout=1000 + + would cause mDOC device to automatically power itself down one second + (1000 milliseconds) after the last read/write access. + + ===> NOTE. Currently mDOC firmware rounds down power-down timeout to + nearest 100 millisecons multiple, i.e. "tffs_dpd_timeout=345' + has the same effect as "tffs_dpd_timeout=300". + + 11.3. DOC driver supports standard Linux 2.6 power management scheme (option + CONFIG_PM in kernel's .config configuration file). The relevant power + suspend/resume code resides in file tffs-pm26.c, and is + self-explanatory. + + + + 12. Improving DOC driver's I/O performance + ========================================== + + 12.1. This Chapter provides overview of the various means of improving + 'read' and 'write' performance of DOC driver. + + 12.2. The duration of the access cycles to mDOC's registers is one of the + major factors affecting both 'read' and 'write' performance of + DOC driver. The duration of these access cycles is usually + determined by the settings of board's Chip Select that mDOC device + is connected to. If duration of these access cycles substantially + exceeds timings specified in documentation for your mDOC device, + 'write' and especially 'read' performance of DOC driver will be + sub-optimal. + + 12.3. It is possible to improve I/O performance of DOC driver by enabling + compiler optimizations when compiling DOC driver. + + If you have choosen to place DOC driver into Linux kernel's source code + tree (see Section 8.2), you can instruct compiler to optimize generated + code by adding the following line to DOC driver's Makefile: + + EXTRA_CFLAGS := -O2 + + If you have choosen to build DOC driver outside of the Linux kernel's + source code tree (see Section 8.3), you can instruct compiler to + optimize generated code by adding the following line to DOC driver's + Makefile: + + CFLAGS += -O2 + + 12.4. For portability reasons, Linux drivers use dedicated macros and routines + to access registers of peripheral devices. By default DOC driver + adheres to this policy. However, in many cases it is possible to + substantially increase performance of DOC driver by instructing it + to use general purpose memory routines (such as memcpy()) to transfer + blocks of data to and from mDOC device. To do so, use driver's + "tffs_memcpy=1" command line option: + + insmod tffs.ko tffs_memcpy=1 + + ===> NOTE. The "tffs_memcpy=1" command line option might not work + with some boards. + + 12.5. If you are using any of the following reference boards: + + - Texas Instruments's OMAP2420 ("H4") + - Intel PXA27x ("Mainstone") + + you can substantially improve DOC driver's 'read' performance by + telling it to use DMA to transfer data between mDOC and main memory. + See Chapter 6 for more details on "tffs_dma_mode=" command + line option. + + If you are using different board, consider adding support for your + specific DMA implementation to DOC driver. + + 12.6. By default, DOC driver attempts to internally combine few 'write' + requests into single 'write' operation on mDOC device (this process is + usually referred to as "gathering" of I/O requests). Similarly, DOC + driver attempts to internally combine few 'read' requests into single + 'read' operation on mDOC device (this process is usually referred to as + "scattering" of I/O requests). + + While this behavior improves DOC driver's performance for many + systems, it might actually reduce it in case of systems with slow + access to DRAM (such as Intel PXA27x "Mainstone"). For this kind of + systems, it is possible to improve DOC driver's performance by + instructing driver not to perform any scattering/gathering of I/O + requests. + + To tell DOC driver not to combine (gather) 'write' requests, use + command line option "tffs_sg_write=0": + + insmod tffs.ko tffs_sg_write=0 + + To tell DOC driver not to combine (scatter) 'read' requests, use + command line option "tffs_sg_read=0": + + insmod tffs.ko tffs_sg_read=0 + + Use both of these command line options to tell DOC driver not to do + any scattering/gathering of I/O requests: + + insmod tffs.ko tffs_sg_write=0 tffs_sg_read=0 + + 12.7. By default, DOC driver uses polled I/O mode, and transfers single + sector (512 bytes) at a time. It is possible to improve driver's + I/O performance by instructing it to transfer multiple sectors a time. + This could be done by using "tffs_pio=" command line option, where + is either 2 (for two-sector transfers) or 4 (for four-sector + transfers). For example: + + insmod tffs.ko tffs_pio=4 + + 12.8. It is possible to substantially improve DOC driver's 'write' performance + by increasing file system's block size. In case of EXT2 file systems, + file system's block size is determined by 'mke2fs' utility when it + initializes file system on the disk partitions (see Section 10.3), and + is set to 1024, 2048 or 4096 bytes depending on the size of this disk + partition. Passing '-b 4096' command line option to 'mke2fs' utility + forces it to use 4096-byte blocks (the largest possible file system + block size) regardless of the actual size of the disk partition, + therefore improving DOC driver's 'write' performance. + + + 13. Reducing DOC driver's load on CPU + ===================================== + + 13.1. During 'write' operations DOC driver normally polls mDOC device in + order to detect completion of the operation. While this approach allows + DOC driver to maximize mDOC's 'write' performance, it also ties up CPU + for extensive periods of time, reducing amount of CPU time available to + all other processes in the Linux system. + + The alternative approach for DOC driver would be to yield CPU right + after starting 'write' operation on mDOC device, and sleep until + completion of this operation. While this approach is optimal in terms + of minimizing DOC driver's load on CPU, it is only possible if + DOC driver supports mDOC interrupt generation on your particular + system. + + See Chapter 7 for more details regarding mDOC interrupts. + + 13.2. If mDOC interrupt isn't supported for your particular board, it is still + possible to reduce DOC driver's load on CPU by using the command line + option "tffs_skip_sleeps=", where values depend on the type of + mDOC device. You should specify values equal to or greater then + 100. Greater values will improve DOC driver's 'write' + performance, but will also increase it's load on CPU. The optimal + value depends on the desired tradeoff between 'write' performance and + load on CPU. You can start by trying set to 5000: + + insmod tffs.ko tffs_skip_sleeps=5000 + + and measure DOC driver's 'write' performance, and it's load on CPU. + If DOC driver's load on CPU will be acceptable but it's 'write' + performance is too low, try increasing value. If DOC driver's + load on CPU will be too high, try decreasing value until you + reduced the load on CPU to the desired level. + + + + 14. Access to DOC driver's Extended Functions + ============================================= + + 14.1. In addition to standard block device functionality, DOC driver provides + access to DOC driver's Extended Functions, which is not a part of the + standard file system API. See included manual "DOC Driver Extended + Functions Developer Guide" for detailed explanation of all DOC driver's + Extended Functions. + + ===> NOTE. For security reasons, FL_IOCTL_DELETE_SECTORS Extended + function was disabled in the current version of DOC + driver. + + The following section describes only the functionality that is not + supported by DOC drivers for other operating systems. + + Your application code which utilizes DOC driver's IOCTLs, should contain + the following: + + #include "tffsioct.h" + + Your application's Makefile should add DOC driver's headers to + compiler's include path. For example, if you added DOC driver to + kernel's source tree (see Section 8.2): + + -I/drivers/tffs + + The 'ioctl_example' sub-directory in DOC driver archive contains + example application code which shows how to access Extended Functions + via IOCTL calls to DOC driver. + + 14.2. IOCTL limitations + + 14.2.1. All pointers in IOCTL structures should be valid values or null, even + if not used in IOCTL. + + 14.2.2. For FL_IOCTL_FLASH_FORMAT call, 'volumeLabel, 'embeddedSIC' and + 'progressCallback' fields of formatParams must be NULL. The DOC + driver must be restarted right after calling this IOCTL. + + 14.2.3. The FL_IOCTL_SET_ACCESS_ROUTINE and FL_IOCTL_GET_ACCESS_ROUTINE are + not supported. + + + + 15. Formatting mDOC + =================== + + 15.1. The easiest way to format mDOC is to start DOC driver with + "tffs_format=" command line parameter. The argument + specifies which mDOC to format; it is usually specified as zero: + + insmod tffs.ko tffs_format=0 + + In this case DOC driver will re-format mDOC using standard formatting + parameters. + + 15.2. If you are interested in formatting mDOC using custom formatting + parameters, you can accomplish this using FL_IOCTL_FLASH_FORMAT mDOC + Extended Function. See Chapter 14 for more information on mDOC + Extended Functions. + + 15.3. Although not mandatory, it's a good idea to reset mDOC (for example + by rebotting the system) right after formatting it. + + + + 16. Updating firmware in mDOC devices + ===================================== + + 16.1. DOC driver comes with the utility program 'doch-firmware' which can be + used to upgrade firmware in mDOC devices. The source code and Makefile + for this utility program reside in subdirectory 'doch-firmware' in DOC + driver's archive. + + 16.1.1. By default, doch-firmware/Makefile assumes XScale compiler + 'iwmmxt_le-gcc'. If you are using different compiler, change + definition of macro 'CC' in this Makefile accordingly. + + 16.1.2. You will need to change definition of macro 'INCLUDE_DIR' in + doch-firmware/Makefile to point to the directory where all your + applications #include .h files from. + + ===> NOTE. The applications' 'INCLUDE_DIR' is different from + the your kernel's /include directory that is used + in kernel builds. For example, header + exists in the former but not in the latter directories. + + 16.1.3. Change to 'doch-firmware' subdirectory, and build 'doch-firmware' + utility program: + + cd doch-firmware + make + + 16.1.4. Copy doch-firmware/doch-firmware utility program to the + appropriate location on the target's root file system, and + set permissions accordingly. For example: + + cp doch-firmware /sbin + chmod 750 /sbin/doch-firmware + + 16.2. Login to the target as superuser ("root"), and verify that DOC driver is + loaded and running. + + 16.3. Copy mDOC firmware file to the target. + + 16.4. To prevent corruption of the file systems that reside on mDOC, + unmount previously mounted mDOC partition(s) (see Chapter 10 + for more details on mouting mDOC partition(s)). + + 16.5. Execute: + + /sbin/doch-firmware /dev/tffsa + + where is mDOC firmware file (see Section 16.3). + + 16.6. Reset target system to put new mDOC firmware into effect. + + + + 17. Memory footprint + ==================== + + 17.1. This Section describes DOC driver's memory footprint (amount of RAM + that DOC driver's code and data take at runtime) for the reference + case of Intel's PXA27x ("Mainstone") board (ARM processer). DOC + driver's memory footprint varies significabtly between various + processor architectures and compiler optimizations. + + In case of Intel's PXA27x ("Mainstone") board, if compiled without + any optimizations, DOC driver takes about 240 KB of kernel memory + for it's code and data. + + In addition to the above, DOC driver may also do the following + dynamic memory allocations if respective runtime configuration + options are enabled: + + - The buffer for internal scatter/gather operations (see + Section 12.6). By default, size of this buffer is 64 KB. + + - If DMA is used (see Chapter 6), DOC driver allocates internal + 4 KB buffer for use with DMA operations. + + + + 18. Known limitations + ===================== + + - Current version of DOC driver limits number of "disks" per mDOC + "socket" to 12. + + - Current version of DOC driver doesn't support FL_IOCTL_GET_INFO + Extended Function on OTW BDTL partitions ("disks"). + + - Current version of DOC driver fails to re-format 16Gbit mDOC + H3 devices that have protected BDTL partitions ("disks") on them. + + - Current version of DOC driver will not recognize mDOC H3 devices if + they are configured to work in 128KB window mode. + + - When formatting with flCreateLogicalPartitions + - Minimal size for logical partition is twice flash unit size + - Usable user space is one flash unit size less than allocated (FAT + alignment overhead) + + Device Minimal Partition Size Overhead + + mDOC H3 128MB and MCP45 512 KB 256KB + mDOC H3 1GB 4 MB 2MB + mDOC H3 2GB 8 MB 4MB + + - More than one device of mDOC H3 in one system is not supported. + + - Using PortaDOC when DOC is configured for 128KB window, requires flSystem + adaptation. + + - IPL size in normal mode 128KB window should not exceed 8KB. + This limitation is not applicable to paged RAM mode and Virtual mode. + + - The field fastAreaLength in structure BDTLPartitionFormatParams3 must + always be set to zero (already set to zero in SDK default). + + - Burst mode not supported. + - Burst Mode with DMA is supported in the following mDoc H3 products: + + SDEDX-aaab-ccc (X 5 or 7, a,b,c arbitrary numbers) + + - In MCP45: DOCH_IM_IDLE and DOCH_IM_DPD disables AutoDPD. Selecting + DOCH_IM_IDLE_2_DPD (default) is required in order to have autoDPD enabled. + + - In MCP45: Inserting wrong key to a protected partition more than 16 + times will cause rejection of any further attempt until host reset. + + - When using 8KB memory window, only boot from lowest mDOC address + (mDOC base address, typically address zero) is supported. + Boot from top address (mDOC base address + 0x1ffe) is not supported, as mDOC + top address range (0x1800-0x1ffe) does not alias IPL in this mode. + + - flIdentifyProtection will return flHWProtection when the requested + partition is RW protected and the key is not inserted. + + - IPL in virtual ram mode in cascaded configuration is not supported. + + - Fast area is supported on the following products: + + SDEDX-aaab-ccc (X 5 or 7, a,b,c arbitrary numbers) + + - IPL in paged ram mode is not supported in the following devices: + + SDED5-aaab-ccc devices (a,b,c arbitrary numbers) + + + + 19. Disclaimer of Liability + =========================== + + SanDisk IL Ltd.'s general policy does not recommend the use of its products + in life support applications wherein a failure or malfunction of the + product may directly threaten life or injury. + Accordingly, in any use of products in life support systems or other + applications where failure could cause damage, injury or loss of life, + the products should only be incorporated in systems designed with + appropriate redundancy, fault tolerant or back-up features. + + SanDisk IL shall not be liable for any loss, injury or damage caused by + use of the Products in any of the following applications: + + Special applications such as military related equipment, nuclear reactor + control, and aerospace + + Control devices for automotive vehicles, train, ship and traffic + equipment + + Safety system for disaster prevention and crime prevention + + Medical-related equipment including medical measurement device. + + + + 20. Contact information + ======================= + + For comments, questions and bug reports, please contact your SanDisk + representative or e-mail us at oemsupport@sandisk.com. + + This document is for information use only and is subject to change + without prior notice. + + SanDisk IL Ltd. assumes no responsibility for any errors that may + appear in this document, nor for incidental or consequential damages + resulting from the furnishing, performance or use of this material. + + SanDisk IL's products are not warranted to operate without failure. + SanDisk IL's general policy does not recommend the use of its products + in life support applications where a failure or malfunction of the + product could cause injury or loss of life. Per SanDisk IL's Terms and + Conditions of Sale, the user of SanDisk IL's products in life support + applications assumes all risk of such use and indemnifies SanDisk IL + against all damages. See "Disclaimer of Liability". Accordingly, in + any use of the Product in life support systems or other applications + where failure could cause injury or loss of life, the Product should + only be incorporated in systems designed with appropriate and + sufficient redundancy or backup features. + + All parts of the SanDisk IL's documentation are protected by copyright + law and all rights reserved. + + Contact your local SanDisk sales office or distributor to obtain the + latest specifications before placing your order. + + (C) 1995-2007 SanDisk IL Ltd. All rights reserved. + + mDOC, DOC, TrueFFS, SureFS, SanDisk and SanDisk logo are registered + trademarks of SanDisk IL Ltd. and SanDisk Corporation, respectively. + Other product names or service marks mentioned herein may be trademarks + or registered trademarks of their respective owners and are hereby + acknowledged. diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/VERSIONS.TXT b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/VERSIONS.TXT new file mode 100755 index 00000000..c3b447a8 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/VERSIONS.TXT @@ -0,0 +1,215 @@ + + ******************************************************************************* + * * + * DOC Driver for Linux 2.6 * + * Source Code Edition * + * * + * VERSIONS * + * * + * * + * Version 1.0.85-beta, released on February 06 2008 * + * Based on DOC Driver Block Device SDK version 1.1.0 EQA9 * + * * + * Copyright (C) SanDisk IL Ltd. 2008 * + * Please note that effective January 1, 2007, the name msystems Ltd. was * + * changed to SanDisk IL Ltd. * + * * + * Email questions to: oemsupport@sandisk.com * + * * + ******************************************************************************* + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program, * + * except for the rights expressly granted in this License. * + * * + ******************************************************************************* + +This package is beta version for DOC driver for mDOC H3. + +The list below documents and logs the changes in DOC driver for Linux +over time. + + +Version 1.0.85-beta - February 06, 2008 +---------------------------------------- +1. DOC Driver SDK changes. +1.1. Bug Fixes + - init sequence: + -- Wait enough time for mount to complete before sofware reset. + -- Wait for both floors to be ready after software reset. + -- Part of configuration registers should be set only after device + selection. + -- Add delay between sequential access to same register. + - Check for format completeness in flAbsMountVolume. + - flChangeProtectionType() and flIPLChangeProtectionType() do not support + OTW_PROTECTED flag. + - Verify write on cascaded device. + - flRecoverFromPowerLoss fixed sequence. + - Multiple mount on the same partition caused memory leak. + - flUnformat should not delete all partitions only if identified + protected partitions. + - Alignment to unit in FAT32 format. + - Simulator's file register was not updated correctly in case of failure. + - Simulator's last partition fast area size fixed to fit real + device calculation. + + +Version 1.0.84-alpha - November 16, 2007 +---------------------------------------- +1. Linux driver changes. +1.1. Added "tffs_unformat= command line option for unformatting mDOC device +1.2. New cylinder/head/sectors-per-track geometry calculation for mDOC capacities + of 4 GByte and higher. +1.3. Improved locking in tffsdrv26.c. + + +Version 1.0.83 - January 07, 2007 +--------------------------------- +1. Supports the following mDOC Products: + - mDOC H3 family + +2. DOC Driver SDK changes. +2.1. Bug Fixes + - Fixed various compilation warnings. + - Added wait for ATA BUSY de assertion before performing ATA reset during init. + - Fixed IRQ handling in case of cascaded configuration. + - Fixed OTW for cascaded configuration. + - Enable removing 'lock enabled' attribute from a partition. + - Added SDK level secure-wipe power-failure immunity. +2.2. Added mDOC H3 2GBit device simulation. + +3. Linux driver changes. +3.1. Added support for Intel PXA27x board (aka "Mainstone"). +3.2. The following bugs has been fixed in this version: + - The FL_IOCTL_GET_INFO Advanced Function causes CPU fault on 13-th and + higher disks. + - The FL_IOCTL_IPL_HW_PROTECTION Advanced Function fails. + - Write performance is low in case of cascaded mDOC H3 configuration. +3.3. The following files have been changed: + - tffsdrv26.c + - tffsarch.c + - tffs-pm26.c + - flcustom.c + - flsystem.c + - flcustom.h + - flsystem.h + - tffsdrv.h + + +Version 1.0.82-beta - November 13, 2006 +--------------------------------------- +1. Supports the following mDOC Products: + - mDOC H3 family + +2. DOC Driver SDK changes. +2.1. Bug Fixes: + - Cascaded configuration support. + - DMA handling when data size exceeds frame size. + - OTW setting changed when changing protection type. + - SLOCK setting disabled when using flChangeProtectionType. + - flChangeProtectionKey() returned flWrongKey instead of flHWProtection upon failure. + - Set IPL partition as 'protectable' upon creation. +2.2. API Changes: + - IPL protection APIs added. + - 16 partitions supported (14 user partitions + mandatory IPL and OTP partitions). + - TL_LEAVE_SOME_PARTITIONS added to flFlashFormat() + - RW protection enabled. +2.3. Joint Protection removed. +2.4. Compilation warnings fixed. + +3. Linux driver changes. +3.1. Added mDOC IRQ support for Texas Instruments OMAP2420 ("H4") board. +3.2. Added s/w DMA support for Texas Instruments OMAP2420 ("H4") board. +3.3. Added suspend/resume support for Texas Instruments OMAP2420 ("H4") board. +3.4. Added "tffs_dpd_timeout=" command line option for better automatic + power-down control. +3.5. Added "tffs_memcpy=1" command line option to improve performance. +3.6. Number of supported "disks" (BDTL partitions) has been increased from + 6 to 12. + + + +Version 1.0.81-alpha - August 10, 2006 +-------------------------------------- +1. Supports the following mDOC Products: + - mDOC H3 family + + + +Disclaimer of Liability +----------------------- + +SanDisk IL Ltd.'s general policy does not recommend the use of its products +in life support applications wherein a failure or malfunction of the +product may directly threaten life or injury. +Accordingly, in any use of products in life support systems or other +applications where failure could cause damage, injury or loss of life, +the products should only be incorporated in systems designed with +appropriate redundancy, fault tolerant or back-up features. + +SanDisk IL shall not be liable for any loss, injury or damage caused by +use of the Products in any of the following applications: + +Special applications such as military related equipment, nuclear reactor +control, and aerospace + +Control devices for automotive vehicles, train, ship and traffic +equipment + +Safety system for disaster prevention and crime prevention + +Medical-related equipment including medical measurement device. + + + +Contact information +------------------- + +For comments, questions and bug reports, please contact your SanDisk +representative or e-mail us at oemsupport@sandisk.com. + + This document is for information use only and is subject to change + without prior notice. + + SanDisk IL Ltd. assumes no responsibility for any errors that may + appear in this document, nor for incidental or consequential damages + resulting from the furnishing, performance or use of this material. + + SanDisk IL's products are not warranted to operate without failure. + SanDisk IL's general policy does not recommend the use of its products + in life support applications where a failure or malfunction of the + product could cause injury or loss of life. Per SanDisk IL's Terms and + Conditions of Sale, the user of SanDisk IL's products in life support + applications assumes all risk of such use and indemnifies SanDisk IL + against all damages. See "Disclaimer of Liability". Accordingly, in + any use of the Product in life support systems or other applications + where failure could cause injury or loss of life, the Product should + only be incorporated in systems designed with appropriate and + sufficient redundancy or backup features. + + All parts of the SanDisk IL's documentation are protected by copyright + law and all rights reserved. + + Contact your local SanDisk sales office or distributor to obtain the + latest specifications before placing your order. + + (C) 1995-2007 SanDisk IL Ltd. All rights reserved. + + mDOC, DOC, TrueFFS, SureFS, SanDisk and SanDisk logo are registered + trademarks of SanDisk IL Ltd. and SanDisk Corporation, respectively. + Other product names or service marks mentioned herein may be trademarks + or registered trademarks of their respective owners and are hereby + acknowledged. diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_common.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_common.h new file mode 100755 index 00000000..7a12be3c --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_common.h @@ -0,0 +1,124 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/***********************************************************************************/ +/* */ +/* Header file containing definitions used by external API */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 7.0/TrueFFS FS/src/mdoc/_common.h-arc $ + * + * Rev 1.3 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.2 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.1 Aug 09 2006 16:52:44 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef _COMMON_H +#define _COMMON_H + +/**************************************************************************/ +/* General types definitions */ +/* TrueFFS interface of all packages uses the following types as the */ +/* variable definision. */ +/**************************************************************************/ + +typedef int FLBoolean; +typedef unsigned char FLByte; /* 8 bit unsigned variable */ +typedef unsigned short FLWord; /* 16 bit unsigned variable */ +typedef unsigned long FLDword; /* 32 bit unsigned variable */ +typedef unsigned int FLNative; /* Native variable at least 16 bits */ +typedef signed char FLSByte; /* 8 bit signed variable */ +typedef signed short FLSWord; /* 16 bit signed variable */ +typedef signed long FLSDword; /* 32 bit signed variable */ +typedef int FLSNative; /* Signed native variable at least 16 bits */ +typedef FLSWord FLWchar; /* Unicode type variable */ +typedef FLDword CardAddress ; /* Physical offset on card */ + +/**************************************************************************/ +/* I O r e q */ +/* */ +/* IOreq is a common structure passed to all TrueFFS functions. */ +/* Refer to the description of individual functions for specific usage */ +/* of fields. Some fields have different names when used by different */ +/* functions, hence the use of unions. */ +/* */ +/**************************************************************************/ + +typedef unsigned FLHandle; /* Handle of an open file or drive. */ + /* Actually an index to file table or */ + /* drive table. */ + + +typedef struct { + FLHandle irHandle; /* Handle of file or drive for operation*/ + FLDword irFlags; /* function-specific flags */ + void * irPath; /* path of file for operation */ + void * irData; /* Pointer to user-buffer for operation */ + FLSDword irLength; /* No. of bytes, size or position for */ + /* operation */ + FLSDword irCount; /* Count or offset for operaion */ +} IOreq; + +/**************************************************************************/ +/* Special ioreq field names: */ +/* IOReq structure is the basic IO type used for all TrueFFS calls. */ +/* Some of the fields has additional name for more trivial use of the */ +/* function. The duplicate names are defined below. */ +/**************************************************************************/ +#define irSectorCount irCount +#define irSectorNo irLength +#define irByteCount irCount +#define irAddress irLength + +#define FL_GET_SOCKET_FROM_HANDLE(ioreq) (FLByte)((ioreq)->irHandle & 0x0f) +#define FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq) (FLByte)(((ioreq)->irHandle & 0xf0) >> 4) + +#endif /*_COMMON_H*/ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_dochapi.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_dochapi.h new file mode 100755 index 00000000..76109ae9 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_dochapi.h @@ -0,0 +1,2621 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/***********************************************************************************/ +/* */ +/* Internal header file for doch_api module */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 7.0/TrueFFS FS/src/h3/_dochapi.h-arc $ + * + * Rev 1.23 Dec 03 2007 18:54:24 einat.avidan + * Add flag for DochRecoverFromPowerLoss + * Remove flDOCHWipeSectorsByWriting + * + * Rev 1.22 Oct 30 2007 15:29:20 einat.avidan + * add new function flDOCHWipeSectorsByWriting + * + * Rev 1.21 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.20 Oct 21 2007 15:28:26 einat.avidan + * fix compilation warnings + * + * Rev 1.19 Oct 11 2007 18:47:12 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * Add support for reporting internal errors + * add compilation flags for SOTP and SLPP + * + * Rev 1.18 Mar 22 2007 17:12:10 einat.avidan + * add SOTP + * + * Rev 1.17 Mar 13 2007 13:47:18 einat.avidan + * add support for SLPP + * + * Rev 1.16 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.15 Sep 10 2006 10:02:40 Yaniv.Iarovici + * Change SA SDK sub-version to "1.51 Prelim2". + * + * Rev 1.14 Aug 24 2006 11:40:36 Yaniv.Iarovici + * Added 'DOCH_ACCESS_ALL_PARTITIONS' to structure 'DOCH_Access_Op'. + * + * Rev 1.13 Aug 16 2006 08:43:02 Yaniv.Iarovici + * change SA SDK sub-version to Fin4 + * Change DOCH_SECTOR_SIZE_BITS to bit-manipulation on DOCH_SECTOR_SIZE_BITS insead of value of 512 + * Add #define DOCH_MAX_DRQ_SUPPORTED to indicate max DRQ size supported by the SDK + * Change description of flDOCHGetPowerMode() and flDOCHSetPowerMode() to fit SW Spec 0.84 + * + * Rev 1.12 Aug 09 2006 17:27:42 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.10 Jul 03 2006 22:45:02 polina.marimont + * version change + * + * Rev 1.9 Jul 03 2006 22:12:32 polina.marimont + * version changed + * + * Rev 1.8 Jun 22 2006 16:56:32 Polina.Marimont + * version changed + * + * Rev 1.7 Jun 21 2006 18:23:34 Polina.Marimont + * 1. version update + * 2. set power mode function description updated + * + * Rev 1.6 Jun 18 2006 13:01:58 Polina.Marimont + * 1. version changed + * 2. power mode save function chaged + * + * Rev 1.5 Jun 14 2006 17:31:52 Polina.Marimont + * version updated + * + * Rev 1.4 May 30 2006 10:40:24 polina.marimont + * version change to 1.42 Pre 3 + * + * Rev 1.3 May 28 2006 12:48:26 polina.marimont + * version 1.42 Pre1 + * + * Rev 1.2 May 18 2006 14:40:46 polina.marimont + * PVCS inside + */ + +#ifndef _DOCHAPI +#define _DOCHAPI + +#include "_common.h" + +/***********************/ +/* SDK Version Number */ +/***********************/ +#define DochSDKVersion "0151" +#define DochSDKSubVersion "Pre2" + +/********************/ +/* Partitions */ +/********************/ + +/* Pattern to indicate a boolean global variable was set + (to deal with "naughty" compilers...)*/ +#define DOCH_GLOBAL_BOOL_PATTERN 0xCA + +/* Max number of paritions */ +#define DOCH_MAX_PARTITIONS 16 + +/*IPL partition*/ +#define DOCH_IPL_PARTITION 0 +#define IPL_PARTITION_SIZE_SECTORS 0x200 /*256KB in sectors*/ +#define IPL_PARTITION_SIZE_V_SECTORS 0x10 /* 8K KB sectors*/ + + +/********************/ +/* Various Defines */ +/********************/ + +/* On/Off definitions */ +#define DOCH_OFF 0 +#define DOCH_ON 1 + +/* size of DOCH data block in FLBytes */ +#define DOCH_SECTOR_SIZE_BITS 9 +#define DOCH_SECTOR_SIZE (1<irHandle & 0x0f) +#define DOCH_SET_SOCKET_TO_IOREQ_HANDLE(ioreq, socket) ((ioreq)->irHandle |= (socket)) + +#define DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) (FLByte)(((ioreq)->irHandle & 0xf0) >> 4) +#define DOCH_SET_PARTITION_TO_IOREQ_HANDLE(ioreq, part) ((ioreq)->irHandle = \ + ( ((part & 0xF) << 4) | ((ioreq)->irHandle & 0xFFFFFF0F)) ) + +/* Operation type (for long operations) */ +#define DOCH_NORMAL_OPERATION 0x00 +#define DOCH_IMMEDIATE_OPERATION 0x80 + +/* Data transfer modes */ +typedef enum { DOCH_DATA_XFER_MODE_SINGLE = 0x00, + DOCH_DATA_XFER_MODE_MULT = 0x01 +} DOCH_DataTransferMode; +/*Max supported DRQ*/ +#define DOCH_MAX_DRQ_SUPPORTED 4 + +/*ETFFS Alert Levels*/ +typedef enum { + DOCH_ALERT_LEVEL_CRASH = 0, /*Prints only errors that H3 can not recover from*/ + DOCH_ALERT_LEVEL_EMERGENCY = 1, /*Prints only important, but not lethal errors*/ + DOCH_ALERT_LEVEL_REPORT = 2, /*Prints basic report on H3 operations*/ + DOCH_ALERT_LEVEL_DEBUG = 3, /*Prints full report on H3 progress*/ + DOCH_ALERT_LEVEL_BORING = 4 /*Prints every operation done by H3*/ +} DOCH_AlertLevel; + +/* Power mode constants */ +typedef enum { + DOCH_PM_SET_NONE = 0x00, + DOCH_PM_SET_WORK_MODE = 0x01, + DOCH_PM_SET_INACTIVE_MODE = 0x02, + DOCH_PM_SET_BOTH_MODES = 0x03 +} DOCH_SetPowerMode; + +typedef enum { + DOCH_PM_WORK_MODE = 0x00, + DOCH_PM_INACTIVE_MODE = 0x04 +} DOCH_SelectedPowerMode; + +typedef enum { + DOCH_WM_NORMAL = 0x00, /*Same as ATA ACTIVE Mode*/ + DOCH_WM_LOW_FREQ = 0x01, /*Same as ATA IDLE Mode*/ + DOCH_WM_NORMAL_AND_AUTO_STBY = 0x02, + DOCH_WM_LOW_FREQ_AND_AUTO_STBY = 0x03 +} DOCH_WorkMode; + +typedef enum { + DOCH_IM_IDLE = 0x00, /*Same as ATA STANDBY Mode*/ + DOCH_IM_DPD = 0x10, /*Same as ATA SLEEP Mode*/ + DOCH_IM_IDLE_2_DPD = 0x20 /*No timeout IDLE ==> DPD */ +} DOCH_InactiveMode; + +#define DOCH_PM_SAVE_DEFAULT 0x10 /*Save power mode settings as device default*/ + +/* Custom Parameters Table */ +typedef enum { + DOCH_CP_BOOT_MODE = 0x00, /*Boot Mode (See DOCH_IPLModes)*/ + DOCH_CP_XIP_TEST_MODE = 0x01, /*XIP Test Modes (See DOCH_XIPTestModes)*/ + DOCH_CP_XIP_MAX_SIZE = 0x02, /*Max XIP Size*/ + DOCH_CP_XIP_ETFFS_SIZE = 0x03, /*Returns the size of the currently saved ETFFS (required for uploading the ETFFS)*/ + DOCH_CP_WORK_MODES = 0x04, /*Work Modes (Bit Field, see enum DOCH_CPWorkModes)*/ + DOCH_CP_SLOCK_CTRL = 0x05, /*Sticky Lock control (See DOCH_SlockCtrl)*/ + DOCH_CP_BYTE_SWAP_CTRL = 0x06, /*Byte Swap control (See DOCH_ByteSwapCtrl)*/ + DOCH_CP_FLASH_TEST_MODE = 0x07, /*Enable/Disable flash test mode (See DOCH_FlashTestModeCtrl)*/ + DOCH_CP_REPORT_ECC_MODE =0x08 /*Enable/Disable report of ECC errors (See DOCH_EccErrorCtrl)*/ +} DOCH_CustomParams; + +#define DOCH_CUSTOM_PARAM_TEMP 1 +#define DOCH_CUSTOM_PARAM_DEFAULT 0 + +/* IPL Modes */ +typedef enum { + DOCH_IPL_MODE_NORMAL_RAM = 0x0000, + DOCH_IPL_MODE_PAGED_RAM = 0x0001, + DOCH_IPL_MODE_VIRTUAL_RAM = 0x0002, + DOCH_IPL_MODE_CS_DELAY = 0x1000, /*Should be Or`ed with 0x0XX0, where bits 4-11 indicating delay*/ + DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT = 0x2000, + DOCH_IPL_MODE_ACTIVE_SWAP_BYTES = 0x4000, + DOCH_IPL_MODE_8KB_WINDOW = 0x8000 +} DOCH_IPLModes; + +#define DOCH_IPL_WRITE_FIRST_CHUNK 0x80000000 /*Defines first chunk when writing IPL in chunks*/ + +/* XIP Test Modes */ /*No default value, will be cleared upon reset*/ +typedef enum { + DOCH_XIP_NORMAL = 0x0000, + DOCH_XIP_WRITEABLE = 0x0001, + DOCH_XIP_FILL_PATTERN = 0x0002, /*"M-Systems" and the rest with consecutive 16bit numbers*/ + DOCH_XIP_PIPELINE = 0x0003 /*Places the device in pipeline access mode*/ +} DOCH_XIPTestModes; + +typedef enum { + DOCH_WORK_MODES_BLOCK_SPI = 0x0002 /*Block SPI*/ +} DOCH_CPWorkModes; + +typedef enum { + DOCH_STICKY_LOCK_UNSET = 0x00, + DOCH_STICKY_LOCK_SET = 0x01 +} DOCH_SlockCtrl; + +typedef enum { + DOCH_BYTE_SWAP_UNSET = 0x00, + DOCH_BYTE_SWAP_SET = 0x01 +} DOCH_ByteSwapCtrl; + +typedef enum { + DOCH_DISABLE_FLASH_TEST_MODE = 0x00, + DOCH_ENABLE_FLASH_TEST_MODE = 0x01 +} DOCH_FlashTestModeCtrl; + +typedef enum { + DOCH_DISABLE_REPORT_ECC_ERRORS = 0x00, + DOCH_ENABLE_REPORT_ECC_ERRORS = 0x01 +} DOCH_EccErrorCtrl; + + +typedef enum { + DOCH_DLMCODE_DOWNLOAD = 0x01, /*Download is for immediate, temporary use*/ + DOCH_DLMCODE_DOWNLOAD_AND_SAVE = 0x07, /*Save downloaded code for immediate & future use*/ + DOCH_DLMCODE_DOWNLOAD_AND_LAST_SAVE = 0x87, /*Same as code 0x07, but marking this as the last permanent + download accepted by the device*/ + DOCH_DLMCODE_UPLOAD = 0xFF +} DOCH_DLMcodeModes; + +/* Set of access options for DOCH_EN_ACCESS_WPWD */ +typedef enum { DOCH_ACCESS_USER_PASSWORD = 0x00, + DOCH_ACCESS_MASTER_PASSWORD = 0x01, + DOCH_ACCESS_GATE_KEEPER = 0x02, + + DOCH_ACCESS_ALL_PARTITIONS = 0xFF +} DOCH_Access_Op; + +/*Defines for DOCHConfigHW*/ +/*------------------------*/ +typedef enum { + DOCH_BURST_WRITE_MODE_CTRL = 0x0, + DOCH_BURST_READ_MODE_CTRL = 0x1, + DOCH_IPL_CTRL = 0x2, + DOCH_WARM_BOOT_CTRL = 0x3, + DOCH_POWER_DOWN = 0x4, + DOCH_DMA_CTRL = 0x5, + DOCH_DMA_ENABLE = 0x6, + DOCH_DMA_NEGATION_CTRL = 0x7, + DOCH_SLOCK = 0x8, + DOCH_ENDIAN_CTRL = 0x9, + DOCH_OPERATION_MODE_CTRL = 0xA, + DOCH_POWER_MODE_CTRL = 0xB +} DOCH_HwConfigType; + +/* DOCH_NUM_OF_DCONFIGHW_ITEMS should be set to number of items in DOCH_HwConfigType*/ +#define DOCH_NUM_OF_DCONFIGHW_ITEMS 0xC + +/*IPL Control Register*/ +#define DOCH_IPL_WRITE_DISABLE 0x0000 +#define DOCH_IPL_WRITE_READY 0x0001 +#define DOCH_IPL_WRITE_ENABLE 0x0002 + +#define DOCH_IPL_ALL_CS_ENABLED 0x0000 +#define DOCH_IPL_CLOSE_2LOW_IPLS 0x0010 +#define DOCH_IPL_CLOSE_2HIGH_IPLS 0x0020 +#define DOCH_IPL_CLOSE_ALL_IPLS 0x0030 + +/*Warm Boot Register*/ +#define DOCH_WARM_RST_POLARITY_LOW 0x0000 +#define DOCH_WARM_RST_POLARITY_HIGH 0x0001 + +#define DOCH_WARM_RST_BURST_ON 0x0000 +#define DOCH_WARM_RST_BURST_NO_CHNG 0x0002 + +/*Deep Power Down Mode Register*/ +#define DOCH_DPD_PIN_POL_LOW 0x0000 +#define DOCH_DPD_PIN_POL_HIGH 0x0001 + +#define DOCH_DPD_PIN_DISABLED 0x0000 +#define DOCH_DPD_PIN_ENABLED 0x0002 + +#define DOCH_DPD_WAKEUP_HOST_CE 0x0000 +#define DOCH_DPD_WAKEUP_ASYNC_CLK 0x0100 + +/*DMA Control Register*/ +#define DOCH_DMA_REQ_DISABLE 0x0000 +#define DOCH_DMA_REQ_ENABLE 0x0001 + +#define DOCH_DMA_REQ_POL_HIGH 0x0000 +#define DOCH_DMA_REQ_POL_LOW 0x0002 + +#define DOCH_DMA_REQ_LEVEL 0x0000 +#define DOCH_DMA_REQ_EDGE 0x0004 + +/*SLOCK Control Register*/ +#define DOCH_SLOCK_ACTIVE 0x0001 +#define DOCH_SLOCK_OFF 0x0000 + +/*Burst write/read mode control*/ +#define DOCH_BURST_DISABLE 0x0000 +#define DOCH_BURST_ENABLE 0x0002 + +#define DOCH_BURST_HOLD_1_CLK 0x0000 +#define DOCH_BURST_HOLD_2_CLK 0x2000 + +#define DOCH_BURST_LEN_4_CYC 0x0000 +#define DOCH_BURST_LEN_8_CYC 0x0800 +#define DOCH_BURST_LEN_16_CYC 0x1000 +#define DOCH_BURST_LEN_32_CYC 0x1800 + +/*Endian Control Register*/ +#define DOCH_END_SWAP_OFF 0x0000 +#define DOCH_END_SWAP_ON 0x0101 + +/*Operation Mode Register*/ +#define DOCH_NON_PIPE_ACCESS 0x00 +#define DOCH_PIPE_ACCESS 0x01 + +#define DOCH_NO_ADDR_SHIFT 0x00 +#define DOCH_ADDR_SHIFT 0x02 + +/*Power Mode Register*/ +#define DOCH_POWER_MODE_DPD 0x0001 + +/*Environment variables*/ +typedef enum { + DOCH_ENV_VERIFY_WRITE = 0x01, /* Verifies every written sector by reading it back from device */ + DOCH_ENV_ATA_DEBUG = 0x02, /* Retrieve debug buffer from device after completion of ATA command */ + DOCH_ENV_BLOCK_SPI = 0x03, /* Block SPI */ + DOCH_ENV_NO_ATA_TIMEOUT = 0x04, /* Disable ATA command timeout */ + DOCH_ENV_AUTO_DPD_BY_HOST = 0x05 /* Host automatically enters device to DPD after every command*/ +} DOCH_EnVars; + +/*Flags for read/write operations using DMA/Burst*/ +#define DOCH_USE_DMA 0x01 +#define DOCH_USE_BURST 0x02 + +/* Strings lengths */ +#define DOCH_PASS_KEY_LEN 0x80 +#define DOCH_PASS_KEY_LEN_NO_NULL (H3_PASS_KEY_LEN-1) +#define DOCH_SER_NO_LEN 0x14 +#define DOCH_MODEL_NO_LEN 0x28 +#define DOCH_PROG_NAME_LEN 0x10 +#define DOCH_PROG_VER_LEN 0x8 + +/* DOCHRecoverFromPowerLoss flags */ +#define DOCH_DO_NOT_REINIT_MASTER 0x1 + + +/* DOCH error codes */ +/*------------------*/ +#define DOCH_ATA_ERROR_BASE 0x0 +#define DOCH_SDK_ERROR_BASE 0x100 +#define DOCH_FS_ERROR_BASE 0x200 + +typedef enum { DOCH_OK = 0, + + /*ATA Error codes*/ + + DOCH_ATA_NO_ERROR = DOCH_ATA_ERROR_BASE + 0x00, + DOCH_ATA_ERROR_MEDIA_ERROR_DETECTED = DOCH_ATA_ERROR_BASE + 0x01, /*ATA-4*/ + DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND = DOCH_ATA_ERROR_BASE + 0x01, /*Repeat last operation*/ + DOCH_ATA_ERROR_TRACK_0_NOT_FOUND = DOCH_ATA_ERROR_BASE + 0x02, /*Protection violation*/ + DOCH_ATA_ERROR_NO_MEDIA = DOCH_ATA_ERROR_BASE + 0x02, /*ATA-4*/ + DOCH_ATA_ERROR_ABORT = DOCH_ATA_ERROR_BASE + 0x04, /*Always need to be supplied*/ + DOCH_ATA_ERROR_MEDIA_CHANGE_REQUESTED = DOCH_ATA_ERROR_BASE + 0x08, /*Not to use for now*/ + DOCH_ATA_ERROR_ID_NOT_FOUND = DOCH_ATA_ERROR_BASE + 0x10, /*Passing partition boundary*/ + DOCH_ATA_ERROR_MEDIA_CHANGE_DETECTED = DOCH_ATA_ERROR_BASE + 0x20, /*Not to use for now*/ + DOCH_ATA_ERROR_WRITE_PROTECTED = DOCH_ATA_ERROR_BASE + 0x40, /*on writes - only if we run out of space*/ + DOCH_ATA_ERROR_UNCORRECTABLE_DATA = DOCH_ATA_ERROR_BASE + 0x40, /*on reads - possible for unrecoverable ECC - should not be returned by write routines*/ + DOCH_ATA_ERROR_ICRC = DOCH_ATA_ERROR_BASE + 0x80, /*on DMA xfers - to leave for now*/ + + /*SDK Error Codes*/ + DOCH_TimedOut = DOCH_SDK_ERROR_BASE, + DOCH_GeneralFailure = DOCH_SDK_ERROR_BASE + 5, + DOCH_AdapterNotFound = DOCH_SDK_ERROR_BASE + 6, + DOCH_DeviceTurnedOff = DOCH_SDK_ERROR_BASE + 7, + DOCH_BadParameter = DOCH_SDK_ERROR_BASE + 10, + DOCH_DriveNotAvailable = DOCH_SDK_ERROR_BASE + 15, + DOCH_DriveNotReady = DOCH_SDK_ERROR_BASE + 20, + DOCH_NotEnoughMemory = DOCH_SDK_ERROR_BASE + 25, + DOCH_ReadFault = DOCH_SDK_ERROR_BASE + 30, + DOCH_WriteFault = DOCH_SDK_ERROR_BASE + 31, + DOCH_VerifyFault = DOCH_SDK_ERROR_BASE + 32, + DOCH_ProtectionFault = DOCH_SDK_ERROR_BASE + 33, + DOCH_UnknownCmd = DOCH_SDK_ERROR_BASE + 35, + DOCH_DiskNotFound = DOCH_SDK_ERROR_BASE + 40, + DOCH_PartitionNotFound = DOCH_SDK_ERROR_BASE + 45, + DOCH_PartitionLimitExceeded = DOCH_SDK_ERROR_BASE + 50, + DOCH_FeatureNotSupported = DOCH_SDK_ERROR_BASE + 55, + DOCH_ATABusyNotCleared = DOCH_SDK_ERROR_BASE + 60, + DOCH_ATANotReady = DOCH_SDK_ERROR_BASE + 61, + DOCH_ATAErrorDetected = DOCH_SDK_ERROR_BASE + 65 + +} DOCH_Error; + + +/* IOCTL Codes */ +typedef enum { + /*Get Info*/ + SDK_IDENTIFY_DISKONCHIP_DEVICE = 0x200, + SDK_GET_RESET_STATUS = 0x201, + SDK_NOTIFY_RESET = 0x202, + SDK_NOTIFY_PLATFORM_RESUMED = 0x203, + SDK_GET_PARTITION_INFO = 0x204, + SDK_SET_DISK_USER_ATTR = 0x205, + SDK_GET_DISK_USER_ATTR = 0x206, + SDK_GET_CONFIG_DATA = 0x207, + SDK_SET_CONFIG_DATA = 0x208, + + /*Media*/ + SDK_SET_DEFAULT_PARTITION = 0x210, + SDK_SET_DATA_XFER_MODE = 0x211, + SDK_OPTIMIZE_MEDIA = 0x212, + SDK_DELETE_PARTITIONS = 0x213, + SDK_ADD_PARTITION = 0x214, + SDK_UNFORMAT_DEVICE = 0x215, + SDK_WRITE_IPL = 0x216, + SDK_READ_IPL = 0x217, + + /*IO*/ + SDK_READ_PARTITION_SECTORS = 0x220, + SDK_WRITE_PARTITION_SECTORS = 0x221, + SDK_WRITE_AND_LOCK = 0x222, + SDK_WIPE_SECTORS = 0x223, + SDK_FREE_SECTORS = 0x224, + SDK_PREPARE_FOR_WRITE = 0x225, + SDK_WIPE_SECTORS_BY_WRITING = 0x226, + + /*Flexi-Flash*/ + SDK_WRITE_FLEXI_FAST = 0x230, + SDK_WRITE_FLEXI_NORMAL = 0x231, + SDK_REWRITE_FLEXI_NORMAL = 0x232, + + /*Hash*/ + SDK_READ_WITH_HASH_VERIFY = 0x240, + SDK_READ_HASH = 0x241, + SDK_WRITE_HASH = 0x242, + + /*Protection*/ + SDK_ACCESS_PART_WITH_PWD = 0x250, + SDK_DISABLE_PART_ACCESS = 0x251, + SDK_SET_PART_PROTECTION = 0x252, + SDK_SET_PART_USER_ATTR = 0x253, + SDK_GET_PART_USER_ATTR = 0x254, + + /*PKI*/ + SDK_PKI_HOST = 0x260, + SDK_PKI_DOCH = 0x261, + SDK_PKI_VERIFY_HOST_KEY = 0x262, + + /*Custom Parameters*/ + SDK_GET_CUSTOM_PARAM = 0x270, + SDK_SET_CUSTOM_PARAM = 0x271, + + /*Atomic Read/Write Sequence*/ + SDK_ATOMIC_WRITE_SEQ = 0x280, + + /*Algorithms*/ + SDK_REPORT_SUPP_ALG = 0x290, + SDK_REPORT_ALG_CAPAB = 0x291, + SDK_SET_ALG_MODE = 0x292, + + /*Hash*/ + SDK_AUTO_HASH_CTRL = 0x2A0, + SDK_READ_CALC_HASH = 0x2A1, + SDK_WRITE_CALC_HASH = 0x2A2, + SDK_READ_ORIG_HASH = 0x2A3, + SDK_WRITE_GIVEN_HASH = 0x2A4, + SDK_START_HASH_STREAM_CALC = 0x2A5, + SDK_READ_HASH_STREAM_CALC = 0x2A6, + SDK_RETURN_RAND_NUMS = 0x2A7, + SDK_SET_HASH_KEY = 0x2A8, + + /*General (Control/Configuration)*/ + SDK_SET_POWER_MODE = 0x2B0, + SDK_GET_POWER_MODE = 0x2B1, + SDK_HW_CONFIG = 0x2B2, + SDK_RECOVER_FROM_POWER_LOSS = 0x2B3, + SDK_RESET_SOCKET = 0x2B4, + SDK_SET_ENV_VAR = 0x2B5, + SDK_CLEAR_ATA_INTERRUPT = 0x2B6, +#ifndef FL_SLPP + SDK_GET_PHYSICAL_ADDRESS = 0x2B7 +#else /*FL_SLPP*/ + SDK_GET_PHYSICAL_ADDRESS = 0x2B7, + /*SLPP Specific*/ + SDK_SLPP_UNLOCK_RANGE = 0x2C0, + SDK_SLPP_UNLOCK_ENTIRE_PARTITION = 0x2C1, + SDK_SLPP_LOCK_RANGE = 0x2C2, + SDK_SLPP_STICKY_LOCK_RANGE = 0x2C3, + SDK_SLPP_REPORT_LOCKED_RANGES = 0x2C4 +#endif /*FL_SLPP*/ + +} SDKFunctionNo; + +/* runtime socket init data */ +typedef struct { + unsigned int nDeviceAddress; +} DOCH_InitSocket; + +/* Access layer routines registration structure */ +typedef struct { + unsigned char (*hal_get_ata_reg_user) (volatile unsigned char *base, int reg); + void (*hal_set_ata_reg_user) (volatile unsigned char *base, int reg, unsigned int val); + unsigned short(*hal_get_ctrl_reg_user) (volatile unsigned char *base, int reg); + void (*hal_set_ctrl_reg_user) (volatile unsigned char *base, int reg, unsigned int val); + int (*hal_blk_read_user) (volatile unsigned char *base, unsigned char *buf, int sectors); + int (*hal_blk_write_user) (volatile unsigned char *base, unsigned char *buf, int sectors); + int (*hal_release_user) (int socketNo); +} DOCH_BusAccess_routines; + +/********************/ +/* API Defines */ +/********************/ + +/* set of DOCH ATA registers */ +typedef enum { + DOCH_DATA_REG = 0x00, + DOCH_ERROR_REG = 0x01, + DOCH_FEATURES_REG = 0x01, + DOCH_SECTOR_CNT_REG = 0x02, + DOCH_SECTOR_NO_REG = 0x03, + DOCH_CYLINDER_LOW_REG = 0x04, + DOCH_CYLINDER_HIGH_REG = 0x05, + DOCH_DRIVE_HEAD_REG = 0x06, + DOCH_STATUS_REG = 0x07, + DOCH_COMMAND_REG = 0x07, + DOCH_ALT_STATUS_REG = 0x0E, + DOCH_CONTROL_REG = 0x0E +} DOCH_Reg; + +/* ATA registers structure */ +typedef struct { FLByte bFeaturesError; /* DOCH_FEATURES_REG or DOCH_ERROR_REG */ + FLByte bSectorCount; /* DOCH_SECTOR_CNT_REG */ + FLByte bSectorNumber; /* DOCH_SECTOR_NO_REG */ + FLByte bCylLow; /* DOCH_CYLINDER_LOW_REG */ + FLByte bCylHigh; /* DOCH_CYLINDER_HIGH_REG */ + FLByte bDriveHead; /* DOCH_DRIVE_HEAD_REG */ + FLByte bCommandStatus; /* DOCH_COMMAND_REG or DOCH_STATUS_REG*/ + FLByte bContorlAltStatus; /* DOCH_CONTROL_REG or DOCH_ALT_STATUS_REG*/ +} DOCH_Registers; + +/* Set of operation codes for PassThru */ +typedef enum { DOCH_PASSTHRU_NO_DATA = 0x00, + DOCH_PASSTHRU_DATA_IN = 0x01, + DOCH_PASSTHRU_DATA_OUT = 0x02 +} DOCH_PassThru_Op; + +typedef enum { DOCH_PASSTHRU_NO_INT = 0x00, + DOCH_PASSTHRU_USE_INT = 0x04 + +} DOCH_PassThru_Int; + + +/*OPTIMIZE_MEDIA*/ +#define DOCH_OPTIMIZE_BY_PREPARE_FOR_WRITE 0 +#define DOCH_OPTIMIZE_DEFAULT 1 + +typedef enum { + SET_DEFAULT_PARTITION_TEMP = 0x0, + SET_DEFAULT_PARTITION_PERM = 0x1 +} DOCH_DefaultPartSet; + +typedef enum { + DOCH_FAST_PARTITOIN_DELETE = 0x0, + DOCH_COMPLETE_PARTITION_DELETE = 0x8 +} DOCH_DeletePartitionsMode; + + +/******************************************************************************/ +/* + * Partition Info structure, sub-structures and ENUMS + */ +/******************************************************************************/ + +/*Partition dwCommandFlagsOrStatuses Offsets*/ +#define DOCH_CFSO_FAST_AREA_SIZE_TYPE 8 +#define DOCH_CFSO_USER_AUTHENTICATED 16 +#define DOCH_CFSO_PERM_LOCKED 17 +#define DOCH_CFSO_MASTER_AUTHENTICATED 18 +#ifdef FL_SOTP +#define DOCH_CFSO_SOTP_LOCKED 19 +#endif /*FL_SOTP*/ +#define DOCH_CFSO_HW_LOCK_ASSERTED 30 +#define DOCH_CFSO_SW_LOCK_ASSERTED 31 + +/*Partition dwCommandFlagsOrStatuses Bits*/ +#define DOCH_CFSB_FAST_AREA_SIZE_TYPE 0x00000100 +#define DOCH_CFSB_USER_AUTHENTICATED 0x00010000 +#define DOCH_CFSB_PERM_LOCKED 0x00020000 +#define DOCH_CFSB_MASTER_AUTHENTICATED 0x00040000 +#ifdef FL_SOTP +#define DOCH_CFSB_SOTP_LOCKED 0x00080000 +#endif /*FL_SOTP*/ +#define DOCH_CFSB_HW_LOCK_ASSERTED 0x40000000 +#define DOCH_CFSB_SW_LOCK_ASSERTED 0x80000000 + +/*Partition Attribute1 Offsets*/ +#define DOCH_PA1O_PARTITION_TYPE 0 +#define DOCH_PA1O_PERFORMANCE_CTRL 8 +#define DOCH_PA1O_PAGE_SIZE_EXP 16 +#define DOCH_PA1O_HASH_TYPE 24 + +/*Partition Attribute1 Bits*/ +#define DOCH_PA1B_PARTITION_TYPE 0x000000FF +#define DOCH_PA1B_PERFORMANCE_CTRL 0x00000F00 +#define DOCH_PA1B_PAGE_SIZE_EXP 0x000F0000 +#define DOCH_PA1B_HASH_TYPE 0x3F000000 + +/*Partition Attribute2 Offsets*/ +#define DOCH_PA2O_PROTECTION_TYPE 0 +#define DOCH_PA2O_USER_MODE 6 +#define DOCH_PA2O_GUEST_MODE 9 +#define DOCH_PA2O_MASTER_CTRL 12 +#define DOCH_PA2O_ENCRYPT_TYPE 15 +#define DOCH_PA2O_OTP_BIT 21 +#define DOCH_PA2O_LOCK_CTRL 22 +#define DOCH_PA2O_MAX_AUTH_ATTEMPTS 24 + +/*Partition Attribute2 Bits*/ +#define DOCH_PA2B_PROTECTION_TYPE 0x00000007 /*DOCH_ProtectionType*/ +#define DOCH_PA2B_USER_MODE 0x000001C0 /*DOCH_PartitionAccessMode*/ +#define DOCH_PA2B_GUEST_MODE 0x00000E00 /*DOCH_PartitionAccessMode*/ +#define DOCH_PA2B_MASTER_CTRL 0x00007000 /*DOCH_PartitionAccessMode*/ +#define DOCH_PA2B_ENCRYPT_TYPE 0x00038000 /*DOCH_EncryptType*/ +#define DOCH_PA2B_OTP_BIT 0x00200000 +#define DOCH_PA2B_LOCK_CTRL 0x00C00000 /*DOCH_LockControl*/ +#define DOCH_PA2B_MAX_AUTH_ATTEMPTS 0x0F000000 + +/* Structure that holds various partition data*/ +typedef struct { + FLByte bDevice; /*On which device (0/1) the partition reside*/ +} DOCH_PartitionAttr; + +/*Partition formatting info*/ + +/*API exported for partition preporties*/ +typedef struct { + FLDword dwProtectionType; /*DOCH_ProtectionType*/ + FLDword dwUserAccessMode; /*DOCH_PartitionAccessMode*/ + FLDword dwGuestAccessMode; /*DOCH_PartitionAccessMode*/ + FLDword dwMasterControl; /*DOCH_PartitionAccessMode*/ + FLDword dwEncryptionType; /*DOCH_EncryptType*/ + FLDword dwLockControl; /*DOCH_LockControl*/ + FLDword dwMaxNumOfAuthAttempts; /*0 = Unlimited number*/ + FLByte bPasskey[0x80]; /*ASCII*/ +} DOCH_PartitionProtectionAPI; + +typedef enum { + DOCH_PASSKEY_VALID = 0x01, /* Passkey in DOCH_PartitionProtectionAPI is valid */ + DOCH_ATTRIBUTES_VALID = 0x02, /* All attributes in DOCH_PartitionProtectionAPI besides passkey are valid */ + DOCH_LOCK_AS_OTP = 0x04, /* Lock the partition for writing */ + DOCH_SEQUENTIAL_OTP = 0x08 /* Enable sequential OTP partition, must be always set with DOCH_LOCK_AS_OTP*/ +} DOCH_PartitionProtectioValidity; + +/*Partition Info structure*/ + +typedef struct { + FLByte bReserved1[0x4]; + FLDword dwCommandFlagsOrStatuses; /*Dynamic info*/ + FLDword partitionAttributes1; + FLDword partitionAttributes2; + FLDword nPartitionSize; /*In Sectors*/ + FLDword nFastAreaSize; /*In Sectors or Percent. for IPL partition: size reported in XIP*/ + FLWord wFastAreaFactor; /*Exponent*/ + FLByte bReserved2[0x2]; + FLDword wPartitionStartSector; + FLWord wCurrentSectorsPerTrack; + FLWord wDefaultSectorsPerTrack; + FLWord wCurrentCylinders; + FLWord wDefaultCylinders; + FLWord wCurrentHeads; + FLWord wDefaultHeads; + FLByte bReserved3[0x4]; /*44-48*/ + FLDword dwSOTPoffset; + FLByte bReserved4[0xC]; + FLWord wFastAreaSectorsInErasableUnit; /*Exponent*/ + FLWord wNormalAreaSectorsInErasableUnit; /*Exponent*/ + FLWord wRecommendedSectorsPerCluster; + FLWord wFastMaxRelatedSectors; + FLWord wNormalMaxRelatedSectors; + FLByte bReserved5[0xB6]; + FLByte bPartitionKey[0x80]; + FLByte bReserved6[0x80]; +} DOCH_PartitionInfo; + +typedef struct { + FLDword dwPartitionType; /*DCOH_PartitionType*/ + FLDword dwPerformanceControl; /*DOCH_PerformanceControl*/ + FLDword dwPageSizeExp; /*DOCH_PageSizeExp*/ + FLDword dwHashType; /*DOCH_HashType*/ + FLDword dwFastAreaSizeType; /*DOCH_FastAreaType*/ + FLDword dwProtectionType; /*DOCH_ProtectionType*/ + FLDword dwUserAccessMode; /*DOCH_PartitionAccessMode*/ + FLDword dwGuestAccessMode; /*DOCH_PartitionAccessMode*/ + FLDword dwMasterControl; /*DOCH_PartitionAccessMode*/ + FLDword dwEncryptionType; /*DOCH_EncryptType*/ + FLDword dwLockControl; /*DOCH_LockControl*/ + FLDword dwOtpEnabled; /*DOCH_OTPBit*/ + FLDword dwMaxNumOfAuthAttempts; /*0 = Unlimited number*/ + FLNative nPartitionSize; /*In Sectors*/ + FLNative nFastAreaSize; /*In Sectors or Percent**/ + FLWord wFastAreaFactor; /*Exponent*/ + FLByte bPasskey[0x80]; /*ASCII*/ +#ifdef FL_SOTP + FLByte bSOTP; /*SOTP partition*/ +#endif /*FL_SOTP*/ +} DOCH_PartitionFormatInfoAPI; + +/*Partition formatting info*/ +typedef struct { + FLByte bReserved1[0x4]; + FLDword dwCommandFlagsOrStatuses; + FLDword partitionAttributes1; + FLDword partitionAttributes2; + FLDword nPartitionSize; /*In Sectors*/ + FLDword nFastAreaSize; /*In Sectors or Percent*/ + FLWord wFastAreaFactor; /*Exponent*/ + FLByte bReserved2[0x12]; + FLDword dwValidity; /*DOCH_PartitionProtectioValidity*/ + FLByte bReserved3[0xD0]; + FLByte bPasskey[0x80]; + FLByte bReserved4[0x80]; +} DOCH_PartitionFormatInfo; + +/*Device dwCommandFlagsOrStatuses Offsets*/ +#define DOCH_DCFSO_CURRENT_XFER_MODE 0 +#define DOCH_DCFSO_CURRENT_MULTI_SECTOR 8 +#define DOCH_DCFSO_HW_LOCK_ASSERTED 30 +#define DOCH_DCFSO_SW_LOCK_ASSERTED 31 + +/*Device dwCommandFlagsOrStatuses Bits*/ +#define DOCH_DCFSB_CURRENT_XFER_MODE 0x00000007 +#define DOCH_DCFSB_CURRENT_MULTI_SECTOR 0x00000F00 +#define DOCH_DCFSB_HW_LOCK_ASSERTED 0x40000000 +#define DOCH_DCFSB_SW_LOCK_ASSERTED 0x80000000 + +/*Device Attributes1 Offsets*/ +#define DOCH_DA1O_SUPPORTED_XFER_MODES_BMP 0 +#define DOCH_DA1O_MAX_MULTI_SEC_XFER_SIZE 8 +#define DOCH_DA1O_SUPPORT_48_BITS 31 + +/*Device Attributes1 Bits*/ +#define DOCH_DA1B_SUPPORTED_XFER_MODES_BMP 0x000000FF +#define DOCH_DA1B_MAX_MULTI_SEC_XFER_SIZE 0x00000F00 +#define DOCH_DA1B_SUPPORT_48_BITS 0x80000000 + +/*Gate Keeper Attributes Offsets*/ +#define DOCH_DA2O_AUTH_TYPE 0 /*DOCH_DeviceAuthType*/ +#define DOCH_DA2O_GUEST_ACCESS_MODE 9 /*DOCH_DeviceAccessMode*/ +#define DOCH_DA2O_MASTER_CONTROL 12 /*DOCH_DeviceAccessMode*/ +#define DOCH_DA2O_MAX_AUTH_ATTEMPTS 24 + +/*Gate Keeper Attributes Bits*/ +#define DOCH_DA2B_AUTH_TYPE 0x00000003 +#define DOCH_DA2B_GUEST_ACCESS_MODE 0x00000E00 +#define DOCH_DA2B_MASTER_CONTROL 0x00007000 +#define DOCH_DA2B_MAX_AUTH_ATTEMPTS 0x0F000000 + +/*Authentication types*/ +typedef enum { + DOCH_DEVICE_AUTH_NONE = 0, + DOCH_DEVICE_AUTH_PWD = 1, + DOCH_DEVICE_AUTH_RSA = 2 +} DOCH_DeviceAuthType; +/*Access modes*/ +typedef enum { + DOCH_DEVICE_ACCESS_MODE_FULL = 0, + DOCH_DEVICE_ACCESS_MODE_RO = 1, + DOCH_DEVICE_ACCESS_MODE_NONE = 2 +} DOCH_DeviceAccessMode; + +#define DOCH_CONFIGURATION_EXISTS_SIGN 0x1F2E3D4C + +typedef struct { + FLWord wVersion; + FLWord wVersionCompatability; + FLDword dwCommandFlagsOrStatuses; + FLDword dwDiskAttributes1; + FLDword dwRservedGateKeeperAttr; + FLDword dwMiscFlags; + FLByte bReserved2[0xC]; + FLByte bUniqueID[0x10]; + FLByte bReserved3[0x10]; + FLByte bSerialNumber[0x14]; + FLByte bModelNumber[0x28]; + FLWord wTotalNumOfPartitions; /*0=IPL not present, 1=Only IPL Present, ... 16=IPL partition + 15 user partitions (MAX)*/ + FLWord wDefaultPartitionNumber; + FLDword dwUnformattedCapacity; /*In Sectors*/ + FLDword dwConfigurationPartitionExistsSign; + FLDword dwETFFSVER; + FLDword dwReservedConfigPartitionSize; /*In Sectors*/ + FLByte bProgrammerName[0x10]; + FLByte bProgrammerVersion[0x8]; + FLDword dwUnitSize; /* In Sectors */ + FLByte bReserved5[0x54]; /*In Sectors*/ + FLByte bReservedGateKeeperKey[0x80]; + FLByte bReserved6[0x80]; +} DOCH_DeviceInfo; + +/*Enums*/ +/*=====*/ +typedef enum { DOCH_PRT_TYPE_NORMAL = 0, /*normal*/ + DOCH_PRT_TYPE_PAGED = 1, /*paged*/ + DOCH_PRT_TYPE_PAGED_DIGEST = 2, /*paged + keeps digest information*/ + DOCH_PRT_TYPE_PAGED_COMPRESSED = 3, /*paged + keeps data in compressed form */ + DOCH_PRT_TYPE_PAGED_DIGEST_COMPRESSED= 4 /*paged + keeps data in compressed form + digest*/ +} DCOH_PartitionType; + + +/*Performance Control*/ +typedef enum { DOCH_NORMAL_PERFORMANCE = 0, /*MLC*/ + DOCH_FIRM_FLASH_OPTIMIZE = 1, /*Rigid MLC/SLC division, fast area field defines division*/ + DOCH_FLEXI_FLASH_OPTIMIZE= 2 /*Adaptive MLC/SLC division, fast area field defines size of spare capacity for performance optimization*/ +} DOCH_PerformanceControl; + +/*Page size exponent (for paged partitions)*/ +typedef enum { DOCH_PAGE_SIZE_512B = 0, + DOCH_PAGE_SIZE_1KB = 1, + DOCH_PAGE_SIZE_2KB = 2, + DOCH_PAGE_SIZE_4KB = 3, + DOCH_PAGE_SIZE_8KB = 4, + DOCH_PAGE_SIZE_16KB = 5, + DOCH_PAGE_SIZE_32KB = 6 +} DOCH_PageSizeExp; + +/*Page size exponent (for paged partitions)*/ +typedef enum { DOCH_HASH_TYPE_SHA1 = 0 +} DOCH_HashType; + +/*Fast Area Type*/ +typedef enum { DOCH_FAST_AREA_TYPE_SECTORS = 0, + DOCH_FAST_AREA_TYPE_PERCENT = 1 +} DOCH_FastAreaType; + +/*Protection Type*/ +typedef enum { DOCH_PARTITION_NOT_PROTECTED = 0, + DOCH_PARTITION_PWD_PROTECTED = 1, + DOCH_PARTITION_RSA_PROTECTED = 2, + DOCH_PARTITION_SLPP_PROTECTED = 3 +} DOCH_ProtectionType; + +#define DOCH_MAX_PWD_ATTEMPTS 5 /*"0" for Unlimited # of attempts*/ + +/*Partition access mode*/ +typedef enum { + DOCH_PART_ACCESS_MODE_FULL = 0, + DOCH_PART_ACCESS_MODE_RO = 1, + DOCH_PART_ACCESS_MODE_NONE = 2 +} DOCH_PartitionAccessMode; + +/*Encryption Type*/ +typedef enum { DOCH_ENCRYPT_NONE = 0, /*Partition is not encrypted*/ + DOCH_ENCRYPT_AES_CTR = 1, /*Partition is AES-encrypted, CTR mode*/ + DOCH_ENCRYPT_RC4 = 2 /*Partition is RC4-encrypted*/ +} DOCH_EncryptType; + + +/*Lock Control*/ +typedef enum { DOCH_LOCK_NOT_ACTIVE = 0,/*LOCK# signal or soft-lock do not affect the access to this partition*/ + DOCH_LOCK_ACTIVE = 1 /*After LOCK# signal is active or soft-lock is written, access to partition*/ + /*can not be authenticated. If access has already been authenticated, it remains*/ +} DOCH_LockControl; + +/*OTP Bit*/ +typedef enum { DOCH_OTP_BIT_OFF = 0, + DOCH_OTP_BIT_ON = 1 +} DOCH_OTPBit; + +typedef enum { + PARTITION_TYPE_IPL = 0x00, + PARTITION_TYPE_BDTL = 0x01, + PARTITION_TYPE_BINARY = 0x02, + PARTITION_TYPE_OTP = 0x03 +} DOCH_PartitionType; + +/******************************************************************************/ +/* + * Partition Access structure + */ +/******************************************************************************/ + +/*Structure for DOCH_VSCMD_EXT_DEVICE_CTRL::DOCH_SET_PARTITION_PROTECTION + and DOCH_VSCMD_EXT_SECURITY_CTRL::DOCH_EN_ACCESS_WPWD*/ +typedef struct { + FLByte bReserved1[0x100]; + FLByte bPassword[0x80]; + FLByte bReserved2[0x80]; +} DOCH_PartitionAcessPassword; + +/******************************************************************************/ +/* + * PKI structures + */ +/******************************************************************************/ + +#define DOCH_CHLNG_SIZE 0x40 +#define DOCH_PKI_KEY_SIZE 0x80 + +/*Structure for DOCH_VSCMD_EXT_SECURITY_CTRL::DOCH_TX_HOST_PUBLICKEY*/ +typedef struct { + FLWord wVersion; + FLByte bReserved1[0xBE]; + FLByte bHostRandomChallange[DOCH_CHLNG_SIZE]; + FLByte bHostPublicKey[DOCH_PKI_KEY_SIZE]; + FLByte bReservedForLargerKey[0x80]; +} DOCH_HostPublicKey; + +/*Structure for DOCH_VSCMD_EXT_SECURITY_CTRL::DOCH_RX_DOCH_PUBLICKEY*/ +typedef struct { + FLWord wVersion; + FLByte bReserved1[0x3E]; + FLByte bHostRandomChallangeByDochPrivateKey[DOCH_CHLNG_SIZE]; + FLByte bReserved2[0x40]; + FLByte bDochRandomChallange[DOCH_CHLNG_SIZE]; + FLByte bDochPublicKey[DOCH_PKI_KEY_SIZE]; + FLByte bReservedForLargerKey[0x80]; +} DOCH_DochPublicKey; + +/*Structure for DOCH_VSCMD_EXT_SECURITY_CTRL::DOCH_VERIFY_HOST_KEY*/ +typedef struct { + FLWord wVersion; + FLByte bReserved1[0x3E]; + FLByte bDochRandomChallangeByHostPrivateKey[DOCH_CHLNG_SIZE]; + FLByte bReserved2[0x180]; +} DOCH_VerifyHostKey; + +/******************************************************************************/ +/* + * Algorithm structures + */ +/******************************************************************************/ + +/*Supported algorithms retrieval structure*/ +/*----------------------------------------*/ +typedef struct { + FLWord wVersion; + FLByte bReserved1[0x2]; + FLDword wSymmetricAlgorithmsSupported; /*Bitmap: AES...*/ + FLDword wAsymmetricAlgorithmsSupported; /*Bitmap: RSA...*/ + FLDword wHashSchemesSupported; /*Bitmap: SHA-1...*/ + FLDword wRNGSchemesSupported; /*Bitmap: TrueRandom...*/ + FLDword wDecompressionSchemesSupported; /*Bitmap: LZ77...*/ + FLDword wCompressionSchemesSupported; /*Bitmap: LZ77...*/ + FLByte bReserved2[0x1E4]; +} DOCH_supportedAlgorithms; + +/*Specific algorithm capabilities retrieval structure and sub-structures*/ +/*----------------------------------------------------------------------*/ +typedef struct { + FLDword dwSize; + FLDword dwCalcTime; /*For the key, in nano*/ +} KeyAttr; + +typedef struct { + FLByte bName[8]; /*In ASCII*/ + FLWord wKeySizes; /*Bitmap of key sizes supported by this mode*/ + FLByte bReserved[0x6]; +} ModeAttr; + +typedef struct { + FLWord wVersion; + FLByte bReserved1[0x2]; + FLByte bAlgorithmName[0x10]; /*In ASCII*/ + FLWord wNumOfKeySizesSupported; + FLWord wNumOfModesSupported; + FLByte bReserved2[0x8]; + KeyAttr keysAttributes[0x8]; + ModeAttr modesAttributes[0x18]; +} DOCH_AlgorithmCapabilities; + +/*Enums for HASH control*/ +/*----------------------*/ +typedef enum { + DOCH_HASH_REINITIALIZE = 0x00, + DOCH_HASH_CONTINUE = 0x01, + DOCH_HASH_CONTINUE_ACCUM = 0x00, + DOCH_HASH_STOP_ACCUM = 0x01, + DOCH_HASH_DONT_RETURN_DATA = 0x00, + DOCH_HASH_RETURN_ACCUM_DIGEST = 0x02 +} DOCH_HashStartStream; + +typedef enum { + DOCH_HASH_DECRYPTION_KEY = 0x00, + DOCH_HASH_ENCRYPTION_KEY = 0x01, + + /*For Decryption*/ + DOCH_HASH_USE_DOCH_PUBLIC_KEY = 0x00, + DOCH_HASH_USE_HOST_PUBLIC_KEY = 0x01, + DOCH_HASH_USE_PARTITION_PUBLIC_KEY = 0x02, + + /*For Encryption*/ + DOCH_HASH_USE_DOCH_PRIVATE_KEY = 0x00, + DOCH_HASH_USE_HOST_PRIVATE_KEY = 0x01 +} DOCH_HashSetKey; + +#ifdef FL_SLPP +/*SLPP Specific*/ +/* should be replaced by the real values/structures once they are defined!!! */ + +#define DOCH_SLPP_MAX_LOCK_RANGES 16 + +typedef enum { + DOCH_SLPP_UNLOCKED_RANGE = 1, + DOCH_SLPP_PERM_LOCKED_RANGE = 2 +} DOCH_SLPPRangeType; + +typedef struct { + FLDword dwRangeStartSector; + FLDword dwRangeSizeInSectors; + FLDword lockType; +} DOCH_SLPPRange; + +typedef struct { + FLDword numOfActiveRanges; + DOCH_SLPPRange rangeParams[DOCH_SLPP_MAX_LOCK_RANGES]; + FLByte spare[0x200 - (DOCH_SLPP_MAX_LOCK_RANGES*sizeof(DOCH_SLPPRange)) - sizeof(FLDword)]; +} DOCH_SLPPReport; + +typedef struct { + FLDword dwRangeStartSector; + FLDword dwRangeSizeInSectors; + FLByte passkey[0x80]; + FLByte spare[0x178]; +} DOCH_SLPPRangeRequestSector; +#endif /*FL_SLPP*/ + +/********************/ +/* API Routines */ +/********************/ + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t D e f a u l t P a r t i t i o n */ +/* */ +/* Set default partition for Standard-ATA commands */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : SET_DEFAULT_PARTITION_TEMP */ +/* SET_DEFAULT_PARTITION_PERM */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_DEFAULT_PARTITION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetDefaultPartition(ioreq) bdCallDOCH(SDK_SET_DEFAULT_PARTITION, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t D a t a T r a n s f e r M o d e */ +/* */ +/* Set Data transfer mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Requested data transfer mode: */ +/* DOCH_DATA_XFER_MODE_SINGLE */ +/* DOCH_DATA_XFER_MODE_MULT */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_DATA_XFER_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetDataTransferMode(ioreq) bdCallDOCH(SDK_SET_DATA_XFER_MODE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H I d e n t i f y D i s k O n C h i p D e v i c e */ +/* */ +/* Returns general information about the Device */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_IDENTIFY_FROM_FLASH */ +/* DOCH_IDENTIFY_EXISTANCE */ +/* irData : Address of DOCH_DeviceInfo struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_IDENTIFY_DISKONCHIP_DEVICE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHIdentifyDiskOnChipDevice(ioreq) bdCallDOCH(SDK_IDENTIFY_DISKONCHIP_DEVICE, ioreq) +#define DOCH_IDENTIFY_FROM_FLASH 0x0 +#define DOCH_IDENTIFY_EXISTANCE DRIVE_HEAD_OPT1 + + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t R e s e t S t a t u s */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_RESET_STATUS */ +/* */ +/* Returns: */ +/* irCount : 0 = No reset since last query */ +/* 1 = The device has been reset since last*/ +/* query */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetResetStatus(ioreq) bdCallDOCH(SDK_GET_RESET_STATUS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H N o t i f y R e s e t */ +/* */ +/* Notify the Device on an upcoming reset initiated by the Host. */ +/* Host should NOT perform actual reset before this command completes */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_NOTIFY_RESET */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHNotifyReset(ioreq) bdCallDOCH(SDK_NOTIFY_RESET, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H N o t i f y P l a t f o r m R e s u m e d */ +/* */ +/* Notify the Device that there was a reset, */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_NOTIFY_PLATFORM_RESUMED */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHNotifyPlatformResumed(ioreq) bdCallDOCH(SDK_NOTIFY_PLATFORM_RESUMED, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H P a r t i t i o n I n f o */ +/* */ +/* Get information about a specific partition. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read partition */ +/* information into. */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_PARTITION_INFO */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHPartitionInfo(ioreq) bdCallDOCH(SDK_GET_PARTITION_INFO, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H D e l e t e P a r t i t i o n s */ +/* */ +/* Delete range of partitions */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* irCount : First partition to delete */ +/* irLength : Last partition to delete */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_DELETE_PARTITIONS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHDeletePartitions(ioreq) bdCallDOCH(SDK_DELETE_PARTITIONS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H U n f o r m a t */ +/* */ +/* Unformats DOCH device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_DELETE_PARTITIONS */ +/* DOCH_SET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHUnformatDevice(ioreq) bdCallDOCH(SDK_UNFORMAT_DEVICE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H A d d P a r t i t i o n */ +/* */ +/* Adds a partition */ +/* The new partition is created on existing un-formatted disk capacity */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_ADD_PARTITION */ +/* */ +/* Returns: */ +/* irCount : Number of the created partition */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHAddPartition(ioreq) bdCallDOCH(SDK_ADD_PARTITION, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e I P L */ +/* */ +/* Writes IPL partition. */ +/* Sets IPL mode and size. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : DOCH_IPL_MODE_NORMAL_RAM */ +/* DOCH_IPL_MODE_PAGED_RAM */ +/* DOCH_IPL_MODE_VIRTUAL_RAM */ +/* DOCH_IPL_MODE_CS_DELAY */ +/* DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT */ +/* DOCH_IPL_MODE_ACTIVE_SWAP_BYTES */ +/* DOCH_IPL_MODE_8KB_WINDOW */ +/* DOCH_IPL_WRITE_FIRST_CHUNK */ +/* irCount : Max IPL size */ +/* Up to 32KB for Normal Mode */ +/* Up to 128KB for Virtual Mode */ +/* Up to 256KB for Paged Mode */ +/* irLength : Current chunk length (in sectors) */ +/* irData : Pointer to user buffer (length defined by */ +/* irLength) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteIPL(ioreq) bdCallDOCH(SDK_WRITE_IPL, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d I P L */ +/* */ +/* Read specified sectors from IPL partition. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : First sector to read */ +/* irLength : Number of sectors to read */ +/* irData : Pointer to user buffer (length defined by */ +/* irLength) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* irFlags : DOCH_IPL_MODE_NORMAL_RAM */ +/* DOCH_IPL_MODE_PAGED_RAM */ +/* DOCH_IPL_MODE_VIRTUAL_RAM */ +/* DOCH_IPL_MODE_CS_DELAY */ +/* DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT */ +/* DOCH_IPL_MODE_ACTIVE_SWAP_BYTES */ +/* DOCH_IPL_MODE_8KB_WINDOW */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadIPL(ioreq) bdCallDOCH(SDK_READ_IPL, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d P a r t i t i o n S e c t o r s */ +/* */ +/* Reads sectors by sector no from a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read into */ +/* irSectorNo : First sector no. to read. */ +/* irSectorCount : Number of consecutive sectors to read */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadPartitionSectors(ioreq) bdCallDOCH(SDK_READ_PARTITION_SECTORS, ioreq) + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e P a r t i t i o n S e c t o r s */ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +#define flDOCHWritePartitionSectors(ioreq) bdCallDOCH(SDK_WRITE_PARTITION_SECTORS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e A n d L o c k */ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteAndLock(ioreq) bdCallDOCH(SDK_WRITE_AND_LOCK, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H F r e e S e c t o r s */ +/* */ +/* Marks absolute sectors by sector no. as free to be written */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorNo : First sector no. to delete */ +/* irSectorCount : Number of consecutive sectors to delete */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ERASE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually deleted */ +/*----------------------------------------------------------------------*/ +#define flDOCHFreeSectors(ioreq) bdCallDOCH(SDK_FREE_SECTORS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W i p e S e c t o r s */ +/* */ +/* Securely erase data in sectors */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorCount : Number of sectors to transfer (1..2). */ +/* irData : 1..2 sectors with following layout: */ +/* - 1st 8bytes - reserved as zeroes */ +/* - (FLDWord) : First sector to delete */ +/* (FLDWord) : # of sectors to delete */ +/* - (FLDWord) : Second sector to delete */ +/* (FLDWord) : # of sectors to delete */ +/* - ... */ +/* - (FLDWord) : Nth sector to delete */ +/* (FLDWord) : # of sectors to delete */ +/* * Last transaction should have both start */ +/* and length fields set to 0. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SECURE_ERASE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHWipeSectors(ioreq) bdCallDOCH(SDK_WIPE_SECTORS, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H P r e p a r e F o r W r i t e */ +/* */ +/* Signal to DOCH that these sectors are going to be over-written in */ +/* following write command */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHPrepareForWrite(ioreq) bdCallDOCH(SDK_PREPARE_FOR_WRITE, ioreq) + +/* Flexi-Flash */ + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e F l e x i F a s t */ +/* */ +/* Flexi-Flash Write Fast */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_FLEXI */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteFlexiFast(ioreq) bdCallDOCH(SDK_WRITE_FLEXI_FAST, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e F l e x i N o r m a l */ +/* */ +/* Flexi-Flash Write Normal */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_FLEXI */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteFlexiNormal(ioreq) bdCallDOCH(SDK_WRITE_FLEXI_NORMAL, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e W r i t e N o r m a l */ +/* */ +/* Flexi-Flash Re-Write Normal */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually re-written */ +/*----------------------------------------------------------------------*/ +#define flDOCHReWriteFlexiNormal(ioreq) bdCallDOCH(SDK_REWRITE_FLEXI_NORMAL, &ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H M a n a g e A t o m i c W r i t e S e q */ +/* */ +/* Manage atomic write sequence per partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : DOCH_START_ATOMIC_WRITE */ +/* DOCH_FINISH_ATOMIC_WRITE */ +/* DOCH_ABORT_ATOMIC_WRITE */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_ATOMIC_WRITE_SEQUENCE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHManageAtomicWriteSeq(ioreq) bdCallDOCH(SDK_ATOMIC_WRITE_SEQ, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H A c c e s s P a r t W i t h P w d */ +/* */ +/* Insert the protection key in order to remove the protection of the */ +/* specified partition or the entire media */ +/* Partition could be authenticated both by user and master password */ +/* the last successful authentication supersedes the previous one. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* 0xF - for authenticating the entire device */ +/* irFlags : Authentication Type */ +/* : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irData : pointer to an DOCH_PartitionAcessPassword struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_EN_ACCESS_WPWD */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHAccessPartWithPwd(ioreq) bdCallDOCH(SDK_ACCESS_PART_WITH_PWD, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H D i s a b l e P a r t A c c e s s */ +/* */ +/* Remove the protection key making the partition protected again */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* 0xF - for disabling access to the entire*/ +/* media */ +/* irFlags : Authentication to withdraw */ +/* DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_DISABLE_ACCESS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHDisablePartAccess(ioreq) bdCallDOCH(SDK_DISABLE_PART_ACCESS, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e n d H o s t P u b l i c K e y */ +/* */ +/* Host sends its public key for this partition & random challenge */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* 0xF - for disabling access to the entire */ +/* media */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irData : Pointer to DOCH_HostPublicKey structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_TX_HOST_PUBLICKEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSendHostPublicKey(ioreq) bdCallDOCH(SDK_PKI_HOST, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e c e i v e D o c h P u b l i c K e y */ +/* */ +/* DOCH sends its public key, host's random challenge encrypted by DOCH */ +/* private key, and DOCH's random challenge to host */ +/* */ +/* Parameters: */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* 0xF - for disabling access to the entire */ +/* media */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_RX_DOCH_PUBLICKEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReceiveDochPublicKey(ioreq) bdCallDOCH(SDK_PKI_DOCH, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H V e r i f y H o s t K e y */ +/* */ +/* Host sends DOCH's random challenge encrypted by host's private key */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_VERIFY_HOST_KEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHVerifyHostKey(ioreq) bdCallDOCH(SDK_PKI_VERIFY_HOST_KEY, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t P a r i t i o n P r o t e c t i o n */ +/* */ +/* Set partition properties (attributes/passkey) . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionProtectionAPI */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_PARTITION_PROTECTION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetParitionProtection(ioreq) bdCallDOCH(SDK_SET_PART_PROTECTION, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t P a r i t i o n U s e r A t t r i b u t e s */ +/* */ +/* Set partition user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionUserAttr */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_PARTITION_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetParitionUserAttributes(ioreq) bdCallDOCH(SDK_SET_PART_USER_ATTR, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P a r i t i o n U s e r A t t r i b u t e s */ +/* */ +/* Get partition user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionUserAttr */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_PARTITION_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetParitionUserAttributes(ioreq) bdCallDOCH(SDK_GET_PART_USER_ATTR, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t D i s k U s e r A t t r i b u t e s */ +/* */ +/* Set disk user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1 sector of data */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetDiskUserAttributes(ioreq) bdCallDOCH(SDK_SET_DISK_USER_ATTR, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t D i s k U s e r A t t r i b u t e s */ +/* */ +/* Get disk user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1 sector of data */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetDiskUserAttributes(ioreq) bdCallDOCH(SDK_GET_DISK_USER_ATTR, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t C o n f i g u r a t i o n D a t a */ +/* */ +/* Read the device configuration data. No authentication is required */ +/* for calling this command, but the fields containing keys in the */ +/* configuration data will be masked by ETFFS using zeros. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1..3 sector(s) of data. */ +/* irCount : Sector offset in the configuration data to start */ +/* reading from. */ +/* irLength : Number of sectors of configuration data to read. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_CONFIGURATION_DATA */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetConfigurationData(ioreq) bdCallDOCH(SDK_GET_CONFIG_DATA, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t C o n f i g u r a t i o n D a t a */ +/* */ +/* Save the device configuration data. Calling this command will */ +/* succeed only if there are no partitions present on the media */ +/* (including partition 0). */ +/* You should use this command in the process of duplicating DiskOnChip */ +/* device to make sure all configuration data of the original device */ +/* have been duplicated to the new device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1..3 sector(s) of data. */ +/* irCount : Sector offset in the configuration data to start */ +/* reading from. */ +/* irLength : Number of sectors of configuration data to read. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_CONFIGURATION_DATA */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetConfigurationData(ioreq) bdCallDOCH(SDK_SET_CONFIG_DATA, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H O p t i m i z e M e d i a */ +/* */ +/* Performs garbage collection. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* */ +/* irCount : DOCH_OPTIMIZE_SINGLE_PARTITION */ +/* DOCH_OPTIMIZE_WHOLE_MEDIA */ +/* */ +/* irLength : DOCH_OPTIMIZE_BY_PREPARE_FOR_WRITE */ +/* based on information collected during previous */ +/* PREPARE FOR WRITE commands */ +/* DOCH_OPTIMIZE_DEFAULT */ +/* performs default optimization of the whole */ +/* partition or media */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_OPTIMIZE_MEDIA */ +/* */ +/* Returns: */ +/* irLength : Actual number of sectors available for writes */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHOptimizeMedia(ioreq) bdCallDOCH(SDK_OPTIMIZE_MEDIA, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t C u s t o m P a r a m e t e r */ +/* */ +/* Returns 16-bit custom DOCH parameter */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : Parameter# (see DOCH_CustomParams) */ +/* irFlags : DOCH_CUSTOM_PARAM_DEFAULT - default value */ +/* DOCH_CUSTOM_PARAM_TEMP - current (saved) value*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* irSectorNo : Custom parameter value (16-Bit) */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetCustomParameter(ioreq) bdCallDOCH(SDK_GET_CUSTOM_PARAM, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t C u s t o m P a r a m e t e r */ +/* */ +/* Sets 16-bit custom DOCH parameter */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Custom Parameter Number (DOCH_CustomParams) */ +/* irSectorNo : Custom Parameter Value (16-Bit) */ +/* irFlags : DOCH_CUSTOM_PARAM_DEFAULT - default value */ +/* DOCH_CUSTOM_PARAM_TEMP - current (saved) value*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetCustomParameter(ioreq) bdCallDOCH(SDK_SET_CUSTOM_PARAM, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H A u t o H a s h C o n t r o l */ +/* */ +/* Enable/Disable Auto Hash Read/Write */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : AUTO_HASH_ENABLE */ +/* AUTO_HASH_DISABLE */ +/* irLength : AUTO_HASH_READ */ +/* AUTO_HASH_WRITE */ +/* irFlags : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_AUTO_HASH_CONTROL */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHAutoHashControl(ioreq) bdCallDOCH(SDK_AUTO_HASH_CTRL, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d C a l c u l a t e d H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers to host digest(s) calculated from data on the flash. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_CALCULATED_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadCalculatedHash(ioreq) bdCallDOCH(SDK_READ_CALC_HASH, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e C a l c u l a t e d H a s h */ +/* */ +/* Command for Paged partitions */ +/* No data is transfered. Digest(s) calculated from data in the flash */ +/* are stored to the dedicated area on flash. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_CALCULATED_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteCalculatedHash(ioreq) bdCallDOCH(SDK_WRITE_CALC_HASH, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d O r i g i n a l H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers to host digest(s) stored previously on dedicated area on */ +/* flash */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_ORIGINAL_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadOriginalHash(ioreq) bdCallDOCH(SDK_READ_ORIG_HASH, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H W r i t e G i v e n H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers from host digest(s) and stores them to the dedicated area */ +/* on flash */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_GIVEN_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHWriteGivenHash(ioreq) bdCallDOCH(SDK_WRITE_GIVEN_HASH, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e p o r t S u p p o r t e d A l g o r i t h m s */ +/* */ +/* Report supported algorithms */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_REPORT_SUPPORTED_ALGORITHMS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReportSupportedAlgorithms(ioreq) bdCallDOCH(SDK_REPORT_SUPP_ALG, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t A l g o r i t h m C a p a b i l i t i e s */ +/* */ +/* Get algorithms capabilities */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_ALGORITHM_CAPABILITIES */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetAlgorithmCapabilities(ioreq) bdCallDOCH(SDK_REPORT_ALG_CAPAB, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t A l g o r i t h m M o d e */ +/* */ +/* Set algorithms mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* bits 16..24 - Mode index */ +/* bits 24..31 - Key size index */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_ALGORITHM_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetAlgorithmMode(ioreq) bdCallDOCH(SDK_SET_ALG_MODE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S t a r t H a s h S t r e a m C a l c u l a t i o n */ +/* */ +/* Restart/Continue hash stream calculation */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* irLength : HASH_REINITIALIZE */ +/* HASH_CONTINUE */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_START_HASH_STREAM_CALC */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHStartHashStreamCalculation(ioreq) bdCallDOCH(SDK_START_HASH_STREAM_CALC, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d S t o p H a s h S t r e a m C a l c */ +/* */ +/* Read/Stop hash stream calculation */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_CONTINUE_ACCUM */ +/* DOCH_HASH_STOP_ACCUM */ +/* irLength : DOCH_HASH_DONT_RETURN_DATA */ +/* DOCH_HASH_RETURN_ACCUM_DIGEST */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_READ_STOP_HASH_STREAM_CALC */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReadStopHashStreamCalc(ioreq) bdCallDOCH(SDK_READ_HASH_STREAM_CALC, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e t u r n R a n d om N u m b e r s */ +/* */ +/* Return random numbers */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* irLength : # of 32-Bit random numbers to generate */ +/* (max is 64, e.g full sector) */ +/* irData : Pointer to 1 sector of data which will hold */ +/* the number of requested random numbers */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_RETURN_RANDOM_NUMBERS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHReturnRandomNumbers(ioreq) bdCallDOCH(SDK_RETURN_RAND_NUMS, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t H a s h K e y */ +/* */ +/* Set hash key */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_DECRYPTION_KEY */ +/* DOCH_HASH_ENCRYPTION_KEY */ +/* irLength : DOCH_HASH_USE_DOCH_PUBLIC_KEY */ +/* DOCH_HASH_USE_HOST_PUBLIC_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_KEYS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetHashKey(ioreq) bdCallDOCH(SDK_SET_HASH_KEY, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P o w e r M o d e */ +/* */ +/* Retrieve device power mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_POWER_MODE */ +/* */ +/* Returns: */ +/* irFlags : */ +/* DOCH_PM_WORK_MODE */ +/* DOCH_PM_INACTIVE_MODE */ +/* irCount : */ +/* Bits 0..1 : Work Mode */ +/* DOCH_WM_NORMAL */ +/* DOCH_WM_LOW_FREQ */ +/* DOCH_WM_NORMAL_AND_AUTO_STBY */ +/* DOCH_WM_LOW_FREQ_AND_AUTO_STBY */ +/* Bits 4..5 : Inactive Mode */ +/* DOCH_IM_IDLE */ +/* DOCH_IM_DPD */ +/* DOCH_IM_IDLE_2_DPD */ +/* irLength : Value of timeout for automatic transfer to */ +/* Inactive mode (0 = disabled) */ +/* Timer value is in milliseconds. */ +/* If Inactive mode is "Standby to DPD" timer */ +/* resolution is 100 ms. */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetPowerMode(ioreq) bdCallDOCH(SDK_GET_POWER_MODE, ioreq) + +/*----------------------------------------------------------------------*/ +/* D O C H S e t P o w e r M o d e */ +/* */ +/* Set device power mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : */ +/* Bits 0..1 - which mode(s) should be set */ +/* DOCH_PM_SET_WORK_MODE */ +/* DOCH_PM_SET_INACTIVE_MODE */ +/* DOCH_PM_SET_BOTH_MODES */ +/* DOCH_PM_SET_NONE */ +/* Bit 2 - which mode device should pass to after set */ +/* DOCH_PM_WORK_MODE */ +/* DOCH_PM_INACTIVE_MODE */ +/* Bit 4 */ +/* DOCH_PM_SAVE_DEFAULT */ +/* (Save new settings as default settings ) */ +/* irCount : */ +/* Bits 0..1 : Work Mode to be set */ +/* DOCH_WM_NORMAL */ +/* DOCH_WM_LOW_FREQ */ +/* DOCH_WM_NORMAL_AND_AUTO_STBY */ +/* DOCH_WM_LOW_FREQ_AND_AUTO_STBY */ +/* Bits 4..5 : Inactive Mode to be set */ +/* DOCH_IM_IDLE */ +/* DOCH_IM_DPD */ +/* DOCH_IM_IDLE_2_DPD */ +/* irLength : Value of timeout for automatic transfer to */ +/* Inactive mode (0 = disabled) */ +/* Timer value is in milliseconds. */ +/* If Inactive mode is "Standby to DPD" timer */ +/* resolution is 100 ms. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_POWER_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSetPowerMode(ioreq) bdCallDOCH(SDK_SET_POWER_MODE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H C o n f i g H W */ +/* */ +/* Control HW registers */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : HW Configuration type */ +/* (See DOCH_HwConfigType for values) */ +/* irLength : HW configuration type dependant */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHConfigHW(ioreq) bdCallDOCH(SDK_HW_CONFIG, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e c o v e r F r o m P o w e r L o s s */ +/* */ +/* Set last known values of DOCH control registers back to device after */ +/* power loss was detected. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHRecoverFromPowerLoss(ioreq) bdCallDOCH(SDK_RECOVER_FROM_POWER_LOSS, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t E n v V a r */ +/* */ +/* Set environment variable. */ +/* Available environment variables are listed in DOCH_EnVars. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based, if relevant) */ +/* irFlags : Environment variable */ +/* */ +/* irLength : Value to set */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif +DOCH_Error flDOCHSetEnvVar(IOreq* ioreq); +#ifdef __cplusplus +} +#endif + +/*----------------------------------------------------------------------*/ +/* f l D O C H C l e a r I R Q */ +/* */ +/* Clear the ATA interrupt. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHClearIRQ(ioreq) bdCallDOCH(SDK_CLEAR_ATA_INTERRUPT, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P h y s i c a l A d d r e s s */ +/* */ +/* Retrieve physical address of the socket. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* irCount : Socket Physical Address */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHGetPhysicalAddress(ioreq) bdCallDOCH(SDK_GET_PHYSICAL_ADDRESS, ioreq) + +#ifndef flFormatFS +/*----------------------------------------------------------------------*/ +/* f l F o r m a t F S */ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 11-8 - Logical partition in Flash partition (zero based)*/ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irSectorNo : First absolute sector of logical partition */ +/* (if bit 13 is set) */ +/* irSectorCount : Number of sectors in logical partition */ +/* (if bit 13 is set) */ +/* irData : Address of the FATFormatParams structure */ +/* irFlags : */ +/* bit 14 - FL_DO_NOT_UPDATE_MBR */ +/* bit 13 - FL_MEDIA_WITHOUT_MBR */ +/* bit 12 - FL_MOUNT_ON_GIVEN_RANGE */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flFormatFS(ioreq) formatCall(FL_FORMAT_FS,ioreq) +#endif /*flFormatFS*/ + +#ifndef flCreateLogicalPartitions +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : Number of LogicalPartitionParams structures */ +/* irData : Address of array of LogicalPartitionParams structures */ +/* irFlags : 0 - reserved */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flCreateLogicalPartitions(ioreq) formatCall(FL_CREATE_LOGICAL_PARTITIONS,ioreq) +#endif /*flCreateLogicalPartitions*/ + +#ifndef flFindLogicalPartition +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 11-8 - Logical partition in Flash */ +/* partition (zero based) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irFlags : 0 - reserved */ +/* irData : Address of the LogPartitionInfo structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flFindLogicalPartition(ioreq) formatCall(FL_FIND_LOGICAL_PARTITION,ioreq) +#endif /* flFindLogicalPartition */ +#ifdef FL_SLPP +/*SLPP Specific*/ +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P U n l o c k R a n g e */ +/* */ +/* Unlock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of the DOCH_SLPPRangeRequestSector */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_UNLOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPUnlockRange(ioreq) bdCallDOCH(SDK_SLPP_UNLOCK_RANGE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P L o c k R a n g e */ +/* */ +/* Lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of the DOCH_SLPPRangeRequestSector */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_LOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPLockRange(ioreq) bdCallDOCH(SDK_SLPP_LOCK_RANGE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P U n l o c k E n t i r e P a r t i t i o n */ +/* */ +/* Unlock an entire Sector Protected Partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_UNLOCK_ENTIRE_PARTITION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPUnlockEntirePartition(ioreq) bdCallDOCH(SDK_SLPP_UNLOCK_ENTIRE_PARTITION, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P S t i c k y L o c k R a n g e */ +/* */ +/* Applies sticky lock to a range of sectors on a sector protected */ +/* partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of the DOCH_SLPPRangeRequestSector */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_STICKY_LOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPStickyLockRange(ioreq) bdCallDOCH(SDK_SLPP_STICKY_LOCK_RANGE, ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P R e p o r t R a n g e s */ +/* */ +/* Reports unlocked and sticky locked ranges of sector protected */ +/* partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of the DOCH_SLPPReport */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SLPP_REPORT_LOCKED_RANGES */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDOCHSLPPReportRanges(ioreq) bdCallDOCH(SDK_SLPP_REPORT_LOCKED_RANGES, ioreq) +#endif /*FL_SLPP*/ + +#ifdef __cplusplus +extern "C" { +#endif +/*Pass-Thru routine*/ +DOCH_Error DOCHAtaPassThrough(FLSNative socketNum, + FLSNative passThruOP, + DOCH_Registers *in_regs, + DOCH_Registers *out_regs, + FLNative secNum, + void* userBuff, + FLBoolean useInterrupt); + + +DOCH_Error DOCHIdentifyDiskOnChipDeviceSingleFloor(IOreq* ioreq); + +/*Flags for format operation*/ +#define DOCH_LEAVE_PARTITIONS 0x8 + + +#ifdef __cplusplus +} +#endif + +#endif /*_DOCHAPI*/ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_docsys.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_docsys.h new file mode 100755 index 00000000..0d977adb --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_docsys.h @@ -0,0 +1,205 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/************************************************************************ * + * I M P O R T A N T * + * * + * The file contains DiskOnChip memory access routines and macros * + * defintions. * + * * + * In order to use the complete set of TrueFFS memory access routine * + * that allows runtime configuration of each socket access type make * + * sure the FL_NO_USE_FUNC is not defined in FLCUSTOM.H: * + * * + * If you know the exact configuration of your application you can * + * uncomment the FL_NO_USE_FUNC definition and set the proper access * + * type using the macroe defintion bellow. * + * * + ************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/_docsys.h-arc $ + * + * Rev 1.4 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.3 Feb 28 2007 09:53:20 einat.avidan + * No change + * + * Rev 1.2.1.1 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.2.1.0 Aug 08 2006 15:55:34 Polina.Marimont + * DOC Driver 1.0 initial + */ + + +#ifndef _DOCSYS_H +#define _DOCSYS_H + +#include "defs.h" + +#ifdef FL_NO_USE_FUNC + +/*--------------------------------------------------------------------------*/ + +/* Default access layer for 16 bit configuration */ + +#ifndef flDirectWrite8BitReg +#ifdef FL_BIG_ENDIAN +#define flDirectWrite8BitReg(flash,offset,val) \ + FLWRITE_IO_WORD((((FLWord)val)<<8),((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) +#else +#define flDirectWrite8BitReg(flash,offset,val) \ + FLWRITE_IO_WORD(((FLWord)val),((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) +#endif /* FL_BIG_ENDIAN */ +#endif /* flDirectWrite8BitReg */ + +#ifndef flDirectWrite16BitReg +#define flDirectWrite16BitReg(flash,offset,val) \ + FLWRITE_IO_WORD(val,((volatile FLByte FAR0 *)((flash)->win)+(offset))) +#endif /* flDirectWrite16BitReg */ + +#ifndef flDirectRead8BitReg +#ifdef FL_BIG_ENDIAN +#define flDirectRead8BitReg(flash,offset) \ + (Reg8bitType)(((offset & 0x1) == 0) ? \ + ((FLREAD_IO_WORD((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) >> 8) : \ + ((FLREAD_IO_WORD((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) ) ) +#else +#define flDirectRead8BitReg(flash,offset) \ + (Reg8bitType)(((offset & 0x1) != 0) ? \ + ((FLREAD_IO_WORD((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) >> 8) : \ + ((FLREAD_IO_WORD((volatile FLWord FAR0 *)((flash)->win)+((offset)>>1))) ) ) +#endif /* FL_BIG_ENDIAN */ +#endif /* flDirectRead8BitReg */ + +#ifndef flDirectRead16BitReg +#define flDirectRead16BitReg(flash,offset) \ + FLREAD_IO_WORD((flash)->win+(offset)) +#endif + +#ifndef flReadEvenNumberOfBytes +#define flReadEvenNumberOfBytes(flash,offset,dest,count) \ + TFFSCPY_FROM_IO_16_BITS( dest,((flash)->win + (offset)), count) +#endif + +#ifndef flWriteEvenNumberOfBytes +#define flWriteEvenNumberOfBytes(flash,offset,src,count) \ + TFFSCPY_TO_IO_16_BITS(((flash)->win + (offset)),src,count) +#endif + +#ifndef flRead512Bytes +#define flRead512Bytes(flash,offset,dest) flReadEvenNumberOfBytes(flash,offset,dest,512) +#endif + +#ifndef flWrite512Bytes +#define flWrite512Bytes(flash,offset,src) flWriteEvenNumberOfBytes(flash,offset,src,512) +#endif + +#ifndef flDocWindow +#define flDocWindow(flash) (0x2000) +#endif + +/*--------------------------------------------------------------------------*/ + +#else /* FL_NO_USE_FUNC */ + +/*--------------------------------------------------------------------------*/ + +/* Redirect to runtime access layer */ + +#ifndef flDirectWrite8BitReg +#define flDirectWrite8BitReg(flash,offset,val) (flash)->memWrite8bit((flash)->win,offset,val) +#endif + +#ifndef flDirectWrite16BitReg +#define flDirectWrite16BitReg(flash,offset,val) (flash)->memWrite16bit((flash)->win,offset,val) +#endif + +#ifndef flDirectRead8BitReg +#define flDirectRead8BitReg(flash,offset) (flash)->memRead8bit((flash)->win,offset) +#endif + +#ifndef flDirectRead16BitReg +#define flDirectRead16BitReg(flash,offset) (flash)->memRead16bit((flash)->win,offset) +#endif + +#ifndef flReadEvenNumberOfBytes +#define flReadEvenNumberOfBytes(flash,offset,dest,count) (flash)->memRead((flash)->win,offset,dest,count) +#endif + +#ifndef flWriteEvenNumberOfBytes +#define flWriteEvenNumberOfBytes(flash,offset,src,count) (flash)->memWrite((flash)->win,offset,src,count) +#endif + +#ifndef flRead512Bytes +#define flRead512Bytes(flash,offset,dest) flReadEvenNumberOfBytes(flash,offset,dest,512) +#endif + +#ifndef flWrite512Bytes +#define flWrite512Bytes(flash,offset,src) flWriteEvenNumberOfBytes(flash,offset,src,512) +#endif + +#ifndef flDocWindow +#define flDocWindow(flash) (flash->memWindowSize()) +#endif + +/*--------------------------------------------------------------------------*/ + +/* (private) types of DiskOnChip access configurations */ + +#define FL_8BIT_DOC_ACCESS 0x00000000L /* Has 8 data bits */ +#define FL_16BIT_DOC_ACCESS 0x00000100L /* Has 16 data bits */ +#define FL_XX_DATA_BITS_MASK 0x00000300L /* Mask of the above */ +#define FL_8BIT_FLASH_ACCESS 0x00000400L /* 8 bits of flash per cycle */ +#define FL_16BIT_FLASH_ACCESS 0x00000800L /* 16 bits of flash per cycle */ +#define FL_XX_FLASH_ACCESS_MASK 0x00000C00L /* Mask of the above */ + +#define FL_ACCESS_USER_DEFINED 0x00001000L /* User defined routines */ + +/* DiskOnChip routines prototypes */ + +extern FLStatus FAR1 setBusTypeOfFlash(FLFlash * flash,FLDword access); + +#endif /* FL_NO_USE_FUNC */ +#endif /* DOCSYS_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_fltl.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_fltl.h new file mode 100755 index 00000000..81a9602a --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_fltl.h @@ -0,0 +1,172 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/_fltl.h-arc $ + * + * Rev 1.9 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.8 Feb 28 2007 10:49:44 einat.avidan + * removed unnecessary decleration + * + * Rev 1.7 Oct 09 2006 14:03:52 yaniv.iarovici + * Removed legacy devices related code and definitions + * + * Rev 1.6 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.5 Aug 09 2006 16:52:46 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef _FLTL_H +#define _FLTL_H + +typedef struct { + SectorNo sectorsInVolume; + FLDword bootAreaSize; + FLDword eraseCycles; + FLDword tlUnitBits; +} TLInfo; + + +/* Defragment modes types */ +#define FL_FAST_SPACE 0 +#define FL_NORMAL_SPACE 1 + + + +typedef struct tTLrec TLrec; /* Defined by translation layer */ + + +struct tTL { + TLrec *rec; + FLByte partitionNo; + FLByte socketNo; + + /* information is necessary for hard-disk TL implementation */ + FLWord cylinders; + FLWord heads; + FLWord sectorsPerTrack; + /* they should not be concealed in TL->rec field: when the media is formatted + it would be best if geometry written in BPB would match actual disk geometry */ + + /* information necessary to support fast+normal geometry */ + FLDword fastAreaSectors; + FLWord fastArea_SectorsInUnit_Bits; + FLWord normalArea_SectorsInUnit_Bits; + FLWord riskZoneSectors; /* largest of fast and normal risk zones */ + FLWord recommendedSectorsInCluster; /* or just call it sectorsInPage (also largest) */ + /* there is no need to hide these vars via "recommendedClusterInfo" : + they are not used by TL itself. BTW, getTLinfo is not necessary for same reason */ + + void FAR1* progressCallback; + +#ifndef FL_NEW_MAPSECTOR + const void FAR0 *(*mapSector)(TLrec *, SectorNo sectorNo, CardAddress *physAddr); +#else + FLStatus (*mapSector)(TLrec *, SectorNo sectorNo, void * *retBuffer); +#endif + + FLStatus (*writeSector)(TLrec *, SectorNo sectorNo, void FAR1 *fromAddress); + + FLStatus (*writeMultiSector)(TLrec *, SectorNo sectorNo, void FAR1 *fromAddress,SectorNo sectorCount); + FLStatus (*readSectors)(TLrec *, SectorNo sectorNo, void FAR1 *dest,SectorNo sectorCount); + + FLStatus (*deleteSector)(TLrec *, SectorNo sectorNo, SectorNo noOfSectors); + FLStatus (*tlSetBusy)(TLrec *, FLBoolean); + void (*dismount)(TLrec *); + FLStatus (*defragment)(TLrec *, FLSDword FAR2 *sectorsNeeded, FLDword normalSpace); + FLStatus (*checkVolume)(TLrec *); + SectorNo (*sectorsInVolume)(TLrec *); + FLStatus (*getTLInfo)(TLrec *, TLInfo *tlInfo); + void (*recommendedClusterInfo)(TLrec *, FLDword *sectorsPerCluster, FLDword *clusterAlignment); + + FLStatus (*readBBT)(TLrec *, CardAddress FAR1 * buf, FLSDword FAR2 * mediaSize, unsigned FAR2 * noOfBB); + + FLStatus (*notifyChange)(TLrec *, void FAR1 * reserved, FLEnvVars variableType , FLDword value); + FLStatus (*completeOperation)(TLrec *); + + FLDword (* getLastMappedSectorAddress)(TLrec *); /* use after mapSector */ + FLStatus (* ensureFreeSectorsInUnit)(TLrec *, FLWord wVirtualUnit, FLWord * wFreeSectorsRequired); + FLStatus (*secureDeleteSector)(TLrec *, SectorNo sectorNo, SectorNo noOfSectors, FLBoolean secureOperation); +}; + + + +/* The address of this, if returned from map, denotes a data error */ +#ifndef FL_NEW_MAPSECTOR +/* extern FLStatus dataErrorObject; +#define dataErrorToken ((void FAR0 *) &dataErrorObject) */ + +#define dataErrorToken ((void FAR0 *) 0xFFFFFFFF) +/* temporary - should not be necessary with new mapSector +old method (address of dataErrorObject) is not translatable across BD-FS split +or translatable with added code/complexity */ +#endif /* FL_NEW_MAPSECTOR */ + +#ifdef FLFLASH_H +/* Translation layer registration information */ + +extern int noOfTLs; /* No. of translation layers actually registered */ + +typedef struct { + FLStatus (*mountRoutine) (unsigned volNo, TL *tl, FLFlash *flash, FLFlash **volForCallback); + FLStatus (*formatRoutine) (unsigned volNo, TLFormatParams *deviceFormatParams, FLFlash *flash); + FLStatus (*preMountRoutine)(FLFunctionNo callType, IOreq FAR2* ioreq ,FLFlash* flash,FLStatus* status); +} TLentry; + +extern FLStatus noFormat (unsigned volNo, TLFormatParams *formatParams, FLFlash *flash); +extern FLStatus flMount(unsigned volNo, unsigned socketNo,TL *, FLBoolean useFilters , FLFlash *flash); +extern FLStatus flPreMount(FLFunctionNo callType, IOreq FAR2* ioreq , FLFlash *flash); +extern unsigned noOfDrives; + +#ifdef FL_FORMAT_VOLUME +extern FLStatus flFormat(unsigned volNo, TLFormatParams *formatParams, FLFlash * flash); +#endif /* FL_FORMAT_VOLUME */ + +#endif /* FLFLASH_H */ + +#endif /* FLTL_H */ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_tffsioct.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_tffsioct.h new file mode 100755 index 00000000..628ee5ad --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/_tffsioct.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef __TFFSIOCT_H +#define __TFFSIOCT_H + + +typedef struct +{ + unsigned long command; + unsigned long data; +}flInputLnxRecord; + + +typedef struct +{ + unsigned long status; + unsigned long data; +} flOutputLnxRecord; + + +/* replicas of structures in doch_api.h */ + +typedef struct { unsigned char bFeaturesError; + unsigned char bSectorCount; + unsigned char bSectorNumber; + unsigned char bCylLow; + unsigned char bCylHigh; + unsigned char bDriveHead; + unsigned char bCommandStatus; + unsigned char bContorlAltStatus; + } flDochRegisters; + +typedef struct { int socketNum; + int passThruOP; + flDochRegisters in_regs; + flDochRegisters out_regs; + unsigned int secNum; + void *userBuff; + unsigned long userBuffSize; + int status; + } flAtaPassthrough; + + +#endif /* __TFFSIOCT_H */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/bddefs.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/bddefs.h new file mode 100755 index 00000000..59ba4bd6 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/bddefs.h @@ -0,0 +1,108 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/bddefs.h-arc $ + * + * Rev 1.7 Oct 22 2007 11:34:46 einat.avidan + * update copyrights header + * + * Rev 1.6 Feb 28 2007 09:58:42 einat.avidan + * No change + * + * Rev 1.5.1.2 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.5.1.1 Aug 22 2006 13:22:06 Yaniv.Iarovici + * Add 'extern "c"' on vols[] external definition + * + * Rev 1.5.1.0 Aug 08 2006 15:55:34 Polina.Marimont + * DOC Driver 1.0 initial + */ + +#ifndef BDDEFS_H +#define BDDEFS_H + +#include "defs.h" +#include "fltl.h" +#include "flbuffer.h" +#include "docsys.h" + + +typedef struct { + FLSByte flags; /* See description in flreq.h */ + + FLDword sectorsInVolume; + unsigned mountCount; /* can be opened/closed several times */ + + FLMutex* volExecInProgress; + FLFlash FAR2* flash; /* flash structure for low level operations */ + TL tl; /* Translation layer methods */ + FLSocket *socket; /* Pointer to socket */ + + FLBoolean globalAttFlag; /* indication of global attention flag */ +} Volume; + +#define VOLUME_NOT_OCCUPIED 0 +#define VOLUME_LOW_LVL_MOUNTED 1 /* Volume is mounted for low level operations */ +#define VOLUME_MOUNTED 2 /* Volume is mounted */ +#define VOLUME_12BIT_FAT 4 /* Volume uses 12-bit FAT */ +#define VOLUME_ABS_MOUNTED 8 /* Volume is mounted for abs calls */ +#define VOLUME_OCCUPIED 32 /* Volume record in use */ +#define VOLUME_MOUNTED_NO_MBR 64 +#define VOLUME_MOUNTED_ON_RANGE 128 + + +#define execInProgress (pVol->volExecInProgress) + +#ifdef __cplusplus +extern "C" { +#endif +extern Volume vols[FL_VOLUMES]; +#ifdef __cplusplus +} +#endif + +FLStatus lockForIO(FLByte socket, FLByte partition, FLBoolean onOff); +void setTL(FLByte socket, FLByte partition, TL * fsVol); + +#endif diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/bdkemul.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/bdkemul.h new file mode 100755 index 00000000..224b31d0 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/bdkemul.h @@ -0,0 +1,135 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/bdkemul.h-arc $ + * + * Rev 1.15 Dec 11 2007 12:25:10 einat.avidan + * Add format start and format complete signatures in disk user attributes + * + * Rev 1.14 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.13 Sep 11 2006 13:45:10 yaniv.iarovici + * Legal header added + * + * Rev 1.12 Aug 09 2006 17:34:14 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.11 May 28 2006 12:48:42 polina.marimont + * comments + * + * Rev 1.10 May 17 2006 12:51:04 polina.marimont + * 1. DOCH_DiskUserAttrWithBinary - changed to support floors + * 2. DOCH macros use instead of numerical constants + * + * Rev 1.9 Mar 22 2006 17:35:46 DoronC + * Bug fix - add signature to disk attributes in order to use only + * format made by TrueFFS 7.1 and not by host SDK. + * Other format will force reformating of the media. + * + * Rev 1.8 Feb 16 2006 11:32:36 DoronC + * Store binary partition flags in the attributes and return then + * when requested by extendedInfo for compatability with legacy + * devices. + * + * Rev 1.7 Feb 14 2006 10:50:04 DoronC + * Remove large variables from stack. use one global buffer for + * all large buffers needs. + */ +#ifndef BDKEMUL_H +#define BDKEMUL_H + +#include "part_inf.h" + +/*Unit size*/ +#define BDK_SECTORS_IN_UNIT 0x200 +#define BDK_UNIT_SIZE (BDK_SECTORS_IN_UNIT< Erasable Block Size + * flWriteFault - fail in buffer writing + * flNoSpaceInVolume - end of media was prematurely reached + *-------------------------------------------------------------------*/ +#define bdkWriteBlock(ioreq) bdCall(FL_BINARY_WRITE_BLOCK,ioreq) + + +/*------------------------------------------------------------------- + * bdkErase - erase given number of blockdsin the BDK area. + * + * Erase given number of blockds in the binary sub partition. + * + * Parameters: ioreq + * 'irHandle' - Drive number (0, 1, ...) + * bits 7-4 - Partition # (zero based) + * bits 3-0 - Socket # (zero based) + * 'irData' - bdkParams record + * startingBlock - unit number of the sub-partition to start erasing from + * length - number of blocks to erase + * oldSign - signature of the sub-partition + * + * Return: flOK - success + * flBadLength - buffer length > Erasable Block Size + * flWriteFault - fail in buffer writing + * flNoSpaceInVolume - end of media was prematurely reached + *-------------------------------------------------------------------*/ +#define bdkErase(ioreq) bdCall(FL_BINARY_ERASE,ioreq) + + + +/*------------------------------------------------------------------- + * bdkCreate - create new BDK partition . + * + * Init create operations on the DiskOnChip starting at 'startUnit', with + * a # of 'units' and 'signature'. + * + * Note : Blocks in the DiskOnChip are marked with a 4-character signature + * followed by a 4-digit hexadecimal number. + * + * Parameters: ioreq + * 'irHandle' - Drive number (0, 1, ...) + * bits 7-4 - Partition # (zero based) + * bits 3-0 - Socket # (zero based) + * 'irData' - bdkParams record + * length - number of blocks to create + * oldSign - signature of the sub-partition + * newSign - the replacing signature + * + * Return: flOK - success + * flBadLength - buffer length > Erasable Block Size + * flWriteFault - fail in buffer writing + * flNoSpaceInVolume - end of media was prematurely reached + *-------------------------------------------------------------------*/ +#define bdkCreate(ioreq) bdCall(FL_BINARY_CREATE,ioreq) + +/*----------------------------------------------------------------------*/ +/* b d k P a r t i t i o n I n f o */ +/* */ +/* Parameters: */ +/* irHandle : volume number */ +/* irData : pointer to structure that hold socket */ +/* parameters */ +/* irLength : Physical size of the binary volume */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed. */ +/*----------------------------------------------------------------------*/ +#define bdkPartitionInfo(ioreq) bdCall(FL_BINARY_PARTITION_INFO,ioreq) + + +/* DEEP_POWER_DOWN 1 defined in flflash.h */ + + +/*----------------------------------------------------------------------*/ +/* f l W r i t e I P L */ +/* */ +/* Place a user buffer to both copies of the IPL area */ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* 4 LSB - Socket number */ +/* irData : Pointer to user buffer */ +/* irLength : Size of the buffer */ +/* irFlags : See flags bellow */ +/* FL_IPL_MODE_NORMAL */ +/* FL_IPL_VIRTUAL_RAM_MODE */ +/* FL_DOC_IPL_PAGED_RAM_MODE */ +/* FL_IPL_128K_WINDOW_MODE */ +/* FL_IPL_SWAP_BYTES_MODE */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flWriteIPL(ioreq) bdCall(FL_WRITE_IPL,ioreq) + +/*----------------------------------------------------------------------*/ +/* r e a d I P L */ +/* */ +/* Read IPL to user buffer. */ +/* */ +/* Note : Read length must be a multiplication of 512 bytes */ +/* Note : Causes DiskOnChip Millennium Plus to download (i,e protection */ +/* key will be removed from all partitions. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* 4 LSB - Socket number */ +/* irData : Pointer to user buffer */ +/* irLength : Size of the buffer */ +/* irCount : Used IPL size on the media */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flReadIPL(ioreq) bdCall(FL_READ_IPL,ioreq) + + + + +/*----------------------------------------------------------------------*/ +/* f l I n i t */ +/* */ +/* Initializes the FLite system. */ +/* */ +/* Calling this function is optional. If it is not called, */ +/* initialization will be done automatically on the first FLite call. */ +/* This function is provided for those applications who want to */ +/* explicitly initialize the system and get an initialization status. */ +/* */ +/* Calling flInit after initialization was done has no effect. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +TFFS_DLL_API FLStatus NAMING_CONVENTION flInit(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/*----------------------------------------------------------------------*/ +/* f l E x i t */ +/* */ +/* If the application ever exits, flExit should be called before exit. */ +/* flExit flushes all buffers, closes all open files, powers down the */ +/* sockets and removes the interval timer. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* Nothing */ +/*----------------------------------------------------------------------*/ +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +TFFS_DLL_API void NAMING_CONVENTION flExit(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/*----------------------------------------------------------------------*/ +/* f l G e t P h y s i c a l I n f o */ +/* */ +/* Get physical information of the media. The information includes */ +/* JEDEC ID, unit size and media size. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* irData : Address of user buffer to read physical */ +/* information into. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irLength : Window base address. note mast be cast to */ +/* unsigned. */ +/*----------------------------------------------------------------------*/ +#define flGetPhysicalInfo(ioreq) bdCall(FL_GET_PHYSICAL_INFO, ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l E x t e n d e d G e t D i s k I n f o */ +/* */ +/* Returns general information about the Device and a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Must be set to 0 */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : Partition number */ +/* irFlags : Either FL_BDK_PARTITION or FL_DISK_PARTITION */ +/* irData : Address of FLExtendedDiskInfo structure */ +/* irLength : Floor number to access - FL_ALL_FLOORS */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flGetExtendedDiskInfo(ioreq) bdCall(FL_GET_EXTENDED_DISK_INFO,ioreq) + + + + + +/*----------------------------------------------------------------------*/ +/* f l I d e n t i f y P r o t e c t i o n */ +/* b d k I d e n t i f y P r o t e c t i o n */ +/* f l I p l I d e n t i f y P r o t e c t i o n */ +/* */ +/* Returns the specified partitions protection attributes */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irFlags CHANGEABLE_PROTECTION - changeable protection type */ +/* PROTECTABLE - partition can recieve protection */ +/* READ_PROTECTED - partition is read protected */ +/* WRITE_PROTECTED - partition is write protected */ +/* LOCK_ENABLED - HW lock signal is enabled */ +/* LOCK_ASSERTED - HW lock signal is asserted */ +/* KEY_INSERTED - key is inserted (not currently */ +/* protected. */ +/*----------------------------------------------------------------------*/ +#define flIdentifyProtection(ioreq) bdCall(FL_PROTECTION_GET_TYPE,ioreq) +#define bdkIdentifyProtection(ioreq) bdCall(FL_BINARY_PROTECTION_GET_TYPE,ioreq) +#define flIplIdentifyProtection(ioreq) bdCall(FL_IPL_PROTECTION_GET_TYPE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l I n s e r t P r o t e c t i o n K e y */ +/* b d k I n s e r t P r o t e c t i o n K e y */ +/* f l I p l I n s e r t P r o t e c t i o n K e y */ +/* */ +/* Insert the protection key in order to remove the protection of the */ +/* partititon specified by the drive handle */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : pointer to an 8 bytes key array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flInsertProtectionKey(ioreq) bdCall(FL_PROTECTION_INSERT_KEY,ioreq) +#define bdkInsertProtectionKey(ioreq) bdCall(FL_BINARY_PROTECTION_INSERT_KEY,ioreq) +#define flIplInsertProtectionKey(ioreq) bdCall(FL_IPL_PROTECTION_INSERT_KEY,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l R e m o v e P r o t e c t i o n K e y */ +/* b d k R e m o v e P r o t e c t i o n K e y */ +/* f l I p l R e m o v e P r o t e c t i o n K e y */ +/* */ +/* Remove the protection key making the partition protected again */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flRemoveProtectionKey(ioreq) bdCall(FL_PROTECTION_REMOVE_KEY,ioreq) +#define bdkRemoveProtectionKey(ioreq) bdCall(FL_BINARY_PROTECTION_REMOVE_KEY,ioreq) +#define flIplRemoveProtectionKey(ioreq) bdCall(FL_IPL_PROTECTION_REMOVE_KEY,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l H a r d w a r e P r o t e c t i o n L o c k */ +/* b d k H a r d w a r e P r o t e c t i o n L o c k */ +/* */ +/* Enabled or disabled the affect of the hardware LOCK signal */ +/* The hardware lock signal disables the removal of protection through */ +/* the key therefore the partition will remain protected until the */ +/* hardware LOCK signal will be removed */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irFlags : LOCK_ENABLED locks the partition otherwise */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flHardwareProtectionLock(ioreq) bdCall(FL_PROTECTION_SET_LOCK,ioreq) +#define bdkHardwareProtectionLock(ioreq) bdCall(FL_BINARY_PROTECTION_CHANGE_LOCK,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l C h a n g e P r o t e c t i o n K e y */ +/* b d k C h a n g e P r o t e c t i o n K e y */ +/* f l I p l C h a n g e P r o t e c t i o n K e y */ +/* */ +/* Changes the current protection key with a new one. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to the new 8 bytes key array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flChangeProtectionKey(ioreq) bdCall(FL_PROTECTION_CHANGE_KEY,ioreq) +#define bdkChangeProtectionKey(ioreq) bdCall(FL_BINARY_PROTECTION_CHANGE_KEY,ioreq) +#define flIplChangeProtectionKey(ioreq) bdCall(FL_IPL_PROTECTION_CHANGE_KEY,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l C h a n g e P r o t e c t i o n T y p e */ +/* b d k C h a n g e P r o t e c t i o n T y p e */ +/* f l I p l C h a n g e P r o t e c t i o n T y p e */ +/* */ +/* Changes the protection attributes of the partitions. */ +/* In order for a partition to change its protection type (without */ +/* reformating the media) it must have the CHANGEABLE_PRTOECTION */ +/* attribute. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flChangeProtectionType(ioreq) bdCall(FL_PROTECTION_CHANGE_TYPE,ioreq) +#define bdkChangeProtectionType(ioreq) bdCall(FL_BINARY_PROTECTION_SET_TYPE,ioreq) +#define flIplChangeProtectionType(ioreq) bdCall(FL_IPL_PROTECTION_CHANGE_TYPE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l A p p l y S t i c k y L o c k */ +/* */ +/* Enable the sticky lock mode to all relevant partitions */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Must be set to 0 */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flApplyStickyLock(ioreq) bdCall(FL_PROTECTION_STICKY_LOCK,ioreq) + +#ifdef FL_SLPP +/*SLPP Specific*/ +/*----------------------------------------------------------------------*/ +/* f l S L P P U n l o c k R a n g e */ +/* */ +/* Unlock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to unlock */ +/* irLength : Number of sectors to unlock */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flSLPPUnlockRange(ioreq) bdCall(FL_SLPP_UNLOCK_RANGE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l S L P P U n l o c k E n t i r e P a r t i t i o n */ +/* */ +/* Unlock all sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flSLPPUnlockEntirePartition(ioreq) bdCall(FL_SLPP_UNLOCK_ENTIRE_PARTITION,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l S L P P L o c k R a n g e */ +/* */ +/* Lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to lock */ +/* irLength : Number of sectors to lock */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flSLPPLockRange(ioreq) bdCall(FL_SLPP_LOCK_RANGE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l S L P P S t i c k y L o c k R a n g e */ +/* */ +/* Sticky lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to sticky lock */ +/* irLength : Number of sectors to sticky lock */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flSLPPStickyLockRange(ioreq) bdCall(FL_SLPP_STICKY_LOCK_RANGE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l S L P P R e p o r t L o c k e d R a n g e s */ +/* */ +/* Report currently defined unlocked/stick locked ranges on a sector */ +/* protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to DOCH_SLPPReport structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irCount : Number of currently defined ranges */ +/*----------------------------------------------------------------------*/ +#define flSLPPReportLockedRanges(ioreq) bdCall(FL_SLPP_REPORT_LOCKED_RANGES,ioreq) + +#endif /*FL_SLPP*/ + +/*----------------------------------------------------------------------*/ +/* f l O T P S i z e */ +/* */ +/* Get the OTP size and stated */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irLength : The size of the used OTP area in bytes */ +/* irCount : The size of the OTP ara in bytes */ +/* irFlags : LOCKED_OTP for a locked area otherwise unlocked */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flOTPSize(ioreq) bdCall(FL_OTP_SIZE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l O T P W r i t e A n d L o c k */ +/* */ +/* Write to the OTP area while locking it at the end. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer to write from */ +/* irLength : number of bytes to write */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flOTPWriteAndLock(ioreq) bdCall(FL_OTP_WRITE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l O T P R e a d */ +/* */ +/* Read from the OTP area */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer to read into */ +/* irLength : number of bytes to read */ +/* irCount : offset to read from (starting at the begining of */ +/* the OTP area */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flOTPRead(ioreq) bdCall(FL_OTP_READ,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l G e t U n i q u e I D */ +/* */ +/* Returns the 16 bytes device unique ID */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to a 16 bytes buffer to read into the */ +/* unique ID data */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irData : 16 bytes unique ID buffer */ +/*----------------------------------------------------------------------*/ +#define flGetUniqueID(ioreq) bdCall(FL_UNIQUE_ID,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l G e t C u s t o m e r I D */ +/* */ +/* Returns the 4 bytes customer ID */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to a 4 bytes buffer to read into the */ +/* customer ID */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irData : 4 bytes unique ID buffer */ +/*----------------------------------------------------------------------*/ +#define flGetCustomerID(ioreq) bdCall(FL_CUSTOMER_ID,ioreq) + + +/*----------------------------------------------------------------------*/ +/* f l D e e p P o w e r D o w n M o d e */ +/* */ +/* Forces the device into and out of the deep power down mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irFlags : DEEP_POWER_DOWN forces the low power consumption */ +/* mode. otherwise turning to the regular mode */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +#define flDeepPowerDownMode(ioreq) bdCall(FL_DEEP_POWER_DOWN_MODE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l R e c o v e r F r o m P o w e r L o s s */ +/* */ +/* Recover from a power OFF without full TrueFFS initialization. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +#define flRecoverFromPowerLoss(ioreq) bdCall(FL_RECOVER_FROM_POWER_LOSS,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l C l e a r Q u i c k M o u n t I n f o */ +/* */ +/* Clear all quick mount informtion. */ +/* */ +/* Must be called before calling mount volume routines. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* : Partition number ( 0,1,2... ) */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flClearQuickMountInfo(ioreq) bdCall(FL_CLEAR_QUICK_MOUNT_INFO,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l W r i t e Q u i c k M o u n t S t a t u s */ +/* */ +/* Get the status of the quick mount information. */ +/* */ +/* Can NOT be called before calling mount volume routines. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* : Partition number ( 0,1,2... ) */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flWriteQuickMountInfo(ioreq) bdCall(FL_WRITE_QUICK_MOUNT_INFO,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l G e t Q u i c k M o u n t S t a t u s */ +/* */ +/* Get the status of the quick mount information. */ +/* */ +/* Can be called before calling mount volume routines. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* : Partition number ( 0,1,2... ) */ +/* irFlags : return the quick mount info: */ +/* FL_ON if valid FL_OFF if not */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flGetQuickMountStatus(ioreq) bdCall(FL_GET_QUICK_MOUNT_STATUS,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l H w C o n f i g */ +/* */ +/* his routine enables to control DiskOnChip H/W features. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irFlags : Descrbing H/W configuration Type */ +/* irLength : New value to use - Different for each H/W */ +/* configuration type chosen. */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +#define flHwConfig(ioreq) bdCall(FL_HW_CONFIG,ioreq) + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +/*----------------------------------------------------------------------*/ +/* f l B u i l d G e o m e t r y */ +/* */ +/* Get C/H/S information of the disk according to number of sectors. */ +/* */ +/* Parameters: */ +/* capacity : Number of Sectors in Volume */ +/* cylinders : Pointer to Number of Cylinders */ +/* heads : Pointer to Number of Heads */ +/* sectors : Pointer to Number of Sectors per Track */ +/* oldFormat : True for one sector per culoster */ +/* wIrHandle : Disk partition handle to proccess */ +/* */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API void NAMING_CONVENTION flBuildGeometry(FLDword capacity, FLDword FAR2 *cylinders, + FLDword FAR2 *heads,FLDword FAR2 *sectors, FLBoolean oldFormat, FLWord wIrHandle); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------*/ +/* r e a d B B T */ +/* */ +/* Read Bad Blocks Table of device to user buffer */ +/* */ +/* Note: the buffer is not initialized by the function */ +/* */ +/* Parameters: */ +/* irData : User buffer. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irLength : returns the media size */ +/* irFlags : returns the actual number of badBlocks */ +/*----------------------------------------------------------------------*/ +#define flReadBBT(ioreq) bdCall(FL_READ_BBT,ioreq) + + + + +/*----------------------------------------------------------------------*/ +/* f l O T P S i z e */ +/* */ +/* Get the OTP size and stated */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irLength : The size of the used OTP area in bytes */ +/* irCount : The size of the OTP ara in bytes */ +/* irFlags : LOCKED_OTP for a locked area otherwise unlocked */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#define flMCOTPSize(ioreq) bdCall(FL_MCOTP_SIZE,ioreq) +/* LOCKED_OTP 1 defined in flflash.h */ + +/*----------------------------------------------------------------------*/ +/* f l O T P R e a d */ +/* */ +/* Read from the OTP area */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer to read into */ +/* irLength : number of bytes to read */ +/* irCount : offset to read from (starting at the begining of */ +/* the OTP area */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#define flMCOTPRead(ioreq) bdCall(FL_MCOTP_READ,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l O T P W r i t e A n d L o c k */ +/* */ +/* Write to the OTP area while locking it at the end. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer to write from */ +/* irLength : number of bytes to write */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#define flMCOTPWriteAndLock(ioreq) bdCall(FL_MCOTP_WRITE,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l F o r m a t F S */ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 11-8 - Logical partition in Flash partition (zero based)*/ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irSectorNo : First absolute sector of logical partition */ +/* (if bit 13 is set) */ +/* irSectorCount : Number of sectors in logical partition */ +/* (if bit 13 is set) */ +/* irData : Address of the FATFormatParams structure */ +/* irFlags : */ +/* bit 14 - FL_DO_NOT_UPDATE_MBR */ +/* bit 13 - FL_MEDIA_WITHOUT_MBR */ +/* bit 12 - FL_MOUNT_ON_GIVEN_RANGE */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flFormatFS(ioreq) formatCall(FL_FORMAT_FS,ioreq) + + +/*----------------------------------------------------------------------*/ +/* f o r m a t C a l l */ +/* */ +/* Common entry-point to all file-system format functions. Macros are */ +/* to call individual function, which are separately described below. */ +/* */ +/* Parameters: */ +/* function : file-system function code (listed below) */ +/* ioreq : IOreq structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +TFFS_DLL_API FLStatus NAMING_CONVENTION formatCall(FLFunctionNo functionNo, IOreq FAR2 *ioreq); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : Number of LogicalPartitionParams structures */ +/* irData : Address of array of LogicalPartitionParams structures */ +/* irFlags : 0 - reserved */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flCreateLogicalPartitions(ioreq) formatCall(FL_CREATE_LOGICAL_PARTITIONS,ioreq) + +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 11-8 - Logical partition in Flash partition (zero based)*/ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irFlags : 0 - reserved */ +/* irData : Address of the LogPartitionInfo structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flFindLogicalPartition(ioreq) formatCall(FL_FIND_LOGICAL_PARTITION,ioreq) + +/*----------------------------------------------------------------------*/ +/* f l D o c h P a s s T h r o u g h */ +/* */ +/* Passes ATA command directly to the DOCH device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer (for DATA IN and DATA out */ +/* commands) */ +/* irLength : number of sectors in buffer, pointed to by irData*/ +/* irCount : bits 0..1 - pass through operation flow, where */ +/* 0 - No Data(CTRL), 1 - Data IN, 2 - Data OUT */ +/* bit 2 - 1, when interrupt should be used, */ +/* 0 - otherwise */ +/* bits 4..7 - frame size exponent, should be set */ +/* to 0 for now - 1 sector */ +/* irPath : pointer to buffer from type DOCH_Registers* */ +/* IN - input registers, OUT - out registers */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +#define flDochPassThrough(ioreq) bdCall(FL_DOCH_PASS_THROUGH,ioreq) + +#endif /* BLOCKDEV_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/defs.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/defs.c new file mode 100755 index 00000000..1cdb671a --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/defs.c @@ -0,0 +1,341 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/DocDriver/TrueFFS BD/src/defs.c-arc $ + * + * Rev 1.8 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.7 Oct 29 2006 11:27:26 Yaniv.Iarovici + * Removed unusable variable - 'readBackBuffer'. + * + * Rev 1.6 Oct 29 2006 10:59:40 Yaniv.Iarovici + * Removed unused variable - 'volBuffers'. + * + * Rev 1.5 Oct 09 2006 14:05:12 yaniv.iarovici + * Removed legacy devices related code and definitions + * + * Rev 1.4 Oct 05 2006 11:00:18 yaniv.iarovici + * Fixed compilation warnings. + * + * Rev 1.3 Sep 13 2006 10:43:00 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.2 Sep 11 2006 13:45:12 yaniv.iarovici + * Legal header added + * + * Rev 1.1 Aug 22 2006 13:22:20 Yaniv.Iarovici + * Remove decleration fo 'void flInitGlobalVars(void)' + * + * Rev 1.0 Aug 08 2006 15:47:24 Polina.Marimont + * Initial revision. + */ + + +#include "flcustom.h" +#include "flchkdef.h" +#include "flsystyp.h" +#include "blockdev.h" +#include "bddefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*============================================================================*/ +/*==== from blockdev.c */ +/********************* Global variables Start **************************/ + +Volume vols[FL_VOLUMES]; +static FLBoolean initDone = FALSE; /* Initialization not done yet */ +static FLBoolean initGlobalVarsDone = FALSE; /* Initialization of environment */ + /* and access type variables not */ + /* done yet. */ +unsigned noOfDrives; +/* + * bus configuration + * DiskOnChip minimal bus width + */ +#ifndef FL_NO_USE_FUNC +FLDword flBusConfig[FL_SOCKETS]; +#endif /* FL_NO_USE_FUNC */ +/*----------------------------------------------------------------------*/ +/* f l I n i t */ +/* */ +/* Initializes the FLite system, sockets and timers. */ +/* */ +/* Calling this function is optional. If it is not called, */ +/* initialization will be done automatically . */ +/* This function is provided for those applications who want to */ +/* explicitly initialize the system and get an initialization status. */ +/* */ +/* Calling flInit after initialization was done has no effect. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +FLStatus _flInit(void) +{ + unsigned volNo; + Volume * pVol = vols; + + if (initDone) + return flOK; + + + flInitGlobalVars(); + +#ifdef FL_ENVIRONMENT_VARS + + /* Call users initialization routine + */ + flSetEnvVar(); + +#endif /* FL_ENVIRONMENT_VARS */ + + /* + * 1) Mark all the volumes as not used and free to be allocated. + * 2) Clear password in order to make it invalid. + */ + + tffsset(vols,0,sizeof(vols)); + + for (volNo = 0,pVol = vols; volNo < FL_VOLUMES; volNo++,pVol++) + { + /* The actual number of sockets is not yet known and will be retrieved by + * flRegisterComponents routine by the socket components. For now supply + * each of the possible sockets with its buffer and socket number. + */ + if ( volNo < FL_SOCKETS) + { + pVol->socket = flSocketOf(volNo); + pVol->flash = flFlashOf((FLByte)volNo); + tffsset(pVol->socket,0,sizeof(FLSocket)); + pVol->socket->volNo = volNo; + } + else + { + pVol->flash = NULL; + } + pVol->volExecInProgress = NULL; + } + + +#ifdef FL_BACKGROUND + flCreateBackground(); +#endif + noOfDrives = 0; + noOfSockets = 0; + return flOK; +}/*_flInit*/ + + +/*----------------------------------------------------------------------*/ +/* f l I n i t G l o b a l V a r s */ +/* */ +/* Initializes the FLite system, environment and access type variables. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* None */ +/*----------------------------------------------------------------------*/ + +void flInitGlobalVars(void) +{ + FLFlash * flash; + int i,j; + + if(initGlobalVarsDone == TRUE) + return; + + /* Do not initialize variables on next call */ + initGlobalVarsDone = TRUE; + initDone = FALSE; + + /* + * Set default values to per socket/volume variables + */ + + for(i=0; i< FL_SOCKETS; i++) + { + flash = flFlashOf((FLByte)i); + /* tffsset is not yet initialized */ + for(j=0;j<(int)sizeof(FLFlash);j++) + { + ((FLByte *)flash)[j] = 0; + } +#ifndef FL_NO_USE_FUNC + flBusConfig[i] = FL_DEFAULT_BUS_MODE(i); +#endif /* FL_NO_USE_FUNC */ + + } +}/*flInitGlobalVars*/ + +/*============================================================================*/ + +/*============================================================================*/ +/*==== from flflash.c */ +static FLFlash flashes[FL_SOCKETS]; + + +/************************************************************************/ +/************************************************************************/ +/*** ***/ +/*** E X P O R T E D R O U T I N E S ***/ +/*** ***/ +/************************************************************************/ +/************************************************************************/ + +/*----------------------------------------------------------------------*/ +/* f l F l a s h O f */ +/* */ +/* Gets the flash connected to a volume no. */ +/* */ +/* Parameters: */ +/* volNo : Volume no. for which to get flash */ +/* */ +/* Returns: */ +/* flash of volume no. */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API FLFlash * NAMING_CONVENTION flFlashOf(FLByte volNo) +{ + return &flashes[volNo]; +} + +/*============================================================================*/ +#ifdef __cplusplus +} +#endif + + + +/*============================================================================*/ +/*=== from bdstub.c */ +#include "dochstub.h" +/*----------------------------------------------------------------------*/ +/* Function name : lockForIO*/ +/* Description : */ +/* Return type : FLStatus */ +/* Argument : FLByte socket*/ +/* Argument : FLByte partition*/ +/* Argument : FLBoolean onOff*/ +/*----------------------------------------------------------------------*/ +FLStatus lockForIO(FLByte socket, FLByte partition, FLBoolean onOff) +{ + +#if (FS_SOCKETS < FL_SOCKETS) || (FS_MAX_TL_PARTITIONS < FL_MAX_TL_PARTITIONS) + /* then caller's check is not good enough */ + if ((socket >= FL_SOCKETS) || (partition >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; +#endif + + checkStatus(dochSetBusy(socket, onOff, partition)); /* take DOCH mutex */ + return flOK; +}/*lockForIO()*/ +/*============================================================================*/ + + +/*============================================================================*/ +/*=== from flsocket.c */ +FLByte noOfSockets; /* No. of drives actually registered */ + +static FLSocket sockets[FL_SOCKETS]; + + +/*----------------------------------------------------------------------*/ +/* f l S o c k e t O f */ +/* */ +/* Gets the socket connected to a volume no. */ +/* */ +/* Parameters: */ +/* volNo : Volume no. for which to get socket */ +/* */ +/* Returns: */ +/* socket of volume no. */ +/*----------------------------------------------------------------------*/ + +FLSocket *flSocketOf(unsigned volNo) +{ + return &sockets[volNo]; +} + +/*----------------------------------------------------------------------*/ +/* u d a t e S o c k e t P a r a m e t e r s */ +/* */ +/* Pass socket parameters to the socket interface layer. */ +/* This function should be called after the socket parameters (like */ +/* size and base) are known. If these parameters are known at */ +/* registration time then there is no need to use this function, and */ +/* the parameters can be passed to the registration routine. */ +/* The structure passed in irData is specific for each socket interface.*/ +/* */ +/* Note : When using DiskOnChip this routine returns the socekt */ +/* parameters instead of initializing them. */ +/* */ +/* Parameters: */ +/* vol : Pointer identifying drive */ +/* params : Record returning (or sending) the flsocket record */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success */ +/*----------------------------------------------------------------------*/ +FLStatus updateSocketParameters(FLSocket * pVol, void FAR1 *params) +{ + if (pVol->updateSocketParams) + pVol->updateSocketParams(pVol, params); + + return flOK; +} + +/*============================================================================*/ + +/*end of file*/ + + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/defs.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/defs.h new file mode 100755 index 00000000..6abfcbbc --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/defs.h @@ -0,0 +1,238 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/DocDriver/TrueFFS BD/src/defs.h-arc $ + * + * Rev 1.6 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.5 Oct 11 2007 18:47:46 Einat.Avidan + * remove unused or duplicated definitions + * + * Rev 1.4 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.3 Oct 09 2006 14:05:18 yaniv.iarovici + * Removed legacy devices related code and definitions + * + * Rev 1.2 Sep 11 2006 13:45:12 yaniv.iarovici + * Legal header added + * + * Rev 1.1 Aug 22 2006 13:22:40 Yaniv.Iarovici + * 1) Remove decleration fo 'void flInitGlobalVars(void)' + * 2) Add 'extern "c"' on: + * - flIdentifyFlash() external definition + * - flHandleConversionTable[] external definition + * - _flInit() definition + * + * Rev 1.0 Aug 08 2006 15:47:24 Polina.Marimont + * Initial revision. + */ + +#ifndef _DEFS_H +#define _DEFS_H + + +/*=============================================================*/ +/* from flsocket.h */ +#include "flbuffer.h" + +#define ATTRIBUTE_SPACE_MAPPED 0x8000 +#define UNDEFINED_MAPPING 0x7fff + + +typedef enum {PowerOff, PowerGoingOff, PowerOn} PowerState; + +extern FLByte noOfSockets; /* No. of drives actually registered */ + +typedef struct tSocket FLSocket; +/*=============================================================*/ + +/*=============================================================*/ +/* from _flsoc.h */ +struct tSocket { + unsigned volNo; /* Volume no. of socket */ + + PowerState DPDState; /* Actual DPD state */ + FLBoolean remapped; /* set to TRUE whenever the socket window is moved */ + + void (*powerOnCallback)(void *flash); /* Notification routine for Vcc on */ + void * flash; /* Flash object for callback */ + + struct { /* Window state */ + unsigned int baseAddress; /* Physical base as a 4K page */ + unsigned int currentPage; /* Our current window page mapping */ + void FAR0 * base; /* Pointer to window base */ + FLSDword size; /* Window size (must by power of 2) */ + unsigned speed; /* in nsec. */ + unsigned busWidth; /* 8 or 16 bits */ + } window; + FLBoolean (*cardDetected)(FLSocket * pVol); + void (*VccOn)(FLSocket * pVol); + void (*VccOff)(FLSocket * pVol); + FLStatus (*initSocket)(FLSocket * pVol); + void (*setWindow)(FLSocket * pVol); + void (*setMappingContext)(FLSocket * pVol, unsigned page); + FLBoolean (*getAndClearCardChangeIndicator)(FLSocket * pVol); + FLBoolean (*writeProtected)(FLSocket * pVol); + void (*updateSocketParams)(FLSocket * pVol, void FAR1 *params); +#ifdef FL_EXIT + void (*freeSocket)(FLSocket * pVol); +#endif +}; + + +/* See interface documentation of functions in socket.c */ + +extern FLStatus updateSocketParameters(FLSocket *, void FAR1 *); + + +extern FLSocket* flSocketOf(unsigned volNo); + + +/*=============================================================*/ + +/*=============================================================*/ +/* from flflash.h */ + +/* Some useful types for mapped Flash locations */ + +typedef volatile FLByte FAR0 * FlashPTR; +typedef volatile unsigned short int FAR0 * FlashWPTR; +typedef volatile FLDword FAR0 * FlashDPTR; +typedef FLWord FlashType; /* JEDEC id */ +typedef volatile FLByte FAR0* NDOC2window; + +typedef FLByte Reg8bitType; +typedef FLWord Reg16bitType; + + +/* Media types */ +#define H3_TYPE 15 + +/* protection specific defintions */ +#define PROTECTION_KEY_LENGTH 8 /* Size of protection key in bytes */ +#define DEFAULT_KEY "00000000" + + +/****************************/ +/* Special services API */ +/****************************/ + + +/* Flash array identification structure */ +typedef struct tFlash FLFlash; /* Forward definition */ + +/*=============================================================*/ + + +/*=============================================================*/ +/* from _flflash.h */ + +struct tFlash { + FLBoolean wasIdentified; + FlashType type; + FlashType subType; + FLByte mediaType; + FLDword busAccessType; + FLByte if_cfg; + FLByte bBusType; + FLWord flags; + void * mtdVars; + FLSocket * socket; + NDOC2window win; + void (*setPowerOnCallback)(FLFlash *); + FLStatus (*flashRead)(FLFlash *); + FLStatus (*setCallBack)(FLFlash *); + FLStatus (*dismount)(FLFlash *); + FLStatus (*prepareForPowerChanges) (FLFlash *,FLByte) ; + FLStatus (*clearCallBack)(FLFlash *); + FLStatus (*enterDeepPowerDownMode)(FLFlash *,FLWord state); + +#ifndef FL_NO_USE_FUNC + FLMemWindowSize FAR1* memWindowSize; /* Doc memory window size */ + FLMemRead FAR1* memRead; /* Doc memory read routine */ + FLMemWrite FAR1* memWrite; /* Doc memory write routine */ + FLMemSet FAR1* memSet; /* Doc memory set routine */ + FLMemRead8bit FAR1* memRead8bit; /* Doc memory 8 bit read routine */ + FLMemWrite8bit FAR1* memWrite8bit; /* Doc memory 8 bit write routine */ + FLMemRead16bit FAR1* memRead16bit; /* Doc memory 16 bit read routine */ + FLMemWrite16bit FAR1* memWrite16bit; /* Doc memory 16 bit write routine */ + FLMemSetGetMode FAR1* memSetGetMode; /* Interleave change event - */ + /* call back to plant new routines */ +#endif /* FL_NO_USE_FUNC */ +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +extern TFFS_DLL_API FLFlash * NAMING_CONVENTION flFlashOf(FLByte volNo); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/*=============================================================*/ + + +/*=============================================================*/ +/*=== from nandefs.h */ + +/*=============================================================*/ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ +FLStatus _flInit(void); +void flInitGlobalVars(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /*_DEFS_H*/ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docbdk.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docbdk.h new file mode 100755 index 00000000..9275d9a8 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docbdk.h @@ -0,0 +1,550 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/docbdk.h-arc $ + * + * Rev 1.8 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.7 Sep 11 2006 13:45:12 yaniv.iarovici + * Legal header added + * + * Rev 1.6 Aug 09 2006 16:52:46 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +/************************************************************************/ +/* Caution: The BDK_ACCESS compilation flag is for M-SYSTEMS internal */ +/* use ONLY. This flag is used by M-SYSTEMS drivers and */ +/* therfore it is SHOULD NOT be used by this package */ +/************************************************************************/ + +/***************************************************************************** +* File Header * +* ----------- * +* Name : docbdk.h * +* * +* Description : This file contains the binary partition defintions , data * +* structures and function prototypes. * +* * +* Note : The file exports 2 interfaces each under its own compilation flag: * +* * +* BDK package - Standalone package that exports routines for binary * +* partitions handling(MTD_STANDALONE compilation flag). * +* OSAK module - Separated module of the OSAK package that exports a * +* common entry point to the same routines. (BDK_ACCESS * +* compilation flag). * +* * +* Warning : Do not use this file with the BDK_ACCESS compilation flag unless * +* you own the full OSAK package. * +*****************************************************************************/ + +#ifndef DOCBDK_H +#define DOCBDK_H +/*---------------------------------------------------------------------*/ +/* Include the proper header files. */ +/*---------------------------------------------------------------------*/ + +#include "flcommon.h" + +#ifndef MTD_STANDALONE +#ifdef BDK_ACCESS +#include "flstruct.h" +#endif /* BDK_ACCESS */ +#endif /* MTD_STANDALONE */ + +/* Use the define bellow to set the size of the page buffer used by the BDK */ +#ifndef BDK_SECTORS_PER_PAGE +#define BDK_SECTORS_PER_PAGE (8L /* 2KB PAGE */) +#endif /* BDK_SECTORS_PER_PAGE */ + +#ifndef BDK_SECTORS_PER_WRITE +#define BDK_SECTORS_PER_WRITE (4L/*Planes*/*BDK_SECTORS_PER_PAGE/*Sectors per page*/*2/*MLC*/) +#endif /* BDK_SECTORS_PER_WRITE */ + + +/* BDK specific flag area */ +#define ERASE_BEFORE_WRITE 8 +#define BDK_SPARE_BLOCKS_SIGN "S4BB" /* Must be the same as BINARY_SPARE_BLOCKS_SIGN (FLFORMAT.H) */ + + +/*----------------------------------------------------------------------*/ +/* b d k F i n d D i s k O n C h i p */ +/* */ +/* Find and identify DiskOnChip device if installed in the system. The */ +/*search address are set by the flregisterDOCXXXSOC call in flcustom.c */ +/*file. */ +/* */ +/* */ +/* Parameters: */ +/* docAddress : Pointer to return value of DiskOnChip */ +/* address (if found). */ +/* docSize : Pointer to return value of DiskOnChip */ +/* address window size (if found). */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success (DiskOnChip found) */ +/* otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkFindDiskOnChip (CardAddress FAR2 *docAddress, + FLDword FAR2 *docSize ); +/*----------------------------------------------------------------------*/ +/* b d k I n i t */ +/* */ +/* Initialize the BDK SW package. This function is normaly called */ +/*automatically by the first call to the BDK package functions. */ +/* */ +/* Parameters: */ +/* None. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +void bdkInit( void ); + +#ifdef FL_EXIT +/*----------------------------------------------------------------------*/ +/* b d k E X i t */ +/* */ +/* Reset the BDK SW package. This function is normaly called as the last*/ +/*reference to the BDK package, providing clean exit and clearing all */ +/*allocated memory. */ +/* */ +/* Parameters: */ +/* None. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +void bdkExit (void); +#endif /* FL_EXIT */ + +/*----------------------------------------------------------------------*/ +/* b d k S e t B o o t P a r t i t i o n N o */ +/* */ +/* Set the current BDK partition in use. The default partition is */ +/*partition 0. For operation on other partitions, this routine should be*/ +/*called prior to actual command. The partition set is valid until the */ +/*next time this function is called. */ +/* */ +/* Parameters: */ +/* partitionNo : partition number to be access next. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkSetBootPartitionNo (FLByte partitionNo); + +/*----------------------------------------------------------------------*/ +/* b d k G e t B o o t P a r t i t i o n I n f o */ +/* */ +/* Get information regarding the actual size and used size of a binary */ +/*(sub) partition. */ +/* */ +/* Parameters: */ +/* startUnit : First block containing data (usually 0) */ +/* partitionSize : Pointer to output value of full */ +/* sub partition size. */ +/* realPartitionSize : Pointer to return value of used size. */ +/* unitSize : Pointer to return value of unit size. */ +/* signature : Signature of retrieved sub partition. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkGetBootPartitionInfo (FLWord startUnit, + FLDword FAR2 *partitionSize, + FLDword FAR2 *realPartitionSize, + FLDword FAR2 *unitSize, + FLByte FAR2 *signature); + +/*----------------------------------------------------------------------*/ +/* b d k C o p y B o o t A r e a */ +/* */ +/* Copy data from binary partition to RAM */ +/* */ +/* Parameters: */ +/* startAddressPtr : Pointer to start RAM address */ +/* wStartUnit : No' of first block in partition(usualy 0).*/ +/* dwAreaLen : Length of read area. */ +/* bCheckSumPtr : Pointer to output chksum calculation. */ +/* signPtr : Signature of retrieved sub partition. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCopyBootArea (FLByte FAR1 *startAddressPtr, + FLWord wStartUnit, + FLDword dwAreaLen, + FLByte FAR2 *bCheckSumPtr, + FLByte FAR2 *signPtr); + +/*----------------------------------------------------------------------*/ +/* b d k C o p y B o o t A r e a I n i t */ +/* */ +/* Initialize read process from BDK area. This routine must be called */ +/*prior to any series of bdkCopyBootAreaBlock calls. The areaLen set by */ +/*this routine must be total len of all calls to following */ +/*bdkCopyBootAreaBlock calls. */ +/* */ +/* Parameters: */ +/* startUnit : first unit to read (must contain data). */ +/* areaLen : length of bdk are to be read. */ +/* signature : Signature of retrieved sub partition. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCopyBootAreaInit (FLWord startUnit, + FLDword areaLen, + FLByte FAR2 *signature); + +/*----------------------------------------------------------------------*/ +/* b d k C o p y B o o t A r e a B l o c k */ +/* */ +/* read the next chunk of data from BDK area. This routine call must */ +/*follow a call to bdkCopyBootAreaInit and cannot be used without */ +/*proper init call. */ +/* */ +/* Parameters: */ +/* buf : Buffer where to read the data. */ +/* bufferLen : Length of current read buffer. */ +/* checkSum : Pointer for output ChkSum calculation of */ +/* read data. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCopyBootAreaBlock (FLByte FAR1 *buf , + FLDword bufferLen, + FLByte FAR2 *checkSum); + +/*----------------------------------------------------------------------*/ +/* b d k U p d a t e B o o t A r e a I n i t */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkUpdateBootAreaInit (FLWord startUnit, + FLDword areaLen, + FLByte updateFlag, + FLByte FAR2 *signature ); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkUpdateBootAreaBlock (FLByte FAR1 *buf , + FLDword bufferLen ); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkGetProtectionType (FLWord * protectionType); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkInsertKey (FLByte FAR1* key); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkRemoveKey (void); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkStickyLock (void); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkLockEnable (FLByte enable); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkChangeKey (FLByte FAR1* key); +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkSetProtectionType (FLWord newType); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCreateBootArea (FLWord noOfBlocks, + FLByte FAR2 * oldSign, + FLByte FAR2 * newSign); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkEraseBootArea (FLWord startUnit, + FLWord noOfBlocks, + FLByte FAR2 * signature); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkGetUniqueID(FLByte FAR1* buf); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkReadOtp(FLWord offset,FLByte FAR1 * buffer,FLWord length); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkWriteAndLockOtp(const FLByte FAR1 * buffer,FLWord length); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkGetOtpSize(FLDword FAR2* sectionSize, FLDword FAR2* usedSize, + FLWord FAR2* locked); + +/*----------------------------------------------------------------------*/ +/* x */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkWriteIPL (FLByte FAR1 * buf , FLDword bufLen , FLDword offset,FLDword flags); + +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkCopyBootAreaFile ( FLSByte FAR2 *fname, + FLWord startUnit, + FLDword areaLen, + FLByte FAR2 *checkSum, + FLByte FAR2 *signature ); + +/*----------------------------------------------------------------------*/ +/* */ +/* */ +/* XXXX */ +/* XXXX */ +/* XXXX */ +/* */ +/* Parameters: */ +/* xx : xxxx */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success otherwise for failure */ +/*----------------------------------------------------------------------*/ +FLStatus bdkUpdateBootAreaFile(FLSByte FAR2 *fname, FLWord startUnit, + FLDword areaLen, FLByte FAR2 *signature); + +#endif /* DOCBDK_H */ + + + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docdrv.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docdrv.c new file mode 100755 index 00000000..8ccdc7f2 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docdrv.c @@ -0,0 +1,452 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/DocDriver/TrueFFS BD/src/docdrv.c-arc $ + * + * Rev 1.12 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.11 Sep 04 2007 15:26:44 einat.avidan + * add printouts + * + * Rev 1.10 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.9 Feb 28 2007 10:32:00 einat.avidan + * CX tools support + * + * Rev 1.8 Feb 15 2007 17:40:52 Einat.Avidan + * Add support in edge\level and polarity within FL_DMA_INIT compilation flag + * + * Rev 1.7 Nov 13 2006 15:13:48 Yaniv.Iarovici + * Added environment variable - 'FL_DISABLE_MEMCPY'. + * + * Rev 1.6 Oct 30 2006 15:50:16 yaniv.iarovici + * Add call to flDOCHIdentifyDiskOnChipDevice() after flInit() is completed + * for updating actual number of partitions. + * + * Rev 1.5 Sep 11 2006 13:45:14 yaniv.iarovici + * Legal header added + * + * Rev 1.4 Aug 22 2006 13:22:54 Yaniv.Iarovici + * Bug fix: 'FL_DMA_HW_ENABLED' was NOT treated as bit but as a value in flInit(). + * + * Rev 1.3 Aug 16 2006 08:43:26 Yaniv.Iarovici + * Add support for Environment Variable: 'FL_SET_TRANSFER_MODE' - Controls DRQ size + * + * Rev 1.2 Aug 10 2006 10:39:48 Polina.Marimont + * reinit fix + * + * Rev 1.1 Aug 10 2006 10:37:14 Polina.Marimont + * bug fix - avoid initializing twice + * + * Rev 1.0 Aug 08 2006 15:47:22 Polina.Marimont + * Initial revision. + */ +#include "flchkdef.h" +#include "flcommon.h" +#include "flstdcmp.h" +#include "blockdev.h" +#include "tffs_api.h" +#include "doch_api.h" +#include "doch_ata.h" +#include "bddefs.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +FLStatus bdSetBusy(Volume * pVol, FLBoolean state, FLByte partition); + +extern FLBoolean dochBdCallWasCalled; +#ifndef DOCH_USE_FUNC +FLFlash * DOCHFlash; +#endif /* DOCH_USE_FUNC */ + + +bdCallType bdCall = bdCallTFFSToDOCH; +static FLBoolean fDocDriverInitDone = FALSE; + + +extern FLBoolean flPreventMemcpy; + +#ifdef CX_ATA_SNIFFER + FILE * ataLogFile ; +#endif /*CX_ATA_SNIFFER*/ + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flInit */ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flInit() +{ +#if (!defined(DOCH_USE_FUNC)) && (!defined (FL_NO_USE_FUNC)) + FLStatus flStatus; + FLDword dwBusConfig = flBusConfig[0]; +#endif /*!DOCH_USE_FUNC && !FL_NO_USE_FUNC*/ + DOCH_Error status_HDOC = DOCH_OK; + DOCH_DeviceInfo tempDOCDI; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, 0); + +#ifdef CX_ATA_SNIFFER + ataLogFile=fopen("atalog.bin","wb"); + if (! ataLogFile) + { + DBG_PRINT_FLOW(FLZONE_ABS, "\r\n*** Cannot Create atalog file in flInit() ***\r\n\n\n"); + return DOCH_ATA_ERROR_ABORT; + } +#endif /*CX_ATA_SNIFFER*/ + + if( fDocDriverInitDone == TRUE ) + return flOK; + + _flInit(); + + flSysfunInit(); + + DBG_PRINT_FLOW(FLZONE_ABS, "Searching for H3 device... \r\n"); + +#ifndef DOCH_USE_FUNC + /* Initialize DOCHFlash and redirect to regular MTD access layer */ + DOCHFlash = flFlashOf(0); +#ifndef FL_NO_USE_FUNC + dwBusConfig |= FL_16BIT_DOC_ACCESS ; + dwBusConfig |= FL_16BIT_FLASH_ACCESS ; + dwBusConfig |= FL_BUS_HAS_16BIT_ACCESS; + flStatus = setBusTypeOfFlash(DOCHFlash,dwBusConfig); + if(flStatus != flOK) + return flStatus; +#endif /* FL_NO_USE_FUNC */ +#endif /* DOCH_USE_FUNC */ + + status_HDOC = DochSDKInit(); + if(status_HDOC == DOCH_OK) /*DOCH Device*/ + { + DBG_PRINT_FLOW(FLZONE_ABS, "H3 Device found !!! \r\n\n"); + bdCall = bdCallTFFSToDOCH; +#ifdef FL_DMA_INIT + { + IOreq myIoreq; + FLDword ctrl; + FLByte bDmaInit = FL_DMA_INIT(0); + if( (bDmaInit & FL_DMA_HW_ENABLED) == FL_DMA_HW_ENABLED ) /*if DMA enabled by default -> set this to SA SDK*/ + { + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irFlags = DOCH_DMA_ENABLE; + myIoreq.irLength = TRUE; + status_HDOC = flDOCHConfigHW(&myIoreq); + if( status_HDOC!=DOCH_OK ) + { + DBG_PRINT_FLOW_PRM(FLZONE_ABS, (FLTXT("Fail to enable DMA with status %d \r\n"),status_HDOC)); + } + } + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irFlags = DOCH_DMA_CTRL; + ctrl = ((DOCH_DMA_PULSE_WIDTH)<<4) | DOCH_DMA_REQ_POL_LOW; + if (bDmaInit & FL_DMA_REQ_EDGE) + ctrl |= DOCH_DMA_REQ_EDGE; + if (bDmaInit & FL_NEGATED_0_ASSERTED_1) + ctrl &= ~DOCH_DMA_REQ_POL_LOW; + myIoreq.irLength = ctrl; + status_HDOC = flDOCHConfigHW(&myIoreq); + if( status_HDOC!=DOCH_OK ) + { + DBG_PRINT_FLOW_PRM(FLZONE_ABS, (FLTXT("Fail to set DMA control register with status %d \r\n"),status_HDOC)); + } + } +#endif /*FL_DMA_INIT*/ + + /* Update number of partitions*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + ioreq.irData = &tempDOCDI; + status_HDOC = flDOCHIdentifyDiskOnChipDevice(&ioreq); + pdev->wTotalNumOfPartitions = tempDOCDI.wTotalNumOfPartitions; + + if( status_HDOC==DOCH_OK ) + fDocDriverInitDone = TRUE; + + return (status_HDOC==DOCH_OK)?flOK:((status_HDOC==DOCH_DiskNotFound)?flAdapterNotFound:flGeneralFailure); + } + + DBG_PRINT_ERR(FLZONE_ABS, "flInit(): failed to find mDoc! \r\n\n"); + DBG_PRINT_FLOW(FLZONE_ABS, "\r\n*** Exiting flInit() ***\r\n\n\n"); + + return flAdapterNotFound; +}/* flInit() */ + +#ifdef FL_EXIT + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flExit*/ +/* Description : */ +/* Return type : TFFS_DLL_API void */ +/***********************************************************************************/ +TFFS_DLL_API void NAMING_CONVENTION flExit() +{ + tffsApiExit(); + dochBdCallWasCalled = FALSE; + fDocDriverInitDone = FALSE; +#ifdef CX_ATA_SNIFFER + fclose(ataLogFile); +#endif /*CX_ATA_SNIFFER*/ +}/*flExit()*/ +#endif /*FL_EXIT*/ + +#ifdef FL_ENVIRONMENT_VARS + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flSetEnvVolume */ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLEnvVars variableType */ +/* Argument : FLByte socket */ +/* Argument : FLByte volume */ +/* Argument : FLDword value */ +/* Argument : FLDword FAR2 *prevValue */ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flSetEnvVolume(FLEnvVars variableType, FLByte socket, FLByte volume, + FLDword value, FLDword FAR2 *prevValue) +{ + IOreq ioreq; + + ioreq.irHandle = socket + (volume << 4); + /*For utilities which uses env vars on legacy devices and not needed for H3*/ + if ((variableType == FL_DEBUG_MODES) || + (variableType == FL_SUSPEND_MODE) || + (variableType == FL_DIMAGE_CFG)) + return flOK; + + if(variableType == FL_SET_TRANSFER_MODE) + { + tffsset(&ioreq, 0, sizeof(ioreq)); + /*Fill ioreq structure according to flDOCHSetDataTransferMode API*/ + /*Single sector transfer mode*/ + if(value == 1) + { + ioreq.irCount = DOCH_DATA_XFER_MODE_SINGLE; + } + /*Multi-sector transfer mode*/ + else + { + ioreq.irCount = DOCH_DATA_XFER_MODE_MULT; + ioreq.irLength = value; + } + + /*Set requested Transfer Mode and Length*/ + if (flDOCHSetDataTransferMode(&ioreq) == DOCH_OK) + return flOK; + + /*If the operation failed*/ + return flFeatureNotSupported; + } + else if (variableType == FL_ENV_ATA_DEBUG) + ioreq.irFlags = DOCH_ENV_ATA_DEBUG; + else if(variableType == FL_DISABLE_MEMCPY) + flPreventMemcpy = value; + else + { + switch(variableType) + { +#ifdef FL_VERIFY_WRITE + case FL_VERIFY_WRITE_BDTL: + case FL_VERIFY_WRITE_BINARY: + case FL_VERIFY_WRITE_OTHER: + ioreq.irFlags = DOCH_ENV_VERIFY_WRITE; + break; +#endif /*FL_VERIFY_WRITE*/ +#if (!defined(FL_NO_USE_FUNC) || defined(FL_BD_AUTO_DPD_MODE)) + case FL_SET_AUTO_DPD_MODE: +#ifndef DOCH_AUTO_DPD_BY_HOST + case FL_SET_ACTIVE_DPD_MODE: + case FL_SET_INACTIVE_DPD_MODE: + case FL_SET_TIMEOUT_DPD: +#endif /*DOCH_AUTO_DPD_BY_HOST*/ + return tffsApiSetAutoDpd(variableType, (FLSDword)socket, value, prevValue); +#endif /*(!defined(FL_NO_USE_FUNC) || defined (FL_BD_AUTO_DPD_MODE))*/ + default: + ioreq.irFlags = 0; + }/*switch*/ + } + ioreq.irLength = value; + if (flDOCHSetEnvVar(&ioreq) == DOCH_OK) + return flOK; + return flFeatureNotSupported; +}/*flSetEnvVolume()*/ + + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flSetEnvSocket*/ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLEnvVars variableType*/ +/* Argument : FLByte socket*/ +/* Argument : LDword value*/ +/* Argument : FLDword FAR2 *prevValue*/ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flSetEnvSocket(FLEnvVars variableType, FLByte socket, + FLDword value, FLDword FAR2 *prevValue) +{ + return flSetEnvVolume(variableType, socket, 0, value, prevValue); +}/*flSetEnvSocket()*/ + + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flSetEnvAll */ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLEnvVars variableType */ +/* Argument : FLDword value */ +/* Argument : FLDword FAR2 *prevValue */ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flSetEnvAll( FLEnvVars variableType,FLDword value, + FLDword FAR2 *prevValue) +{ + return flSetEnvVolume(variableType, 0, 0, value, prevValue); +}/*flSetEnvAll*/ +#endif /*FL_ENVIRONMENT_VARS*/ + +#ifndef FL_NO_USE_FUNC + + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flGetDocBusRoutine*/ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLByte socket */ +/* Argument : FLAccessStruct FAR1 * structPtr */ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flGetDocBusRoutine(FLByte socket, FLAccessStruct FAR1 * structPtr) +{ + FLFlash* flash; + + /* Arg sanity check */ +#ifndef FL_SKIP_ARGS_CHECK + if (socket >= FL_SOCKETS) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"ERROR - Change FL_SOCKETS definition in flcustom.h to support that many sockets.\r\n"); + return flFeatureNotSupported; + } + if(structPtr == NULL) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"ERROR - structPtr argument is NULL.\r\n"); + return flBadParameter; + } +#endif /* FL_SKIP_ARGS_CHECK */ + + /* Make sure global variables are initialized to their default values */ + flInitGlobalVars(); + + flash = flFlashOf(socket); + + structPtr->memWindowSize = flash->memWindowSize; + structPtr->memRead = flash->memRead; + structPtr->memWrite = flash->memWrite; + structPtr->memSet = flash->memSet; + structPtr->memRead8bit = flash->memRead8bit; + structPtr->memRead16bit = flash->memRead16bit; + structPtr->memWrite8bit = flash->memWrite8bit; + structPtr->memWrite16bit = flash->memWrite16bit; + structPtr->memSetGetMode = flash->memSetGetMode; + structPtr->access = flBusConfig[socket]; + + return flOK; +}/*flGetDocBusRoutine()*/ + + +/***********************************************************************************/ +/* Function name : NAMING_CONVENTION flSetDocBusRoutine*/ +/* Description : */ +/* Return type : TFFS_DLL_API FLStatus */ +/* Argument : FLByte socket*/ +/* Argument : FLAccessStruct FAR1 * structPtr*/ +/***********************************************************************************/ +TFFS_DLL_API FLStatus NAMING_CONVENTION flSetDocBusRoutine(FLByte socket,FLAccessStruct FAR1 * structPtr) +{ + FLFlash* flash; + + /* Arg sanity check */ +#ifndef FL_SKIP_ARGS_CHECK + if (socket >= FL_SOCKETS) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"ERROR - Change FL_SOCKETS definition in flcustom.h to support that many sockets.\r\n"); + return flFeatureNotSupported; + } + if(structPtr == NULL) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"ERROR - structPtr argument is NULL.\r\n"); + return flBadParameter; + } +#endif /* FL_SKIP_ARGS_CHECK */ + + /* Make sure global variables are initialized to their default values */ + flInitGlobalVars(); + + flash = flFlashOf(socket); + + flash->memWindowSize = structPtr->memWindowSize; + flash->memRead = structPtr->memRead; + flash->memWrite = structPtr->memWrite; + flash->memSet = structPtr->memSet; + flash->memRead8bit = structPtr->memRead8bit; + flash->memRead16bit = structPtr->memRead16bit; + flash->memWrite8bit = structPtr->memWrite8bit; + flash->memWrite16bit = structPtr->memWrite16bit; + flash->memSetGetMode = structPtr->memSetGetMode; + flBusConfig[socket] = FL_ACCESS_USER_DEFINED; + return flOK; +}/*flSetDocBusRoutine*/ + +#endif /*FL_NO_USE_FUNC*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +/* ----------------------------------------------------------------------------------- */ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch-firmware/Makefile b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch-firmware/Makefile new file mode 100755 index 00000000..86fbe11d --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch-firmware/Makefile @@ -0,0 +1,72 @@ +#================================================================================ +# +# Makefile for 'doch-firmware' (mDOC firmware upgrade) application. +# +#================================================================================ +# +# Copyright (C) 2006 msystems Ltd. 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 msystems nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#=============================================================================== + + +# +# Specify path to usr/include as appropriate +# for your installation. +# +INCLUDE_DIR = /opt/ti/omap2420/rootfs-mvlcee31/usr/include + +# +# Specify compiler as appropriate for your installation. +# Default is ARM/GCC compiler. +# +CC = arm-unknown-linux-gnu-gcc + +# +# Specify compiler flags. +# +CFLAGS += -I$(INCLUDE_DIR) +CFLAGS += -I.. +CFLAGS += -Wall +# CFLAGS += -g + +# +# 'make all' rule +# +all : doch-firmware + +# +# make 'ioctl-example' demo application +# +doch-firmware : doch-firmware.c + $(CC) $(CFLAGS) -o $@ $< + +# +# 'make clean' rule +# +clean : + rm -f *.o doch-firmware + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch-firmware/doch-firmware.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch-firmware/doch-firmware.c new file mode 100755 index 00000000..06e41078 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch-firmware/doch-firmware.c @@ -0,0 +1,206 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2006, msystems Ltd. 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 msystems nor the names of its contributors may be */ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/******************************************************************************/ + +/*********************************************************************************** + * * + * This utility program updates firmware in mDOC H3 devices. It takes two * + * parameters: name of mDOC's device file (for example /dev/tffsa), and name * + * of mDOC firmware file (for example, "image.enc-0050"). Here is an example: * + * * + * doch-firmware /dev/tffsa image.enc-0050 * + * * + ***********************************************************************************/ + + +/* + * $Log$ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "tffsioct.h" + + + + +#ifndef FL_SECTOR_SIZE +# define FL_SECTOR_SIZE 512 +#endif + + + +/* + * Calculate simple checksum on buffer 'buf' containing 'buf_size' bytes. + * We expect 'buf_size' to be multiple of 4. + */ +static +unsigned long chksum (unsigned long * buf, int buf_size) +{ + register unsigned long s = 0; + register int n; + + assert ((buf != NULL) && ((buf_size % sizeof(long)) == 0)); + + for (n = ((buf_size / sizeof(long)) - 1); n >= 0; n--) + s ^= buf[n]; + + return s; +} + + + + +/* + * Write firmware to DiskOnChip via IOCTL call to DiskOnChip driver. + * We expect 'buf_size' to be multiple of sector size. + */ +static +int write_firmware (int fd, void * buf, int buf_size) +{ + flIOctlRecord ioctl_record; + flInputLnxRecord in; + flOutputLnxRecord out; + flAtaPassthrough ata_passthrough; + int rc; + + assert (buf != NULL); + assert ((buf_size % FL_SECTOR_SIZE) == 0); /* must be multiple of sector size */ + assert ((buf_size / FL_SECTOR_SIZE) <= 256); /* max 256 sectors at once */ + + ioctl_record.inputRecord = ∈ + ioctl_record.outputRecord = &out; + + in.command = 5; /* ATA pass through command */ + in.data = (unsigned long) &ata_passthrough; + + out.data = (unsigned long) NULL; + + memset (&ata_passthrough, 0, sizeof(ata_passthrough)); + ata_passthrough.socketNum = 0; + ata_passthrough.userBuff = buf; + ata_passthrough.userBuffSize = buf_size; + ata_passthrough.secNum = (buf_size / FL_SECTOR_SIZE); + ata_passthrough.passThruOP = DOCH_PASSTHRU_DATA_OUT; + ata_passthrough.in_regs.bCommandStatus = DOCH_DOWNLOAD_MICROCODE; + ata_passthrough.in_regs.bFeaturesError = DOCH_DLMCODE_DOWNLOAD_AND_SAVE; + ata_passthrough.in_regs.bSectorCount = (unsigned char) (buf_size / FL_SECTOR_SIZE); + ata_passthrough.in_regs.bSectorNumber = (unsigned char)((buf_size / FL_SECTOR_SIZE) >> 8); + + rc = ioctl (fd, FL_IOCTL_LNX, &ioctl_record); + if ((rc != 0) || (ata_passthrough.status != 0)) + { + fprintf (stderr, "Error %d writing DiskOnChip firmware\n", (int)out.status); + rc = -1; + } + else + fprintf (stdout, "Success writing DiskOnChip firmware\n"); + + return rc; +} + + + + +/* + * Main + */ +int main ( int argc, char * argv[] ) +{ + int fd; + void * buf; + int buf_size; + int rc = -1; + + /* arg check */ + if ((argc != 3) || (argv[1] == NULL) || (strlen(argv[1]) == 0) || + (argv[2] == NULL) || (strlen(argv[2]) == 0)) + { + fprintf (stderr, "Usage: doch-firmware \n"); + fprintf (stderr, "Example: doch-firmware /dev/tffsa image.enc-0050\n"); + exit (-1); + } + + /* open firmware file */ + if((fd = open(argv[2], O_RDONLY)) == -1) + { perror ("Can't open firmware file"); exit (-1); } + + /* find out size of firmware file */ + if ((buf_size = lseek(fd, 0, SEEK_END)) == -1) + { perror ("Can't determine size of firmware file"); exit (-1); } + + /* set file pointer back to start of firmware file */ + if( lseek(fd, 0, SEEK_SET) != 0) + { perror ("Can't rewind firmware file"); exit (-1); } + + /* allocate buffer to hold firmware file's contents, and clear it */ + if ((buf = calloc(buf_size + FL_SECTOR_SIZE, sizeof(char))) == NULL) + { perror ("Can't allocate memory"); exit (-1); } + + /* read firmware file into the buffer */ + if( read(fd, buf, buf_size) != buf_size ) + { perror ("Can't read firmware file"); exit (-1); } + + /* close firmware file */ + close (fd); + + /* round up 'buf_size' to multiple of FL_SECTOR_SIZE */ + buf_size = (((buf_size - 1) / FL_SECTOR_SIZE) + 1) * FL_SECTOR_SIZE; + + if ((buf_size / FL_SECTOR_SIZE) > 256) + { perror ("Firmware file too large"); free (buf); exit (-1); } + + /* calculate checksum on the buffer */ + fprintf (stdout, "Firmware file checksum 0x%lx\n", chksum(buf, buf_size)); + + /* open device file */ + if((fd = open(argv[1], O_RDWR)) == -1) + { perror ("Can't open device"); free (buf); exit (-1); } + + /* issue IOCTL to device */ + rc = write_firmware (fd, buf, buf_size); + + /* close device file */ + close (fd); + + /* clear and free allocated buffer */ + memset (buf, 0, buf_size); + free (buf); + + fprintf (stdout, "Reset DiskOnChip to activate new firmware\n"); + + exit (rc); +} diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_api.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_api.c new file mode 100755 index 00000000..afedb796 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_api.c @@ -0,0 +1,9149 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_api.c-arc $ + * + * Rev 1.82 Dec 26 2007 10:12:52 einat.avidan + * add flow printout for verify write + * dochATAReset() - update delay required + * doch_reset() does not include waiting before reset + * doch_reset() fixed bug (waiting for both floors to be ready after reset) + * + * Rev 1.81 Dec 16 2007 11:35:20 einat.avidan + * add debug printout + * + * Rev 1.80 Dec 11 2007 12:26:08 einat.avidan + * init sequence and DOCHConfigHW: change parameters of internal functions + * + * Rev 1.79 Dec 04 2007 17:54:20 einat.avidan + * Remove flDOCHWipeSectorsByWriting + * Change algorithm of DOCHWipeSectors and for AUTO_WIPE_SECTORS + * Bug fix: verify write on cascaded device. + * Bug fix: DochRecoverFromPowerLoss + * + * Rev 1.78 Oct 30 2007 16:13:54 einat.avidan + * add new function flDOCHWipeSectorsByWriting + * bug fix: DOCHDeletePartitions migth access second floor even + * if it does not exist. + * DOCHAddPartition: add support in fast area in cascaded configuration + * add new function DOCHWipeSectorsByWriting + * + * Rev 1.77 Oct 23 2007 15:32:10 einat.avidan + * fix compilation warnings + * + * Rev 1.76 Oct 23 2007 12:27:52 einat.avidan + * optimization: delay after setting head register only + * when switching floors + * + * Rev 1.75 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.74 Oct 21 2007 10:27:32 Einat.Avidan + * bug fix: reported fast area on spanned partition + * set LBA bit on device head register + * fix compilation warnings + * + * Rev 1.73 Oct 11 2007 18:48:02 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * fix printouts + * add compilation flags for SOTP and SLPP + * support cascaded configuration: add delay after device switch + * Interrupts are enabeled\ disabeled in the ATA level instead of API level + * DOCHReadPartitionSectorsSingleFloor was added + * DOCHWritePartitionSectorsSingleFloor was added + * in every write to drive head register set LBA bit. + * + * Rev 1.72 Sep 04 2007 15:28:18 einat.avidan + * fix printouts + * avoid locking OTP when passed length (in sectors) is zero + * + * Rev 1.71 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.70 Mar 22 2007 17:12:10 einat.avidan + * add SOTP + * + * Rev 1.69 Mar 13 2007 13:47:20 einat.avidan + * add support for SLPP + * + * Rev 1.68 Mar 11 2007 16:28:46 einat.avidan + * bug fix: update number of partitions when spanned partition that does not cover whole media was added + * bug fix: internal API flDOCHAtaReset may cause confusion in the XIP window identification. + * + * Rev 1.67 Feb 28 2007 10:32:28 einat.avidan + * bug fix: scr 2255 Compatibility on Big\Little Endian + * bug fix: during flInit device head register was changed to Slave, even if MAX_ATA_DEVICES is 1. + * may cause a bug during boot. + * bug fix: internal API flDOCHAtaReset may cause confusion in the XIP window identification. + * + * Rev 1.66 Feb 15 2007 17:42:06 Einat.Avidan + * add support for DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + * + * Rev 1.65 Dec 05 2006 14:59:28 Yaniv.Iarovici + * Fix bug in auto secure-wipe mechanism. + * + * Rev 1.64 Dec 03 2006 15:38:56 Yaniv.Iarovici + * Fixed compilation warning + * + * Rev 1.63 Dec 03 2006 13:31:24 Yaniv.Iarovici + * Encapsulate auto wipe-sector operation for Dev1 under '#ifndef DOCH_NO_AUTO_WIPE_SECTORS_DEV1' + * + * Rev 1.62 Nov 30 2006 10:23:36 Yaniv.Iarovici + * 1. Fixed compilation warnings. + * 2. Added SDK level secure-wipe power-failure immunity. + * 3. Fixed flDOCHAtaReset in case of cascaded configuration. + * + * Rev 1.61 Nov 21 2006 14:26:14 Yaniv.Iarovici + * 1. Fixed IRQ handling in case of cascaded configuration. + * 2. Fixed OTW setting of a partition residing on Dev1 (cascaded configuration). + * + * Rev 1.60 Nov 12 2006 09:46:42 Yaniv.Iarovici + * Modify parameter list of doch_reset(). + * + * Rev 1.59 Oct 31 2006 12:23:22 yaniv.iarovici + * Search for the current window after resetting Dev0 in flDOCHAtaReset(). + * + * Rev 1.58 Oct 30 2006 15:50:24 yaniv.iarovici + * Add call to DOCHAddPartition() after creating spanned partition + * for updating actual number of partitions. + * + * Rev 1.57 Oct 25 2006 09:10:26 Yaniv.Iarovici + * Fix for cascaded scenario in which last partition on dev0 is NOT spanned, and is RW protected. + * + * Rev 1.56 Oct 05 2006 11:00:28 yaniv.iarovici + * 1. Retrieve MAX DRQ supported by the device. + * 2. Check that requested DRQ size is supported by the device. + * 3. Remove verify write option from DOCHWriteIPLSingleFloor(). + * + * Rev 1.55 Sep 14 2006 09:56:30 yaniv.iarovici + * DOCHSetCustomParameterSingleFloor() to return DOCH_ProtectionFault in case of protection violation. + * + * Rev 1.54 Sep 13 2006 10:30:46 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.53 Sep 11 2006 13:45:14 yaniv.iarovici + * Legal header added + * + * Rev 1.52 Sep 10 2006 10:03:14 Yaniv.Iarovici + * 1. Bug Fix: Calculation of total number of partitions in DOCHIdentifyDiskOnChipDevice() in cascaded configuration, when last partition on Dev0 fills the first floor entirely. + * + * 2. Bug Fix: Support creation of Read protected partition which is spanned on both devices in cascaded configuration. + * + * 3. Bug Fix: Setting configuration register values to Dev1 in cascaded configuration (DOCHConfigHW()). + * + * Rev 1.51 Sep 03 2006 14:44:22 Yaniv.Iarovici + * 1. Fixed logic of setting bLastDev0PartSpanned in case last partition on Dev0 fills entire Dev0. (Cascaded configuration) + * 2. Preserve current OTW setting when changing protection type. (Can only be set by AddPartition) + * + * Rev 1.50 Aug 24 2006 11:40:46 Yaniv.Iarovici + * API Change to following protection related routines: + * - DOCHAccessPartWithPwdSingleFloor + * - DOCHDisablePartAccessSingleFloor + * - DOCHSendHostPublicKey + * - DOCHReceiveDochPublicKey + * - DOCHVerifyHostKey + * (The change differs DOCH_ACCESS_ALL_PARTITIONS flag from partition number field + * in ioreq) + * + * Rev 1.49 Aug 22 2006 13:23:36 Yaniv.Iarovici + * 1) Bug fix: 'pdev->bAtaDevNum' was not recovered correctly to 'origDevNum' (multiple places) + * 2) In DOCHWriteIPLSingleFloor(), set rc = DOCH_OK at decleration, to prevent compilation warning + * 3) Bug fix: flDOCHAddPartition - Cascaded configuration + * + * Rev 1.48 Aug 16 2006 08:44:18 Yaniv.Iarovici + * 1) Fix bdCallDOCH() Description + * 2) Check if ETFFS was identified on the device - if not, return 'DOCH_FeatureNotSupported' + * 2) Free MUTEX before returning error when (gDochAccessNanosec == 0) is detected + * 3) Check that Multi-sector transfer mode does not exceed max allowed in DOCHSetDataTransferModeSingleFloor() + * 4) Set pdev->device[devNum].ETFFS_Identified = TRUE adfter a SUCCESSFULL completion of DOCHIdentifyDiskOnChipDeviceSingleFloor() + * 5) Remove unneccesary code from DOCHGetResetStatus() + * 6) Reset pdev->bAtaDevNum to original value upon failure (various places in the code) + * 7) Check that pdev is valid in the various routines + * 8) Change description of DOCHGetPowerMode() and DOCHSetPowerMode() to fit SW Spec 0.84 + * + * Rev 1.47 Aug 09 2006 17:26:50 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#include "flchkdef.h" +#include "flsystyp.h" +#include "flcommon.h" +#include "flsysfun.h" +#include "doch_func.h" +#include "doch_ata.h" +#include "flstdcmp.h" +#include "hib.h" +#include "part_inf.h" +#include "dochtl.h" +#ifdef FL_MIGRATION_VERSION +#include "docsys.h" +#endif /* FL_MIGRATION_VERSION */ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************************************************************/ +/* + * Global variables + */ +/******************************************************************************/ + +/* NOTE: Global variables with "boolean like" behavior are set to a unique pattern (DOCH_GLOBAL_BOOL_PATTERN) + to indicate them as "TRUE" */ +#ifdef FL_VERIFY_WRITE +FLByte gDochVerifyWrite[DOCH_MAX_SOCKETS]; /*Indicates to perform verify operation on every written sector to the specified socket*/ +#endif /*FL_VERIFY_WRITE*/ +FLByte gDochAtaDebug = 0; /*Indicates to retrieve ATA debug buffer upon completion of ATA command */ + +FLByte gSdkInitDone = 0; /*Indicates that DochSDKInit() was completed */ + +FLByte gSdkDOCAddressObtained = 0; /*Indicates that DOC address was obtained (used by DOCHConfigHW) */ + +FLDword gConfigHWDefaults[DOCH_NUM_OF_DCONFIGHW_ITEMS]; +FLByte gConfigHWInitDone = 0; /*Indicates that gConfigHWDefaults[] was set to defaults */ + +FLDword gIPLChunkOffsetInSectors = 0; /*Offset of current IPL chunk to write*/ + +FLByte gSDKUpdatesDiskAttributes = 0; /*Indication that first 0x40 bytes of disk user attributes should be written as well*/ + +FLByte gIsDMAEnabled = 0; /*DMA is Enabled/Disabled*/ + +FLByte gAutoDPDByHost = 0; /*Host enters device to DPD automatically after every command*/ + +FLBoolean gDochIrqEnabled[DOCH_MAX_SOCKETS]; /* holds TRUE, when interrupt enable for socket, FALSE otherwise */ + +extern FLDword gAccessLayerType; + +extern FLByte gATANoTimeout; + +#ifdef DOCH_DMA_CONFIG +extern FLByte gDMAChannelOpen; +#endif /*DOCH_DMA_CONFIG*/ + +extern DOCH_DpdSettings gDpdSettings; + +extern DOCH_Socket sockets [DOCH_MAX_SOCKETS]; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +extern FLByte gDeviceTurnedOff; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +extern FLDword gUseShortWaitOnBusy; + +#ifdef DEBUG_TIMEOUT +extern FLDword SysTimerFrequency; +extern void GetInternalSysTimer(FLDword * ticksHigh, FLDword * ticksLow); +#endif /*DEBUG_TIMEOUT*/ + +/******************************************************************************/ +/* + * Extern routines + */ +/******************************************************************************/ + +extern DOCH_Error io_input(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs, void *buf, FLNative secNum); +extern DOCH_Error io_output(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs, void *buf, FLNative secNum); +extern DOCH_Error get_out_registers(DOCH_Socket* pdev, FLSNative devNum, DOCH_Registers* out_regs); + +void DOCH_SetBits(FLDword* var, FLDword mask, FLByte offset, FLDword val) +{ + FLDword temp = *var; + + + temp &= ~(mask); + temp |= (val << offset); + + *var = temp; +} + +extern DOCH_Error dochSetMutex(FLByte socketNum, + FLBoolean state, + FLByte partition); + +/******************************************************************************/ +/* + * Static routines + */ +/******************************************************************************/ +static DOCH_Error performSectorsOperation(DOCH_Command cmd, + FLByte devHeadOptions, + DOCH_Socket* pdev, + IOreq* ioreq, + DOCH_Registers* out_regs, + FLSNative sectorsToPerfrom, + FLSNative * sectorNumber, + FLSNative * totalNumOfSectors, + FLSNative * sectorsPerformed, + FLSNative * buf_offset, + FLByte* buf_ptr); + + +#ifdef DOCH_BIG_ENDIAN +static FLWord be_FLWord (FLByte * v); +static FLDword be_FLDword (FLByte * v); +#endif /*DOCH_BIG_ENDIAN*/ + +DOCH_Error DOCHGetParitionUserAttributesSingleFloor(IOreq* ioreq); +DOCH_Error DOCHAccessPartWithPwdSingleFloor(IOreq* ioreq); +DOCH_Error DOCHSetParitionProtectionSingleFloor(IOreq* ioreq); + +/******************************************************************************/ +/* + * Static Buffers + */ +/******************************************************************************/ +static DOCH_PartitionFormatInfo partFormatInfo; +static DOCH_DeviceInfo diskOnChipDeviceInfo; +static DOCH_DeviceInfo diskOnChipDeviceInfo2; +static DOCH_DeviceUserAttr devUserAttr; +static DOCH_PartitionInfo partitionInfoTemp; +static DOCH_PartitionFormatInfoAPI partInfoTemp; +static DOCH_PartitionProtectionAPI protAPI; +static DOCH_PartitionAcessPassword partAccessTemp; +static FLByte currentAttributes[DOCH_SECTOR_SIZE]; +#ifdef FL_VERIFY_WRITE +static FLByte verifyBuf[DOCH_SECTOR_SIZE]; +#endif /*FL_VERIFY_WRITE*/ +static FLDword wipeSectorsDev[((2*DOCH_SECTOR_SIZE) / sizeof(FLDword))]; + +/******************************************************************************/ +/* + * Local MACROs + */ +/******************************************************************************/ +#ifdef DOCH_DMA_CONFIG +#define DOCH_OPEN_DMA_CHANNEL \ + { \ + DMA_Params_S dmaParams; \ + \ + if(pdev->bUseDMA && (gDMAChannelOpen == 0)) \ + { \ + dmaParams.bOpType = DOCH_DMA_OPEN_CHANNEL; \ + DOCH_DMA_CONFIG(&dmaParams); \ + if(dmaParams.fDmaStatus != 0) \ + { \ + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("DOCH_DMA_OPEN_CHANNEL Failed with dmaStatus: %d \r\n"),dmaParams.fDmaStatus)); \ + return DOCH_GeneralFailure; \ + } \ + \ + gDMAChannelOpen = DOCH_GLOBAL_BOOL_PATTERN; \ + \ + DBG_PRINT_FLOW(FLZONE_API, "\r\nDMA Channel opened\r\n"); \ + } \ + } +#endif /*DOCH_DMA_CONFIG*/ + +#define DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, sectorNumber, deviceNum) \ + addr_vals.bSecNum = (FLByte) sectorNumber; \ + addr_vals.bCylLow = (FLByte) (sectorNumber >> 8); \ + addr_vals.bCylHi = (FLByte) (sectorNumber >> 16); \ + addr_vals.bDevHead = (FLByte) (((sectorNumber >> 24) & 0x0f) | DOCH_LBA | (deviceNum<<4)); + + +#define DOCH_PARTITION_ON_DEV0 \ + ((!pdev->sSpanData.secondFloorActive) || (partNum < pdev->sSpanData.bLastPartitionOnDev0) || \ + ((partNum == pdev->sSpanData.bLastPartitionOnDev0) && (!pdev->sSpanData.bLastDev0PartSpanned))) + +#define DOCH_PARTITION_ON_DEV1 \ + (((pdev->sSpanData.secondFloorActive) && (partNum > pdev->sSpanData.bLastPartitionOnDev0)) \ + && (pdev->wNumOfDevices > 1)) + +#define DOCH_PARTITION_IS_SPANNED \ + (((pdev->sSpanData.bLastDev0PartSpanned) && (partNum == pdev->sSpanData.numOfSpannedPartitionOnDev0)) \ + && (pdev->wNumOfDevices > 1)) + +/*----------------------------------------------------------------------*/ +/* p e r f o r m S e c t o r O p e r a t i o n */ +/* */ +/* Performs sector(s) operation */ +/* */ +/* Parameters: */ +/* cmd : ATA command to perform */ +/* pdev : Socket to perform on */ +/* ioreq : IOreq */ +/* totalNumOfSectors : Total num of sectors to perform */ +/* sectorsPerformed : Num of sectors actually performed */ +/* */ +/* Returns: */ +/* device head with proper bit */ +/*----------------------------------------------------------------------*/ +static +DOCH_Error performSectorsOperation(DOCH_Command cmd, + FLByte devHeadOptions, + DOCH_Socket* pdev, + IOreq* ioreq, + DOCH_Registers* out_regs, + FLSNative sectorsToPerfrom, + FLSNative * sectorNumber, + FLSNative * totalNumOfSectors, + FLSNative * sectorsPerformed, + FLSNative * buf_offset, + FLByte* buf_ptr) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + Addressing_Values_s addr_vals; + + /*Perform 1 operation cycle*/ + /*=========================*/ + + /*Set ATA addressing registers*/ + /*---------------------------*/ + DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, (*sectorNumber), (pdev->bAtaDevNum)); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + if(sectorsToPerfrom < DOCH_MAX_SECTORS) + in_regs.bSectorCount = sectorsToPerfrom; + else + in_regs.bSectorCount = 0; /*DOCH_MAX_SECTORS*/ + + in_regs.bSectorNumber = addr_vals.bSecNum; + in_regs.bCylLow = addr_vals.bCylLow; + in_regs.bCylHigh = addr_vals.bCylHi; + in_regs.bDriveHead = addr_vals.bDevHead | devHeadOptions; + in_regs.bCommandStatus = cmd; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + out_regs, + (void*)(&buf_ptr[*buf_offset]), + sectorsToPerfrom); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "performSectorsOperation(): ATA Error: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + DBG_PRINT_ERR(FLZONE_API, "\r\n"); + + return rc; + } + + /*Update feedback values*/ + /*----------------------*/ + *sectorsPerformed += out_regs->bSectorCount; + + /*For next possible cycle*/ + /*-----------------------*/ + *sectorNumber += sectorsToPerfrom; + *totalNumOfSectors -= sectorsToPerfrom; + *buf_offset += sectorsToPerfrom * DOCH_SECTOR_SIZE; + + return DOCH_OK; +} + +#ifdef DOCH_BIG_ENDIAN +/****************************************************************************** + * * + * be _ s h o r t * + * be _ l o n g * + * * + * Little-to-CPU-native integer conversion routines for big-endian CPUs. * + * * + * Parameters : * + * v : correctly aligned little endian value * + * Returns : * + * value in CPU native format * + * * + ******************************************************************************/ + +static +FLWord be_FLWord (FLByte * v) +{ + register FLWord x = *((FLWord *)v); + return ((x >> 8) | (x << 8)); +} + +static +FLDword be_FLDword (FLByte * v) +{ + register FLDword x = *((FLDword *)v); + return ((x >> 24) | ((x >> 8) & 0x0000ff00) | + ((x << 8) & 0x00ff0000) | (x << 24)); +} +#endif /*DOCH_BIG_ENDIAN*/ + +/******************************************************************************/ +/* + * DOCH SDK API Routines + */ +/******************************************************************************/ + +/*----------------------------------------------------------------------*/ +/* b d C a l l D O C H */ +/* */ +/* Performs needed general operations before calling actual function */ +/* Calls appropriate DOCH function */ +/* */ +/* Parameters: */ +/* functionNo : DOCH SDK function to run */ +/* ioreq : DOCH ioreq structure */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error bdCallDOCH(FLSNative functionNo, IOreq FAR2 *ioreq) +{ + DOCH_Error rc; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* gDeviceTurnedOff will be updated by API routines*/ + gDeviceTurnedOff = FALSE; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /*If ETFFS wasnt identified, prevent using bdCallDOCH()*/ + if(!sockets[DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)].device[0].ETFFS_Identified) + return DOCH_FeatureNotSupported; + + /* Take mutex for current device */ + rc = dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_ON, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallDOCH(): dochSetMutex failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + return rc; + } + + /*Check if requested operation is wither Read or Write which are performance critical + (All other operations are directed from within the switch case) + -------------------------------------------------------------*/ + if(functionNo == SDK_READ_PARTITION_SECTORS) + { + rc = DOCHReadPartitionSectors(ioreq); + } + else if (functionNo == SDK_WRITE_PARTITION_SECTORS) + { + rc = DOCHWritePartitionSectors(ioreq); + } + else + { + /*Branch to appropriate DOCH routine according to function#*/ + /*---------------------------------------------------------*/ + switch (functionNo) + { + /*Get Info*/ + case SDK_IDENTIFY_DISKONCHIP_DEVICE: + rc = DOCHIdentifyDiskOnChipDevice(ioreq); + break; + + case SDK_GET_RESET_STATUS: + rc = DOCHGetResetStatus(ioreq); + break; + + case SDK_NOTIFY_RESET: + rc = DOCHNotifyReset(ioreq); + break; + + case SDK_NOTIFY_PLATFORM_RESUMED: + rc = DOCHNotifyPlatformResumed(ioreq); + break; + + case SDK_GET_PARTITION_INFO: + rc = DOCHPartitionInfo(ioreq); + break; + + case SDK_SET_DISK_USER_ATTR: + rc = DOCHSetDiskUserAttributes(ioreq); + break; + + case SDK_GET_DISK_USER_ATTR: + rc = DOCHGetDiskUserAttributes(ioreq); + break; + + case SDK_GET_CONFIG_DATA: + rc = DOCHGetConfigurationData(ioreq); + break; + + case SDK_SET_CONFIG_DATA: + rc = DOCHSetConfigurationData(ioreq); + break; + + /*Media*/ + case SDK_SET_DEFAULT_PARTITION: + rc = DOCHSetDefaultPartition(ioreq); + break; + + case SDK_SET_DATA_XFER_MODE: + rc = DOCHSetDataTransferMode(ioreq); + break; + + case SDK_OPTIMIZE_MEDIA: + rc = DOCHOptimizeMedia(ioreq); + break; + + case SDK_DELETE_PARTITIONS: + rc = DOCHDeletePartitions(ioreq); + break; + + case SDK_ADD_PARTITION: + rc = DOCHAddPartition(ioreq); + break; + + case SDK_UNFORMAT_DEVICE: + rc = DOCHUnformatDevice(ioreq); + break; + + case SDK_WRITE_IPL: + rc = DOCHWriteIPL(ioreq); + break; + + case SDK_READ_IPL: + rc = DOCHReadIPL(ioreq); + break; + + /*IO*/ + case SDK_WRITE_AND_LOCK: + rc = DOCHWriteAndLock(ioreq); + break; + + case SDK_WIPE_SECTORS: + rc = DOCHWipeSectors(ioreq); + break; + + case SDK_FREE_SECTORS: + rc = DOCHFreeSectors(ioreq); + break; + + case SDK_PREPARE_FOR_WRITE: + rc = DOCHPrepareForWrite(ioreq); + break; + +#if 0 + /*Flexi-Flash*/ + case SDK_WRITE_FLEXI_FAST: + rc = DOCHWriteFlexiFast(ioreq); + break; + + case SDK_WRITE_FLEXI_NORMAL: + rc = DOCHWriteFlexiNormal(ioreq); + break; + + case SDK_REWRITE_FLEXI_NORMAL: + rc = DOCHReWriteFlexiNormal(ioreq); + break; +#endif /*0*/ + + /*Protection*/ + case SDK_ACCESS_PART_WITH_PWD: + rc = DOCHAccessPartWithPwd(ioreq); + break; + + case SDK_DISABLE_PART_ACCESS: + rc = DOCHDisablePartAccess(ioreq); + break; + + case SDK_SET_PART_PROTECTION: + rc = DOCHSetParitionProtection(ioreq); + break; + +#if 0 + /*PKI*/ + case SDK_PKI_HOST: + rc = DOCHSendHostPublicKey(ioreq); + break; + + case SDK_PKI_DOCH: + rc = DOCHReceiveDochPublicKey(ioreq); + break; + + case SDK_PKI_VERIFY_HOST_KEY: + rc = DOCHVerifyHostKey(ioreq); + break; +#endif /*0*/ + + /*Custom Parameters*/ + case SDK_GET_CUSTOM_PARAM: + rc = DOCHGetCustomParameter(ioreq); + break; + + case SDK_SET_CUSTOM_PARAM: + rc = DOCHSetCustomParameter(ioreq); + break; + +#if 0 + /*Atomic Read/Write Sequence*/ + case SDK_ATOMIC_WRITE_SEQ: + rc = DOCHManageAtomicWriteSeq(ioreq); + break; + + /*Algorithms*/ + case SDK_REPORT_SUPP_ALG: + rc = DOCHReportSupportedAlgorithms(ioreq); + break; + + case SDK_REPORT_ALG_CAPAB: + rc = DOCHGetAlgorithmCapabilities(ioreq); + break; + + case SDK_SET_ALG_MODE: + rc = DOCHSetAlgorithmMode(ioreq); + break; + + /*Hash*/ + case SDK_AUTO_HASH_CTRL: + rc = DOCHAutoHashControl(ioreq); + break; + + case SDK_READ_CALC_HASH: + rc = DOCHReadCalculatedHash(ioreq); + break; + + case SDK_WRITE_CALC_HASH: + rc = DOCHWriteCalculatedHash(ioreq); + break; + + case SDK_READ_ORIG_HASH: + rc = DOCHReadOriginalHash(ioreq); + break; + + case SDK_WRITE_GIVEN_HASH: + rc = DOCHWriteGivenHash(ioreq); + break; + + case SDK_START_HASH_STREAM_CALC: + rc = DOCHStartHashStreamCalculation(ioreq); + break; + + case SDK_READ_HASH_STREAM_CALC: + rc = DOCHReadStopHashStreamCalc(ioreq); + break; + + case SDK_RETURN_RAND_NUMS: + rc = DOCHReturnRandomNumbers(ioreq); + break; + + case SDK_SET_HASH_KEY: + rc = DOCHSetHashKey(ioreq); + break; + +#endif /*0*/ + + /*General*/ + case SDK_SET_PART_USER_ATTR: + rc = DOCHSetParitionUserAttributes(ioreq); + break; + + case SDK_GET_PART_USER_ATTR: + rc = DOCHGetParitionUserAttributes(ioreq); + break; + + case SDK_SET_POWER_MODE: + rc = DOCHSetPowerMode(ioreq); + break; + + case SDK_GET_POWER_MODE: + rc = DOCHGetPowerMode(ioreq); + break; + + case SDK_HW_CONFIG: + rc = DOCHConfigHW(ioreq); + break; + + case SDK_RECOVER_FROM_POWER_LOSS: + rc = DOCHRecoverFromPowerLoss(ioreq); + break; + + case SDK_CLEAR_ATA_INTERRUPT: + rc = DOCHClearIRQ(ioreq); + break; + + case SDK_GET_PHYSICAL_ADDRESS: + rc = DOCHGetPhysicalAddress(ioreq); + break; + +#ifdef FL_SLPP + case SDK_SLPP_UNLOCK_RANGE: + rc = DOCHSLPPUnlockRange(ioreq); + break; + + case SDK_SLPP_UNLOCK_ENTIRE_PARTITION: + rc = DOCHSLPPUnlockEntirePartition(ioreq); + break; + + case SDK_SLPP_LOCK_RANGE: + rc = DOCHSLPPLockRange(ioreq); + break; + + case SDK_SLPP_STICKY_LOCK_RANGE: + rc = DOCHSLPPStickyLockRange(ioreq); + break; + + case SDK_SLPP_REPORT_LOCKED_RANGES: + rc = DOCHSLPPReportLockedRanges(ioreq); + break; +#endif /*FL_SLPP*/ + + default: + rc = DOCH_FeatureNotSupported; + break; + } + } + +#ifdef DOCH_AUTO_DPD_BY_HOST + if(gAutoDPDByHost == DOCH_GLOBAL_BOOL_PATTERN) + { + FLDword tries; + DOCH_Socket* pdev; + FLDword i; + FLByte status; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + { + /* Free mutex for current device */ + dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_OFF, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + + return DOCH_BadParameter; + } + tries = (DOCH_SHORT_WAIT * (1000000UL / gDochAccessNanosec)); + + /*Check if socket is registered*/ + if(pdev != NULL) + { + /*Enter dev0 to DPD mode*/ + /*----------------------*/ + /*Set device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + /*Set device to inactive mode*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (DOCH_PM_SET_NONE | DOCH_PM_INACTIVE_MODE)); + + /*Invoke command*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, DOCH_SET_POWER_MODE); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, DOCH_VSCMD_EXT_DEVICE_CTRL); + + /*Wait for Dev0 to become ready*/ + for(i=0; ibRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + goto doch_Dev0_DPD_OK; + } + +doch_Dev0_DPD_OK: + + if(pdev->wNumOfDevices > 1) + { + /*Enter dev1 to DPD mode*/ + /*----------------------*/ + /*Set device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV1); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,1); + /*Set device to inactive mode*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (DOCH_PM_SET_NONE | DOCH_PM_INACTIVE_MODE)); + + /*Invoke command*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, DOCH_SET_POWER_MODE); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, DOCH_VSCMD_EXT_DEVICE_CTRL); + + /*Wait for Dev1 to become ready*/ + for(i=0; ibRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + goto doch_Dev1_DPD_OK; + } + +doch_Dev1_DPD_OK: + /*Do Nothing*/; + } + } + } +#endif /*DOCH_AUTO_DPD_BY_HOST*/ + + /* Free mutex for current device */ + dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_OFF, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + return DOCH_DeviceTurnedOff; + } +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t D e f a u l t P a r t i t i o n */ +/* */ +/* Set default partition for Standard-ATA commands */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : SET_DEFAULT_PARTITION_TEMP */ +/* SET_DEFAULT_PARTITION_PERM */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_DEFAULT_PARTITION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetDefaultPartition(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte dev_head_opt; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == SET_DEFAULT_PARTITION_PERM) + dev_head_opt = PERM_DEFAULT_PART_OP; + else + dev_head_opt = 0; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_DEFAULT_PARTITION; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum) | (dev_head_opt)); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetDefaultPartition(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t D a t a T r a n s f e r M o d e */ +/* */ +/* Set Data transfer mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Requested data transfer mode: */ +/* DOCH_DATA_XFER_MODE_SINGLE */ +/* DOCH_DATA_XFER_MODE_MULT */ +/* irLength : In case of DOCH_DATA_XFER_MODE_MULT, */ +/* specifies DRQ block size */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_DATA_XFER_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetDataTransferModeSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_TransferMode requstedXferMode = (DOCH_TransferMode)(ioreq->irCount); + FLByte requestedDrqSize = (FLByte)(ioreq->irLength); + FLSNative socketNum = DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq); + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, socketNum); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check that Multi-sector transfer mode does not exceed max allowed*/ + if((ioreq->irCount == DOCH_DATA_XFER_MODE_MULT) && + ((ioreq->irLength > DOCH_MAX_DRQ_SUPPORTED) || + (ioreq->irLength > (FLSDword)pdev->device[pdev->bAtaDevNum].dwMulti_MAX)) + ) + return DOCH_FeatureNotSupported; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_DATA_XFER_MODE; + in_regs.bSectorCount = (FLByte)(ioreq->irCount); + if(ioreq->irCount == DOCH_DATA_XFER_MODE_MULT) + in_regs.bSectorNumber = (FLByte)(ioreq->irLength); + else + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead =DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( socketNum, + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + { + /*If operation succeeded - update transfer mode in SDK as well*/ + /*------------------------------------------------------------*/ + rc = doch_setTransferMode(socketNum, pdev->bAtaDevNum, requstedXferMode, requestedDrqSize); + + return rc; + } + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetDataTransferModeSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + return DOCH_GeneralFailure; + } + +} + +DOCH_Error DOCHSetDataTransferMode(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + pdev->bAtaDevNum = 0; + rc = DOCHSetDataTransferModeSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHSetDataTransferModeSingleFloor(ioreq); + pdev->bAtaDevNum = 0; + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H I d e n t i f y D i s k O n C h i p D e v i c e */ +/* */ +/* Returns general information about the Device */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_IDENTIFY_FROM_FLASH */ +/* DOCH_IDENTIFY_EXISTANCE */ +/* irData : Address of DOCH_DeviceInfo struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_IDENTIFY_DISKONCHIP_DEVICE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHIdentifyDiskOnChipDeviceSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Socket* pdev; + DOCH_DeviceInfo* localDiskOnChipDeviceInfo = (DOCH_DeviceInfo*)(ioreq->irData); + FLSNative devNum; + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + devNum = pdev->bAtaDevNum; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_IDENTIFY_DISKONCHIP_DEVICE; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum) | ((FLByte)ioreq->irCount)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + devNum, + &in_regs, + &out_regs, + ioreq->irData, + sizeof(DOCH_DeviceInfo) / DOCH_SECTOR_SIZE); + + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + localDiskOnChipDeviceInfo->wVersion = be_FLWord((FLByte*)&localDiskOnChipDeviceInfo->wVersion); + + localDiskOnChipDeviceInfo->dwCommandFlagsOrStatuses = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwCommandFlagsOrStatuses); + localDiskOnChipDeviceInfo->dwDiskAttributes1 = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwDiskAttributes1); + localDiskOnChipDeviceInfo->dwRservedGateKeeperAttr = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwRservedGateKeeperAttr); + + localDiskOnChipDeviceInfo->wTotalNumOfPartitions = be_FLWord((FLByte*)&localDiskOnChipDeviceInfo->wTotalNumOfPartitions); + localDiskOnChipDeviceInfo->wDefaultPartitionNumber = be_FLWord((FLByte*)&localDiskOnChipDeviceInfo->wDefaultPartitionNumber); + + localDiskOnChipDeviceInfo->dwUnformattedCapacity = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwUnformattedCapacity); + + localDiskOnChipDeviceInfo->dwReservedConfigPartitionSize = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwReservedConfigPartitionSize); + localDiskOnChipDeviceInfo->dwUnitSize = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwUnitSize); + localDiskOnChipDeviceInfo->dwConfigurationPartitionExistsSign = be_FLDword((FLByte*)&localDiskOnChipDeviceInfo->dwConfigurationPartitionExistsSign); + #endif /*DOCH_BIG_ENDIAN*/ + + /*Update device structure*/ + /*=======================*/ + if(rc == DOCH_OK) + { + /*ETFFS detected*/ + pdev->device[devNum].ETFFS_Identified = TRUE; + + /*Extract MAX DRQ size from the Disk Attributes field*/ + pdev->device[devNum].dwMulti_MAX = (1 << + ((localDiskOnChipDeviceInfo->dwDiskAttributes1 & DOCH_DA1B_MAX_MULTI_SEC_XFER_SIZE) >> DOCH_DA1O_MAX_MULTI_SEC_XFER_SIZE)); + + if((localDiskOnChipDeviceInfo->dwUnformattedCapacity != 0) && + (localDiskOnChipDeviceInfo->wVersionCompatability == 0) +#ifndef DOCH_DONT_CHECK_EXISTANCE_SIGN + && (localDiskOnChipDeviceInfo->dwConfigurationPartitionExistsSign == DOCH_CONFIGURATION_EXISTS_SIGN) +#endif /*DOCH_DONT_CHECK_EXISTANCE_SIGN*/ + ) + { + rc = update_device_info(pdev, localDiskOnChipDeviceInfo, devNum); + + #ifdef CHECK_POWER_ON_EVERY_COMMAND + { + IOreq ioreq2; + + /*Make sure next calls to DOCHGetResetStatus() will reflect actual reset*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irHandle = ioreq->irHandle; + DOCHGetResetStatus(&ioreq2); + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return DOCH_OK; + } + DBG_PRINT_ERR(FLZONE_API, "ERROR: DOCHIdentifyDiskOnChipDevice(): read incorrect data\r\n"); + } + if(devNum == 0) + { + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "ERROR: DOCHIdentifyDiskOnChipDevice(): failed "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("with status: 0x%x \r\n"), rc)); + } + } + else + { + /*Prevent invoking Dev1 if it was not detected!!!*/ + tffsset(&pdev->sSpanData, 0, sizeof(pdev->sSpanData)); + + DBG_PRINT_WRN(FLZONE_API, "DOCHIdentifyDiskOnChipDevice(): Dev1 not found\r\n"); + } + return DOCH_GeneralFailure; +} + +DOCH_Error DOCHIdentifyDiskOnChipDevice(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + DOCH_DeviceInfo* tempDiskOnChipDeviceInfo; + FLByte requestedDevice; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + requestedDevice = pdev->bAtaDevNum; + + /*Identify Dev0*/ + tempDiskOnChipDeviceInfo = (DOCH_DeviceInfo*)(ioreq->irData); + pdev->bAtaDevNum = 0; + + /*Identify command should have a short timeout*/ + gUseShortWaitOnBusy = DOCH_LONG_IDENTIFY_TIMEOUT; + rc = DOCHIdentifyDiskOnChipDeviceSingleFloor(ioreq); + gUseShortWaitOnBusy = 0; + + pdev->bAtaDevNum = requestedDevice; + if(rc != DOCH_OK) + return rc; + + /*If only 1 device is present, return*/ + if(pdev->wNumOfDevices > 1) + { + /*Identify Dev1*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = &diskOnChipDeviceInfo2; + + pdev->bAtaDevNum = 1; + /*Identify command should have a short timeout*/ + gUseShortWaitOnBusy = DOCH_LONG_IDENTIFY_TIMEOUT; + rc = DOCHIdentifyDiskOnChipDeviceSingleFloor(&ioreq2); + gUseShortWaitOnBusy = 0; + pdev->bAtaDevNum = requestedDevice; + if(rc != DOCH_OK) + return rc; + + /*Combine data*/ + tempDiskOnChipDeviceInfo->dwUnformattedCapacity += diskOnChipDeviceInfo2.dwUnformattedCapacity; + + tempDiskOnChipDeviceInfo->wTotalNumOfPartitions += diskOnChipDeviceInfo2.wTotalNumOfPartitions; + + if(diskOnChipDeviceInfo2.wTotalNumOfPartitions > 1) + { + if((pdev->sSpanData.bLastDev0PartSpanned)) + tempDiskOnChipDeviceInfo->wTotalNumOfPartitions -= 2; + else + tempDiskOnChipDeviceInfo->wTotalNumOfPartitions -= 1; + } + else if(diskOnChipDeviceInfo2.wTotalNumOfPartitions == 1) + tempDiskOnChipDeviceInfo->wTotalNumOfPartitions -= 1; + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H G e t R e s e t S t a t u s */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_RESET_STATUS */ +/* */ +/* Returns: */ +/* irCount : 0 = No reset since last query */ +/* 1 = The device has been reset since last*/ +/* query */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetResetStatus(IOreq* ioreq) +{ + DOCH_Error rc; + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + pdev->bUseInterrupt=FALSE; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_RESET_STATUS; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead =DOCH_SELECT_DEV (pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Update device structure*/ + /*=======================*/ + if(rc == DOCH_OK) + { + /*Return reset status*/ + ioreq->irCount = out_regs.bSectorCount; + + return DOCH_OK; + } + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetResetStatus(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H N o t i f y R e s e t */ +/* */ +/* Notify the Device on an upcoming reset initiated by the Host. */ +/* Host should NOT perform actual reset before this command completes */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_NOTIFY_RESET */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHNotifyResetSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_NOTIFY_RESET; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + 0, + &in_regs, + &out_regs, + NULL, + 0); + + /*Update device structure*/ + /*=======================*/ + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHNotifyResetSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } + + return DOCH_OK; +} + +DOCH_Error DOCHNotifyReset(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + pdev->bAtaDevNum = 0; + rc = DOCHNotifyResetSingleFloor(ioreq); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHNotifyResetSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H N o t i f y P l a t f o r m R e s u m e d */ +/* */ +/* Notify the Device that there was a reset, */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_NOTIFY_PLATFORM_RESUMED */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHNotifyPlatformResumedSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_NOTIFY_PLATFORM_RESUMED; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + 0, + &in_regs, + &out_regs, + NULL, + 0); + + /*Update device structure*/ + /*=======================*/ + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHNotifyPlatformResumedSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } + + /*Restore DPD settings */ + /*=====================*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + + ioreq2.irFlags = (DOCH_PM_SET_BOTH_MODES | DOCH_PM_WORK_MODE); + ioreq2.irCount = (gDpdSettings.activeMode | gDpdSettings.inActiveMode); + ioreq2.irLength = gDpdSettings.timeOut; + + rc = DOCHSetPowerMode(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Restore transfer mode */ + /*======================*/ + tffsset(&ioreq2, 0, sizeof(ioreq)); + + ioreq2.irCount = pdev->device[pdev->bAtaDevNum].dataTransferMode; + ioreq2.irLength = pdev->device[pdev->bAtaDevNum].dwMulti_Current; + + rc = DOCHSetDataTransferModeSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + + + return DOCH_OK; +} + +DOCH_Error DOCHNotifyPlatformResumed(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + pdev->bAtaDevNum = 0; + rc = DOCHNotifyPlatformResumedSingleFloor(ioreq); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHNotifyPlatformResumedSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t D i s k U s e r A t t r i b u t e s */ +/* */ +/* Set disk user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1 sector of data */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetDiskUserAttributes(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + +#ifdef DOCH_BIG_ENDIAN + DOCH_DeviceUserAttr* devUserAttrOrig = (DOCH_DeviceUserAttr*)(ioreq->irData); + DOCH_PartitionSpanData* devSpanInfo= &devUserAttrOrig->sdkAttributes.sSpanInfo; + DOCH_SecureDeleteDev1* devSecureDelete= &devUserAttrOrig->sdkAttributes.sSecureDeleteDev1; +#endif /*DOCH_BIG_ENDIAN*/ + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(!gSDKUpdatesDiskAttributes) + { + /*First retrieve current attributes sector + (for protecting first 0x40 bytes that are SDK specific*/ + /*------------------------------------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = currentAttributes; + DOCHGetDiskUserAttributes(&ioreq2); + + /*Use currentAttributes bytes 0x41..0x200 to set requested*/ + /*--------------------------------------------------------*/ + tffscpy(ioreq->irData, currentAttributes, DOCH_PART_INFO_SDK_RESERVED_BYTES); + } + +#ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + devSpanInfo->dwSpanSector = be_FLDword((FLByte*)&devSpanInfo->dwSpanSector); + devSpanInfo->dwSpanSizeOnDev0 = be_FLDword((FLByte*)&devSpanInfo->dwSpanSizeOnDev0); + devSecureDelete->dwSecureDeleteNumOfSectors = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteNumOfSectors); + devSecureDelete->dwSecureDeleteStartSector = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteStartSector); +#endif /*DOCH_BIG_ENDIAN*/ + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_DISK_USER_ATTR; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (1)); + +#ifdef DOCH_BIG_ENDIAN + /*The spanInfo buffer is in use later on, therefore recover it*/ + devSpanInfo->dwSpanSector = be_FLDword((FLByte*)&devSpanInfo->dwSpanSector); + devSpanInfo->dwSpanSizeOnDev0 = be_FLDword((FLByte*)&devSpanInfo->dwSpanSizeOnDev0); + devSecureDelete->dwSecureDeleteNumOfSectors = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteNumOfSectors); + devSecureDelete->dwSecureDeleteStartSector = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteStartSector); +#endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetDiskUserAttributes(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t D i s k U s e r A t t r i b u t e s */ +/* */ +/* Get disk user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1 sector of data */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_DISK_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetDiskUserAttributes(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + +#ifdef DOCH_BIG_ENDIAN + DOCH_DeviceUserAttr* devUserAttrOrig = (DOCH_DeviceUserAttr*)(ioreq->irData); + DOCH_PartitionSpanData* devSpanInfo= &devUserAttrOrig->sdkAttributes.sSpanInfo; + DOCH_SecureDeleteDev1* devSecureDelete= &devUserAttrOrig->sdkAttributes.sSecureDeleteDev1; +#endif /*DOCH_BIG_ENDIAN*/ + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_DISK_USER_ATTR; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (1)); + + +#ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + devSpanInfo->dwSpanSector = be_FLDword((FLByte*)&devSpanInfo->dwSpanSector); + devSpanInfo->dwSpanSizeOnDev0 = be_FLDword((FLByte*)&devSpanInfo->dwSpanSizeOnDev0); + devSecureDelete->dwSecureDeleteNumOfSectors = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteNumOfSectors); + devSecureDelete->dwSecureDeleteStartSector = be_FLDword ((FLByte*)&devSecureDelete->dwSecureDeleteStartSector); +#endif /*DOCH_BIG_ENDIAN*/ + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetDiskUserAttributes(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t C o n f i g u r a t i o n D a t a */ +/* */ +/* Read the device configuration data. No authentication is required */ +/* for calling this command, but the fields containing keys in the */ +/* configuration data will be masked by ETFFS using zeros. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1..3 sector(s) of data. */ +/* irCount : Sector offset in the configuration data to start */ +/* reading from. */ +/* irLength : Number of sectors of configuration data to read. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_CONFIGURATION_DATA */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetConfigurationData(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_CONFIGURATION_DATA; + in_regs.bSectorCount = (FLByte)ioreq->irLength; + in_regs.bSectorNumber = (FLByte)ioreq->irCount; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (ioreq->irLength)); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetConfigurationData(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t C o n f i g u r a t i o n D a t a */ +/* */ +/* Save the device configuration data. Calling this command will */ +/* succeed only if there are no partitions present on the media */ +/* (including partition 0). */ +/* You should use this command in the process of duplicating DiskOnChip */ +/* device to make sure all configuration data of the original device */ +/* have been duplicated to the new device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to 1..3 sector(s) of data. */ +/* irCount : Sector offset in the configuration data to start */ +/* writing from. */ +/* irLength : Number of sectors of configuration data to write.*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_CONFIGURATION_DATA */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetConfigurationData(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_CONFIGURATION_DATA; + in_regs.bSectorCount = (FLByte)ioreq->irLength; + in_regs.bSectorNumber = (FLByte)ioreq->irCount; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (ioreq->irLength)); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetConfigurationData(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H P a r t i t i o n I n f o */ +/* */ +/* Get information about a specific partition. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read partition */ +/* information into. */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_PARTITION_INFO */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHPartitionInfoSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Socket * pdev; + +#ifdef DOCH_BIG_ENDIAN + DOCH_PartitionInfo* partInfo = (DOCH_PartitionInfo*)(ioreq->irData); + DOCH_PartitionInfo* partInfoToBig = partInfo; +#endif /*DOCH_BIG_ENDIAN*/ + + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_INFO; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_PartitionInfo) / DOCH_SECTOR_SIZE)); + +#ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + partInfoToBig->dwCommandFlagsOrStatuses = be_FLDword((FLByte*)&partInfoToBig->dwCommandFlagsOrStatuses); + partInfoToBig->partitionAttributes1 = be_FLDword((FLByte*)&partInfoToBig->partitionAttributes1); + partInfoToBig->partitionAttributes2 = be_FLDword((FLByte*)&partInfoToBig->partitionAttributes2); + partInfoToBig->nPartitionSize = be_FLDword((FLByte*)&partInfoToBig->nPartitionSize); + partInfoToBig->nFastAreaSize = be_FLDword((FLByte*)&partInfoToBig->nFastAreaSize); + + partInfoToBig->wFastAreaFactor = be_FLWord((FLByte*)&partInfoToBig->wFastAreaFactor); + + partInfoToBig->wPartitionStartSector = be_FLWord((FLByte*)&partInfoToBig->wPartitionStartSector); + partInfoToBig->wCurrentSectorsPerTrack = be_FLWord((FLByte*)&partInfoToBig->wCurrentSectorsPerTrack); + partInfoToBig->wDefaultSectorsPerTrack = be_FLWord((FLByte*)&partInfoToBig->wDefaultSectorsPerTrack); + partInfoToBig->wCurrentCylinders = be_FLWord((FLByte*)&partInfoToBig->wCurrentCylinders); + partInfoToBig->wDefaultCylinders = be_FLWord((FLByte*)&partInfoToBig->wDefaultCylinders); + partInfoToBig->wCurrentHeads = be_FLWord((FLByte*)&partInfoToBig->wCurrentHeads); + partInfoToBig->wDefaultHeads = be_FLWord((FLByte*)&partInfoToBig->wDefaultHeads); + + partInfoToBig->wFastAreaSectorsInErasableUnit = be_FLWord((FLByte*)&partInfoToBig->wFastAreaSectorsInErasableUnit); + partInfoToBig->wNormalAreaSectorsInErasableUnit = be_FLWord((FLByte*)&partInfoToBig->wNormalAreaSectorsInErasableUnit); + partInfoToBig->wRecommendedSectorsPerCluster = be_FLWord((FLByte*)&partInfoToBig->wRecommendedSectorsPerCluster); + partInfoToBig->wFastMaxRelatedSectors = be_FLWord((FLByte*)&partInfoToBig->wFastMaxRelatedSectors); + partInfoToBig->wNormalMaxRelatedSectors = be_FLWord((FLByte*)&partInfoToBig->wNormalMaxRelatedSectors); +#endif /*DOCH_BIG_ENDIAN*/ + + /*Update pdev fields*/ +#if 0 + pdev->device[pdev->bAtaDevNum].dwMulti_Current = + ((partInfo->dwCommandFlagsOrStatuses & DOCH_DCFSB_CURRENT_MULTI_SECTOR) >> DOCH_DCFSO_CURRENT_MULTI_SECTOR); +#endif /* 0 */ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHPartitionInfoSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHPartitionInfo(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + DOCH_PartitionInfo* partInfo; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + pdev->bAtaDevNum = 0; + rc = DOCHPartitionInfoSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*If partition resides ENTIRELY on Dev1 - return info*/ + /*===================================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*Retrieve first chunk info*/ + /*-------------------------*/ + pdev->bAtaDevNum = 0; + partInfo = (DOCH_PartitionInfo*)(ioreq->irData); + rc = DOCHPartitionInfoSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + /*Retrieve 2nd chunk info*/ + /*-----------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = &partitionInfoTemp; + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + pdev->bAtaDevNum = origDevNum; + if(rc != DOCH_OK) + return rc; + + /*Combine info*/ + /*------------*/ + partInfo->nPartitionSize += partitionInfoTemp.nPartitionSize; + partInfo->nFastAreaSize += partitionInfoTemp.nFastAreaSize; + } + + return DOCH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* D O C H D e l e t e P a r t i t i o n s */ +/* */ +/* Delete range of partitions */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* DOCH_FAST_PARTITOIN_DELETE */ +/* DOCH_COMPLETE_PARTITION_DELETE */ +/* irCount : First partition to delete */ +/* irLength : Last partition to delete */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_DELETE_PARTITIONS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHDeletePartitionsSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte action_type = 0; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if((ioreq->irFlags & DOCH_IMMEDIATE_OPERATION) == DOCH_IMMEDIATE_OPERATION) + action_type |= ERASE_IMMEDIATE; + + if((ioreq->irFlags & DOCH_COMPLETE_PARTITION_DELETE) == DOCH_COMPLETE_PARTITION_DELETE) + action_type |= DELETE_PARTITIONS_COMPLETE; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_DELETE_PARTITIONS; + in_regs.bSectorCount = (FLByte)(ioreq->irCount); + in_regs.bSectorNumber = (FLByte)(ioreq->irLength); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 'D'; + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum) | action_type); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + { + pdev->wTotalNumOfPartitions = 0; + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irData = &diskOnChipDeviceInfo; + rc = DOCHIdentifyDiskOnChipDevice(&ioreq2); + if(rc != DOCH_OK) + return rc; + + pdev->wTotalNumOfPartitions = diskOnChipDeviceInfo.wTotalNumOfPartitions; + + return DOCH_OK; + } + else + { + + DBG_PRINT_ERR(FLZONE_API, "DOCHDeletePartitionsSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHDeletePartitions(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + /*If partition resides ENTIRELY on Dev0 - return info*/ + /*===================================================*/ + if(!pdev->sSpanData.secondFloorActive || pdev->wNumOfDevices ==1) + { + pdev->bAtaDevNum = 0; + rc = DOCHDeletePartitionsSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + return rc; + } + else + { + /*Protect against illegal operation*/ + if(ioreq->irLength < (pdev->wTotalNumOfPartitions-1)) + { + pdev->bAtaDevNum = origDevNum; + return DOCH_GeneralFailure; + } + + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + /*Do not delete partitions from Dev0 if they do not reside on it!*/ + if(ioreq->irCount <= pdev->sSpanData.bLastPartitionOnDev0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + /*If last partition to delete resides on Dev1, erase irCount and on on Dev0 as well*/ + if(ioreq->irLength >= pdev->sSpanData.bLastPartitionOnDev0) + ioreq2.irLength = 0xFF; + + pdev->bAtaDevNum = 0; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + /*Preserve IPL on Dev1 if it was preserved on Dev0*/ + if(ioreq->irCount == 0) + ioreq2.irCount = 0; + else + ioreq2.irCount = 1; + + ioreq2.irLength = 0xFF; + + pdev->bAtaDevNum = 1; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + pdev->bAtaDevNum = origDevNum; + + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + } + else + { + ioreq2.irCount = ((ioreq->irCount - pdev->sSpanData.bLastPartitionOnDev0) + 1); + if(ioreq->irLength != 0xFF) + ioreq2.irLength = ((ioreq->irLength - pdev->sSpanData.bLastPartitionOnDev0) + 1); + + pdev->bAtaDevNum = 1; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + pdev->bAtaDevNum = origDevNum; + + if(rc != DOCH_OK) + return rc; + + /*Still spanned!*/ + return DOCH_OK; + } + } + + /*Update span info structure*/ + /*--------------------------*/ + pdev->bAtaDevNum = 0; + + /*Retrieve current attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + rc = DOCHGetDiskUserAttributes(&ioreq2); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*Set span info*/ + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = FALSE; + devUserAttr.sdkAttributes.sSpanInfo.secondFloorActive = FALSE; + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = 0; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = + devUserAttr.sdkAttributes.sSpanInfo.numOfSpannedPartitionOnDev0 = 0; + + /*Set attributes back to the device*/ + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*Update pdev as well*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + + pdev->bAtaDevNum = origDevNum; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H A d d P a r t i t i o n */ +/* */ +/* Adds a partition */ +/* The new partition is created on existing un-formatted disk capacity */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to DOCH_PartitionFormatInfoAPI struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_ADD_PARTITION */ +/* */ +/* Returns: */ +/* irCount : Number of the created partition */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHAddPartitionSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_PartitionFormatInfoAPI* partInfo = (DOCH_PartitionFormatInfoAPI*)(ioreq->irData); + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /* Clear partFormatInfo */ + /*----------------------*/ + tffsset(&partFormatInfo, 0, sizeof(DOCH_PartitionFormatInfo)); + + /* Format DOCH_PartitionFormatInfoAPI to DOCH_PartitionFormatInfo */ + /*----------------------------------------------------------------*/ + DOCH_SetBits(&partFormatInfo.dwCommandFlagsOrStatuses, + DOCH_CFSB_FAST_AREA_SIZE_TYPE, + DOCH_CFSO_FAST_AREA_SIZE_TYPE, + partInfo->dwFastAreaSizeType); + + DOCH_SetBits(&partFormatInfo.partitionAttributes1, + DOCH_PA1B_PARTITION_TYPE, + DOCH_PA1O_PARTITION_TYPE, + partInfo->dwPartitionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes1, + DOCH_PA1B_PERFORMANCE_CTRL, + DOCH_PA1O_PERFORMANCE_CTRL, + partInfo->dwPerformanceControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes1, + DOCH_PA1B_PAGE_SIZE_EXP, + DOCH_PA1O_PAGE_SIZE_EXP, + partInfo->dwPageSizeExp); + DOCH_SetBits(&partFormatInfo.partitionAttributes1, + DOCH_PA1B_HASH_TYPE, + DOCH_PA1O_HASH_TYPE, + partInfo->dwHashType); + + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_PROTECTION_TYPE, + DOCH_PA2O_PROTECTION_TYPE, + partInfo->dwProtectionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_USER_MODE, + DOCH_PA2O_USER_MODE, + partInfo->dwUserAccessMode); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_GUEST_MODE, + DOCH_PA2O_GUEST_MODE, + partInfo->dwGuestAccessMode); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_MASTER_CTRL, + DOCH_PA2O_MASTER_CTRL, + partInfo->dwMasterControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_ENCRYPT_TYPE, + DOCH_PA2O_ENCRYPT_TYPE, + partInfo->dwEncryptionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_OTP_BIT, + DOCH_PA2O_OTP_BIT, + partInfo->dwOtpEnabled); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_LOCK_CTRL, + DOCH_PA2O_LOCK_CTRL, + partInfo->dwLockControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_MAX_AUTH_ATTEMPTS, + DOCH_PA2O_MAX_AUTH_ATTEMPTS, + partInfo->dwMaxNumOfAuthAttempts); + + partFormatInfo.nPartitionSize = partInfo->nPartitionSize; + partFormatInfo.nFastAreaSize = partInfo->nFastAreaSize; + partFormatInfo.wFastAreaFactor = partInfo->wFastAreaFactor; + tffscpy(partFormatInfo.bPasskey, &partInfo->bPasskey, sizeof(partFormatInfo.bPasskey)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + partFormatInfo.dwCommandFlagsOrStatuses = be_FLDword((FLByte*)&partFormatInfo.dwCommandFlagsOrStatuses); + partFormatInfo.partitionAttributes1 = be_FLDword((FLByte*)&partFormatInfo.partitionAttributes1); + partFormatInfo.partitionAttributes2 = be_FLDword((FLByte*)&partFormatInfo.partitionAttributes2); + partFormatInfo.nPartitionSize = be_FLDword((FLByte*)&partFormatInfo.nPartitionSize); + partFormatInfo.nFastAreaSize = be_FLDword((FLByte*)&partFormatInfo.nFastAreaSize); + partFormatInfo.wFastAreaFactor = be_FLWord ((FLByte*)&partFormatInfo.wFastAreaFactor); + #endif /*DOCH_BIG_ENDIAN*/ + + /* Update ATA register values */ + /*----------------------------*/ + in_regs.bFeaturesError = DOCH_ADD_PARTITION; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /* Activate ATA command */ + /*----------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &partFormatInfo, + sizeof(DOCH_PartitionFormatInfo) / DOCH_SECTOR_SIZE); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAddPartitionSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } + + pdev->wTotalNumOfPartitions = 0; + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irData = &diskOnChipDeviceInfo; + rc = DOCHIdentifyDiskOnChipDevice(&ioreq2); + if(rc != DOCH_OK) + return rc; + + pdev->wTotalNumOfPartitions = diskOnChipDeviceInfo.wTotalNumOfPartitions; + + /* Output */ + /*--------*/ + ioreq->irCount = out_regs.bSectorCount; + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAddPartitionSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc,pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHAddPartition(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_PartitionFormatInfoAPI* partInfo = (DOCH_PartitionFormatInfoAPI*)(ioreq->irData); + DOCH_Socket* pdev; + FLDword reqSize = partInfo->nPartitionSize; + FLDword tempPartNum = 0; + FLBoolean dev0MightBeFull = FALSE; + FLByte tempLastPartOnDev0 = 0; + FLByte origDevNum; + FLByte partialDev0Part; + DOCH_DeviceInfo tempDOCDI; + + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + /*If 2nd floor is already active - perform on device1*/ + /*===================================================*/ + if((pdev->sSpanData.secondFloorActive) && (pdev->wNumOfDevices > 1)) + { + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + + /*Update returned partition number*/ + ioreq->irCount += (pdev->sSpanData.bLastPartitionOnDev0); + + if(pdev->sSpanData.bLastDev0PartSpanned) + ioreq->irCount -= 1; + + return rc; + } + + /*If requested size = 0, Add to both Dev0 and Dev1*/ + /*================================================*/ + /*Try adding to Dev0 with size=0*/ + + + if(reqSize == 0) + { + /*Dev0*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + /* if there are two floors and fast area was specified in percents + fast area requested might exceed first floor -must be translated to sectors*/ + if(((pdev->wNumOfDevices > 1)) + &&(partInfo->dwFastAreaSizeType==DOCH_FAST_AREA_TYPE_PERCENT) + && (partInfo->nFastAreaSize)&& (partInfo->nFastAreaSize < 100)) + { + /* Cannot add spanned partition with requested fast area specified in percents */ + DBG_PRINT_ERR(FLZONE_API, "DOCHAddPartition(): Cannot add spanned partition with requested fast area specified in percents\r\n"); + return DOCH_GeneralFailure; + + } + ioreq2.irData = ioreq->irData; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + partialDev0Part = (FLByte)ioreq2.irCount; + if(rc != DOCH_OK) + { + /* If operation failed with insufficient space, + check the option of fast area problem*/ + if((pdev->wNumOfDevices > 1)&&(partInfo->nFastAreaSize) + &&(partInfo->dwFastAreaSizeType==DOCH_FAST_AREA_TYPE_SECTORS)) + { + /* add partition with 100 percents fast area to dev0*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + partInfoTemp.dwFastAreaSizeType =DOCH_FAST_AREA_TYPE_PERCENT; + partInfoTemp.nFastAreaSize = 100; + ioreq2.irData = &partInfoTemp; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + partialDev0Part= (FLByte)ioreq2.irCount; + } + if(rc != DOCH_OK) + { + /* If operation failed with insufficient space, + it means last partition that was added filled Dev0 entirely*/ + dev0MightBeFull = TRUE; + tempLastPartOnDev0 = devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0; + } + + } + + /*Insert key (in case the partition was read protected)*/ + if(partInfo->dwGuestAccessMode == DOCH_DEVICE_ACCESS_MODE_NONE) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffsset(&partAccessTemp, 0, sizeof(partAccessTemp)); + + tffscpy(partAccessTemp.bPassword, partInfo->bPasskey, 0x80); + + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (pdev->device[0].wNumOfPartitions-1)); + ioreq2.irData = &partAccessTemp; + + rc = DOCHAccessPartWithPwdSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + } + + if(!dev0MightBeFull) + { + /*If created partition was IPL:*/ + /*1. Delete all partition on dev1*/ + /*2. Create on Dev1 as well*/ + if((pdev->wNumOfDevices > 1) && (partialDev0Part == 0)) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + ioreq2.irLength = 0xFF; + pdev->bAtaDevNum = 1; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + /*Make sure returned partition number is correct*/ + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = partialDev0Part; + ioreq->irCount = partialDev0Part; + } + + if(pdev->wNumOfDevices > 1) + { + if(!dev0MightBeFull) + { + /*Get actual size of the newly added partition*/ + tempPartNum = partialDev0Part; + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffsset(&partitionInfoTemp, 0, sizeof(partitionInfoTemp)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, tempPartNum); + ioreq2.irData = &partitionInfoTemp; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + } + /*Add User partition to Dev1 with size = 0*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + /*if dwFastAreaSizeType was in percents than nFastAreaSize must be 100 + therefore no need to change partInfoTemp*/ + /*if dwFastAreaSizeType was in sectors - + check how many fast area sectors are needed*/ + if ((partInfo->nFastAreaSize) && (partInfo->dwFastAreaSizeType!=DOCH_FAST_AREA_TYPE_PERCENT)) + { + if (partInfo->nFastAreaSize >partitionInfoTemp.nFastAreaSize) + { + partInfoTemp.nFastAreaSize= partInfo->nFastAreaSize - partitionInfoTemp.nFastAreaSize; + } + else + { + partInfoTemp.nFastAreaSize =0; + } + } + ioreq2.irData = &partInfoTemp; + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + + /*Update span info structure*/ + /*--------------------------*/ + /*Retrieve current attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + rc = DOCHGetDiskUserAttributes(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Set span info*/ + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = (!dev0MightBeFull);/*TRUE;*/ + devUserAttr.sdkAttributes.sSpanInfo.secondFloorActive = TRUE; + + if(!dev0MightBeFull) + { + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = partitionInfoTemp.nPartitionSize; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = + devUserAttr.sdkAttributes.sSpanInfo.numOfSpannedPartitionOnDev0 = (FLByte)(tempPartNum); + } + else + { + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = 0; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = tempLastPartOnDev0; + } + + /*Set attributes back to the device*/ + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + return rc; + + /*Update pdev as well*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + + /* Finally - update number of partitions*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &tempDOCDI; + rc = DOCHIdentifyDiskOnChipDevice(&ioreq2); + pdev->wTotalNumOfPartitions = tempDOCDI.wTotalNumOfPartitions; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; + } + + /*Try adding to Dev0*/ + /*==================*/ + rc = DOCHAddPartitionSingleFloor(ioreq); + if(rc == DOCH_OK) + { + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = (FLByte)(ioreq->irCount); + + /*If created partition was IPL:*/ + /*1. Delete all partition on dev1*/ + /*2. Create on Dev1 as well*/ + if((pdev->wNumOfDevices > 1) && (ioreq->irCount == 0)) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + ioreq2.irLength = 0xFF; + pdev->bAtaDevNum = 1; + rc = DOCHDeletePartitionsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; + } + else if(pdev->wNumOfDevices > 1) + { + FLDword secondChunkSize = 0; + FLDword dwSecondChunkFastAreaSize = 0; + FLDword dwSecondChunkFastAreaType = 0 ; + /*If Adding entire size on Dev0 failed*/ + /*====================================*/ + /*Try adding to Dev0 with size=0*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + partInfoTemp.nPartitionSize = 0; + if((partInfo->dwFastAreaSizeType==DOCH_FAST_AREA_TYPE_PERCENT) && (partInfo->nFastAreaSize < 100)) + { + partInfoTemp.dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_SECTORS; + partInfoTemp.nFastAreaSize = ((partInfo->nPartitionSize/100) * partInfo->nFastAreaSize); + } + + ioreq2.irData = &partInfoTemp; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + partialDev0Part = (FLByte)ioreq2.irCount; + if(rc != DOCH_OK) + { + /*Checking if Fast Area is too big for Dev#0*/ + /*Try adding to Dev0 with size=0 and Fast Area size 100 percent */ + if(partInfo->nFastAreaSize) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + partInfoTemp.nPartitionSize = 0; + partInfoTemp.dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_PERCENT; + partInfoTemp.nFastAreaSize = 100; + ioreq2.irData = &partInfoTemp; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + partialDev0Part = (FLByte)ioreq2.irCount; + } + if(rc != DOCH_OK) + { + /* If operation failed with insufficient space or there is no Fast Area, + it means last partition that was added filled Dev0 entirely*/ + dev0MightBeFull = TRUE; + tempLastPartOnDev0 = devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0; + /*return rc;*/ + } + } + + if(!dev0MightBeFull) + { + /*Insert key (in case the partition was read protected)*/ + if(partInfoTemp.dwGuestAccessMode == DOCH_DEVICE_ACCESS_MODE_NONE) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffsset(&partAccessTemp, 0, sizeof(partAccessTemp)); + + tffscpy(partAccessTemp.bPassword, partInfoTemp.bPasskey, 0x80); + + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (pdev->device[0].wNumOfPartitions-1)); + ioreq2.irData = &partAccessTemp; + + rc = DOCHAccessPartWithPwdSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + } + + /*Make sure returned partition number is correct*/ + ioreq->irCount = partialDev0Part; + + /*Get actual size of the newly added partition*/ + tempPartNum = partialDev0Part; + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffsset(&partitionInfoTemp, 0, sizeof(partitionInfoTemp)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, tempPartNum); + ioreq2.irData = &partitionInfoTemp; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + /*checking remaining size of fast area for Dev#1*/ + if(partInfo->dwFastAreaSizeType != DOCH_FAST_AREA_TYPE_PERCENT) + { + if(partInfo->nFastAreaSize > partitionInfoTemp.nPartitionSize) + { + dwSecondChunkFastAreaSize = partInfo->nFastAreaSize - partitionInfoTemp.nPartitionSize; + } + else + { + dwSecondChunkFastAreaSize = 0; + } + dwSecondChunkFastAreaType = partInfo->dwFastAreaSizeType; + } + else + { + if(partInfo->nFastAreaSize == 100) + { + dwSecondChunkFastAreaSize = 100; + dwSecondChunkFastAreaType = DOCH_FAST_AREA_TYPE_PERCENT; + } + else + { + dwSecondChunkFastAreaSize = ((partInfo->nFastAreaSize * (partInfo->nPartitionSize/100)) - partitionInfoTemp.nFastAreaSize); + dwSecondChunkFastAreaType = DOCH_FAST_AREA_TYPE_SECTORS; + } + } + secondChunkSize = (reqSize - partitionInfoTemp.nPartitionSize); + } + else + {/*Partition is not spanned - will reside on second floor*/ + secondChunkSize = reqSize; + dwSecondChunkFastAreaSize = partInfo->nFastAreaSize; + dwSecondChunkFastAreaType = partInfo->dwFastAreaSizeType; + } + + /*Try adding to Dev1 with size=secondChunkSize*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + tffscpy(&partInfoTemp, ioreq->irData, sizeof(partInfoTemp)); + partInfoTemp.nPartitionSize = secondChunkSize; + partInfoTemp.nFastAreaSize = dwSecondChunkFastAreaSize; + partInfoTemp.dwFastAreaSizeType = dwSecondChunkFastAreaType; + ioreq2.irData = &partInfoTemp; + + pdev->bAtaDevNum = 1; + rc = DOCHAddPartitionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + + /*Update span info structure*/ + /*--------------------------*/ + /*Retrieve current attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + rc = DOCHGetDiskUserAttributes(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Set span info*/ + devUserAttr.sdkAttributes.sSpanInfo.secondFloorActive = TRUE; + + if(!dev0MightBeFull) + { + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = partitionInfoTemp.nPartitionSize; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = + devUserAttr.sdkAttributes.sSpanInfo.numOfSpannedPartitionOnDev0 = (FLByte)(tempPartNum); + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = TRUE; + + } + else + { + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = 0; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = tempLastPartOnDev0; + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = FALSE; + } + + /*Set attributes back to the device*/ + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + return rc; + + /*Update pdev as well*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + + /* Finally - update number of partitions*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &tempDOCDI; + rc = DOCHIdentifyDiskOnChipDevice(&ioreq2); + pdev->wTotalNumOfPartitions = tempDOCDI.wTotalNumOfPartitions; + if(rc != DOCH_OK) + return rc; + } + else + { + return DOCH_GeneralFailure; + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H U n f o r m a t D e v i c e */ +/* */ +/* Unformats DOCH device. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_DELETE_PARTITIONS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHUnformatSingleDevice(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + + /*1. Delete all partitions */ + /*=========================*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irCount = 0; + ioreq2.irLength = 0xFF; + ioreq2.irFlags = DOCH_COMPLETE_PARTITION_DELETE; + + rc = DOCHDeletePartitions(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHUnformatDevice(): DOCHDeletePartitions() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + /*2. Delete Disk Attributes */ + /*==========================*/ + tffsset(¤tAttributes, 0, sizeof(currentAttributes)); + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irData = currentAttributes; + + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHUnformatDevice(): DOCHSetDiskUserAttributes() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + return DOCH_OK; +} + +DOCH_Error DOCHUnformatDevice(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + pdev->bAtaDevNum = 0; + rc = DOCHUnformatSingleDevice(ioreq); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHUnformatSingleDevice(ioreq); + pdev->bAtaDevNum = 0; + + if(rc != DOCH_OK) + return rc; + } + + /*Update span info structure*/ + /*--------------------------*/ + pdev->bAtaDevNum = 0; + + /*Retrieve current attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + rc = DOCHGetDiskUserAttributes(&ioreq2); + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*Set span info*/ + devUserAttr.sdkAttributes.sSpanInfo.bLastDev0PartSpanned = FALSE; + devUserAttr.sdkAttributes.sSpanInfo.secondFloorActive = FALSE; + devUserAttr.sdkAttributes.sSpanInfo.dwSpanSector = 0; + devUserAttr.sdkAttributes.sSpanInfo.bLastPartitionOnDev0 = + devUserAttr.sdkAttributes.sSpanInfo.numOfSpannedPartitionOnDev0 = 0; + + /*Set attributes back to the device*/ + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + { + pdev->bAtaDevNum = origDevNum; + return rc; + } + + /*Update pdev as well*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + + pdev->bAtaDevNum = origDevNum; + + return DOCH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e I P L */ +/* */ +/* Writes IPL partition. */ +/* Sets IPL mode and size. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : DOCH_IPL_MODE_NORMAL_RAM */ +/* DOCH_IPL_MODE_PAGED_RAM */ +/* DOCH_IPL_MODE_VIRTUAL_RAM */ +/* DOCH_IPL_MODE_CS_DELAY */ +/* DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT */ +/* DOCH_IPL_MODE_ACTIVE_SWAP_BYTES */ +/* DOCH_IPL_MODE_8KB_WINDOW */ +/* DOCH_IPL_WRITE_FIRST_CHUNK */ +/* irCount : Max IPL size */ +/* Up to 32KB for Normal Mode */ +/* Up to 128KB for Virtual Mode */ +/* Up to 256KB for Paged Mode */ +/* irLength : Current chunk length (in sectors) */ +/* irData : Pointer to user buffer (length defined by */ +/* irLength) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteIPLSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + FLBoolean firstChunk = ((ioreq->irFlags & DOCH_IPL_WRITE_FIRST_CHUNK) == DOCH_IPL_WRITE_FIRST_CHUNK); + DOCH_Socket* pdev; + + FLSDword total_num_of_sectors; + FLSDword sectorNumber; + FLSNative sectors_written_so_far; + FLByte* buf_ptr; + FLSNative buf_offset; + + FLByte deviceNum = 0; + + Addressing_Values_s addr_vals; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + FLByte operationRetries = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(firstChunk && (pdev->bAtaDevNum == 0)) + { + /*1. Set IPL BOOT Mode */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_BOOT_MODE; + ioreq2.irSectorNo = (FLWord)(ioreq->irFlags); + ioreq2.irFlags = DOCH_CUSTOM_PARAM_DEFAULT; + rc = DOCHSetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteIPLSingleFloor(): DOCHSetCustomParameter(Boot Mode) failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + /*2. Set IPL MAX Size */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_XIP_MAX_SIZE; + ioreq2.irSectorNo = ioreq->irCount; + ioreq2.irFlags = DOCH_CUSTOM_PARAM_DEFAULT; + rc = DOCHSetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteIPLSingleFloor(): DOCHSetCustomParameter(XIP Size) failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + gIPLChunkOffsetInSectors = 0; + } + + /*3. Write chunk of data */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irData = ioreq->irData; + ioreq2.irSectorNo = gIPLChunkOffsetInSectors; + ioreq2.irSectorCount = ioreq->irLength; + + /*Sector arithmetic*/ + /*-----------------*/ + total_num_of_sectors = ioreq2.irSectorCount; + sectorNumber = ioreq2.irSectorNo; + sectors_written_so_far = 0; + + /*Buffer to write from*/ + /*--------------------*/ + buf_ptr = (FLByte*)ioreq2.irData; + buf_offset = 0; + + deviceNum = pdev->bAtaDevNum; + + /*Sanity Check*/ + /*------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(&ioreq2) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Set DMA and Burst modes according to request*/ + /*--------------------------------------------*/ + pdev->bUseDMA = (((ioreq2.irFlags & DOCH_USE_DMA) == DOCH_USE_DMA) && + (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) && + (DOCH_DMA_CHECK_BUFFER(buf_ptr, total_num_of_sectors))); + + pdev->bUseBurst = ((ioreq2.irFlags & DOCH_USE_BURST) == DOCH_USE_BURST); + + /*Perform write cycles in DOCH_MAX_SECTORS quantities*/ + /*---------------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + +dochWriteRetryPointDev1Only: + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(&ioreq2), deviceNum, TRUE); + if(rc != DOCH_OK) + return rc; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /*Perform 1 operation cycle*/ + /*=========================*/ + + /*Set ATA addressing registers*/ + /*---------------------------*/ + DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, sectorNumber, deviceNum); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(&ioreq2); + if(sectors_this_cycle < DOCH_MAX_SECTORS) + in_regs.bSectorCount = sectors_this_cycle; + else + in_regs.bSectorCount = 0; /*DOCH_MAX_SECTORS*/ + + in_regs.bSectorNumber = addr_vals.bSecNum; + in_regs.bCylLow = addr_vals.bCylLow; + in_regs.bCylHigh = addr_vals.bCylHi; + in_regs.bDriveHead = addr_vals.bDevHead; + in_regs.bCommandStatus = DOCH_VSCMD_WRITE_PARTITION; + + /*Activate ATA command*/ + /*--------------------*/ + #ifdef DOCH_DMA_CONFIG + DOCH_OPEN_DMA_CHANNEL + #endif /*DOCH_DMA_CONFIG*/ + + /*Perform ATA command*/ + rc = io_output (pdev, deviceNum, &in_regs, (void*)(&buf_ptr[buf_offset]), sectors_this_cycle); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteIPLSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device num: %d\r\n"), rc,pdev->bAtaDevNum)); + + rc= get_out_registers(pdev, deviceNum, &out_regs); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteIPLSingleFloor(): failed with status(retrieved from out register): "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc , deviceNum)); + + if( ((rc & DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) == DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) && + (operationRetries++ < 4) + ) + goto dochWriteRetryPointDev1Only; + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Cancel DMA and Burst modes*/ + /*--------------------------*/ + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + pdev->bAtaDevNum = 0; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Update feedback values*/ + /*----------------------*/ + sectors_written_so_far += sectors_this_cycle; + + /*For next possible cycle*/ + /*-----------------------*/ + sectorNumber += sectors_this_cycle; + total_num_of_sectors -= sectors_this_cycle; + buf_offset += sectors_this_cycle * DOCH_SECTOR_SIZE; + + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(&ioreq2), deviceNum, FALSE); + if(rc != DOCH_OK) + return rc; + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Cancel DMA and Burst modes*/ + /*--------------------------*/ + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + +#if 0 /*Cant verify IPL writing - IPL must be written continuosly, without read operations in between write operations*/ + + /*If verify was define, perform verify operation with same parameters*/ + /*-------------------------------------------------------------------*/ + if(gDochVerifyWrite[DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(&ioreq2)] == DOCH_GLOBAL_BOOL_PATTERN) + { + IOreq ioreq3; + FLByte* verBufOrig; + FLByte i; + + tffsset(&ioreq3, 0, sizeof(ioreq3)); + tffscpy(&ioreq3.irHandle, &ioreq2.irHandle, sizeof(ioreq3.irHandle)); + ioreq3.irData = verifyBuf; + verBufOrig = (FLByte*)(ioreq2.irData); + + for(i=0; ibAtaDevNum)); + + return rc; + } + + if((pdev->bAtaDevNum == 1) || (pdev->wNumOfDevices == 1)) + gIPLChunkOffsetInSectors += ioreq->irLength; + + return rc; +} + +DOCH_Error DOCHWriteIPL(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + pdev->bAtaDevNum = 0; + rc = DOCHWriteIPLSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHWriteIPLSingleFloor(ioreq); + pdev->bAtaDevNum = 0; + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H R e a d I P L */ +/* */ +/* Read specified sectors from IPL partition. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : First sector to read */ +/* irLength : Number of sectors to read */ +/* irData : Pointer to user buffer (length defined by */ +/* irLength) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* irFlags : DOCH_IPL_MODE_NORMAL_RAM */ +/* DOCH_IPL_MODE_PAGED_RAM */ +/* DOCH_IPL_MODE_VIRTUAL_RAM */ +/* DOCH_IPL_MODE_CS_DELAY */ +/* DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT */ +/* DOCH_IPL_MODE_ACTIVE_SWAP_BYTES */ +/* DOCH_IPL_MODE_8KB_WINDOW */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadIPL(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + ioreq2.irData = ioreq->irData; + ioreq2.irSectorNo = ioreq->irCount; + ioreq2.irSectorCount = ioreq->irLength; + + /*1. Retrieve IPL data */ + rc = DOCHReadPartitionSectors(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadIPL(): DOCHReadPartitionSectors() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + /*2. Retrieve IPL Mode */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_BOOT_MODE; + ioreq2.irFlags = DOCH_CUSTOM_PARAM_DEFAULT; + rc = DOCHGetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadIPL(): DOCHGetCustomParameter() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + ioreq->irFlags = ioreq2.irLength; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/*D O C H R e a d P a r t i t i o n S e c t o r s S i n g l e F l o o r */ +/* */ +/* Reads sectors by sector no from a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read into */ +/* irSectorNo : First sector no. to read. */ +/* irSectorCount : Number of consecutive sectors to read */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* pdev->bAtaDevNum : Floor number */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +static DOCH_Error DOCHReadPartitionSectorsSingleFloor(IOreq* ioreq) +{ + /*parameters*/ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte socketNum =DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq); + FLByte deviceNum = 0; + + /*loop and feedback variables*/ + FLSDword total_num_of_sectors; + FLSDword sectorNumber; + FLSNative sectors_read_so_far; + FLByte* buf_ptr; + FLSNative buf_offset; + + /*internal data structures*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + Addressing_Values_s addr_vals; + + DOCH_get_socket(pdev, socketNum); + + /* General sequence: + 1. Sector arithmetic + 2. Setting buffer + 3. Sanity Check + 4. handle DMA, Burst, Interrupts + 5. Read sectors in DOCH_MAX_SECTORS quantities + 5.1 Set ATA addressing registers + 5.2 Update ATA register values + 5.3 Activate ATA command + 5.4 Update feedback values + 5.5 Update loop variables for next possible cycle + Disable interrupts + 6. Disable DMA,Burst and interrupts + 7. Return actual number of read sectors + */ + + + /*1. Sector arithmetic*/ + /*--------------------*/ + total_num_of_sectors = ioreq->irSectorCount; + sectorNumber = ioreq->irSectorNo; + sectors_read_so_far = 0; + + /*2. Setting buffer*/ + /*-----------------*/ + buf_ptr = (FLByte*)ioreq->irData; + buf_offset = 0; + + deviceNum = pdev->bAtaDevNum; + + /*3. Sanity Check */ + /*----------------*/ + + /*Check if Partition exceeds number of existing partitions*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /* 4. handle DMA, Burst, Interrupts */ + /*------------------------------------*/ + /*Set DMA and Burst modes according to request*/ + pdev->bUseDMA = (((ioreq->irFlags & DOCH_USE_DMA) == DOCH_USE_DMA) && + (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) && + (DOCH_DMA_CHECK_BUFFER(buf_ptr, total_num_of_sectors))); + + pdev->bUseBurst = ((ioreq->irFlags & DOCH_USE_BURST) == DOCH_USE_BURST); + +#ifdef DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + if (!pdev->bUseDMA) + { + pdev->bUseBurst= FALSE; + } +#endif /*DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA*/ + + + /*Enable interrupts if DMA is enabled*/ + if(pdev->bUseDMA) + { + pdev->bUseInterrupt = TRUE; + + } + + /*5. Read sectors in DOCH_MAX_SECTORS quantities*/ + /*----------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), deviceNum, TRUE); + if(rc != DOCH_OK) + return rc; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /*Perform 1 operation cycle*/ + /*=========================*/ + + /*5.1 Set ATA addressing registers*/ + /*--------------------------------*/ + DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, sectorNumber, deviceNum); + + /*5.2 Update ATA register values*/ + /*------------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + if(sectors_this_cycle < DOCH_MAX_SECTORS) + in_regs.bSectorCount = sectors_this_cycle; + else + in_regs.bSectorCount = 0; /*DOCH_MAX_SECTORS*/ + + in_regs.bSectorNumber = addr_vals.bSecNum; + in_regs.bCylLow = addr_vals.bCylLow; + in_regs.bCylHigh = addr_vals.bCylHi; + in_regs.bDriveHead = addr_vals.bDevHead; + in_regs.bCommandStatus = DOCH_VSCMD_READ_PARTITION; + + /*5.3 Activate ATA command*/ + /*------------------------*/ + #ifdef DOCH_DMA_CONFIG + DOCH_OPEN_DMA_CHANNEL + #endif /*DOCH_DMA_CONFIG*/ + + /*Perform ATA command*/ + rc = io_input (pdev, deviceNum, &in_regs, (void*)(&buf_ptr[buf_offset]), sectors_this_cycle); + + if(rc != DOCH_OK) + { + DOCH_Error rc2; + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): io_input failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + /*Disable DMA,Burst, interrupts */ + /*-----------------------------*/ + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc2 = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), deviceNum, FALSE); + if(rc2 != DOCH_OK) + return rc2; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + if(rc == DOCH_TimedOut) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): io_input returned DOCH_TimedOut! \r\n "); + return rc; + } + + rc2 = get_out_registers(pdev, deviceNum, &out_regs); + + if(rc2 != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc2)); + + if((rc2 & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc2 & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + + return rc; + } + + /*5.4 Update feedback values*/ + /*--------------------------*/ + sectors_read_so_far += sectors_this_cycle; + + /*5.5 Update loop variables for next possible cycle*/ + /*-------------------------------------------------*/ + sectorNumber += sectors_this_cycle; + total_num_of_sectors -= sectors_this_cycle; + buf_offset += sectors_this_cycle * DOCH_SECTOR_SIZE; + + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), deviceNum, FALSE); + if(rc != DOCH_OK) + return rc; + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + } /* end of loop */ + + /*6. Disable DMA,Burst and interrupts*/ + /*-----------------------------------*/ + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + + /*7. Return actual number of read sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_read_so_far; + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e a d P a r t i t i o n S e c t o r s */ +/* */ +/* Reads sectors by sector no from a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to read into */ +/* irSectorNo : First sector no. to read. */ +/* irSectorCount : Number of consecutive sectors to read */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadPartitionSectors(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + if(pdev == NULL) + return DOCH_AdapterNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + pdev->bAtaDevNum=0; + rc= DOCHReadPartitionSectorsSingleFloor(ioreq); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): DOCHReadPartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): Failure on partition that resides ENTIRELY on Dev0 "); + } + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + IOreq ioreq2; + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + + rc= DOCHReadPartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): DOCHReadPartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): Failure on partition that resides ENTIRELY on Dev1 "); + } + ioreq->irSectorCount =ioreq2.irSectorCount; + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + IOreq ioreq2; + FLDword sectorsToReadFromFirstChunk; + FLDword sectorsToReadFromSecondChunk; + + /*irLength => First sector to read*/ + /*irCount => Number of sectors to read*/ + if( ((FLDword)((ioreq->irLength + ioreq->irCount))) > pdev->sSpanData.dwSpanSector) + { + if(((FLDword)ioreq->irLength) >= pdev->sSpanData.dwSpanSector) + { + sectorsToReadFromFirstChunk = 0; + sectorsToReadFromSecondChunk = ioreq->irCount; + + } + else + { + sectorsToReadFromFirstChunk = (pdev->sSpanData.dwSpanSector - ioreq->irLength); + sectorsToReadFromSecondChunk = (ioreq->irCount - sectorsToReadFromFirstChunk); + } + } + else + { + sectorsToReadFromFirstChunk = ioreq->irCount; + sectorsToReadFromSecondChunk = 0; + } + + ioreq->irSectorCount =0; + + /*Read first chunk from Dev0*/ + /*--------------------------*/ + if(sectorsToReadFromFirstChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToReadFromFirstChunk; + pdev->bAtaDevNum = 0; + rc= DOCHReadPartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): DOCHReadPartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): Failure on spanned partition when reading chunk from Dev0 "); + return rc; + } + ioreq->irSectorCount =ioreq2.irSectorCount; + + } + + /*Read 2nd chunk from Dev1*/ + /*------------------------*/ + if(sectorsToReadFromSecondChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToReadFromSecondChunk; + + if(sectorsToReadFromFirstChunk > 0) + ioreq2.irLength = 0; + else + { + ioreq2.irLength = (ioreq->irLength - pdev->sSpanData.dwSpanSector); + } + ioreq2.irData = (FLByte*)ioreq->irData + (sectorsToReadFromFirstChunk<sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + + rc= DOCHReadPartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): DOCHReadPartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHReadPartitionSectors(): Failure on spanned partition when reading chunk from Dev1 "); + } + pdev->bAtaDevNum = 0; + ioreq->irSectorCount +=ioreq2.irSectorCount; + return rc; + } + } + + return DOCH_OK; +} + +/*-----------------------------------------------------------------------*/ +/*D O C H W r i t e P a r t i t i o n S e c t o r s S i n g l e F l o o r*/ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*-----------------------------------------------------------------------*/ +DOCH_Error DOCHWritePartitionSectorsSingleFloor(IOreq* ioreq) +{ + /* parameters */ + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + FLByte socketNum=DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq); + DOCH_Error rc = DOCH_OK; + FLByte deviceNum = 0; + DOCH_Socket* pdev; + + /*loop and feedback variables*/ + FLSDword total_num_of_sectors; + FLSDword sectorNumber; + FLSNative sectors_written_so_far; + FLByte* buf_ptr; + FLSNative buf_offset; + FLByte operationRetries = 0; + + /*internal data structures*/ + Addressing_Values_s addr_vals; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + +#ifdef FL_VERIFY_WRITE + IOreq ioreq2; + FLByte* verBufOrig; + register int i; +#endif /*FL_VERIFY_WRITE*/ + + /* General sequence: + 1. Sector arithmetic + 2. Setting buffer + 3. Sanity Check + 4. handle DMA, Burst and Interrupts + 5. Perform write cycles in DOCH_MAX_SECTORS quantities + 5.1 Set ATA addressing registers + 5.2 Update ATA register values + 5.3 Activate ATA command + 5.4 Update feedback values + 5.5 Update loop variables for next possible cycle + 6. Disable DMA and Burst and Interrupts. + 7. If verify was define, perform verify operation with same parameters + 8. Return actual number of written sectors + */ + + DOCH_get_socket(pdev, socketNum); + deviceNum = pdev->bAtaDevNum; + + + /*1. Sector arithmetic*/ + /*-----------------*/ + total_num_of_sectors = ioreq->irSectorCount; + sectorNumber = ioreq->irSectorNo; + sectors_written_so_far = 0; + + /*2. Setting Buffer to write from*/ + /*-------------------------------*/ + buf_ptr = (FLByte*)ioreq->irData; + buf_offset = 0; + + + /*3. Sanity Check*/ + /*---------------*/ + if(partNum >= pdev->device[deviceNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*4. handle DMA, Burst and Interrupts*/ + /*-----------------------------------*/ + + /*Enable interrupts*/ + pdev->bUseInterrupt = TRUE; + + /*Set DMA and Burst modes according to request*/ + pdev->bUseDMA = (((ioreq->irFlags & DOCH_USE_DMA) == DOCH_USE_DMA) && + (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) && + (DOCH_DMA_CHECK_BUFFER(buf_ptr, total_num_of_sectors))); + + pdev->bUseBurst = ((ioreq->irFlags & DOCH_USE_BURST) == DOCH_USE_BURST); + + /*5. Perform write cycles in DOCH_MAX_SECTORS quantities*/ + /*------------------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + +dochWriteRetryPoint: + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(socketNum, deviceNum, TRUE); + if(rc != DOCH_OK) + return rc; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /*Perform 1 operation cycle*/ + /*=========================*/ + + /*5.1 Set ATA addressing registers*/ + /*--------------------------------*/ + DOCH_SET_ATA_ADDRESS_VALUES(addr_vals, sectorNumber, deviceNum); + + /*5.2 Update ATA register values*/ + /*------------------------------*/ + in_regs.bFeaturesError = partNum; + if(sectors_this_cycle < DOCH_MAX_SECTORS) + in_regs.bSectorCount = sectors_this_cycle; + else + in_regs.bSectorCount = 0; /*DOCH_MAX_SECTORS*/ + + in_regs.bSectorNumber = addr_vals.bSecNum; + in_regs.bCylLow = addr_vals.bCylLow; + in_regs.bCylHigh = addr_vals.bCylHi; + in_regs.bDriveHead = addr_vals.bDevHead; + in_regs.bCommandStatus = DOCH_VSCMD_WRITE_PARTITION; + + /*5.3 Activate ATA command*/ + /*------------------------*/ + #ifdef DOCH_DMA_CONFIG + DOCH_OPEN_DMA_CHANNEL + #endif /*DOCH_DMA_CONFIG*/ + + /*Perform ATA command*/ + rc = io_output (pdev, deviceNum, &in_regs, (void*)(&buf_ptr[buf_offset]), sectors_this_cycle); + + if(rc != DOCH_OK) + { + DOCH_Error rc2 = DOCH_OK; + + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectorsSingleFloor(): io_output returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc,deviceNum)); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("parameters: irHandle:%d ,irSectorNo:%d, irSectorConut:%d \r\n"), ioreq->irHandle,ioreq->irSectorNo,ioreq->irSectorCount)); + + /* Disable DMA,BURST and interrupts */ + /************************************/ + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc2 = dochCheckPFSymptom(socketNum, deviceNum, FALSE); + if(rc2 != DOCH_OK) + return rc2; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + if(rc == DOCH_TimedOut) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectorsSingleFloor(): io_output returned DOCH_TimedOut! \r\n "); + return rc; + } + + rc2 = get_out_registers(pdev, deviceNum, &out_regs); + + if(rc2 != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): failed with status (retrieved from register): "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc2)); + + if( ((rc2 & DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) == DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) && + (operationRetries++ < 4) + ) + goto dochWriteRetryPoint; + + /*pdev->bAtaDevNum = 0;*/ + + if((rc2 & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc2 & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + return rc; + } /*rc != DOCH_OK*/ + + /*5.4 Update feedback values*/ + /*--------------------------*/ + sectors_written_so_far += sectors_this_cycle; + + /*5.5 Update loop variables for next possible cycle*/ + /*-------------------------------------------------*/ + sectorNumber += sectors_this_cycle; + total_num_of_sectors -= sectors_this_cycle; + buf_offset += sectors_this_cycle * DOCH_SECTOR_SIZE; + + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(socketNum, deviceNum, FALSE); + if(rc != DOCH_OK) + return rc; + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + } /* while(total_num_of_sectors > 0) */ + + /*6. Disable DMA and Burst and Interrupts*/ + /*---------------------------------------*/ + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + +#ifdef FL_VERIFY_WRITE + /*7. If verify was define, perform verify operation with same parameters*/ + /*----------------------------------------------------------------------*/ + if(gDochVerifyWrite[socketNum] == DOCH_GLOBAL_BOOL_PATTERN) + { + DBG_PRINT_FLOW(FLZONE_API, "DOCHWritePartitionSectorsSingleFloor(): verify write\r\n"); + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&ioreq2.irHandle, &ioreq->irHandle, sizeof(ioreq2.irHandle)); + ioreq2.irData = verifyBuf; + verBufOrig = (FLByte*)(ioreq->irData); + + for(i=0; iirSectorCount; i++) + { + ioreq2.irSectorCount = 1; + ioreq2.irSectorNo = (ioreq->irSectorNo + i); + rc = DOCHReadPartitionSectorsSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectorsSingleFloor(): DOCHReadPartitionSectors() failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,deviceNum)); + + return rc; + } + + if(tffscmp(verifyBuf, verBufOrig, DOCH_SECTOR_SIZE)) + { + DBG_PRINT_ERR(FLZONE_API, "\r\nDOCHWritePartitionSectorsSingleFloor(): Sector "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("#%d device number:%d "), i,deviceNum)); + DBG_PRINT_ERR(FLZONE_API, "Verify failed ! \r\n"); + + return DOCH_WriteFault; + } + + verBufOrig += DOCH_SECTOR_SIZE; + } + } +#endif /*FL_VERIFY_WRITE*/ + /*8. Return actual number of written sectors*/ + /*------------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return rc; + +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e P a r t i t i o n S e c t o r s */ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWritePartitionSectors(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + if(pdev == NULL) + return DOCH_AdapterNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + pdev->bAtaDevNum=0; + rc= DOCHWritePartitionSectorsSingleFloor(ioreq); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): DOCHWritePartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): Failure on partition that resides ENTIRELY on Dev0 "); + } + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + IOreq ioreq2; + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc= DOCHWritePartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): DOCHWritePartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): Failure on partition that resides ENTIRELY on Dev1 "); + } + ioreq->irSectorCount =ioreq2.irSectorCount; + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + IOreq ioreq2; + FLDword sectorsToWriteToFirstChunk; + FLDword sectorsToWriteToSecondChunk; + + /*irLength => First sector to read*/ + /*irCount => Number of sectors to read*/ + if( ((FLDword)((ioreq->irLength + ioreq->irCount))) > pdev->sSpanData.dwSpanSector) + { + if(((FLDword)ioreq->irLength) >= pdev->sSpanData.dwSpanSector) + { + sectorsToWriteToFirstChunk = 0; + sectorsToWriteToSecondChunk = ioreq->irCount; + + } + else + { + sectorsToWriteToFirstChunk = (pdev->sSpanData.dwSpanSector - ioreq->irLength); + sectorsToWriteToSecondChunk = (ioreq->irCount - sectorsToWriteToFirstChunk); + } + } + else + { + sectorsToWriteToFirstChunk = ioreq->irCount; + sectorsToWriteToSecondChunk = 0; + } + + ioreq->irSectorCount = 0; + /*Write first chunk to Dev0*/ + /*-------------------------*/ + if(sectorsToWriteToFirstChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToWriteToFirstChunk; + pdev->bAtaDevNum = 0; + rc= DOCHWritePartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): DOCHWritePartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): Failure on spanned partition when writing chunk to Dev0 "); + return rc; + } + ioreq->irSectorCount =ioreq2.irSectorCount; + + }/*end of Write first chunk to Dev0*/ + + /*Write 2nd chunk to Dev1*/ + /*-----------------------*/ + if(sectorsToWriteToSecondChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToWriteToSecondChunk; + + /*Fix first sector to read*/ + if(sectorsToWriteToFirstChunk > 0) + ioreq2.irLength = 0; + else + { + ioreq2.irLength = (ioreq->irLength - pdev->sSpanData.dwSpanSector); + } + + ioreq2.irData = (FLByte*)ioreq->irData + (sectorsToWriteToFirstChunk<sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + + rc= DOCHWritePartitionSectorsSingleFloor(&ioreq2); + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): DOCHWritePartitionSectorsSingleFloor returned status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + DBG_PRINT_ERR(FLZONE_API, "DOCHWritePartitionSectors(): Failure on spanned partition when writing chunk to Dev1 "); + } + pdev->bAtaDevNum = 0; + ioreq->irSectorCount +=ioreq2.irSectorCount; + return rc; + }/*end of Write 2nd chunk to Dev1*/ + + }/*DOCH_PARTITION_IS_SPANNED*/ + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e A n d L o c k */ +/* */ +/* Writes sectors by sector no to a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* irFlags : DOCH_USE_DMA */ +/* DOCH_USE_BURST */ +/* Note: 4 methods of data transfer are */ +/* available: */ +/* Normal transfer */ +/* DMA transfer */ +/* Burst transfer */ +/* DMA & Burst transfer */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_PARTITION */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors NOT read (in case of an */ +/* error - this number may not be accurate) */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteAndLockSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + IOreq ioreq2; + DOCH_Registers out_regs; + + /*Sector arithmetic*/ + /*-----------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_written_so_far = 0; + + /*Buffer to write from*/ + /*--------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Set DMA and Burst modes according to request*/ + /*--------------------------------------------*/ + pdev->bUseDMA = (((ioreq->irFlags & DOCH_USE_DMA) == DOCH_USE_DMA) && + (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) && + (DOCH_DMA_CHECK_BUFFER(buf_ptr, total_num_of_sectors))); + + pdev->bUseBurst = ((ioreq->irFlags & DOCH_USE_BURST) == DOCH_USE_BURST); + + /*Write sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + + rc = performSectorsOperation(DOCH_VSCMD_WRITE_PARTITION, + 0, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_written_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteAndLockSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc,pdev->bAtaDevNum)); + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Cancel DMA and Burst modes*/ + /*--------------------------*/ + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Cancel DMA and Burst modes*/ + /*--------------------------*/ + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + /* Now lock the partition as OTP */ + /*-------------------------------*/ + tffsset(&protAPI, 0, sizeof(DOCH_PartitionProtectionAPI)); + tffsset(&ioreq2, 0, sizeof(ioreq2)); + tffscpy(&ioreq2.irHandle, &ioreq->irHandle, sizeof(ioreq2.irHandle)); + ioreq2.irData = &protAPI; + ioreq2.irFlags = DOCH_LOCK_AS_OTP; + rc = DOCHSetParitionProtectionSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteAndLockSingleFloor(): DOCHSetParitionProtection failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d \r\n"), rc, pdev->bAtaDevNum)); + + return rc; + } + + /*Return actual number of written sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return DOCH_OK; +} + +DOCH_Error DOCHWriteAndLock(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + FLDword sectorsToWriteToFirstChunk; + FLDword sectorsToWriteToSecondChunk; + FLByte* buf; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + /*avoid locking OTP when passed length (in sectors) is zero*/ + if (ioreq->irCount==0) + return DOCH_BadParameter; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHWriteAndLockSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHWriteAndLockSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*irLength => First sector to read*/ + /*irCount => Number of sectors to read*/ + if( ((FLDword)((ioreq->irLength + ioreq->irCount))) > pdev->sSpanData.dwSpanSector) + { + if(((FLDword)ioreq->irLength) >= pdev->sSpanData.dwSpanSector) + { + sectorsToWriteToFirstChunk = 0; + sectorsToWriteToSecondChunk = ioreq->irCount; + + } + else + { + sectorsToWriteToFirstChunk = (pdev->sSpanData.dwSpanSector - ioreq->irLength); + sectorsToWriteToSecondChunk = (ioreq->irCount - sectorsToWriteToFirstChunk); + } + } + else + { + sectorsToWriteToFirstChunk = ioreq->irCount; + sectorsToWriteToSecondChunk = 0; + } + + /*Write first chunk to Dev0*/ + /*-------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToWriteToFirstChunk; + rc = DOCHWriteAndLockSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Write 2nd chunk to Dev1*/ + /*-----------------------*/ + if(sectorsToWriteToSecondChunk > 0) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToWriteToSecondChunk; + ioreq2.irLength = 0; + buf = (FLByte*)ioreq->irData; + ioreq2.irData = buf + (sectorsToWriteToFirstChunk<sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHWriteAndLockSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H F r e e S e c t o r s */ +/* */ +/* Marks absolute sectors by sector no. as free to be written */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorNo : First sector no. to free */ +/* irSectorCount : Number of consecutive sectors to free */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ERASE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually deleted */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHFreeSectorsSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_freed_so_far = 0; + + /*Dummy buffer for use of performSectorsOperation()*/ + /*-------------------------------------------------*/ + FLByte* buf_ptr = NULL; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Free sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + + rc = performSectorsOperation(DOCH_VSCMD_ERASE_PARTITION_SECTORS, + 0, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_freed_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHFreeSectorsSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Return actual number of freed sectors*/ + /*-------------------------------------*/ + ioreq->irSectorCount = sectors_freed_so_far; + + return DOCH_OK; +} + +DOCH_Error DOCHFreeSectors(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + FLDword sectorsToDeleteFromFirstChunk; + FLDword sectorsToDeleteFromSecondChunk; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHFreeSectorsSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHFreeSectorsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*irLength => First sector to read*/ + /*irCount => Number of sectors to read*/ + if( ((FLDword)((ioreq->irLength + ioreq->irCount))) > pdev->sSpanData.dwSpanSector) + { + if(((FLDword)ioreq->irLength) >= pdev->sSpanData.dwSpanSector) + { + sectorsToDeleteFromFirstChunk = 0; + sectorsToDeleteFromSecondChunk = ioreq->irCount; + + } + else + { + sectorsToDeleteFromFirstChunk = (pdev->sSpanData.dwSpanSector - ioreq->irLength); + sectorsToDeleteFromSecondChunk = (ioreq->irCount - sectorsToDeleteFromFirstChunk); + } + } + else + { + sectorsToDeleteFromFirstChunk = ioreq->irCount; + sectorsToDeleteFromSecondChunk = 0; + } + + /*Free first chunk from Dev0*/ + /*--------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToDeleteFromFirstChunk; + rc = DOCHFreeSectorsSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Free 2nd chunk from Dev1*/ + /*------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irCount = sectorsToDeleteFromSecondChunk; + ioreq2.irLength = 0; + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHFreeSectorsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* D O C H W i p e S e c t o r s */ +/* */ +/* Securely erase data in sectors */ +/* */ +/* Parameters: */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorCount : Number of sectors to wipe */ +/* irSectorNumber : Start sector to wipe */ +/* */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SECURE_ERASE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWipeSectorsSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLDword dwStartSector=ioreq->irSectorNo; + FLDword dwSectorCount=0; + FLDword dwLastSector =(ioreq->irSectorCount + dwStartSector); + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(partNum >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + tffsset(wipeSectorsDev, 0, sizeof(wipeSectorsDev)); + + while (dwStartSector< dwLastSector) + { + if (!(dwStartSector%DOCH_MINIMAL_UNIT_SIZE)) + { + /*aligned to unit*/ + if (dwLastSector-dwStartSector>=DOCH_MINIMAL_UNIT_SIZE) + dwSectorCount= DOCH_MINIMAL_UNIT_SIZE; + else + dwSectorCount=TFFSMIN(DOCH_MINIMAL_PAGE_SIZE,(dwLastSector-dwStartSector)); + } else + { + /*not aligned to unit*/ + if (!(dwStartSector%DOCH_MINIMAL_PAGE_SIZE)) + { /*aligned to page*/ + dwSectorCount=TFFSMIN(DOCH_MINIMAL_PAGE_SIZE,(dwLastSector-dwStartSector)); + } + else + { /*not aligned to page*/ + dwSectorCount=TFFSMIN(DOCH_MINIMAL_PAGE_SIZE,(dwLastSector-dwStartSector)); + dwSectorCount=TFFSMIN((DOCH_MINIMAL_PAGE_SIZE-(dwStartSector%DOCH_MINIMAL_PAGE_SIZE)),dwSectorCount); + } + } + + /* sector to transfer: 1..2 sectors with following layout: */ + /* - 1st 8bytes - reserved as zeros */ + /* - (FLDWord) : First sector to delete */ + /* (FLDWord) : # of sectors to delete */ + /* - (FLDWord) : Second sector to delete */ + /* (FLDWord) : # of sectors to delete */ + /* - ... */ + /* - (FLDWord) : Nth sector to delete */ + /* (FLDWord) : # of sectors to delete */ + /* * Last transaction should have both start */ + /* and length fields set to 0. */ + + toLE4(wipeSectorsDev[2], dwStartSector); + toLE4(wipeSectorsDev[3], dwSectorCount); + + /* Update ATA register values */ + /*----------------------------*/ + in_regs.bFeaturesError = DOCH_SECURE_ERASE; + in_regs.bSectorCount = partNum; + in_regs.bSectorNumber = 1/*one sector to transfer*/; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /* Activate ATA command */ + /*----------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + wipeSectorsDev, + 1 /*one sector to transfer*/); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWipeSectorsSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d partition:%d \r\n") + ,rc, pdev->bAtaDevNum,partNum)); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("Parameters: startSector:%d sectorNo:%d \r\n") + ,ioreq->irSectorNo,ioreq->irSectorCount)); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("Failed at: startsector:%d sectorNo:%d \r\n") + ,dwStartSector,dwSectorCount)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + dwStartSector+=dwSectorCount; + }/*while loop*/ + + return DOCH_OK; +} + + + +/*----------------------------------------------------------------------*/ +/* D O C H W i p e S e c t o r s */ +/* */ +/* Securely erase data in sectors */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorCount : Number of sectors to wipe */ +/* irSectorNumber : Start sector to wipe */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SECURE_ERASE */ +/* */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +DOCH_Error DOCHWipeSectors(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + +#ifndef DOCH_NO_AUTO_WIPE_SECTORS + /*Retrieve device user attributes*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq2, pdev->wSocketNo); + ioreq2.irData = &devUserAttr; + DOCHGetDiskUserAttributes(&ioreq2); + + /* Set secure delete info of both devices, for case of power failure during operation*/ + devUserAttr.sdkAttributes.sSecureDeleteDev1.bPart = partNum; + devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteStartSector = ioreq->irSectorNo; + devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteNumOfSectors = ioreq->irSectorCount; + devUserAttr.sdkAttributes.sSecureDeleteDev1.bOperationRequired = TRUE; + + /*Set attributes back to the device*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; + if(rc != DOCH_OK) + return rc; +#endif /*DOCH_NO_AUTO_WIPE_SECTORS*/ + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if( (!pdev->sSpanData.secondFloorActive) || (partNum < pdev->sSpanData.bLastPartitionOnDev0) || + ((partNum == pdev->sSpanData.bLastPartitionOnDev0) && (!pdev->sSpanData.bLastDev0PartSpanned)) ) + { + rc = DOCHWipeSectorsSingleFloor(ioreq); + goto InsertCompleteIndication; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(((pdev->sSpanData.secondFloorActive) && (partNum > pdev->sSpanData.bLastPartitionOnDev0)) + && (pdev->wNumOfDevices > 1)) + { + tffscpy(&ioreq2,ioreq, sizeof(ioreq2)); + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHWipeSectorsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + goto InsertCompleteIndication; + } + + /*If partition is spanned */ + /*=======================*/ + if(((pdev->sSpanData.bLastDev0PartSpanned) && (partNum == pdev->sSpanData.numOfSpannedPartitionOnDev0)) + && (pdev->wNumOfDevices > 1)) + { + + FLDword dwDev1StartSector=0; + FLDword dwDev1SectorCount=0; + + tffsset(&ioreq2,0, sizeof(ioreq2)); /*will contain dev0 information*/ + + /*Split requested sectors to delete to Dev0/Dev1*/ + /*----------------------------------------------*/ + + if((FLDword)ioreq->irSectorNo > pdev->sSpanData.dwSpanSector) + { + /* all required sectors are in dev1*/ + dwDev1StartSector= (FLDword)(ioreq->irSectorNo - pdev->sSpanData.dwSpanSector); + dwDev1SectorCount= (FLDword)ioreq->irSectorCount; + } + else if ((FLDword)(ioreq->irSectorNo + ioreq->irSectorCount) > pdev->sSpanData.dwSpanSector) + { + /* part of the sectors is in dev1*/ + dwDev1SectorCount=(FLDword)(ioreq->irSectorCount - (pdev->sSpanData.dwSpanSector - ioreq->irSectorNo)); + ioreq2.irSectorCount= (FLDword)(pdev->sSpanData.dwSpanSector - ioreq->irSectorNo); + ioreq2.irSectorNo = (FLDword)ioreq->irSectorNo; + }else + { + /* all required sectors are in dev0*/ + ioreq2.irSectorNo = (FLDword)ioreq->irSectorNo; + ioreq2.irSectorCount= (FLDword)ioreq->irSectorCount; + } + + + /*Wipe sectors on Dev0*/ + /*--------------------*/ + if (ioreq2.irSectorCount) + { + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2,partNum); + rc = DOCHWipeSectorsSingleFloor(&ioreq2); + if(rc != DOCH_OK) + goto InsertCompleteIndication;; + } + + + /*Wipe Sectors on Dev1*/ + /*--------------------*/ + if (dwDev1SectorCount) + { + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + ioreq2.irSectorNo = (FLDword)dwDev1StartSector; + ioreq2.irSectorCount= (FLDword)dwDev1SectorCount; + + pdev->bAtaDevNum = 1; + rc = DOCHWipeSectorsSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + } + } + +InsertCompleteIndication: + if (rc!=DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWipeSectors(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x partition:%d \r\n"),rc,partNum)); + /* we leave the indication in disk attributes only if + the failure is a result of power loss*/ + if (rc==DOCH_TimedOut || rc==DOCH_DeviceTurnedOff) + return rc; + /* On all other failures- we will not retry erasing */ + } + +#ifndef DOCH_NO_AUTO_WIPE_SECTORS + /* Zero secure delete info */ + devUserAttr.sdkAttributes.sSecureDeleteDev1.bOperationRequired = FALSE; + devUserAttr.sdkAttributes.sSecureDeleteDev1.bPart = 0; + devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteStartSector = 0; + devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteNumOfSectors = 0; + + /*Set attributes back to the device*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = &devUserAttr; + gSDKUpdatesDiskAttributes = DOCH_GLOBAL_BOOL_PATTERN; + rc = DOCHSetDiskUserAttributes(&ioreq2); + gSDKUpdatesDiskAttributes = 0; +#endif /*DOCH_NO_AUTO_WIPE_SECTORS*/ + + return rc; + +} + + + +/*----------------------------------------------------------------------*/ +/* D O C H P r e p a r e F o r W r i t e */ +/* */ +/* Signal to DOCH that these sectors are going to be over-written in */ +/* following write command */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHPrepareForWrite(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectorsPreparedSoFar = 0; + + /*Buffer to "write" from*/ + /*----------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + rc = performSectorsOperation(DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS, + PREPARE_FOR_WRITE_OP, + pdev, + ioreq, + &out_regs, + ioreq->irSectorCount, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §orsPreparedSoFar, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHPrepareForWrite(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + /*If not enough free space - defragment*/ + /*-------------------------------------*/ + if(ioreq->irSectorCount > out_regs.bSectorCount) + { + IOreq ioreq2; + ioreq2.irHandle = ioreq->irHandle; + rc = DOCHOptimizeMedia(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHPrepareForWrite(): DOCHOptimizeMedia failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + + } + + return DOCH_OK; +} + +#if 0 +/* Flexi-Flash */ + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e F l e x i F a s t */ +/* */ +/* Flexi-Flash Write Fast */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_FLEXI */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteFlexiFast(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + FLByte operationRetries = 0; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_written_so_far = 0; + + /*Buffer to write from*/ + /*--------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Write sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + +dochWriteFlexiRetryPoint: + + rc = performSectorsOperation(DOCH_VSCMD_WRITE_FLEXI, + 0, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_written_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteFlexiFast(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if( ((rc & DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) == DOCH_ATA_ERROR_ADDRESS_MARK_NOT_FOUND) && + (operationRetries++ < 4) + ) + goto dochWriteFlexiRetryPoint; + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Return actual number of written sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e F l e x i N o r m a l */ +/* */ +/* Flexi-Flash Write Normal */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_FLEXI */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteFlexiNormal(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_written_so_far = 0; + + /*Buffer to write from*/ + /*--------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Write sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + + rc = performSectorsOperation(DOCH_VSCMD_WRITE_FLEXI, + WRITE_NORMAL_OP, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_written_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteFlexiNormal(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Return actual number of written sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e W r i t e F l e x i N o r m a l */ +/* */ +/* Flexi-Flash Re-Write Normal */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually re-written */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReWriteFlexiNormal(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + DOCH_Registers out_regs; + + /*Sectors arithmetic*/ + /*------------------*/ + FLSDword total_num_of_sectors = ioreq->irSectorCount; + FLSDword sectorNumber = ioreq->irSectorNo; + FLSNative sectors_written_so_far = 0; + + /*Buffer to rewrite from*/ + /*----------------------*/ + FLByte* buf_ptr = (FLByte*)ioreq->irData; + FLSNative buf_offset = 0; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*If a negative number of sectors was requested - return error*/ + /*------------------------------------------------------------*/ + if(total_num_of_sectors < 0) + return DOCH_BadParameter; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = TRUE; + + + /*Write sectors in DOCH_MAX_SECTORS quantities*/ + /*--------------------------------------------*/ + while(total_num_of_sectors > 0) + { + FLSNative sectors_this_cycle; + + if(total_num_of_sectors > DOCH_MAX_SECTORS) + sectors_this_cycle = DOCH_MAX_SECTORS; + else + sectors_this_cycle = total_num_of_sectors; + + rc = performSectorsOperation(DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS, + REWRITE_NORMAL_OP, + pdev, + ioreq, + &out_regs, + sectors_this_cycle, + (FLSNative*)§orNumber, + (FLSNative*)&total_num_of_sectors, + §ors_written_so_far, + &buf_offset, + buf_ptr); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReWriteNormal(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else if((rc & DOCH_ATA_ERROR_ID_NOT_FOUND) == DOCH_ATA_ERROR_ID_NOT_FOUND) + return DOCH_PartitionLimitExceeded; + else + return DOCH_GeneralFailure; + } + } + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + /*Return actual number of written sectors*/ + /*---------------------------------------*/ + ioreq->irSectorCount = sectors_written_so_far; + + return DOCH_OK; +} + + +/*----------------------------------------------------------------------*/ +/* D O C H M a n a g e A t o m i c W r i t e S e q */ +/* */ +/* Manage atomic write sequence per partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : DOCH_START_ATOMIC_WRITE */ +/* DOCH_FINISH_ATOMIC_WRITE */ +/* DOCH_ABORT_ATOMIC_WRITE */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_ATOMIC_WRITE_SEQUENCE */ +/* */ +/* Returns: */ +/* irLength : Maximal possible length */ +/* irFlags : Maximal possible length without performance */ +/* loss. */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHManageAtomicWriteSeq(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_ATOMIC_WRITE_SEQUENCE; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = (FLByte)(ioreq->irCount); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Return values*/ + /*-------------*/ + ioreq->irLength = out_regs.bSectorCount + (out_regs.bSectorNumber << 8); + ioreq->irFlags = out_regs.bCylLow + (out_regs.bCylHigh << 8); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHManageAtomicWriteSeq(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } + +} + +#endif /*0*/ + + +/*----------------------------------------------------------------------*/ +/* D O C H A c c e s s P a r t W i t h P w d */ +/* */ +/* Insert the protection key in order to remove the protection of the */ +/* specified partition or the entire media */ +/* Partition could be authenticated both by user and master password */ +/* the last successful authentication supersedes the previous one. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : Authentication Type */ +/* : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irCount : Authenticate the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* irData : Pointer to an DOCH_PartitionAcessPassword struct */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_EN_ACCESS_WPWD */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHAccessPartWithPwdSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_PartitionAcessPassword* partPwdToBig = (DOCH_PartitionAcessPassword*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_EN_ACCESS_WPWD; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_PartitionAcessPassword) / DOCH_SECTOR_SIZE)); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAccessPartWithPwdSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHAccessPartWithPwd(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHAccessPartWithPwdSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHAccessPartWithPwdSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*Set to chunk on Dev0*/ + /*--------------------*/ + rc = DOCHAccessPartWithPwdSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + /*Set to chunk on Dev0*/ + /*--------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHAccessPartWithPwdSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H D i s a b l e P a r t A c c e s s */ +/* */ +/* Remove the protection key making the partition protected again */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : Disable access for the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* irFlags : Authentication to withdraw */ +/* DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_DISABLE_ACCESS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHDisablePartAccessSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_DISABLE_ACCESS; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHDisablePartAccessSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc,pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHDisablePartAccess(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHDisablePartAccessSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHDisablePartAccessSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*Set to chunk on Dev0*/ + /*--------------------*/ + rc = DOCHDisablePartAccessSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + /*Set to chunk on Dev0*/ + /*--------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHDisablePartAccessSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; +} + +#if 0 + +/*----------------------------------------------------------------------*/ +/* D O C HS e n d H o s t P K e y */ +/* */ +/* Host sends its public key for this partition & random challenge */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irCount : Send key for the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* irData : Pointer to DOCH_HostPublicKey structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_TX_HOST_PUBLICKEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSendHostPublicKey(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_HostPublicKey* hostPublicKeyToBig = (DOCH_HostPublicKey*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_TX_HOST_PUBLICKEY; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_HostPublicKey) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + hostPublicKeyToBig->wVersion = be_FLWord((FLByte*)&hostPublicKeyToBig->wVersion); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSendHostPublicKey(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C HR e c e i v e D o c h P u b l i c K e y */ +/* */ +/* DOCH sends its public key, host's random challenge encrypted by DOCH */ +/* private key, and DOCH's random challenge to host */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irCount : Receive key for the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* irData : Pointer to DOCH_DochPublicKey structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_RX_DOCH_PUBLICKEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReceiveDochPublicKey(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_DochPublicKey* dochPublicKeyToBig = (DOCH_DochPublicKey*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_RX_DOCH_PUBLICKEY; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_DochPublicKey) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + dochPublicKeyToBig->wVersion = be_FLWord((FLByte*)&dochPublicKeyToBig->wVersion); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReceiveDochPublicKey(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H V e r i f y H o s t K e y */ +/* */ +/* Host sends DOCH's random challenge encrypted by host's private key */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : DOCH_ACCESS_USER_PASSWORD */ +/* DOCH_ACCESS_MASTER_PASSWORD */ +/* DOCH_ACCESS_GATE_KEEPER */ +/* irCount : Verify key for the entire device */ +/* DOCH_ACCESS_ALL_PARTITIONS */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_VERIFY_HOST_KEY */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHVerifyHostKey(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_VerifyHostKey* verifyHostKeyToBig = (DOCH_VerifyHostKey*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte sectorCountValue = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + if(ioreq->irCount == DOCH_ACCESS_ALL_PARTITIONS) + sectorCountValue = 0xFF; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_VERIFY_HOST_KEY; + in_regs.bSectorCount = sectorCountValue; + in_regs.bSectorNumber = (FLByte)(ioreq->irFlags); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_VerifyHostKey) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + verifyHostKeyToBig->wVersion = be_FLWord((FLByte*)&verifyHostKeyToBig->wVersion); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHVerifyHostKey(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +#endif /*0*/ + +/*----------------------------------------------------------------------*/ +/* D O C H S e t P a r i t i o n P r o t e c t i o n */ +/* */ +/* Set partition properties (attributes/passkey) . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionProtectionAPI */ +/* irFlags : DOCH_PASSKEY_VALID */ +/* DOCH_ATTRIBUTES_VALID */ +/* DOCH_LOCK_AS_OTP */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_PARTITION_PROTECTION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetParitionProtectionSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_PartitionProtectionAPI* partProperties = (DOCH_PartitionProtectionAPI*)(ioreq->irData); + DOCH_Socket* pdev; + IOreq ioreq2; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + tffsset(&partFormatInfo, 0, sizeof(DOCH_PartitionFormatInfo)); + + /*Retrieve current partition info from DOCH*/ + /*-----------------------------------------*/ + tffsset(&ioreq2, 0, sizeof(IOreq)); + ioreq2.irHandle = ioreq->irHandle; + ioreq2.irData = &partitionInfoTemp; + rc = DOCHPartitionInfoSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetParitionProtectionSingleFloor(): DOCHPartitionInfoSingleFloor Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d"), rc,pdev->bAtaDevNum)); + return rc; + } + + if((ioreq->irFlags & DOCH_ATTRIBUTES_VALID) == DOCH_ATTRIBUTES_VALID) + { + /*Format DOCH_PartitionProtectionAPI structure to DOCH_PartitionFormatInfo*/ + /*------------------------------------------------------------------------*/ + + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_PROTECTION_TYPE, + DOCH_PA2O_PROTECTION_TYPE, + partProperties->dwProtectionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_USER_MODE, + DOCH_PA2O_USER_MODE, + partProperties->dwUserAccessMode); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_GUEST_MODE, + DOCH_PA2O_GUEST_MODE, + partProperties->dwGuestAccessMode); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_MASTER_CTRL, + DOCH_PA2O_MASTER_CTRL, + partProperties->dwMasterControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_ENCRYPT_TYPE, + DOCH_PA2O_ENCRYPT_TYPE, + partProperties->dwEncryptionType); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_LOCK_CTRL, + DOCH_PA2O_LOCK_CTRL, + partProperties->dwLockControl); + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_MAX_AUTH_ATTEMPTS, + DOCH_PA2O_MAX_AUTH_ATTEMPTS, + partProperties->dwMaxNumOfAuthAttempts); + + /*Preserve current OTW setting (Can only be set by AddPartition)*/ + DOCH_SetBits(&partFormatInfo.partitionAttributes2, + DOCH_PA2B_OTP_BIT, + DOCH_PA2O_OTP_BIT, + ((partitionInfoTemp.partitionAttributes2 & DOCH_PA2B_OTP_BIT) >> DOCH_PA2O_OTP_BIT)); + + } + else + partFormatInfo.partitionAttributes2 = 0; + + if((ioreq->irFlags & DOCH_PASSKEY_VALID) == DOCH_PASSKEY_VALID) + tffscpy(&partFormatInfo.bPasskey[0], &partProperties->bPasskey[0], sizeof(partFormatInfo.bPasskey)); + else + tffsset(&partFormatInfo.bPasskey[0], 0, sizeof(partFormatInfo.bPasskey)); + + partFormatInfo.dwValidity = (ioreq->irFlags & (DOCH_PASSKEY_VALID | DOCH_ATTRIBUTES_VALID | DOCH_LOCK_AS_OTP +#ifdef FL_SOTP + |DOCH_SEQUENTIAL_OTP +#endif /*FL_SOTP*/ + )); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + partFormatInfo.dwValidity = be_FLDword((FLByte*)&partFormatInfo.dwValidity); + partFormatInfo.dwCommandFlagsOrStatuses = be_FLDword((FLByte*)&partFormatInfo.dwCommandFlagsOrStatuses); + partFormatInfo.partitionAttributes1 = be_FLDword((FLByte*)&partFormatInfo.partitionAttributes1); + partFormatInfo.partitionAttributes2 = be_FLDword((FLByte*)&partFormatInfo.partitionAttributes2); + partFormatInfo.nPartitionSize = be_FLDword((FLByte*)&partFormatInfo.nPartitionSize); + partFormatInfo.nFastAreaSize = be_FLDword((FLByte*)&partFormatInfo.nFastAreaSize); + + partFormatInfo.wFastAreaFactor = be_FLWord((FLByte*)&partFormatInfo.wFastAreaFactor); + #endif /*DOCH_BIG_ENDIAN*/ + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_PARTITION_PROTECTION; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &partFormatInfo, + (sizeof(DOCH_PartitionFormatInfo) / DOCH_SECTOR_SIZE)); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetParitionProtectionSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d"), rc,pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHSetParitionProtection(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*If partition resides ENTIRELY on Dev0*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV0) + { + rc = DOCHSetParitionProtectionSingleFloor(ioreq); + return rc; + } + + /*If partition resides ENTIRELY on Dev1*/ + /*=====================================*/ + if(DOCH_PARTITION_ON_DEV1) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHSetParitionProtectionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + return rc; + } + + /*If partition is spanned - collect both infos and combine*/ + /*========================================================*/ + if(DOCH_PARTITION_IS_SPANNED) + { + /*Set to chunk on Dev0*/ + /*--------------------*/ + rc = DOCHSetParitionProtectionSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + /*Set to chunk on Dev0*/ + /*--------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.numOfSpannedPartitionOnDev0 + 1)); + + pdev->bAtaDevNum = 1; + rc = DOCHSetParitionProtectionSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t P a r i t i o n U s e r A t t r i b u t e s */ +/* */ +/* Set partition user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionUserAttr */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_SET_PARTITION_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetParitionUserAttributesSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; +#ifdef DOCH_BIG_ENDIAN + DOCH_PartitionUserAttr* partAttrToBig = (DOCH_PartitionUserAttr*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*First retrieve current attributes sector + (for protecting first 0x40 bytes that are SDK specific*/ + /*------------------------------------------------------*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + ioreq2.irData = currentAttributes; + DOCHGetParitionUserAttributesSingleFloor(&ioreq2); + + /*Use currentAttributes bytes 0x41..0x200 to set requested*/ + /*--------------------------------------------------------*/ + tffscpy(¤tAttributes[DOCH_PART_INFO_SDK_RESERVED_BYTES], + (((FLByte*)ioreq->irData) + DOCH_PART_INFO_SDK_RESERVED_BYTES), + (DOCH_SECTOR_SIZE - DOCH_PART_INFO_SDK_RESERVED_BYTES)); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_PARTITION_USER_ATTR; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + currentAttributes, + (sizeof(DOCH_PartitionUserAttr) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetParitionUserAttributesSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHSetParitionUserAttributes(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Partition resides on Dev0*/ + /*-------------------------*/ + if((partNum <= pdev->sSpanData.bLastPartitionOnDev0) || + (!pdev->sSpanData.secondFloorActive)) + { + rc = DOCHSetParitionUserAttributesSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + } + /*Partition resides on Dev1*/ + /*-------------------------*/ + else if(partNum <= pdev->wTotalNumOfPartitions) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHSetParitionUserAttributesSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + if(rc != DOCH_OK) + return rc; + } + /*Partition not present*/ + /*---------------------*/ + else + return DOCH_PartitionNotFound; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H G e t P a r i t i o n U s e r A t t r i b u t e s */ +/* */ +/* Get partition user attributes . */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irData : Pointer to DOCH_PartitionUserAttr */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_PARTITION_MANAGEMENT */ +/* ATA sub-command: */ +/* DOCH_GET_PARTITION_USER_ATTR */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetParitionUserAttributesSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_PartitionUserAttr* partAttrToBig = (DOCH_PartitionUserAttr*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Check if Partition exceeds number of existing partitions*/ + /*--------------------------------------------------------*/ + if(DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq) >= pdev->device[pdev->bAtaDevNum].wNumOfPartitions) + return DOCH_PartitionNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_PARTITION_USER_ATTR; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (pdev->bAtaDevNum * DOCH_DEVICE); + in_regs.bCommandStatus = DOCH_VSCMD_PARTITION_MANAGEMENT; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_PartitionUserAttr) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetParitionUserAttributesSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHGetParitionUserAttributes(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + DOCH_Socket* pdev; + FLByte partNum = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Partition resides on Dev0*/ + /*-------------------------*/ + if((partNum <= pdev->sSpanData.bLastPartitionOnDev0) || + (!pdev->sSpanData.secondFloorActive)) + { + rc = DOCHGetParitionUserAttributesSingleFloor(ioreq); + } + /*Partition resides on Dev1*/ + /*-------------------------*/ + else if(partNum <= pdev->wTotalNumOfPartitions) + { + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + + if(pdev->sSpanData.bLastDev0PartSpanned) + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0 + 1)); + else + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, (partNum - pdev->sSpanData.bLastPartitionOnDev0)); + + pdev->bAtaDevNum = 1; + rc = DOCHGetParitionUserAttributesSingleFloor(&ioreq2); + pdev->bAtaDevNum = 0; + } + /*Partition not present*/ + /*---------------------*/ + else + return DOCH_PartitionNotFound; + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H O p t i m i z e M e d i a */ +/* */ +/* Performs garbage collection. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* */ +/* irLength : DOCH_OPTIMIZE_BY_PREPARE_FOR_WRITE */ +/* based on information collected during previous */ +/* PREPARE FOR WRITE commands */ +/* DOCH_OPTIMIZE_DEFAULT */ +/* performs default optimization of the whole */ +/* partition or media */ +/* irFlags : DOCH_NORMAL_OPERATION */ +/* DOCH_IMMEDIATE_OPERATION */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_OPTIMIZE_MEDIA */ +/* */ +/* Returns: */ +/* irLength : Actual number of sectors available for writes */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHOptimizeMedia(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte action_type; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(ioreq->irFlags == DOCH_IMMEDIATE_OPERATION) + action_type = ERASE_IMMEDIATE; + else + action_type = ERASE_NORMAL; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_OPTIMIZE_MEDIA; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = (FLByte)(ioreq->irLength); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = (action_type|DOCH_LBA); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Actual number of sectors available for writes*/ + ioreq->irSectorCount = out_regs.bSectorNumber + + ((FLSDword)out_regs.bCylLow << 8) + + ((FLSDword)out_regs.bCylHigh << 16) + + ((FLSDword)out_regs.bDriveHead << 24) ; + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHOptimizeMedia(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H G e t C u s t o m P a r a m e t e r */ +/* */ +/* Returns 16-bit custom DOCH parameter */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irCount : Parameter# (see DOCH_CustomParams) */ +/* irFlags : DOCH_CUSTOM_PARAM_DEFAULT - default value */ +/* DOCH_CUSTOM_PARAM_TEMP - current (saved) value*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* irSectorNo : Custom parameter value (16-Bit) */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetCustomParameter(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte setType; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(ioreq->irFlags == DOCH_CUSTOM_PARAM_TEMP) + setType = CUSTOM_PARAM_TEMP; + else if(ioreq->irFlags == DOCH_CUSTOM_PARAM_DEFAULT) + setType = CUSTOM_PARAM_DEFAULT; + else + return DOCH_BadParameter; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_CUSTOM_PARAM; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = (FLByte)(ioreq->irCount & 0x00FF); + in_regs.bDriveHead = ((FLByte)(((ioreq->irCount & 0x0F00) >> 8)) | setType |DOCH_LBA); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Return retrieved custom parameter value*/ + /*---------------------------------------*/ + ioreq->irSectorNo = (out_regs.bCylLow << 8) + out_regs.bSectorNumber; + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetCustomParameter(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t C u s t o m P a r a m e t e r */ +/* */ +/* Sets 16-bit custom DOCH parameter */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Custom Parameter Number (DOCH_CustomParams) */ +/* irSectorNo : Custom Parameter Value (16-Bit) */ +/* irFlags : DOCH_CUSTOM_PARAM_DEFAULT - default value */ +/* DOCH_CUSTOM_PARAM_TEMP - current (saved) value*/ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_CUSTOM_PARAM */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetCustomParameterSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + FLByte setType; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if(ioreq->irFlags == DOCH_CUSTOM_PARAM_TEMP) + setType = CUSTOM_PARAM_TEMP; + else if(ioreq->irFlags == DOCH_CUSTOM_PARAM_DEFAULT) + setType = CUSTOM_PARAM_DEFAULT; + else + return DOCH_BadParameter; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_CUSTOM_PARAM; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = (FLByte)(ioreq->irSectorNo & 0x00FF); + in_regs.bCylLow = (FLByte)((ioreq->irSectorNo & 0xFF00) >> 8); + in_regs.bCylHigh = (FLByte)(ioreq->irCount & 0x00FF); + in_regs.bDriveHead = (((FLByte)(((ioreq->irCount & 0x0F00) >> 8)) | setType) | DOCH_SELECT_DEV(pdev->bAtaDevNum)); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetCustomParameterSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x device number:%d\r\n"), rc, pdev->bAtaDevNum)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) /*Protection violation - IPL is write protected*/ + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHSetCustomParameter(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + FLByte origDevNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + origDevNum = pdev->bAtaDevNum; + + pdev->bAtaDevNum = 0; + rc = DOCHSetCustomParameterSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHSetCustomParameterSingleFloor(ioreq); + pdev->bAtaDevNum = origDevNum; + } + + return rc; +} + +#if 0 +/*----------------------------------------------------------------------*/ +/* D O C H A u t o H a s h C o n t r o l */ +/* */ +/* Enable/Disable Auto Hash Read/Write */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : AUTO_HASH_ENABLE */ +/* AUTO_HASH_DISABLE */ +/* irLength : AUTO_HASH_READ */ +/* AUTO_HASH_WRITE */ +/* irFlags : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_AUTO_HASH_CONTROL */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHAutoHashControl(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_AUTO_HASH_CONTROL; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = (FLByte)((ioreq->irCount) | (ioreq->irLength<<1) | (ioreq->irFlags<<2)); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAutoHashControl(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e a d C a l c u l a t e d H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers to host digest(s) calculated from data on the flash. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_CALCULATED_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadCalculatedHash(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = 0; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_READ_CALCULATED_HASH; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadCalculatedHash(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e C a l c u l a t e d H a s h */ +/* */ +/* Command for Paged partitions */ +/* No data is transfered. Digest(s) calculated from data in the flash */ +/* are stored to the dedicated area on flash. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_CALCULATED_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteCalculatedHash(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = 0; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + if(ioreq->irCount == DOCH_HASH_ENCRYPT_BY_KEY) + in_regs.bDriveHead |= HASH_BY_KEY; + else + in_regs.bDriveHead |= HASH_AS_IS; + in_regs.bCommandStatus = DOCH_VSCMD_WRITE_CALCULATED_HASH; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteCalculatedHash(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e a d O r i g i n a l H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers to host digest(s) stored previously on dedicated area on */ +/* flash */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_READ_ORIGINAL_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadOriginalHash(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Socket* pdev; + DOCH_Registers out_regs; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = 0; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + if(ioreq->irCount == DOCH_HASH_ENCRYPT_BY_KEY) + in_regs.bDriveHead |= HASH_BY_KEY; + else + in_regs.bDriveHead |= HASH_AS_IS; + in_regs.bCommandStatus = DOCH_VSCMD_READ_ORIGINAL_HASH; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadOriginalHash(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H W r i t e G i v e n H a s h */ +/* */ +/* Command for Paged partitions */ +/* Transfers from host digest(s) and stores them to the dedicated area */ +/* on flash */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_NO_ENCRYPTION */ +/* DOCH_HASH_ENCRYPT_BY_KEY */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_WRITE_GIVEN_HASH */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHWriteGivenHash(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = 0; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + if(ioreq->irCount == DOCH_HASH_ENCRYPT_BY_KEY) + in_regs.bDriveHead = HASH_BY_KEY; + else + in_regs.bDriveHead = HASH_AS_IS; + in_regs.bCommandStatus = DOCH_VSCMD_WRITE_GIVEN_HASH; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHWriteGivenHash(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e p o r t S u p p o r t e d A l g o r i t h m s */ +/* */ +/* Report supported algorithms */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irData : Pointer to DOCH_supportedAlgorithms structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_REPORT_SUPPORTED_ALGORITHMS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReportSupportedAlgorithms(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_supportedAlgorithms* suppAlgToBig = (DOCH_supportedAlgorithms*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_REPORT_SUPPORTED_ALGORITHMS; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_supportedAlgorithms) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + suppAlgToBig->wVersion = be_FLWord((FLByte*)&suppAlgToBig->wVersion); + + suppAlgToBig->wSymmetricAlgorithmsSupported = be_FLDword((FLByte*)&suppAlgToBig->wSymmetricAlgorithmsSupported); + suppAlgToBig->wAsymmetricAlgorithmsSupported= be_FLDword((FLByte*)&suppAlgToBig->wAsymmetricAlgorithmsSupported); + suppAlgToBig->wHashSchemesSupported = be_FLDword((FLByte*)&suppAlgToBig->wHashSchemesSupported); + suppAlgToBig->wRNGSchemesSupported = be_FLDword((FLByte*)&suppAlgToBig->wRNGSchemesSupported); + suppAlgToBig->wDecompressionSchemesSupported= be_FLDword((FLByte*)&suppAlgToBig->wDecompressionSchemesSupported); + suppAlgToBig->wCompressionSchemesSupported = be_FLDword((FLByte*)&suppAlgToBig->wCompressionSchemesSupported); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReportSupportedAlgorithms(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H G e t A l g o r i t h m C a p a b i l i t i e s */ +/* */ +/* Get algorithms capabilities */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Algorithm Category */ +/* irLength : Algorithm # in the Category */ +/* irData : Pointer to DOCH_AlgorithmCapabilities */ +/* structure */ +/* */ +/* */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_GET_ALGORITHM_CAPABILITIES */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetAlgorithmCapabilities(IOreq* ioreq) +{ + DOCH_Error rc; +#ifdef DOCH_BIG_ENDIAN + DOCH_AlgorithmCapabilities* algCapToBig = (DOCH_AlgorithmCapabilities*)(ioreq->irData); +#endif /*DOCH_BIG_ENDIAN*/ + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_ALGORITHM_CAPABILITIES; + in_regs.bSectorCount = (FLByte)(ioreq->irCount); + in_regs.bSectorNumber = (FLByte)(ioreq->irLength); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + (sizeof(DOCH_AlgorithmCapabilities) / DOCH_SECTOR_SIZE)); + + #ifdef DOCH_BIG_ENDIAN + /*In case of a BIG ENDIAN host CPU, reorder bytes in 16 and 32 Bit variables*/ + algCapToBig->wVersion = be_FLWord((FLByte*)&algCapToBig->wVersion); + algCapToBig->wNumOfKeySizesSupported = be_FLWord((FLByte*)&algCapToBig->wNumOfKeySizesSupported); + algCapToBig->wNumOfModesSupported = be_FLWord((FLByte*)&algCapToBig->wNumOfModesSupported); + + algCapToBig->keysAttributes->dwSize + = be_FLDword((FLByte*)&algCapToBig->keysAttributes->dwSize); + algCapToBig->keysAttributes->dwCalcTime + = be_FLDword((FLByte*)&algCapToBig->keysAttributes->dwCalcTime); + algCapToBig->modesAttributes->wKeySizes + = be_FLWord((FLByte*)&algCapToBig->modesAttributes->wKeySizes); + #endif /*DOCH_BIG_ENDIAN*/ + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetAlgorithmCapabilities(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t A l g o r i t h m M o d e */ +/* */ +/* Set algorithms mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* bits 16..24 - Mode index */ +/* bits 24..31 - Key size index */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_ALGORITHM_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetAlgorithmMode(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_ALGORITHM_MODE; + in_regs.bSectorCount = (FLByte)(ioreq->irCount & 0x000F); + in_regs.bSectorNumber = (FLByte)((ioreq->irCount & 0x00F0) >> 8); + in_regs.bCylLow = (FLByte)((ioreq->irCount & 0x0F00) >> 16); + in_regs.bCylHigh = (FLByte)((ioreq->irCount & 0xF000) >> 24); + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetAlgorithmMode(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S t a r t H a s h S t r e a m C a l c u l a t i o n */ +/* */ +/* Restart/Continue hash stream calculation */ +/* Several streams can be supported at the same time, but only one */ +/* should be active at any moment. */ +/* Host should issue Stop command to the current stream, before */ +/* starting or resuming a new stream. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category (hash) */ +/* bits 8..15 - Algorithm # in category */ +/* bits 16..23 - Stream # */ +/* irLength : DOCH_HASH_REINITIALIZE */ +/* DOCH_HASH_CONTINUE */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_START_HASH_STREAM_CALC */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHStartHashStreamCalculation(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_START_HASH_STREAM_CALC; + in_regs.bSectorCount = (FLByte)(ioreq->irCount & 0x000F); + in_regs.bSectorNumber = (FLByte)((ioreq->irCount & 0x00F0) >> 8); + in_regs.bCylLow = (FLByte)((ioreq->irCount & 0x0F00) >> 16); + in_regs.bCylHigh = 0; + in_regs.bDriveHead = ((FLByte)(ioreq->irLength))|DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHStartHashStreamCalculation(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e a d S t o p H a s h S t r e a m C a l c */ +/* */ +/* Read/Stop hash stream calculation */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_CONTINUE_ACCUM */ +/* DOCH_HASH_STOP_ACCUM */ +/* irLength : DOCH_HASH_DONT_RETURN_DATA */ +/* DOCH_HASH_RETURN_ACCUM_DIGEST */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_READ_STOP_HASH_STREAM_CALC */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReadStopHashStreamCalc(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_READ_STOP_HASH_STREAM_CALC; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = ((FLByte)(ioreq->irCount) | (FLByte)(ioreq->irLength) |DOCH_LBA); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReadStopHashStreamCalc(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e t u r n R a n d om N u m b e r s */ +/* */ +/* Return random numbers */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : bits 0..7 - Algorithm Category */ +/* bits 8..15 - Algorithm # in category */ +/* irLength : # of 32-Bit random numbers to generate */ +/* (max is 64, e.g full sector) */ +/* irData : Pointer to 1 sector of data which will hold */ +/* the number of requested random numbers */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_RETURN_RANDOM_NUMBERS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHReturnRandomNumbers(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_RETURN_RANDOM_NUMBERS; + in_regs.bSectorCount = (FLByte)(ioreq->irCount & 0x000F); + in_regs.bSectorNumber = (FLByte)((ioreq->irCount & 0x00F0) >> 8); + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = ((FLByte)(ioreq->irLength))|DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + DOCH_SECTOR_SIZE); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHReturnRandomNumbers(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t H a s h K e y */ +/* */ +/* Set hash key */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : DOCH_HASH_DECRYPTION_KEY */ +/* DOCH_HASH_ENCRYPTION_KEY */ +/* irLength : DOCH_HASH_USE_DOCH_PUBLIC_KEY */ +/* DOCH_HASH_USE_HOST_PUBLIC_KEY */ +/* DOCH_HASH_USE_PARTITION_PUBLIC_KEY */ +/* irFlags : DOCH_HASH_USE_DOCH_PRIVATE_KEY */ +/* DOCH_HASH_USE_HOST_PRIVATE_KEY */ +/* irData : 1 Sector of data in case of any "receive" */ +/* option. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_SECURITY_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_KEYS */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetHashKey(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_KEYS; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + + in_regs.bDriveHead = ((FLByte)(ioreq->irCount) | + ((FLByte)(ioreq->irLength & 0x03) << 2) | + ((FLByte)(ioreq->irFlags & 0x03) << 4)) |DOCH_LBA; + + in_regs.bCommandStatus = DOCH_VSCMD_EXT_SECURITY_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetHashKey(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} + +#endif /*0*/ + + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P o w e r M o d e */ +/* */ +/* Retrieve device power mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_POWER_MODE */ +/* */ +/* Returns: */ +/* irFlags : */ +/* DOCH_PM_WORK_MODE */ +/* DOCH_PM_INACTIVE_MODE */ +/* irCount : */ +/* Bits 0..1 : Work Mode */ +/* DOCH_WM_NORMAL */ +/* DOCH_WM_LOW_FREQ */ +/* DOCH_WM_NORMAL_AND_AUTO_STBY */ +/* DOCH_WM_LOW_FREQ_AND_AUTO_STBY */ +/* Bits 4..5 : Inactive Mode */ +/* DOCH_IM_IDLE */ +/* DOCH_IM_DPD */ +/* DOCH_IM_IDLE_2_DPD */ +/* irLength : Value of timeout for automatic transfer to */ +/* Inactive mode (0 = disabled) */ +/* Timer value is in milliseconds. */ +/* If Inactive mode is "Standby to DPD" timer */ +/* resolution is 100 ms. */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetPowerMode(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_POWER_MODE; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead =DOCH_SELECT_DEV (pdev->bAtaDevNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DOCHGetPowerMode(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } + + /*Set output values*/ + ioreq->irFlags = out_regs.bSectorCount; + ioreq->irCount = out_regs.bSectorNumber; + ioreq->irLength = (out_regs.bCylLow + (out_regs.bCylHigh<<8)); + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D O C H S e t P o w e r M o d e */ +/* */ +/* Set device power mode */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFlags : */ +/* Bits 0..1 - which mode(s) should be set */ +/* DOCH_PM_SET_WORK_MODE */ +/* DOCH_PM_SET_INACTIVE_MODE */ +/* DOCH_PM_SET_BOTH_MODES */ +/* DOCH_PM_SET_NONE */ +/* Bit 2 - which mode device should pass to after set */ +/* DOCH_PM_WORK_MODE */ +/* DOCH_PM_INACTIVE_MODE */ +/* Bit 4 */ +/* DOCH_PM_SAVE_DEFAULT */ +/* (Save new settings as default settings ) */ +/* irCount : */ +/* Bits 0..1 : Work Mode to be set */ +/* DOCH_WM_NORMAL */ +/* DOCH_WM_LOW_FREQ */ +/* DOCH_WM_NORMAL_AND_AUTO_STBY */ +/* DOCH_WM_LOW_FREQ_AND_AUTO_STBY */ +/* Bits 4..5 : Inactive Mode to be set */ +/* DOCH_IM_IDLE */ +/* DOCH_IM_DPD */ +/* DOCH_IM_IDLE_2_DPD */ +/* irLength : Value of timeout for automatic transfer to */ +/* Inactive mode (0 = disabled) */ +/* Timer value is in milliseconds. */ +/* If Inactive mode is "Standby to DPD" timer */ +/* resolution is 100 ms. */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_SET_POWER_MODE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSetPowerModeSingleFloor(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + FLByte setType; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + if((ioreq->irFlags & DOCH_PM_SAVE_DEFAULT) == DOCH_PM_SAVE_DEFAULT) + setType = DRIVE_HEAD_OPT1; + else + setType = 0; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SET_POWER_MODE; + in_regs.bSectorCount = (FLByte)(ioreq->irFlags & 0x0000000F); + in_regs.bSectorNumber = (FLByte)ioreq->irCount; + in_regs.bCylLow = (FLByte)(ioreq->irLength & 0x000000FF); + in_regs.bCylHigh = (FLByte)((ioreq->irLength & 0x0000FF00) >> 8); + in_regs.bDriveHead = (DOCH_SELECT_DEV(pdev->bAtaDevNum) | setType); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + if(rc == DOCH_OK) + { + /*Update DPD settings*/ + if( (ioreq->irFlags&DOCH_PM_SET_WORK_MODE) || (ioreq->irFlags&DOCH_PM_SET_BOTH_MODES) ) + { + gDpdSettings.activeMode = (ioreq->irCount & 0x0000000F); + } + if( (ioreq->irFlags&DOCH_PM_SET_INACTIVE_MODE) || (ioreq->irFlags&DOCH_PM_SET_BOTH_MODES) ) + { + gDpdSettings.inActiveMode = (ioreq->irCount & 0x000000F0); + } + + gDpdSettings.timeOut = ioreq->irLength; + + /*If HAL is SPI, disable DPD*/ + if(gAccessLayerType == DOCH_AL_SPI) + gDpdSettings.activeMode = DOCH_WM_NORMAL; + + return DOCH_OK; + } + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSetPowerModeSingleFloor(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x deviceNum:\r\n"), rc,pdev->bAtaDevNum)); + + return DOCH_GeneralFailure; + } +} + +DOCH_Error DOCHSetPowerMode(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + pdev->bAtaDevNum = 0; + rc = DOCHSetPowerModeSingleFloor(ioreq); + if(rc != DOCH_OK) + return rc; + + if(pdev->wNumOfDevices > 1) + { + pdev->bAtaDevNum = 1; + rc = DOCHSetPowerModeSingleFloor(ioreq); + pdev->bAtaDevNum = 0; + } + + return rc; +} + +#if 0 /* save this api because the command defined in spec */ +/*----------------------------------------------------------------------*/ +/* D O C H C a l i b r a t e C l o c k */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irCount : Desired SYS ICMU clock, in MHZ */ +/* irLength : Desired FLASH ICMU clock, in MHZ */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_EXT_DEVICE_CTRL */ +/* ATA sub-command: */ +/* DOCH_CALIBRATE_CLOCK */ +/* */ +/* Returns: */ +/* irCount : SYS ICMU correction factor */ +/* irLength : FLASH ICMU correction factor */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHCalibrateClock(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_CALIBRATE_CLOCK; + in_regs.bSectorCount = (FLByte)ioreq->irCount; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = (FLByte)ioreq->irLength; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + NULL, + 0); + + /*Output*/ + /*------*/ + ioreq->irCount = out_regs.bSectorCount + (out_regs.bSectorNumber << 8); + ioreq->irLength= out_regs.bCylLow + (out_regs.bCylHigh << 8); + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHCalibrateClock(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_GeneralFailure; + } +} +#endif /*0*/ /* save this api because the command defined in spec */ + +/******************************************************************************/ +/* + * General (Control/Configuration) + */ +/******************************************************************************/ + +void setConfigHWDefaults(void) +{ + gConfigHWDefaults[DOCH_BURST_WRITE_MODE_CTRL] = DOCH_BURST_WRITE_MODE_DEFAULT; + + gConfigHWDefaults[DOCH_BURST_READ_MODE_CTRL] = DOCH_BURST_READ_MODE_DEFAULT; + + gConfigHWDefaults[DOCH_IPL_CTRL] = DOCH_IPL_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_WARM_BOOT_CTRL] = DOCH_WARM_BOOT_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_POWER_DOWN] = DOCH_POWER_DOWN_DEFAULT; + + gConfigHWDefaults[DOCH_DMA_CTRL] = DOCH_DMA_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_DMA_NEGATION_CTRL] = DOCH_DMA_NEGATION_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_SLOCK] = DOCH_SLOCK_DEFAULT; + + gConfigHWDefaults[DOCH_ENDIAN_CTRL] = DOCH_ENDIAN_CTRL_DEFAULT; + + gConfigHWDefaults[DOCH_OPERATION_MODE_CTRL] = DOCH_OPERATION_MODE_CTRL_DEFAULT; + + gConfigHWInitDone = DOCH_GLOBAL_BOOL_PATTERN; +} + +/*----------------------------------------------------------------------*/ +/* D O C H H w C o n f i g */ +/* */ +/* Control HW registers */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based) */ +/* irFlags : HW Configuration type */ +/* (See DOCH_HwConfigType for values) */ +/* irLength : HW configuration type dependant */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHConfigHW(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq2; + FLByte devNum = 0; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + if(pdev == NULL) + return DOCH_DiskNotFound; + + /* Set default values if not set yet (e.g. DochSDKInit() was not called yet!) */ + if(gConfigHWInitDone != DOCH_GLOBAL_BOOL_PATTERN) + setConfigHWDefaults(); + + gConfigHWDefaults[ioreq->irFlags] = ioreq->irLength; + + /*If init was not done yet, only keep requested value*/ + if(gSdkDOCAddressObtained != DOCH_GLOBAL_BOOL_PATTERN) + { + return DOCH_OK; + } + +setConfigItemToDevice: + + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV(devNum)); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,devNum); + + + switch((DOCH_HwConfigType)(ioreq->irFlags)) + { + case DOCH_BURST_WRITE_MODE_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_BURST_WRITE_MODE_CTRL_REG, + ioreq->irLength); + break; + + case DOCH_BURST_READ_MODE_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_BURST_READ_MODE_CTRL_REG, + ioreq->irLength); + break; + + case DOCH_IPL_CTRL: + if(ioreq->irLength & DOCH_IPL_WRITE_ENABLE) + { + FLWord wTmpConfigVal = doch_getConfigReg16(pdev, HIB_IPL_CONTROL_REG); + if((wTmpConfigVal & DOCH_IPL_WRITE_READY) != DOCH_IPL_WRITE_READY) + { + rc = DOCH_ATANotReady; + break; + } + } + rc = doch_setConfigReg16 (pdev, + HIB_IPL_CONTROL_REG, + ioreq->irLength); + break; + + case DOCH_WARM_BOOT_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_WARM_BOOT_REG, + ioreq->irLength); + break; + + case DOCH_POWER_DOWN: + rc = doch_setConfigReg16 (pdev, + HIB_POWER_DOWN_REG, + ioreq->irLength); + break; + + case DOCH_DMA_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_DMA_CTRL_REG, + ioreq->irLength); + break; + + case DOCH_DMA_ENABLE: + if(ioreq->irLength) + { +#ifdef DOCH_DMA_CONFIG + gIsDMAEnabled = DOCH_GLOBAL_BOOL_PATTERN; +#endif /*DOCH_DMA_CONFIG*/ + } + else + { + gIsDMAEnabled = 0; + } + break; + + case DOCH_DMA_NEGATION_CTRL: + rc = doch_setConfigReg16 (pdev, + HIB_DMA_NEGATION_REG, + ioreq->irLength); + break; + + case DOCH_SLOCK: + rc = doch_setConfigReg16(pdev, + HIB_SW_LOCK_REG, + ioreq->irLength); + if(rc != DOCH_OK) + break; + + /* If SLOCK was requested, set by ATA command also*/ + if(ioreq->irLength == TRUE) + { + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_SLOCK_CTRL; + ioreq2.irSectorNo = ioreq->irLength; + ioreq2.irFlags = DOCH_CUSTOM_PARAM_TEMP; + rc = DOCHSetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + break; + } + break; + + case DOCH_ENDIAN_CTRL: + rc = doch_setConfigReg16(pdev, + HIB_ENDIAN_CTRL_REG, + ioreq->irLength); + break; + + case DOCH_OPERATION_MODE_CTRL: + rc = doch_setConfigReg16(pdev, + HIB_OPERATION_MODE_REG, + ioreq->irLength); + break; + + case DOCH_POWER_MODE_CTRL: + rc = doch_setConfigReg16(pdev, + HIB_POWER_MODE_REG, + ioreq->irLength); + break; + + default: + return DOCH_FeatureNotSupported; + } + + /* If Dev1 exists, set config Item as well*/ + if ((devNum == 0) && (ATA_MAX_NUM_OF_DEVICES>1)) + { + devNum = 1; + goto setConfigItemToDevice; + } + + if (devNum == 1) + { + /*Set device back to Dev0*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + } + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* D O C H R e c o v e r F r o m P o w e r L o s s */ +/* */ +/* Set last known values of DOCH control registers back to device after */ +/* power loss was detected. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* irFLags : DOCH_DO_NOT_REINIT_MASTER */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHRecoverFromPowerLoss(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket* pdev; + register FLByte i; + IOreq ioreq2; + FLByte bConfFloor = FALSE; + FLByte bFloorsNum; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*general initializations (not required if master was already configured)*/ + if (!(ioreq->irFlags & DOCH_DO_NOT_REINIT_MASTER)) + { + /* Re-set all control register values to device */ + rc = doch_configCommon(pdev); + if(rc != DOCH_OK) + return rc; + bConfFloor =TRUE; + } + + /* init both floors */ + rc = doch_init_floors(pdev,bConfFloor,&bFloorsNum); + if(rc != DOCH_OK) + return rc; + + for (i=0;iwNumOfDevices;i++) + { + pdev->bAtaDevNum = i; + + /*Restore DPD settings */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irHandle = ioreq->irHandle; + ioreq2.irFlags = (DOCH_PM_SET_BOTH_MODES | DOCH_PM_WORK_MODE); + ioreq2.irCount = (gDpdSettings.activeMode | gDpdSettings.inActiveMode); + ioreq2.irLength = gDpdSettings.timeOut; + rc = DOCHSetPowerModeSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + + /*Restore transfer mode */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irHandle =ioreq->irHandle; + ioreq2.irCount = pdev->device[i].dataTransferMode; + ioreq2.irLength = pdev->device[i].dwMulti_Current; + rc = DOCHSetDataTransferModeSingleFloor(&ioreq2); + if(rc != DOCH_OK) + return rc; + +#ifdef FL_REPORT_INTERNAL_ERRORS + /* Set DocH to report internal errors*/ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_REPORT_ECC_MODE; + ioreq2.irSectorNo = (FLWord)(DOCH_ENABLE_REPORT_ECC_ERRORS); + ioreq2.irFlags = DOCH_CUSTOM_PARAM_TEMP; + ioreq2.irHandle =ioreq->irHandle; + rc = DOCHSetCustomParameterSingleFloor(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_WRN_PRM(FLZONE_ATA, (FLTXT("\r\nWARNING: Failed setting mDoc to report internal errors with status %d \r\n"), rc)); + rc=DOCH_OK; + /*return rc;*/ /*do not fail - backward compatibility*/ + } +#endif /*FL_REPORT_INTERNAL_ERRORS*/ + + } /*for each floor*/ + + pdev->bAtaDevNum =0; +#ifdef CHECK_POWER_ON_EVERY_COMMAND + { + IOreq ioreq2; + + /*Make sure next calls to DOCHGetResetStatus() will reflect actual reset*/ + tffscpy(&ioreq2, ioreq, sizeof(ioreq2)); + DOCHGetResetStatus(&ioreq2); + } +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H A t a R e s e t */ +/* */ +/* Perform ATA reset operation for a specific socket */ +/* Effects both Device0 and Device1 */ +/* */ +/* Parameters: */ +/* socketNum : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error flDOCHAtaReset(FLByte socketNum) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_InitSocket initSocket; + + DOCH_get_socket(pdev, socketNum); + + DBG_PRINT_ERR(FLZONE_API, "\r\n***********************************\r\n"); + DBG_PRINT_ERR(FLZONE_API, "\r\n* Performing flDOCHAtaReset() !!! *\r\n"); + DBG_PRINT_ERR(FLZONE_API, "\r\n***********************************\r\n"); + + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + return DOCH_BadParameter; + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + + /*----------------------------------------------------------*/ + /* Reset the device(s) using "Set alert level" command */ + /* In case of cascaded configuration - both devices are */ + /* reset prior to checking status since in case of changing */ + /* window size (8/128KB) - Dev1 will not be reachable after */ + /* resetting Dev0 and reinitializing the SDK window */ + /*----------------------------------------------------------*/ + /*Send reset command to Dev1 (if exists)*/ + if(pdev->wNumOfDevices > 1) + { + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV1); /*Dev1*/ + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,1); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, 0x7F); /*Set Alert Level*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, 1); /*"And Reboot"*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, 0xFF); /*Invalid alert level*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, 0xFC); /*Extended Device Contrl*/ + } + /*Send reset command to Dev0*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); /*Dev0*/ + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, 0x7F); /*Set Alert Level*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, 1); /*"And Reboot"*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, 0xFF); /*Invalid alert level*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, 0xFC); /*Extended Device Contrl*/ + +#ifdef DEBUG_TIMEOUT + { + FLDword dwTimeAfterHigh,dwTimeAfterLow,dwTimeBeforeHigh,dwTimeBeforeLow; + FLDword diffHigh,diffLow,dwWaitingTime; + FLDword scaledFreq; + + GetInternalSysTimer(&dwTimeBeforeHigh,&dwTimeBeforeLow); +#endif /*DEBUG_TIMEOUT*/ + + DOCH_DELAY_MSEC(200); + +#ifdef DEBUG_TIMEOUT + GetInternalSysTimer(&dwTimeAfterHigh,&dwTimeAfterLow); + scaledFreq= SysTimerFrequency/1000; /*mSec*/ + diffHigh=(dwTimeAfterHigh-dwTimeBeforeHigh); + if(dwTimeAfterLow>=dwTimeBeforeLow) + { + diffLow= dwTimeAfterLow-dwTimeBeforeLow; + } + else + { + if (!diffHigh) + { + DBG_PRINT_ERR(FLZONE_ATA,"\nticks difference is negative\n"); + } + diffLow= 0xFFFFFFFFl- dwTimeBeforeLow + dwTimeAfterLow; + diffHigh --; + + } + dwWaitingTime = (FLSDword)( (((0xFFFFFFFFl)/(scaledFreq)))*(diffHigh))+ + (((0xFFFFFFFFl)%(scaledFreq))*(diffHigh+1) + (diffLow))/(scaledFreq); + + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks when started:high %lu low %lu"),dwTimeBeforeHigh,dwTimeBeforeLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks when timeout:high %lu low %lu"),dwTimeAfterHigh,dwTimeAfterLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks diff: high %d low %d"),diffHigh,diffLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nDetected frequency %lu"), SysTimerFrequency)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nDelay time %d msec"), dwWaitingTime)); + + } +#endif /*DEBUG_TIMEOUT*/ + + /* Search for the current window*/ + initSocket.nDeviceAddress = pdev->dwPhysicalAddress; + rc=doch_init_window (socketNum, initSocket); + if(rc != DOCH_OK) + return rc; + + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, socketNum); + ioreq.irFlags= DOCH_DO_NOT_REINIT_MASTER; /* master was initialized in init_window*/ + rc = DOCHRecoverFromPowerLoss(&ioreq); + + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S e t E n v V a r */ +/* */ +/* Set environment variable. */ +/* Available environment variables are listed in DOCH_EnVars. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* Partition number (zero based, if relevant) */ +/* irFlags : Environment variable */ +/* */ +/* irLength : Value to set */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error flDOCHSetEnvVar(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq ioreq2; + + switch((DOCH_EnVars)(ioreq->irFlags)) + { +#ifdef FL_VERIFY_WRITE + case DOCH_ENV_VERIFY_WRITE: + if(ioreq->irLength != 0) + gDochVerifyWrite[DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)] = DOCH_GLOBAL_BOOL_PATTERN; + else + gDochVerifyWrite[DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)] = 0; + return DOCH_OK; +#endif /*FL_VERIFY_WRITE*/ + + case DOCH_ENV_ATA_DEBUG: + if(ioreq->irLength != 0) + gDochAtaDebug = DOCH_GLOBAL_BOOL_PATTERN; + else + gDochAtaDebug = 0; + return DOCH_OK; + + case DOCH_ENV_BLOCK_SPI: + if(gSdkInitDone != DOCH_GLOBAL_BOOL_PATTERN) + { + /* We do not have a window address yet - can be added in the future. */ + DBG_PRINT_ERR(FLZONE_API, "Can not set SPI BLOCKING mode before calling init routine.\r\n"); + return DOCH_ATANotReady; + } + /* Take mutex for current device */ + rc = dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_ON, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallDOCH(): dochSetMutex failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + return rc; + } + + /* SDK is already initialized */ + tffsset(&ioreq2, 0, sizeof(ioreq2)); + ioreq2.irCount = DOCH_CP_WORK_MODES; + ioreq2.irFlags = DOCH_CUSTOM_PARAM_TEMP; + + /*Retreive current value (retrieved in irSectorNo)*/ + rc = DOCHGetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "flDOCHSetEnvVar(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + } + else + { + /*Modify value*/ + if(ioreq->irLength != 0) + { + ioreq2.irSectorNo |= DOCH_WORK_MODES_BLOCK_SPI; + } + else + { + ioreq2.irSectorNo &= ~(DOCH_WORK_MODES_BLOCK_SPI); + } + + /*Set modified value*/ + + rc = DOCHSetCustomParameter(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "flDOCHSetEnvVar(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + } + } + /* Free mutex for current device */ + dochSetMutex(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + DOCH_OFF, + DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq)); + + return rc; + + case DOCH_ENV_NO_ATA_TIMEOUT: + if(ioreq->irLength != 0) + { + gATANoTimeout = DOCH_GLOBAL_BOOL_PATTERN; + } + else + { + gATANoTimeout = 0; + } + + return DOCH_OK; + + case DOCH_ENV_AUTO_DPD_BY_HOST: + if(ioreq->irLength != 0) + gAutoDPDByHost = DOCH_GLOBAL_BOOL_PATTERN; + else + gAutoDPDByHost = 0; + + return DOCH_OK; + + default: + break; + } + + return DOCH_FeatureNotSupported; +} + +/*----------------------------------------------------------------------*/ +/* D O C H _ C l e a n I R Q _ I n t e r r u p t */ +/* */ +/* Clear the ATA interrupt. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHClearIRQ(IOreq* ioreq) +{ + DOCH_Error rc = clearATAInterrupt(DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + return rc; +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H G e t P h y s i c a l A d d r e s s */ +/* */ +/* Retrieve physical address of the socket. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (zero based) */ +/* */ +/* ATA command: */ +/* NONE */ +/* ATA sub-command: */ +/* NONE */ +/* */ +/* Returns: */ +/* irCount : Socket Physical Address */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHGetPhysicalAddress(IOreq* ioreq) +{ + DOCH_Socket* pdev; + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + ioreq->irCount = pdev->dwPhysicalAddress; + + return DOCH_OK; +} + +#ifdef FL_SLPP +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P U n l o c k R a n g e */ +/* */ +/* Unlock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to unlock */ +/* irLength : Number of sectors to unlock */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_UNLOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPUnlockRange(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + DOCH_SLPPRangeRequestSector rangeReq; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + tffsset(&rangeReq, 0, sizeof(rangeReq)); + rangeReq.dwRangeStartSector = ioreq->irCount; + rangeReq.dwRangeSizeInSectors = ioreq->irLength; + tffscpy(&rangeReq.passkey, ioreq->irData, 8); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_UNLOCK_RANGE; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &rangeReq, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPUnlockRange(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P U n l o c k E n t i r e P a r t i t i o n */ +/* */ +/* Unlock an entire Sector Protected Partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_UNLOCK_ENTIRE_PARTITION */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPUnlockEntirePartition(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + DOCH_SLPPRangeRequestSector rangeReq; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + tffsset(&rangeReq, 0, sizeof(rangeReq)); + tffscpy(&rangeReq.passkey, ioreq->irData, 8); + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_UNLOCK_ENTIRE_PARTITION; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &rangeReq, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPUnlockEntirePartition(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P L o c k R a n g e */ +/* */ +/* Lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to lock */ +/* irLength : Number of sectors to lock */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_LOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPLockRange(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + DOCH_SLPPRangeRequestSector rangeReq; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + tffsset(&rangeReq, 0, sizeof(rangeReq)); + rangeReq.dwRangeStartSector = ioreq->irCount; + rangeReq.dwRangeSizeInSectors = ioreq->irLength; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_LOCK_RANGE; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &rangeReq, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPLockRange(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P S t i c k y L o c k R a n g e */ +/* */ +/* Applies sticky lock to a range of sectors on a sector protected */ +/* partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to sticky lock */ +/* irLength : Number of sectors to sticky lock */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_STICKY_LOCK_RANGE */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPStickyLockRange(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + DOCH_SLPPRangeRequestSector rangeReq; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + tffsset(&rangeReq, 0, sizeof(rangeReq)); + rangeReq.dwRangeStartSector = ioreq->irCount; + rangeReq.dwRangeSizeInSectors = ioreq->irLength; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_STICKY_LOCK_RANGE; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + &rangeReq, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPStickyLockRange(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} + +/*----------------------------------------------------------------------*/ +/* f l D O C H S L P P R e p o r t R a n g e s */ +/* */ +/* Reports unlocked and sticky locked ranges of sector protected */ +/* partition. */ +/* */ +/* Parameters: */ +/* irHandle : bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to DOCH_SLPPReport structure */ +/* */ +/* ATA command: */ +/* DOCH_VSCMD_ACCESS_CONTROL */ +/* ATA sub-command: */ +/* DOCH_SLPP_REPORT_LOCKED_RANGES */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHSLPPReportLockedRanges(IOreq* ioreq) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq)); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_SLPP_REPORT_LOCKED_RANGES; + in_regs.bSectorCount = DOCH_GET_PARTITION_FROM_IOREQ_HANDLE(ioreq); + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_LBA; + in_regs.bCommandStatus = DOCH_VSCMD_ACCESS_CONTROL; + + /*Activate ATA command*/ + /*--------------------*/ + rc = doch_command ( DOCH_GET_SOCKET_FROM_IOREQ_HANDLE(ioreq), + pdev->bAtaDevNum, + &in_regs, + &out_regs, + ioreq->irData, + 1); + + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHSLPPReportLockedRanges(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + if((rc & DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) + return DOCH_ProtectionFault; + else + return DOCH_GeneralFailure; + } +} +#endif /*FL_SLPP*/ +/******************************************************************************/ +/* + * Pass-through routine + */ +/******************************************************************************/ + +/*----------------------------------------------------------------------*/ +/* D O C H A t a P a s s T h r o u g h */ +/* */ +/* Parameters: */ +/* socketNum : Socket to perform operation on */ +/* passThruOP : "0" - No Data */ +/* "1" - Data IN */ +/* "2" - Data OUT */ +/* in_regs : ATA Input registers values */ +/* out_regs : ATA Output registers values */ +/* secNum : Number of sectors to perform */ +/* userBuff : Pointer to user buffer */ +/* (for data in/out commands) */ +/* useInterrupt : Use interrupt when waiting on ATA busy */ +/* */ +/* ATA command: */ +/* user defined (in_regs->bCommandStatus) */ +/* ATA sub-command: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +DOCH_Error DOCHAtaPassThrough(FLSNative socketNum, + FLSNative passThruOP, + DOCH_Registers *in_regs, + DOCH_Registers *out_regs, + FLNative secNum, + void* userBuff, + FLBoolean useInterrupt) +{ + DOCH_Error rc; + DOCH_PassThru_Op ptOP = (DOCH_PassThru_Op)passThruOP; + FLSNative devNum = ((in_regs->bDriveHead & DOCH_DEVICE) == DOCH_DEVICE); + DOCH_Socket* pdev; + + DOCH_get_socket(pdev, socketNum); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Enable interrupts*/ + /*-----------------*/ + pdev->bUseInterrupt = useInterrupt; + + + /*Perform ATA command with registers values set above*/ + /*---------------------------------------------------*/ + rc = doch_ata_passthru (socketNum, devNum, ptOP, in_regs, out_regs, userBuff, secNum); + + /*Disable interrupts*/ + /*------------------*/ + pdev->bUseInterrupt = FALSE; + + if(rc == DOCH_OK) + return DOCH_OK; + else + { + DBG_PRINT_ERR(FLZONE_API, "DOCHAtaPassThrough(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return rc; + } + +} + +/*----------------------------------------------------------------------*/ +/* D o c h S D K I n i t */ +/* */ +/* Initializes the DOCH system, sockets and timers. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +DOCH_Error DochSDKInit(void) +{ + DOCH_Error rc = DOCH_OK; + IOreq ioreq; + IOreq ioreq2; + + /*Set global variable values*/ +#ifdef FL_VERIFY_WRITE + tffsset(gDochVerifyWrite, 0, sizeof(gDochVerifyWrite)); +#endif /*FL_VERIFY_WRITE*/ + tffsset(gDochIrqEnabled, 0, sizeof(gDochIrqEnabled)); + gAccessLayerType = DOCH_AL_NONE; + gATANoTimeout = 0; + gAutoDPDByHost = 0; + gDochAccessNanosec = DOCH_ACCESS_NANOSEC; + + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + return DOCH_BadParameter; + + /*Set DPD settings to defaults*/ + gDpdSettings.activeMode = DOCH_DPD_DEFAULT_ACTIVE_MODE; + gDpdSettings.inActiveMode = DOCH_DPD_DEFAULT_INACTIVE_MODE; + gDpdSettings.timeOut = DOCH_DPD_DEFAULT_DPD_TIMEOUT; + + /* Set ConfigHW items to defaults */ + if(gConfigHWInitDone != DOCH_GLOBAL_BOOL_PATTERN) + setConfigHWDefaults(); + +#ifdef DOCH_DMA_CONFIG + /* DMA channel was not opened yet... */ + gDMAChannelOpen = 0; +#endif /*DOCH_DMA_CONFIG*/ + + /* Init system related */ + DOCH_SYS_FUNC_INIT; + + /* Register DOCH components */ + rc = (DOCH_Error)flRegisterDochParams(); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "flRegisterDochParams(): failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + return rc; + } + + +#ifndef DOCH_NO_AUTO_WIPE_SECTORS + /* If Device User Attributes indicate that a secure wipe operation to Dev1 + was not issued (due to power failure) - complete the task before init is declared + as done */ + + /*Retrieve device user attributes*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, 0); + ioreq.irData = &devUserAttr; + DOCHGetDiskUserAttributes(&ioreq); + if(devUserAttr.sdkAttributes.sSecureDeleteDev1.bOperationRequired) + { + DBG_PRINT_ERR(FLZONE_API, "DochSDKInit(): Completing wipe-sectors operation due to power failure...\r\n"); + + tffsset(&ioreq2, 0, sizeof(ioreq2)); + + + ioreq2.irSectorNo = devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteStartSector; + ioreq2.irSectorCount = devUserAttr.sdkAttributes.sSecureDeleteDev1.dwSecureDeleteNumOfSectors; + + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq2, devUserAttr.sdkAttributes.sSecureDeleteDev1.bPart); + + rc = DOCHWipeSectors(&ioreq2); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DochSDKInit(): Wipe-sectors operation NOT completed! \r\n"); + return rc; + } + + DBG_PRINT_ERR(FLZONE_API, "DochSDKInit(): Wipe-sectors operation completed successfully \r\n"); + } +#endif /*DOCH_NO_AUTO_WIPE_SECTORS*/ + /*Set global variable*/ + gSdkInitDone = DOCH_GLOBAL_BOOL_PATTERN; + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* D o c h S D K E x i t */ +/* */ +/* If the application ever exits, DochSDKExit should be called before */ +/* exit. */ +/* DochSDKExit flushes all buffers, closes all open files, powers down */ +/* the sockets and removes the interval timer. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* Nothing */ +/*----------------------------------------------------------------------*/ +void DochSDKExit(void) +{ + #ifdef DOCH_DMA_CONFIG + DMA_Params_S dmaParams; + #endif /*DOCH_DMA_CONFIG*/ + + doch_release_socket(0); + + #ifdef DOCH_DMA_CONFIG + /*Free the DMA channel*/ + dmaParams.bOpType = DOCH_DMA_FREE_CHANNEL; + DOCH_DMA_CONFIG(&dmaParams); + if(dmaParams.fDmaStatus != 0) + { + DBG_PRINT_ERR(FLZONE_API, "DochSDKExit(): DOCH_DMA_FREE_CHANNEL Failed\r\n"); + } + #endif /*DOCH_DMA_CONFIG*/ + + DOCH_SYS_FUNC_RELEASE; + + gConfigHWInitDone = 0; + gSdkInitDone = 0; +} + +/*----------------------------------------------------------------------*/ +/* D o c h R e g i s t e r S o c k e t */ +/* */ +/* Register a DOCH socket */ +/* */ +/* Parameters: */ +/* dwAddress : Address were DOCH socket is located */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failure */ +/*----------------------------------------------------------------------*/ +DOCH_Error DochRegisterSocket(FLDword dwAddress) +{ + DOCH_Error rc; + DOCH_InitSocket initSocket; + tffsset(&initSocket, 0, sizeof(initSocket)); + initSocket.nDeviceAddress = dwAddress; + + rc = doch_init_socket(0,initSocket); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "DochSDKInit(): doch_init_socket Failed on socket #"); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("%d "), 0)); + DBG_PRINT_ERR(FLZONE_API, "with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \r\n"), rc)); + + return DOCH_AdapterNotFound; + } + + return DOCH_OK; +} + +#ifdef __cplusplus +} +#endif diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_api.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_api.h new file mode 100755 index 00000000..ea5625c0 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_api.h @@ -0,0 +1,130 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/***********************************************************************************/ +/* */ +/* Header file for doch_api module */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_api.h-arc $ + * + * Rev 1.32 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.31 Sep 11 2006 13:45:14 yaniv.iarovici + * Legal header added + * + * Rev 1.30 Aug 09 2006 17:26:52 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef _DOCH_API +#define _DOCH_API + +#include "flcommon.h" +#include "flchkdef.h" +#include "_dochapi.h" +#include "blockdev.h" + + +/************************/ +/* Exported routines */ +/************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern FLBoolean gDochIrqEnabled[]; + +DOCH_Error bdCallDOCH(int functionNo, IOreq *ioreq); +extern DOCH_Error doch_init_socket (int socketNo, DOCH_InitSocket); +extern DOCH_Error doch_release_socket( int socketNo ); + +extern FLDword gDochAccessNanosec; + + +/*----------------------------------------------------------------------*/ +/* f l B u i l d G e o m e t r y */ +/* */ +/* Get C/H/S information of the disk according to number of sectors. */ +/* */ +/* Parameters: */ +/* capacity : Number of Sectors in Volume */ +/* cylinders : Pointer to Number of Cylinders */ +/* heads : Pointer to Number of Heads */ +/* sectors : Pointer to Number of Sectors per Track */ +/* oldFormat : True for one sector per culoster */ +/* wIrHandle : Handle of the disk partition to check */ +/* */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API void NAMING_CONVENTION flBuildGeometry(FLDword capacity, FLDword FAR2 *cylinders, + FLDword FAR2 *heads, FLDword FAR2 *sectors, FLBoolean oldFormat, FLWord wIrHandle); + +/* Management routines */ +DOCH_Error flDOCHAtaReset(FLByte socketNum); +DOCH_Error DochSDKInit(void); +void DochSDKExit(void); +DOCH_Error DochRegisterSocket(FLDword dwAddress); + +/* User define component registration routine */ +DOCH_Error flRegisterDochComponents(void); +/* Access layer registration routines */ +DOCH_Error hal_init_nor (FLSNative socketNo); +DOCH_Error hal_init_spi (FLSNative socketNo); +DOCH_Error hal_init_sim (FLSNative socketNo); +DOCH_Error hal_init_nor_noFunc (FLSNative socketNo); +DOCH_Error hal_init_spi_noFunc (FLSNative socketNo); +DOCH_Error hal_init_sim_noFunc (FLSNative socketNo); +DOCH_Error hal_init_user_routines(FLSNative socketNo, DOCH_BusAccess_routines accessPointerStruct); + +void DOCH_SetBits(FLDword* var, FLDword mask, FLByte offset, FLDword val); + +#ifdef __cplusplus +} +#endif + +#endif /*_DOCH_API*/ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_ata.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_ata.c new file mode 100755 index 00000000..bbc2c9fe --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_ata.c @@ -0,0 +1,3599 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_ata.c-arc $ + * + * Rev 1.77 Dec 26 2007 10:13:16 einat.avidan + * io_input() - after data XFER - make sure DRQ is off. + * fixed sequences for init and recoverFromPowerLoss. + * removed DOCH_CHECK_CHIP_ID flag (always check chip ID) + * + * Rev 1.76 Dec 16 2007 11:36:02 einat.avidan + * add debug printout + * + * Rev 1.75 Dec 11 2007 12:28:34 einat.avidan + * init sequence and DOCHConfigHW: change parameters of internal functions + * remove obsolete code (function doch_status) + * + * Rev 1.74 Dec 04 2007 17:27:14 einat.avidan + * Add readiness check before io_x sequences. + * Avoid writing to the same register more than once in short time + * Bug fix: DOCHBLK_READ and DOCHBLK_WRITE do not return value. + * Wait for mount before reset during init sequence + * Bug fix: part of configuration registers should be set only after device selection + * def_dochDelayUsec - receives new parameter: access time. + * + * Rev 1.73 Nov 07 2007 19:18:56 einat.avidan + * fix compilation error in retrieveAndPrintAtaDebug + * + * Rev 1.72 Oct 30 2007 17:01:26 einat.avidan + * replace dochEnableATAInterrupt function with macros + * bug fix: after write DMA transactions-waiting for ready + * was too long. + * + * Rev 1.71 Oct 23 2007 15:35:18 einat.avidan + * failure in reset in 128K window caused failure in init + * + * Rev 1.70 Oct 23 2007 12:27:52 einat.avidan + * optimization: delay after setting head register only + * when switching floors + * + * Rev 1.69 Oct 22 2007 11:34:48 einat.avidan + * update copyrights header + * + * Rev 1.68 Oct 21 2007 16:57:08 einat.avidan + * fix compilation warnings + * + * + * Rev 1.67 Oct 21 2007 10:39:56 Einat.Avidan + * optimization: save address of each Hib area instead of + * saving offset and core address (spare repetitive add commands) + * check return value of DOCH_SET_WINDOW_OFFSET + * fix printout and comments + * optimization:spare allocation of unnecessary local variabeles + * bug fix: cascaded configuration support in doch_init_socket + * make several trials to select second floor and read it's chip ID + * fix compilation warning + * + * Rev 1.66 Oct 11 2007 18:48:22 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * caller responsibility to set device head register + * when calling to doch_check_chipID + * fix printouts + * Interrupts are enabeled\ disabeled in the ATA level instead of API level + * remove unrequired ready check in io_output io_input and io_ctrl + * add long wait in delete partition command + * doch_reset resets both floor (no need of devNum parameter) + * Add support for reporting internal errors + * caller responsible to set device head register + * when calling to dochEnableATAInterrupt + * upport cascaded configuration: add delay after device switch + * add compilation flags for SOTP and SLPP + * + * Rev 1.65 Sep 04 2007 15:37:58 einat.avidan + * fix printouts + * bug fix: in io_output(): add_partition and secure_erase should + * have longer waiting time + * bug fix: in doch_init_socket(): no need to call flDOCHSetPowerMode + * twice for each floor + * + * Rev 1.64 Apr 05 2007 15:44:54 einat.avidan + * compilation warning fix (SCR 2765) + * + * Rev 1.63 Mar 13 2007 13:47:20 einat.avidan + * add support for SLPP + * + * Rev 1.62 Mar 12 2007 14:49:36 einat.avidan + * add compilation flag for disable SW reset + * + * Rev 1.61 Mar 11 2007 16:30:48 einat.avidan + * bug fix: check NULL pointers before using it + * + * Rev 1.60 Feb 28 2007 10:32:50 einat.avidan + * CX tools support + * + * Rev 1.59 Feb 15 2007 17:50:28 Einat.Avidan + * Enable burst without DMA + * bug fix in burst with DMA: sent the ATA command before it entered the burst mode. + * bug fix in burst with DMA:Did not allow DMA with edge + * Enables reading status asynchronous or synchronous in burst + * + * + * Rev 1.57.2.5 Dec 04 2006 12:44:40 Yaniv.Iarovici + * Add ; to MACRO + * + * Rev 1.57.2.4 Nov 30 2006 10:23:46 Yaniv.Iarovici + * Added DOCH_WAIT_B4_DEV1_ID (anchor for setting a delay between Dev0 and Dev1 ID process). + * + * Rev 1.57.2.3 Nov 21 2006 14:26:22 Yaniv.Iarovici + * 1. Typo in comments + * 2. Check ChipID before applying ATA reset. + * + * Rev 1.57.2.2 Nov 12 2006 09:46:52 Yaniv.Iarovici + * 1. Fixed compilation warnings. + * 2. doch_reset(): + * - Added parameter 'FLBoolean waitOnBusy'. + * - Wait for BUSY signal in ATA status register de-assertion before sending SRST, if waitOnBusy is TRUE. + * + * Rev 1.57.2.1 Oct 31 2006 12:23:32 yaniv.iarovici + * Added doch_init_window(). + * + * Rev 1.57.2.0 Oct 29 2006 11:28:54 Yaniv.Iarovici + * Fixed compilation warning. + * + * Rev 1.57 Oct 05 2006 11:00:36 yaniv.iarovici + * 1. Removed dwMulti_Read, dwMulti_Write. + * 2. Added dwMulti_MAX. + * + * Rev 1.56 Sep 14 2006 09:56:38 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.55 Sep 11 2006 13:45:14 yaniv.iarovici + * Legal header added + * + * Rev 1.54 Sep 10 2006 10:03:28 Yaniv.Iarovici + * Bug Fix: DMA handling in io_input() and io_output() (Device Head Register). + * + * Rev 1.53 Sep 03 2006 14:44:34 Yaniv.Iarovici + * Fixed DMA handling handling when DRQ>1. + * + * Rev 1.52 Aug 16 2006 08:45:46 Yaniv.Iarovici + * 1) Remove comment regarding #define DOCH_CHECK_CHIP_ID + * 2) Add global var: 'gIgnoreErrorBit' - used by ready() to ignore error bit when checking status (used when identifying device using ATA standard IDENTIFY DEVICE command) + * 3) Remove commented function - doch_pause() + * 4) Add 2nd argument 'FLSNative devNum' to doch_check_chipID() + * 5) Update clear_socket() to support 'ETFFS_Identified' field + * 6) Move the call to retrieveAndPrintAtaDebug() to after command is completed in doch_ata_passthru() + * 7) Add support to check CHIP ID on specific device (not only Dev0) in doch_check_chipID() + * 8) Add dunction 'doch_ATAstd_IDENTIFY_DEVICE(FLSNative socketNo, FLSNative devNum)' to identify a device using ATA standard IDENTIFY DEIVCE command when ETFFS was not detected on the device + * 9) Modify doch_init_socket() to: + * - Identify a device using ATA standard IDENTIFY DEVICE command when no ETFFS detected. + * - Check CHIP ID on specific device to reduce the time needed to identify NON-existing device. + * - Set Power Mode only if ETFFS was detected on the device. + * + * Rev 1.51 Aug 10 2006 10:23:02 Polina.Marimont + * bug fix - identifying in 128K window failure + * + * Rev 1.50 Aug 09 2006 17:26:52 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +/* + * includes + */ + +#include "flcustom.h" +#include "flsystem.h" +#include "flchkdef.h" +#include "flsystyp.h" +#include "flcommon.h" +#include "flsysfun.h" +#include "doch_func.h" +#include "doch_ata.h" +#include "hib.h" + +#ifdef FL_MIGRATION_VERSION +#include "docsys.h" +#endif /*FL_MIGRATION_VERSION*/ + +FLWord gMemWindowType = 0; +FLDword gDochMemWinSize = 0; + +FLWord gHibContRegAreaAddress = 0; +FLWord gHibDataPortAreaAddress = 0; +FLWord gHibConfigRegAreaAddress = 0; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +FLByte gDeviceTurnedOff = FALSE; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#ifdef DEBUG_TIMEOUT +extern FLDword SysTimerFrequency; +extern void GetInternalSysTimer(FLDword * ticksHigh, FLDword * ticksLow); +#endif /*DEBUG_TIMEOUT*/ + +/* + * types + */ + +/* + * Global Variables + */ + +#ifdef __cplusplus +extern "C" { +#endif + +FLDword gAccessLayerType = 0; + +FLByte gATANoTimeout = 0; + +FLDword gUseShortWaitOnBusy = 0; + +FLDword gIgnoreErrorBit = 0; + +FLDword gDochAccessNanosec = 0; + +#ifdef DOCH_DMA_CONFIG +FLByte gDMAChannelOpen = 0; +#endif /*DOCH_DMA_CONFIG*/ + +DOCH_DpdSettings gDpdSettings; + +/* all DOCH sockets */ +DOCH_Socket sockets [DOCH_MAX_SOCKETS]; + +#ifdef __cplusplus +} +#endif + +#define DISABLE_INTERRUPT(pdev) \ + pdev->device[pdev->bAtaDevNum].flags &= ~DOCH_FLAGSB_USE_INTERRUPT;\ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, DOCH_ATA_NIEN) + +#ifdef DOCH_FILE_SIMULATION +#define ENABLE_INTERRUPT(pdev) \ + if (gAccessLayerType != DOCH_AL_SIM)\ + {\ + pdev->device[pdev->bAtaDevNum].flags |= DOCH_FLAGSB_USE_INTERRUPT;\ + }\ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG,0) +#else /*DOCH_FILE_SIMULATION*/ +#define ENABLE_INTERRUPT(pdev) \ + pdev->device[pdev->bAtaDevNum].flags |= DOCH_FLAGSB_USE_INTERRUPT;\ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG,0) +#endif /*DOCH_FILE_SIMULATION*/ +/* + * static vars + */ +static DOCH_DeviceUserAttr devUserAttr; + +static DOCH_ConfigRegsValue configRegValue; +static DOCH_ConfigRegsSet configRegValueSet; + +static FLByte ataDBG[DOCH_SECTOR_SIZE]; + +static DOCH_DeviceInfo gDiskOnChipDeviceInfo; + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * static routines + */ +static void clear_socket(DOCH_Socket * pdev); +static DOCH_Error ready(DOCH_Socket *pdev, FLSNative devNum, DOCH_Reg reg, FLByte mask, FLByte on_bits, FLDword millisec); +static DOCH_Error doch_find_base_address(FLSNative socketNo, FLDword Address); + +static DOCH_Error doch_check_chipID(FLSNative socketNo); + +/* + * Internal routines + */ +DOCH_Error io_input(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs, void *buf, FLNative secNum); +DOCH_Error io_output(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs, void *buf, FLNative secNum); +DOCH_Error io_ctrl(DOCH_Socket *pdev, FLSNative devNum, DOCH_Registers* regs); + +/* + * externals + */ + +DOCH_Error get_out_registers(DOCH_Socket* pdev, FLSNative devNum, DOCH_Registers* out_regs); + +extern DOCH_Error flUnRegisterDochParams(FLSNative socketNo); + +extern FLByte gSdkDOCAddressObtained; +extern FLDword gConfigHWDefaults[DOCH_NUM_OF_DCONFIGHW_ITEMS]; + +extern FLByte gDochAtaDebug; + +extern FLByte gSdkInitDone; + + +#ifdef CX_ATA_SNIFFER +typedef struct _AtaCmdRec_S +{ + FLSNative socketNo; + FLByte bAtaCmdType; + FLSNative dwDevNum; + DOCH_Registers regs; + FLSNative dwSecNum; + +}AtaCmdRec_S; + +typedef enum _AtaCmdType +{ + CX_ATATYPE_CTRL=0x0, + CX_ATATYPE_INPUT=0x1, + CX_ATATYPE_OUTPUT=0x2 +}AtaCmdType; + +static AtaCmdRec_S ataCmdRec; +#endif /*CX_ATA_SNIFFER*/ + + +/****************************************************************************** + * * + * c l e a r _ s o c k e t * + * * + * Clears socket structure * + * * + * Parameters : * + * pdev : device to act on * + * * + ******************************************************************************/ +static +void clear_socket ( DOCH_Socket * pdev ) +{ + register FLSNative i = 0; + + pdev->wSocketNo = 0; + pdev->wNumOfDevices = 0; + pdev->nTotalCapacity = 0; + pdev->wTotalNumOfPartitions = 0; + pdev->wLastPartitionSpanned = 0; + pdev->bUseDMA = 0; + pdev->bUseInterrupt = 0; + pdev->bUseBurst = 0; + pdev->bAtaDevNum = 0; + pdev->bRegBase = NULL; +#ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + pdev->bLastDevNum = 0xFF; +#endif /*DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES*/ + + for(i = 0; idevice[i].wNumOfPartitions = 0; + + pdev->device[i].ETFFS_Identified = FALSE; + + /* we assume that multiple sector read/writes aren't supported */ + pdev->device[i].dwMulti_MAX = 0; + pdev->device[i].dataTransferMode = DOCH_DATA_MODE_SINGLE; + + pdev->device[i].dwSpare1 = 0; + + } +} + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +/****************************************************************************** + * * + * d o c h C h e c k P F S y m p t o m * + * * + * Wait until particular bit pattern appears in specified DOCH register * + * * + * Parameters : * + * pdev : device to act on * + * reg : DOCH register offset from base address * + * mask : bits we are interested in * + * on_bits : bits we are waiting to become '1' * + * millisec : timeout value in milliseconds * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error dochCheckPFSymptom(FLSNative socketNo, FLByte devNum, FLBoolean beforeCommand /* Used for debug prints */) +{ + DOCH_Error rc; + DOCH_Socket* pdev = NULL; + DOCH_Registers in_regs; + FLByte resetOccured = 0; + + if(!gSdkInitDone) + return DOCH_OK; + + /* Sanity Check*/ + /*=============*/ + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + /*Set Device Head register to appropriate device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV(devNum)); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,devNum); + + /*Check ChipID to detect power failure ("Device Off") */ + if(doch_check_chipID(socketNo) == DOCH_OK) /*caller responsibility to set device head register*/ + { + return DOCH_OK; + } + + /* Check reset status + Note: We DO NOT call DOCHGetResetStatus() to avoid recursion */ + + /*Update ATA register values*/ + /*--------------------------*/ + in_regs.bFeaturesError = DOCH_GET_RESET_STATUS; + in_regs.bSectorCount = 0; + in_regs.bSectorNumber = 0; + in_regs.bCylLow = 0; + in_regs.bCylHigh = 0; + in_regs.bDriveHead = DOCH_SELECT_DEV(devNum); + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + + gUseShortWaitOnBusy = DOCH_LONG_IDENTIFY_TIMEOUT; + rc = io_ctrl (pdev, devNum, &in_regs); + gUseShortWaitOnBusy = 0; + + resetOccured = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_SECTOR_CNT_REG); + + if(rc != DOCH_OK) + { + if(beforeCommand) + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): io_ctrl DOCHGetResetStatus FAILED (Before Command)\r\n"); + else + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): io_ctrl DOCHGetResetStatus FAILED (After Command)\r\n"); + + gDeviceTurnedOff = DOCH_GLOBAL_BOOL_PATTERN; + return DOCH_DeviceTurnedOff; + } + else if(resetOccured) + { + if(beforeCommand) + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): Suspend mode detected (Before Command)\r\n"); + else + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): Suspend mode detected (After Command)\r\n"); + + gDeviceTurnedOff = DOCH_GLOBAL_BOOL_PATTERN; + return DOCH_DeviceTurnedOff; + } + + else + { + if(beforeCommand) + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): Suspend mode not detected but failed to read chip id (Before Command)\r\n"); + else + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochCheckPFSymptom(): Suspend mode not detected but failed to read chip id (After Command)\r\n"); + + gDeviceTurnedOff = DOCH_GLOBAL_BOOL_PATTERN; + return DOCH_DeviceTurnedOff; + } +} +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +/****************************************************************************** + * * + * r e a d y * + * * + * Wait until particular bit pattern appears in specified DOCH register * + * * + * Parameters : * + * pdev : device to act on * + * reg : DOCH register offset from base address * + * mask : bits we are interested in * + * on_bits : bits we are waiting to become '1' * + * millisec : timeout value in milliseconds * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static +DOCH_Error ready ( DOCH_Socket * pdev, + FLSNative devNum, + DOCH_Reg reg, + FLByte mask, + FLByte on_bits, + FLDword millisec ) +{ + DOCH_Error error = DOCH_OK; + register FLDword tries; + FLByte status = 0; + + FLDword use_interrupt = + ( ((pdev->device[devNum].flags & DOCH_FLAGSB_USE_INTERRUPT) == DOCH_FLAGSB_USE_INTERRUPT) && + (pdev->bUseInterrupt) ); + +#ifdef DEBUG_TIMEOUT + FLDword dwTimeAfterHigh,dwTimeAfterLow,dwTimeBeforeHigh,dwTimeBeforeLow; + GetInternalSysTimer(&dwTimeBeforeHigh,&dwTimeBeforeLow); +#endif /*DEBUG_TIMEOUT*/ + + + /*Special case: ignore error bit + (should be ignored when performing ATA standard IDENTIFY DEVICE command)*/ + if(gIgnoreErrorBit) + mask &= ~(DOCH_ERROR); + + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + { + DBG_PRINT_ERR(FLZONE_ATA, "ready(): Bad Parameter "); + return DOCH_BadParameter; + } + tries = millisec * (1000000UL / gDochAccessNanosec); + + /*If popper environment variable was set - set timeout to max*/ + if(gATANoTimeout == DOCH_GLOBAL_BOOL_PATTERN) + { + tries = DOCH_ATA_MAX_TIMEOUT; + } + + /*If gUseShortWaitOnBusy is set, use its value*/ + if(gUseShortWaitOnBusy != 0) + { + tries = gUseShortWaitOnBusy; + } + + /*Protect tries from being set to "0" + (in conjunction with tries-- might cause a very long delay...)*/ + if(tries == 0) + tries = 1; + + /*Wait for BUSY bit to clear*/ + while (tries-- > 0) + { + if ((millisec >= DOCH_LONG_WAIT) && (use_interrupt)) + { + /* wait for device's interrupt */ + DOCH_SLEEP(pdev->wSocketNo, devNum, DOCH_DEFAULT_SLEEP_PERIOD); + } + + status = DOCHREAD_ATA_REG(pdev->bRegBase, reg); + if ((status & mask) == on_bits) + { + /* read status once again, just to be sure .. */ + /*if ((DOCHREAD_ATA_REG(pdev->device[devNum].bRegBase, reg) & mask) == on_bits)*/ + return DOCH_OK; + } + /*If an error was detected - return the error code*/ + else if( ((status & DOCH_ERROR) == DOCH_ERROR) && + ((status & DOCH_BUSY) != DOCH_BUSY)) + { + error = (DOCH_Error)DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_ERROR_REG); + + /*Special Case - Device returned "0" in the error register. + This DOES NOT mean that everything is OK, since the error bit was raised. + Hence, we will return "DOCH_ATA_ERROR_ABORT"*/ + if(error == DOCH_OK) + error = DOCH_ATA_ERROR_ABORT; + + if(pdev->bUseInterrupt && (millisec == DOCH_SHORT_WAIT)) + { + DOCH_UNSERVICED_INTERRUPT(pdev->wSocketNo, devNum); + } + + DBG_PRINT_ERR(FLZONE_ATA, "ready(): ATA Error: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x status:0x%x device number:%d"),error,status,devNum)); + DBG_PRINT_ERR(FLZONE_ATA, "\r\n"); + + return error; + } + } + +#ifdef DEBUG_TIMEOUT + GetInternalSysTimer(&dwTimeAfterHigh,&dwTimeAfterLow); +#endif /*DEBUG_TIMEOUT*/ + + DBG_PRINT_ERR(FLZONE_ATA, "\r\nready(): Timed Out\r\n"); +#ifdef DEBUG_TIMEOUT + { + FLDword diffHigh,diffLow,dwWaitingTime; + FLDword scaledFreq= SysTimerFrequency/1000; /*mSec*/ + + diffHigh=(dwTimeAfterHigh-dwTimeBeforeHigh); + if(dwTimeAfterLow>=dwTimeBeforeLow) + { + diffLow= dwTimeAfterLow-dwTimeBeforeLow; + } + else + { + if (!diffHigh) + { + DBG_PRINT_ERR(FLZONE_ATA,"\nticks difference is negative\n"); + } + diffLow= 0xFFFFFFFFl- dwTimeBeforeLow + dwTimeAfterLow; + diffHigh --; + } + dwWaitingTime = (FLSDword)( (((0xFFFFFFFFl)/(scaledFreq)))*(diffHigh))+ + (((0xFFFFFFFFl)%(scaledFreq))*(diffHigh+1) + (diffLow))/(scaledFreq); + + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks when started:high %lu low %lu"),dwTimeBeforeHigh,dwTimeBeforeLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks when timeout:high %lu low %lu"),dwTimeAfterHigh,dwTimeAfterLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nTicks diff: high %d low %d"),diffHigh,diffLow)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nDetected frequency %lu"), SysTimerFrequency)); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\nWaiting time %d msec"), dwWaitingTime)); + + } +#endif /*DEBUG_TIMEOUT*/ + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\ndevice number:%d status register: 0x%x, mask 0x%x, on_bits 0x%x\r\n"),devNum,status,mask,on_bits)); + + /*recalculate the number of tries for printout*/ + tries = millisec * (1000000UL / gDochAccessNanosec); + if(gATANoTimeout == DOCH_GLOBAL_BOOL_PATTERN) + { + tries = DOCH_ATA_MAX_TIMEOUT; + } + if(gUseShortWaitOnBusy != 0) + { + tries = gUseShortWaitOnBusy; + } + + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\ntries %d ,millisec: %d, gATANoTimeout %d, gUseShortWaitOnBusy %d \r\n"),tries,millisec,gATANoTimeout,gUseShortWaitOnBusy)); + + /* If timeout had occurred, and not whilst looking for a device, + reset ATA and poll for ready */ + if(gUseShortWaitOnBusy == 0) + { + DBG_PRINT_ERR(FLZONE_ATA, "ready(): Resetting device... "); + error = doch_reset(pdev);/*reset both floors*/ + if(error == DOCH_OK) + DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n"); + else + { + DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n"); + return error; + } + } + + return DOCH_TimedOut; +} + +/****************************************************************************** + * * + * i o _ i n p u t * + * * + * Read sectors from DOCH device. * + * * + * Parameters : * + * pdev : device to act on * + * regs : DOCH_Registers * + * buf : user buffer to read to * + * secNum : # of sectors to read * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error io_input ( DOCH_Socket * pdev, + FLSNative devNum, + DOCH_Registers * regs, + void * buf, + FLNative secNum) +{ + FLNative sectors_to_read; + DOCH_Error rc; + FLSNative status; + +#ifdef CX_ATA_SNIFFER + extern FILE * ataLogFile; + ataCmdRec.bAtaCmdType = CX_ATATYPE_INPUT; + ataCmdRec.dwDevNum=devNum; + ataCmdRec.regs=*regs; + ataCmdRec.dwSecNum=(secNum ? secNum : 256); + if (!fwrite(&ataCmdRec,sizeof(AtaCmdRec_S),1,ataLogFile)) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_input():Cannot write command rec to file \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + if (fseek(ataLogFile,ataCmdRec.dwSecNum*DOCH_SECTOR_SIZE,SEEK_CUR )) + { DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_input():Cannot fseek file error. \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + fflush(ataLogFile); +#endif /*CX_ATA_SNIFFER*/ + + /*general sequence: + 1. set drive head register + 2. handle interrupts + 3. write ATA registers (if not DMA) + + 4. if BURST transfer:(Synchronous) + 4.1 set DOCH BURST READ Control Register + 4.2 if reading status sync - enter BURST mode on host + 4.3 initiate ATA Command + 4.4 for each buffer (in size of drqSize): + 4.4.1 Check DRQ ready and not BSY before data xfer + 4.4.2 if reading status async - enter BURST Mode on host + 4.4.3 Perform Read using burst + 4.4.4 if reading status async - exit BURST Mode on host + 4.5 if reading status sync - Exit BURST Mode on host + 4.6 Set DOCH BURST READ Control Register + + 5. else if DMA transfer: + 5.1 calculate number of blocks and start sector + 5.2 Set up the DMA transfer - Platfrom + 5.3 set device head register + 5.5 if burst mode required- Set DOCH BURST READ Control Register + 5.5 Set up the DMA transfer - Device (write DMA ctrl register) + 5.6 write ATA registers + 5.7 if burst mode required- enter BURST Mode + 5.8 Initiate ATA Command + 5.9 Wait for DMA transfer to complete + 5.10 if burst mode required-Exit BURST Mode + 5.11 Disable DMA + 5.12 Check status of DMA operation + 5.13 If DRQ>1 and some sectors are left to be transfered + perform another DMA transaction with altered frame/block sizes + + 6. else (PIO transfer): + 6.1 Initiate ATA Command + 6.2 Check DRQ ready and not BSY before data xfer + 6.3 for each buffer (in size of drqSize): + 6.3.1 read block + 6.3.2 Check DRQ ready (don`t perform after LAST sector was transfered) + + 7. wait until device is ready + 8. check operation's status + */ + + + /*Calculate how many sectors are to be read*/ + /*Note: "0" - 256 Sectors to read*/ + sectors_to_read = (secNum ? secNum : 256); + + /* 1. set drive head register*/ + /*****************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, regs->bDriveHead); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,((regs->bDriveHead & DOCH_DEVICE) == DOCH_DEVICE)); + + /* 2. handle interrupts*/ + /***********************/ + /*enable interrupt - caller responsibility to set floor*/ + if (pdev->bUseInterrupt && DOCH_IRQ_RB_INIT(pdev->wSocketNo)) + { + ENABLE_INTERRUPT(pdev); + } + + /*Wait for busy bit to clear*/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_BUSY|DOCH_DRQ|DOCH_READY))!= DOCH_READY) + { + if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_BUSY|DOCH_DRQ|DOCH_READY), DOCH_READY, DOCH_SHORT_WAIT)) != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before command) \r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + /*3. write ATA registers (if not DMA)*/ + /*************************************/ + /*Write ATA registers, without ATA command register*/ + /*Note: if DMA was requested, registers will be written inside DMA context*/ + if(!pdev->bUseDMA) + { + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, regs->bSectorCount); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, regs->bSectorNumber); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, regs->bCylLow); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, regs->bCylHigh); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + } + + /*******************BURST transfer was requested************************/ + /*4. if BURST transfer:(Synchronous) */ + /*************************************/ + #ifdef DOCH_USE_BURST_MODE_READ + if((pdev->bUseBurst) && (!pdev->bUseDMA)) + { + FLByte drqSize = 0; + FLByte i; + + if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) + { + drqSize = 1; + } + else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + drqSize = (FLByte)pdev->device[devNum].dwMulti_Current; + } + + /*4.1 set DOCH BURST READ Control Register*/ + /******************************************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, + HIB_BURST_READ_MODE_CTRL_REG, + (DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | (DOCH_BURST_LATENCY) | (DOCH_BURST_WAIT_STATE)) + ); + +#ifndef DOCH_READ_STATUS_ASYNC_IN_BURST + /*4.2 if reading status sync - enter BURST mode on host*/ + /******************************************************/ + DOCH_HOST_ENTER_READ_BURST_MODE; +#endif /*DOCH_READ_STATUS_ASYNC_IN_BURST*/ + + /*4.3 initiate ATA Command*/ + /**************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*4.4 for each buffer (in size of drqSize):*/ + /*******************************************/ + for(i=0; ibRegBase, + DOCH_DATA_PORT_AREA_ADDRESS, + (FLByte*)buf + (i<bRegBase, HIB_BURST_READ_MODE_CTRL_REG , DOCH_BURST_DISABLE); + } + else + #endif /*DOCH_USE_BURST_MODE_READ*/ + + /******************* DMA transfer was requested ************************/ + /*5. else if DMA transfer:*/ + /**************************/ + #ifdef DOCH_DMA_CONFIG + if(pdev->bUseDMA) + { + DMA_Params_S dmaParams; + FLDword dmaFirstReqSector, + dmaFirstSectorToPerform, + dmaRemainderSectors, + dmaRemainderOffset, + dmaBlocks, + dmaFrameSize; + FLWord wDmaRegValue = DOCHREAD_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG); + + /*5.1 calculate number of blocks and start sector*/ + /*************************************************/ + /*Initial Value*/ + dmaRemainderOffset = 0; + + /*Save the first sector position*/ + dmaFirstReqSector = (regs->bSectorNumber + + (regs->bCylLow<<8) + + (regs->bCylHigh<<16)+ + ((regs->bDriveHead & 0xF)<<24)); + + dmaFirstSectorToPerform = dmaFirstReqSector; + + if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) + { + dmaRemainderSectors = 0; + dmaFrameSize = 1; + dmaBlocks = sectors_to_read; + } + else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + dmaRemainderSectors = (sectors_to_read % pdev->device[devNum].dwMulti_Current); + + /*Set initial parameters (will be altered afterwards to transfer "remainder" sectors*/ + dmaBlocks = (sectors_to_read / pdev->device[devNum].dwMulti_Current); + dmaFrameSize = pdev->device[devNum].dwMulti_Current; + } + else + { + DBG_PRINT_ERR(FLZONE_ATA, "io_input(): DMA Transfer Mode "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode)); + DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_FeatureNotSupported; + } /* End of if/else on pdev->device[devNum].dataTransferMode */ + +dochIoInputDmaSequence: + if(dmaBlocks > 0) + { + /*5.2 Set up the DMA transfer - Platfrom*/ + /****************************************/ + dmaParams.bOpType = DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST; + + dmaParams.bDiskOnChip_BasePtr = (FLByte*)pdev->bRegBase; + dmaParams.wDiskOnChip_Offset = (FLWord)DOCH_DATA_PORT_AREA; + dmaParams.bDestAddrPtr = (FLByte*)buf + dmaRemainderOffset; + + dmaParams.wFrameSize = (FLWord)(dmaFrameSize * DOCH_SECTOR_SIZE); + dmaParams.wFramesInBlock = (FLWord)(dmaBlocks); + + dmaParams.wFramesXferred = 0; + + DOCH_DMA_CONFIG(&dmaParams); + if(dmaParams.fDmaStatus != 0) + { + DBG_PRINT_ERR(FLZONE_API, "io_input(): DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST Failed\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_GeneralFailure; + } + + /*5.3 set device head register if needed*/ + /****************************************/ + if (dmaFirstSectorToPerform != dmaFirstReqSector) + { /* no need to update device head on first time*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, ((regs->bDriveHead & 0xF0) | + ((FLByte)((dmaFirstSectorToPerform>>24) & 0x0F)))); + + } + + + #ifdef DOCH_USE_BURST_MODE_READ + /*5.4 if burst mode required- Set DOCH BURST READ Control Register*/ + /******************************************************************/ + if(pdev->bUseBurst) + { + /*Set DOCH BURST READ Control Register*/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, + HIB_BURST_READ_MODE_CTRL_REG, + (DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | DOCH_BURST_LATENCY | DOCH_BURST_WAIT_STATE) ); + } + #endif /*DOCH_USE_BURST_MODE_READ*/ + + /*5.5 Set up the DMA transfer - Device (write DMA ctrl register)*/ + /****************************************************************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue | DOCH_DMA_REQ_ENABLE)); + + /*5.6 write ATA registers*/ + /*************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (FLByte)(dmaFrameSize*dmaBlocks)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, (FLByte)(dmaFirstSectorToPerform)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, (FLByte)(dmaFirstSectorToPerform>>8)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, (FLByte)(dmaFirstSectorToPerform>>16)); + /*DOCH_DELAY_AFTER_DEVICE_SWITCH; Actually this delay is unnecessary */ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + + #ifdef DOCH_USE_BURST_MODE_READ + /*5.7 if burst mode required- enter BURST Mode*/ + /**********************************************/ + if(pdev->bUseBurst) + { + DOCH_HOST_ENTER_READ_BURST_MODE; + } + #endif /*DOCH_USE_BURST_MODE_READ*/ + + /*5.8 Initiate ATA Command*/ + /**************************/ + /*This will also start DMA transfer*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*5.9 Wait for DMA transfer to complete*/ + /***************************************/ + dmaParams.bOpType = DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END; + DOCH_DMA_CONFIG(&dmaParams); + + #ifdef DOCH_USE_BURST_MODE_READ + /*5.10 if burst mode required-Exit BURST Mode*/ + /********************************************/ + if(pdev->bUseBurst) + { + DOCH_HOST_EXIT_READ_BURST_MODE; + + /*Set DOCH BURST READ Control Register*/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_BURST_READ_MODE_CTRL_REG , DOCH_BURST_DISABLE); + } + #endif /*DOCH_USE_BURST_MODE_READ*/ + + /*5.11 Disable DMA*/ + /******************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue &= ~DOCH_DMA_REQ_ENABLE)); + + /*5.12 Check status of DMA operation*/ + /************************************/ + if(dmaParams.fDmaStatus != 0) + { + DISABLE_INTERRUPT(pdev); + DBG_PRINT_ERR(FLZONE_API, "io_input(): DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END Failed\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dma status:%d frames xFererred:%d:%d\r\n"), + dmaParams.fDmaStatus,dmaParams.wFramesXferred)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:OpType:%d IrHandle:%d \r\n"), + dmaParams.bOpType,dmaParams.bIrHandle)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:frame size:%d Frames in block:%d\r\n"), + dmaParams.wFrameSize,dmaParams.wFramesInBlock)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:mDoc base:0x%x mDoc offset:0x%x dest address:0x%x \r\n"), + dmaParams.bDiskOnChip_BasePtr,dmaParams.wDiskOnChip_Offset,dmaParams.bDestAddrPtr)); + + DBG_PRINT_ERR(FLZONE_ATA, "io_input(): Resetting device... "); + rc = doch_reset(pdev);/*reset both floors*/ + if(rc == DOCH_OK) + DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n"); + else + { + DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n"); + DISABLE_INTERRUPT(pdev); + return rc; + } + return DOCH_GeneralFailure; + } + + } + + /*5.13 If DRQ>1 and some sectors are left to be transfered + *perform another DMA transaction with altered frame/block sizes*/ + /****************************************************************/ + if(dmaRemainderSectors > 0) + { + dmaRemainderOffset = (dmaBlocks * dmaFrameSize * DOCH_SECTOR_SIZE); + dmaFirstSectorToPerform = (dmaFirstReqSector + (dmaBlocks * dmaFrameSize)); + + dmaBlocks = 1; + dmaFrameSize = dmaRemainderSectors; + + dmaRemainderSectors = 0; + + goto dochIoInputDmaSequence; + } + + } + else + #endif /*DOCH_DMA_CONFIG*/ + + /*******************PIO transfer was requested************************/ + /*6. else (PIO transfer):*/ + /*************************/ + { + FLNative secPerformed; + FLNative offset = 0; + /*6.1 Initiate ATA Command*/ + /**************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*6.2 Check DRQ ready and not BSY before data xfer*/ + /**************************************************/ + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (before data XFER) \r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + + /*6.3 for each buffer (in size of drqSize):*/ + /*******************************************/ + if((pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) || /*Single Sector was requested*/ + (!(regs->bCommandStatus == DOCH_VSCMD_READ_PARTITION)) ) /*Command is OTHER than Read Partition*/ + { + for(secPerformed=1; secPerformed<=sectors_to_read; secPerformed++) + { + /*6.3.1 read block*/ + /******************/ + DOCHBLK_READ(pdev->bRegBase,((FLByte*)buf + offset),1); + + + /*6.3.2 Check DRQ ready and not BSY before next data xfer */ + /**********************************************************/ + /* (don`t perform after LAST sector was transfered) */ + if(secPerformed != sectors_to_read) + { + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (after data XFER) \r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x , sector = %d \r\n"),rc,secPerformed)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + offset += DOCH_SECTOR_SIZE; + } + + } + else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + FLByte multCount = (FLByte)pdev->device[devNum].dwMulti_Current; + FLByte multSecToRead = 0; + + for(secPerformed=0; secPerformed sectors_to_read) + multSecToRead = (sectors_to_read - secPerformed); + else + multSecToRead = multCount; + + /*Perform data xfer*/ + DOCHBLK_READ(pdev->bRegBase, (FLByte*)buf + offset,(multSecToRead)); + + /* Check DRQ ready and not BSY before next data xfer */ + /* (don`t perform after LAST sector was transfered) */ + if((secPerformed + multSecToRead) != sectors_to_read) + { + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (after data XFER) \r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x, sector = %d \r\n"),rc, secPerformed)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + /*Advance number of written sectors and update pointer to buffer*/ + secPerformed += multSecToRead; + offset += (multSecToRead * DOCH_SECTOR_SIZE); + } + } + else + { + DBG_PRINT_ERR(FLZONE_ATA, "io_input(): Transfer Mode "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode)); + DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_FeatureNotSupported; + + } /* End of if/else on pdev->device[devNum].dataTransferMode */ + + } /* End of else on if(pdev->bUseDMA) */ + + /*******************end of different transfer modes ************************/ + + /* 7. wait until device is ready */ + /*********************************/ + rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_BUSY|DOCH_DRQ), + DOCH_READY, DOCH_SHORT_WAIT); + if (rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_input(): ATA not Ready (after completion)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + + /*8. check operation's status */ + /******************************/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_BUSY | DOCH_READY | DOCH_ERROR)) != DOCH_READY) + { + DISABLE_INTERRUPT(pdev); + DBG_PRINT_ERR(FLZONE_ATA, "io_input(): after completion status register indicates a problem: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA,(FLTXT("reported status 0x%x\r\n"),status)); + if((status & DOCH_ERROR) == DOCH_ERROR) + { + return DOCH_ATAErrorDetected; + } + return DOCH_ATANotReady; + + } + + DISABLE_INTERRUPT(pdev); +#ifdef CX_ATA_SNIFFER +{ + FLSDword i=0; + if (fseek(ataLogFile,-ataCmdRec.dwSecNum*DOCH_SECTOR_SIZE,SEEK_CUR )) + { DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_input():Cannot fseek file error. \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + for (i=0;ibCommandStatus!= DOCH_VSCMD_PARTITION_MANAGEMENT)? DOCH_LONG_WAIT:\ + ((regs->bFeaturesError ==DOCH_ADD_PARTITION || regs->bFeaturesError ==DOCH_SECURE_ERASE)? DOCH_VERY_LONG_WAIT:DOCH_LONG_WAIT)); +#ifdef CX_ATA_SNIFFER + extern FILE * ataLogFile; + ataCmdRec.bAtaCmdType = CX_ATATYPE_OUTPUT; + ataCmdRec.dwDevNum=devNum; + ataCmdRec.regs=*regs; + ataCmdRec.dwSecNum=(secNum ? secNum : 256); + if (!fwrite(&ataCmdRec,sizeof(AtaCmdRec_S),1,ataLogFile)) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_output():Cannot write command rec to file \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + + { + FLSDword i=0; + for (i=0;i1 and some sectors are left to be transfered + perform another DMA transaction with altered frame/block sizes + + 6. else (PIO transfer): + 6.1 Initiate ATA Command + 6.2 Check DRQ ready and not BSY before data xfer + 6.3 for each buffer (in size of drqSize): + 6.3.1 read block + 6.3.2 Check DRQ ready (don`t perform after LAST sector was transfered) + + 7. wait until device is ready + 8. check operation's status + */ + + + /*Calculate how many sectors are to be written*/ + /*Note: "0" - 256 Sectors to write*/ + sectors_to_write = (secNum ? secNum : 256); + + /* 1. set drive head register*/ + /*****************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, regs->bDriveHead); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,((regs->bDriveHead & DOCH_DEVICE) == DOCH_DEVICE)); + + /*2. handle interrupts*/ + /**********************/ + /*caller responsibility to set floor*/ + if (pdev->bUseInterrupt && DOCH_IRQ_RB_INIT(pdev->wSocketNo)) + { + ENABLE_INTERRUPT(pdev); + } + + /*Wait for BUSY bit to clear*/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY|DOCH_BUSY|DOCH_DRQ))!= DOCH_READY) + { + if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY|DOCH_BUSY|DOCH_DRQ), DOCH_READY, DOCH_SHORT_WAIT)) != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (before command)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + /*3. write ATA registers (if not DMA)*/ + /*************************************/ + /*Write ATA registers, without ATA command register*/ + /*Note: if DMA was requested, registers will be written inside DMA context*/ + if(!pdev->bUseDMA) + { + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, regs->bSectorCount); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, regs->bSectorNumber); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, regs->bCylLow); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, regs->bCylHigh); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + } + + /*******************BURST transfer was requested************************/ + /*4. if BURST transfer:(Synchronous) */ + /*************************************/ + #ifdef DOCH_USE_BURST_MODE_WRITE + if(pdev->bUseBurst) + { + FLByte drqSize = 0; + FLByte i; + + if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) + { + drqSize = 1; + } + else if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + drqSize = (FLByte)pdev->device[devNum].dwMulti_Current; + } + + /*4.1 initiate ATA Command*/ + /**************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*4.2 set DOCH BURST WRITE Control Register*/ + /******************************************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, + HIB_BURST_WRITE_MODE_CTRL_REG, + (DOCH_BURST_ENABLE | DOCH_BURST_HOLD | DOCH_BURST_LENGTH | DOCH_BURST_LATENCY | DOCH_BURST_WAIT_STATE) + ); + /*4.3 if reading status sync - enter BURST mode on host*/ + /******************************************************/ + DOCH_HOST_ENTER_WRITE_BURST_MODE; + + /*4.4 for each buffer (in size of drqSize):*/ + /*******************************************/ + for(i=0; ibRegBase, + DOCH_DATA_PORT_AREA_ADDRESS, + (FLByte*)buf + (i<bRegBase, HIB_BURST_WRITE_MODE_CTRL_REG, DOCH_BURST_DISABLE); + + } + else + #endif /*DOCH_USE_BURST_MODE_WRITE*/ + /******************* DMA transfer was requested ************************/ + /*5. else if DMA transfer:*/ + /**************************/ + #ifdef DOCH_DMA_CONFIG + /*DMA transfer was requested*/ + if(pdev->bUseDMA) + { + DMA_Params_S dmaParams; + FLDword dmaFirstReqSector, + dmaFirstSectorToPerform, + dmaRemainderSectors, + dmaRemainderOffset, + dmaBlocks, + dmaFrameSize; + FLWord wDmaRegValue = DOCHREAD_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG); + /*5.1 calculate number of blocks and start sector*/ + /*************************************************/ + /*Initial Value*/ + dmaRemainderOffset = 0; + + /*Save the first sector position*/ + dmaFirstReqSector = (regs->bSectorNumber + + (regs->bCylLow<<8) + + (regs->bCylHigh<<16)+ + ((regs->bDriveHead & 0xF)<<24)); + + dmaFirstSectorToPerform = dmaFirstReqSector; + + if(pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) + { + dmaRemainderSectors = 0; + dmaFrameSize = 1; + dmaBlocks = sectors_to_write; + } + else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + dmaRemainderSectors = (sectors_to_write % pdev->device[devNum].dwMulti_Current); + + /*Set initial parameters (will be altered afterwards to transfer "remainder" sectors*/ + dmaBlocks = (sectors_to_write / pdev->device[devNum].dwMulti_Current); + dmaFrameSize = pdev->device[devNum].dwMulti_Current; + } + else + { + DBG_PRINT_ERR(FLZONE_ATA, "io_output(): DMA Transfer Mode "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode)); + DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_FeatureNotSupported; + } /* End of if/else on pdev->device[devNum].dataTransferMode */ + +dochIoOutputDmaSequence: + if(dmaBlocks > 0) + { + /*5.2 Set up the DMA transfer - Platform*/ + /****************************************/ + dmaParams.bOpType = DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE; + + dmaParams.bDiskOnChip_BasePtr = ((FLByte*)pdev->bRegBase); + dmaParams.wDiskOnChip_Offset = DOCH_DATA_PORT_AREA; + dmaParams.bDestAddrPtr = (FLByte*)buf + dmaRemainderOffset; + + dmaParams.wFrameSize = (FLWord)(dmaFrameSize * DOCH_SECTOR_SIZE); + dmaParams.wFramesInBlock = (FLWord)(dmaBlocks); + + dmaParams.wFramesXferred = 0; + + DOCH_DMA_CONFIG(&dmaParams); + if(dmaParams.fDmaStatus != 0) + { + DBG_PRINT_ERR(FLZONE_API, "io_output(): DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE Failed\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_GeneralFailure; + } + + /*5.3 set device head register if needed*/ + /****************************************/ + if (dmaFirstSectorToPerform!= dmaFirstReqSector) + { /* no need to update device head on first time*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, ((regs->bDriveHead & 0xF0) | + ((FLByte)((dmaFirstSectorToPerform>>24) & 0x0F)))); + + } + + /*5.4 Set up the DMA transfer - Device (write DMA ctrl register)*/ + /****************************************************************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue | DOCH_DMA_REQ_ENABLE)); + + /*5.5 write ATA registers*/ + /*************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, (FLByte)(dmaFrameSize*dmaBlocks)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, (FLByte)(dmaFirstSectorToPerform)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, (FLByte)(dmaFirstSectorToPerform>>8)); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, (FLByte)(dmaFirstSectorToPerform>>16)); + /*DOCH_DELAY_AFTER_DEVICE_SWITCH; Actually this delay is unnecessary */ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + + /*5.6 Initiate ATA Command*/ + /**************************/ + /*This will also start DMA transfer*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*5.7 Wait for DMA transfer to complete*/ + /***************************************/ + dmaParams.bOpType = DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END; + DOCH_DMA_CONFIG(&dmaParams); + + /*5.8 Disable DMA*/ + /*****************/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_DMA_CTRL_REG, (wDmaRegValue &= ~DOCH_DMA_REQ_ENABLE)); + + /*5.9 Check status of DMA operation*/ + /***********************************/ + if(dmaParams.fDmaStatus != 0) + { + DISABLE_INTERRUPT(pdev); + DBG_PRINT_ERR(FLZONE_API, "io_output(): DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END Failed\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dma status:%d frames xFererred:%d:%d\r\n"), + dmaParams.fDmaStatus,dmaParams.wFramesXferred)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:OpType:%d IrHandle:%d \r\n"), + dmaParams.bOpType,dmaParams.bIrHandle)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:frame size:%d Frames in block:%d\r\n"), + dmaParams.wFrameSize,dmaParams.wFramesInBlock)); + DBG_PRINT_ERR_PRM(FLZONE_API,(FLTXT("dmaParams:mDoc base:0x%x mDoc offset:0x%x dest address:0x%x \r\n"), + dmaParams.bDiskOnChip_BasePtr,dmaParams.wDiskOnChip_Offset,dmaParams.bDestAddrPtr)); + + DBG_PRINT_ERR(FLZONE_ATA, "io_outut(): Resetting device... "); + rc = doch_reset(pdev); + if(rc == DOCH_OK) + DBG_PRINT_ERR(FLZONE_ATA, "Passed! \r\n"); + else + { + DBG_PRINT_ERR(FLZONE_ATA, "Failed! \r\n"); + return rc; + } + + return DOCH_GeneralFailure; + } + + } + + /*5.10 If DRQ>1 and some sectors are left to be transfered + *perform another DMA transaction with altered frame/block sizes*/ + /****************************************************************/ + if(dmaRemainderSectors > 0) + { + dmaRemainderOffset = (dmaBlocks * dmaFrameSize * DOCH_SECTOR_SIZE); + dmaFirstSectorToPerform = (dmaFirstReqSector + (dmaBlocks * dmaFrameSize)); + + dmaBlocks = 1; + dmaFrameSize = dmaRemainderSectors; + + dmaRemainderSectors = 0; + + goto dochIoOutputDmaSequence; + } + + /*once DMA transation endded - device should be ready*/ + /* do not wait in that case long time*/ + dwLongWait = DOCH_SHORT_WAIT; + + } + else + #endif /*DOCH_DMA_CONFIG*/ + + /*******************PIO transfer was requested************************/ + /*6. else (PIO transfer):*/ + /*************************/ + { + /*6.1 Initiate ATA Command*/ + /**************************/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /*6.2 Check DRQ ready and not BSY before data xfer*/ + /**************************************************/ + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_SHORT_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (before data Xfer)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + DISABLE_INTERRUPT(pdev); + return rc; + } + + /*6.3 for each buffer (in size of drqSize):*/ + /*******************************************/ + if((pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_SINGLE) || /*Single Sector was requested*/ + (!(regs->bCommandStatus == DOCH_VSCMD_WRITE_PARTITION)) ) /*Command is OTHER than Write Partition*/ + { + for(secPerformed=1; secPerformed<=sectors_to_write; secPerformed++) + { + /*6.3.1 write block*/ + /******************/ + DOCHBLK_WRITE(pdev->bRegBase, (FLByte*)buf + offset,1); + + + /*6.3.2 Check DRQ ready and not BSY before next data xfer */ + /**********************************************************/ + /* (don`t perform after LAST sector was transfered) */ + if(secPerformed != sectors_to_write) + { + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (after data Xfer)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x , sector = %d \r\n"),rc,secPerformed)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + offset += DOCH_SECTOR_SIZE; + } + } + else if (pdev->device[devNum].dataTransferMode == DOCH_DATA_MODE_MULT) + { + multCount = (FLByte)pdev->device[devNum].dwMulti_Current; + + for(secPerformed=0; secPerformed sectors_to_write) + multSecToWrite = (sectors_to_write - secPerformed); + else + multSecToWrite = multCount; + + /*Perform data xfer*/ + DOCHBLK_WRITE(pdev->bRegBase, (FLByte*)buf + offset,(multSecToWrite)); + + /* Check DRQ ready and not BSY before next data xfer */ + /* (don`t perform after LAST sector was transfered) */ + if((secPerformed + multSecToWrite) != sectors_to_write) + { + (rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_DRQ | DOCH_BUSY | DOCH_ERROR), + DOCH_READY | DOCH_DRQ, DOCH_LONG_WAIT)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (after data Xfer)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x , sector = %d\r\n"),rc,secPerformed)); + DISABLE_INTERRUPT(pdev); + return rc; + } + } + + /*Advance number of written sectors and update pointer to buffer*/ + secPerformed += multSecToWrite; + offset += (multSecToWrite * DOCH_SECTOR_SIZE); + } + } + else + { + DBG_PRINT_ERR(FLZONE_ATA, "io_output(): Transfer Mode "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x "), pdev->device[devNum].dataTransferMode)); + DBG_PRINT_ERR(FLZONE_ATA, "not supported\r\n"); + DISABLE_INTERRUPT(pdev); + return DOCH_FeatureNotSupported; + } /* End of if/else on pdev->device[devNum].dataTransferMode */ + + } /* End of else on if(pdev->bUseDMA) */ + /*******************end of different transfer modes ************************/ + + /*7. wait until device is ready */ + /*********************************/ + /* This might involve yielding the CPU and waiting for device interrupt, + * so we use DOCH_LONG_WAIT or DOCH_VERY_LONG_WAIT according to the operation + */ + rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY | DOCH_BUSY | DOCH_DRQ), + DOCH_READY, dwLongWait); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_output(): ATA not Ready (after all data completed)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + } + + /*8. check operation's status */ + /******************************/ + /* this also clear IRQ */ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_BUSY | DOCH_READY | DOCH_ERROR)) != DOCH_READY) + { + DISABLE_INTERRUPT(pdev); + DBG_PRINT_ERR(FLZONE_ATA, "io_output(): after completion status register indicates a problem: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA,(FLTXT("reported status 0x%x\r\n"),status)); + if((status & DOCH_ERROR) == DOCH_ERROR) + { + return DOCH_ATAErrorDetected; + } + return DOCH_ATANotReady; + } + DISABLE_INTERRUPT(pdev); + return rc; +} + +/****************************************************************************** + * * + * i o _ c t r l * + * * + * Pass command 'cmd' to DOCH device. * + * * + * Parameters : * + * pdev : device to act on * + * regs : DOCH_Registers * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error io_ctrl ( DOCH_Socket * pdev, + FLSNative devNum, + DOCH_Registers * regs) +{ + DOCH_Error rc; + FLSNative status; + FLDword dwLongWait= ((regs->bCommandStatus!= DOCH_VSCMD_PARTITION_MANAGEMENT)? DOCH_LONG_WAIT:\ + ((regs->bFeaturesError ==DOCH_DELETE_PARTITIONS)? DOCH_VERY_LONG_WAIT:DOCH_LONG_WAIT)); + + +#ifdef CX_ATA_SNIFFER + extern FILE * ataLogFile; + + ataCmdRec.bAtaCmdType = CX_ATATYPE_CTRL; + ataCmdRec.dwDevNum=devNum; + ataCmdRec.regs=*regs; + if (!fwrite(&ataCmdRec,sizeof(AtaCmdRec_S),1,ataLogFile)) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nError:io_ctrl():Cannot write command rec to file \r\n"); + return DOCH_ATA_ERROR_ABORT; + } + fflush(ataLogFile); +#endif /*CX_ATA_SNIFFER*/ + + /* First we write the device head register to ensure we are communicating + with the right device...*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, (regs->bDriveHead|DOCH_LBA)); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,((regs->bDriveHead & DOCH_DEVICE) == DOCH_DEVICE)); + + /*Wait for DOCH BUSY flag to clear*/ + if ((rc = ready(pdev, devNum, DOCH_ALT_STATUS_REG, (DOCH_READY|DOCH_BUSY|DOCH_DRQ),DOCH_READY, DOCH_SHORT_WAIT)) != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_ctrl(): ATA not Ready (before command)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + return rc; + } + + + /*Write ATA registers*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_FEATURES_REG, regs->bFeaturesError); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_CNT_REG, regs->bSectorCount); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_SECTOR_NO_REG, regs->bSectorNumber); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_LOW_REG, regs->bCylLow); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CYLINDER_HIGH_REG, regs->bCylHigh); + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_COMMAND_REG, regs->bCommandStatus); + + /* wait until device is ready */ + rc = ready(pdev, devNum, DOCH_STATUS_REG, (DOCH_READY | DOCH_BUSY), + DOCH_READY, dwLongWait); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nio_ctrl(): ATA not Ready (after command)\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("rc = 0x%x \r\n"),rc)); + return rc; + } + + /* check operation's status; this also clear IRQ */ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_BUSY | DOCH_READY | DOCH_ERROR)) != DOCH_READY) + { + DBG_PRINT_ERR(FLZONE_ATA, "io_ctrl(): after completion status register indicates a problem: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA,(FLTXT("reported status 0x%x\r\n"),status)); + if((status & DOCH_ERROR) == DOCH_ERROR) + { + return DOCH_ATAErrorDetected; + } + return DOCH_ATANotReady; + } + + + return rc; +} + +DOCH_Error retrieveAndPrintAtaDebug(DOCH_Socket* pdev) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + /*FLWord numOfDataBytes;*/ + FLWord currentINTEnabled, currentDMAEnabled, currentBurstEnabled; + + tffsset(&in_regs, 0, sizeof(in_regs)); + in_regs.bFeaturesError = DOCH_RETRIEVE_DBG_MSG; + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + in_regs.bSectorCount = 1; + in_regs.bDriveHead = DOCH_SELECT_DEV(pdev->bAtaDevNum); + + /* Disable interrupts */ + /* Disable DMA/Burst */ + /* (retain original values)*/ + currentINTEnabled = pdev->bUseInterrupt; + currentDMAEnabled = pdev->bUseDMA; + currentBurstEnabled = pdev->bUseBurst; + pdev->bUseInterrupt = FALSE; + pdev->bUseDMA = FALSE; + pdev->bUseBurst = FALSE; + + + /*Perform debug ocommand*/ + rc = io_input(pdev, 0, &in_regs, ataDBG, 1); + + /*Revert interrupts/DMA/Burst to original state*/ + pdev->bUseInterrupt = currentINTEnabled; + pdev->bUseDMA = currentDMAEnabled; + pdev->bUseBurst = currentBurstEnabled; + + + /*Retrieve ATA out registers*/ + rc = get_out_registers(pdev, 0, &out_regs); + if(rc != DOCH_OK) + return rc; + + /*numOfDataBytes = (out_regs.bSectorNumber + (out_regs.bCylLow<<8));*/ + + if(ataDBG[0] != '\0') + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\n~~~~~~~~~~~~~~~~~~~~~~~~~"); + DBG_PRINT_ERR(FLZONE_ATA, "\r\n*** ETFFS Debug string: "); + DBG_PRINT_ATA(FLZONE_ATA,(FLTXT_VAR(ataDBG))); + DBG_PRINT_ERR(FLZONE_ATA, " ***"); + DBG_PRINT_ERR(FLZONE_ATA, "\r\n~~~~~~~~~~~~~~~~~~~~~~~~~\r\n"); + } + + return rc; +} + +/****************************************************************************** + * * + * d o c h _ c o m m a n d * + * * + * Sends 'cmd' command to DOCH device. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * in_regs : DOCH input registers values * + * out_regs : DOCH output registers values * + * buf : user buffer * + * secNum : # of sectors (for data transfer commands) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_command ( FLSNative socketNo, + FLSNative devNum, + DOCH_Registers* in_regs, + DOCH_Registers* out_regs, + void * buf, + FLNative secNum) +{ + DOCH_Socket* pdev; + DOCH_Error rc; + DOCH_Error rc2; + +#ifdef CX_ATA_SNIFFER + ataCmdRec.socketNo=socketNo; +#endif /*CX_ATA_SNIFFER*/ + + /* Sanity Check*/ + /*=============*/ + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc = dochCheckPFSymptom(socketNo, pdev->bAtaDevNum, TRUE); + if(rc != DOCH_OK) + return rc; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#ifdef DOCH_DMA_CONFIG + { + DMA_Params_S dmaParams; + + if(pdev->bUseDMA && (gDMAChannelOpen == 0)) + { + dmaParams.bOpType = DOCH_DMA_OPEN_CHANNEL; + DOCH_DMA_CONFIG(&dmaParams); + if(dmaParams.fDmaStatus != 0) + { + DBG_PRINT_ERR(FLZONE_API, "doch_command(): DOCH_DMA_OPEN_CHANNEL Failed\r\n"); + return DOCH_GeneralFailure; + } + + gDMAChannelOpen = DOCH_GLOBAL_BOOL_PATTERN; + + DBG_PRINT_FLOW(FLZONE_ATA, "\r\nDMA Channel opened\r\n"); + } + + } +#endif /*DOCH_DMA_CONFIG*/ + + /*Branch to proper IO routine according to ATA command*/ + switch ((DOCH_Command)(in_regs->bCommandStatus)) + { + /* Vendor-Specific ATA commands */ + + case DOCH_VSCMD_READ_PARTITION: + case DOCH_VSCMD_READ_CALCULATED_HASH: + case DOCH_VSCMD_READ_ORIGINAL_HASH: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_VSCMD_WRITE_PARTITION: + case DOCH_VSCMD_WRITE_FLEXI: + case DOCH_VSCMD_WRITE_GIVEN_HASH: + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS: + case DOCH_VSCMD_ERASE_PARTITION_SECTORS: + case DOCH_VSCMD_WRITE_CALCULATED_HASH: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_VSCMD_PARTITION_MANAGEMENT: + switch((DOCH_DeviceCtrlOp)(in_regs->bFeaturesError)) + { + + case DOCH_SET_DEFAULT_PARTITION: + case DOCH_DELETE_PARTITIONS: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_GET_PARTITION_INFO: + case DOCH_GET_PARTITION_USER_ATTR: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_SET_PARTITION_PROTECTION: + case DOCH_SET_PARTITION_USER_ATTR: + case DOCH_ADD_PARTITION: + case DOCH_SECURE_ERASE: + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + break; + + case DOCH_VSCMD_ACCESS_CONTROL: + switch((DOCH_SecurityCtrlOp)(in_regs->bFeaturesError)) + { + case DOCH_DISABLE_ACCESS: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_RX_DOCH_PUBLICKEY: + case DOCH_VERIFY_HOST_KEY: +#ifdef FL_SLPP + case DOCH_SLPP_REPORT_LOCKED_RANGES: +#endif /*FL_SLPP*/ + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_EN_ACCESS_WPWD: + case DOCH_TX_HOST_PUBLICKEY: +#ifdef FL_SLPP + case DOCH_SLPP_UNLOCK_RANGE: + case DOCH_SLPP_UNLOCK_ENTIRE_PARTITION: + case DOCH_SLPP_LOCK_RANGE: + case DOCH_SLPP_STICKY_LOCK_RANGE: +#endif /*FL_SLPP*/ + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + break; + + case DOCH_VSCMD_EXT_DEVICE_CTRL: + switch((DOCH_DeviceCtrlOp)(in_regs->bFeaturesError)) + { + + case DOCH_SET_DATA_XFER_MODE: + case DOCH_ATOMIC_WRITE_SEQUENCE: + case DOCH_OPTIMIZE_MEDIA: + case DOCH_GET_RESET_STATUS: + case DOCH_NOTIFY_RESET: + case DOCH_NOTIFY_PLATFORM_RESUMED: + case DOCH_GET_CUSTOM_PARAM: + case DOCH_SET_CUSTOM_PARAM: + case DOCH_SET_POWER_MODE: + case DOCH_GET_POWER_MODE: + case DOCH_ACTIVATE_DEBUG_MODE: + case DOCH_SET_ALERT_LEVEL: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_IDENTIFY_DISKONCHIP_DEVICE: + case DOCH_GET_EXTENDED_DEVICE_INFO: + case DOCH_GET_DISK_USER_ATTR: + case DOCH_GET_CONFIGURATION_DATA: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_SET_DISK_USER_ATTR: + case DOCH_SET_CONFIGURATION_DATA: + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + break; + + case DOCH_VSCMD_EXT_SECURITY_CTRL: + switch((DOCH_SecurityCtrlOp)(in_regs->bFeaturesError)) + { + + case DOCH_SET_ALGORITHM_MODE: + case DOCH_AUTO_HASH_CONTROL: + case DOCH_SET_KEYS: + case DOCH_START_HASH_STREAM_CALC: + case DOCH_READ_STOP_HASH_STREAM_CALC: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_REPORT_SUPPORTED_ALGORITHMS: + case DOCH_GET_ALGORITHM_CAPABILITIES: + case DOCH_RETURN_RANDOM_NUMBERS: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + break; + + default: + return DOCH_UnknownCmd; + } + + /*If IO operation succeeded, retrieve device response from ATA registers + (calling routine might need some data back from the device) + Common IO Read/Write routines are excluded */ + switch( rc ) + { + case DOCH_OK: + if((in_regs->bCommandStatus != DOCH_VSCMD_READ_PARTITION) && + (in_regs->bCommandStatus != DOCH_VSCMD_WRITE_PARTITION) && + (in_regs->bCommandStatus != DOCH_VSCMD_WRITE_FLEXI)) + rc = get_out_registers(pdev, devNum, out_regs); + break; + + case DOCH_ATAErrorDetected: + rc = get_out_registers(pdev, devNum, out_regs); + break; + default: + break; + } + +#ifdef CHECK_POWER_ON_EVERY_COMMAND + /* Check if device was reset */ + rc2 = dochCheckPFSymptom(socketNo, pdev->bAtaDevNum, FALSE); + if(rc2 != DOCH_OK) + return rc2; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + /* If ATA debug was requested - retrieve and print buffer from Device */ + if(gDochAtaDebug == DOCH_GLOBAL_BOOL_PATTERN) + { + rc2 = retrieveAndPrintAtaDebug(pdev); + if(rc2 != DOCH_OK) + return rc2; + } + + return rc; +} + +/****************************************************************************** + * * + * d o c h _ a t a _ p a s s t h r u * + * * + * Pass-thru routine for ATA commands * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * ptOP : Data transfer type (In/Out/No) * + * in_regs : DOCH input registers values * + * out_regs : DOCH output registers values * + * buf : user buffer * + * secNum : Number of sectors (in case of data transfer) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_ata_passthru ( FLSNative socketNo, + FLSNative devNum, + DOCH_PassThru_Op ptOP, + DOCH_Registers * in_regs, + DOCH_Registers * out_regs, + void * buf, + FLNative secNum) +{ + DOCH_Socket* pdev; + DOCH_Error rc = DOCH_OK; + DOCH_Error rc2; + + /* Sanity Check*/ + /*=============*/ + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + switch(ptOP) + { + case DOCH_PASSTHRU_NO_DATA: + rc = io_ctrl (pdev, devNum, in_regs); + break; + + case DOCH_PASSTHRU_DATA_IN: + rc = io_input (pdev, devNum, in_regs, buf, secNum); + break; + + case DOCH_PASSTHRU_DATA_OUT: + rc = io_output (pdev, devNum, in_regs, buf, secNum); + break; + + default: + return DOCH_UnknownCmd; + } + + /*If IO operation succeeded, retrieve device response from ATA registers + (calling routine might need some data back from the device)*/ + if(rc == DOCH_OK) + rc = get_out_registers(pdev, devNum, out_regs); + else + return rc; + + /* If ATA debug was requested - retrieve and print buffer from Device */ + if(gDochAtaDebug == DOCH_GLOBAL_BOOL_PATTERN) + { + rc2 = retrieveAndPrintAtaDebug(pdev); + if(rc2 != DOCH_OK) + return rc2; + } + + return rc; + +} + +/****************************************************************************** + * * + * c l e a r A T A I n t e r r u p t * + * * + * Clear ATA interrupt by simply reading the ATA status register * + * * + * Parameters : * + * pdev : device to perform operation on * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error clearATAInterrupt(FLSNative socketNo) +{ +#ifdef DOCH_USE_FUNC + DOCH_Socket* pdev; + + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + +#else /*DOCH_USE_FUNC*/ + + DOCHREAD_ATA_REG((&sockets[socketNo])->bRegBase, DOCH_STATUS_REG); + +#endif /*DOCH_USE_FUNC*/ + + return DOCH_OK; +} + + +/****************************************************************************** + * * + * g e t _ o u t _ r e g i s t e r s * + * * + * Retrieve ATA output registers values * + * * + * Parameters : * + * pdev : device to perform operation on * + * out_regs : DOCH output registers values * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error get_out_registers(DOCH_Socket* pdev, FLSNative devNum, DOCH_Registers* out_regs) +{ + DOCH_Error error = DOCH_OK; + + out_regs->bFeaturesError = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_ERROR_REG); + out_regs->bSectorCount = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_SECTOR_CNT_REG); + out_regs->bSectorNumber = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_SECTOR_NO_REG); + out_regs->bCylLow = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_CYLINDER_LOW_REG); + out_regs->bCylHigh = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_CYLINDER_HIGH_REG); + out_regs->bDriveHead = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_DRIVE_HEAD_REG); + out_regs->bCommandStatus = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + out_regs->bContorlAltStatus = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_ALT_STATUS_REG); + + /*If an error was detected - return the error code*/ + if((out_regs->bCommandStatus & DOCH_ERROR) == DOCH_ERROR) + { + error = (DOCH_Error)out_regs->bFeaturesError; + + DBG_PRINT_ERR(FLZONE_ATA, "\r\nget_out_registers(): ATA Error\r\n"); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("error = 0x%x \r\n"),error)); + } + + return (error); +} + +/****************************************************************************** + * * + * d o c h _ g e t _ f l a g s * + * * + * Returns all device's flags (DOCH_USE_XXX) . * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * flags : device's flags will be stored there * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_get_flags (FLSNative socketNo, FLSNative devNum, FLDword * flags) +{ + /* Sanity check */ + if ((socketNo < 0) || (socketNo >= DOCH_MAX_SOCKETS) || (flags == NULL)) + return DOCH_BadParameter; + + *flags = sockets[socketNo].device[devNum].flags; + + return DOCH_OK; +} + + +/****************************************************************************** + * * + * d o c h _ s e t _ f l a g s * + * * + * Add various DOCH_USE_... flags to existing device's flags. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * flags : collection of DOCH_USE_... flags to add * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_set_flags (FLSNative socketNo, FLSNative devNum, FLDword flags) +{ + /* args sanity check */ + if ((socketNo < 0) || (socketNo >= DOCH_MAX_SOCKETS)) + return DOCH_BadParameter; + + sockets[socketNo].device[devNum].flags = flags; + + return DOCH_OK; +} + + + +/****************************************************************************** + * * + * d o c h _ r e s e t * + * * + * Reset ATA Protocol . * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error doch_reset (DOCH_Socket* pdev) +{ +#ifndef DOCH_DISABLE_RESET + FLDword tries; + FLDword i = 0; + FLByte status; + + DBG_PRINT_FLOW(FLZONE_ATA, "doch_reset() - enter\r\n"); + /*Protect against access time set to 0*/ + if(gDochAccessNanosec == 0) + { + DBG_PRINT_ERR(FLZONE_ATA,"doch_reset(): Failed with bad parameter access time set to 0 \r\n"); + return DOCH_BadParameter; + } + + /* reset DOCH */ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, DOCH_ATA_SRST); + + /* need to add delay before writing twice in short time to the control register*/ + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + + /* cancel DOCH reset */ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, 0); + + + /*Master is selected*/ + /* Wait for: + READY bit asserted + BUSY bit de-asserted + DRQ bit de-asserted + */ + tries = (DOCH_SHORT_WAIT* (1000000UL / gDochAccessNanosec)); + for(i=0; ibRegBase, DOCH_STATUS_REG); + if( (status & (DOCH_READY | DOCH_BUSY | DOCH_DRQ)) == DOCH_READY) + break; + } + if (!tries) + { + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\ndoch_reset(): Device#0 not ready (after reset): #0x%x \r\n"), status)); + return DOCH_TimedOut; + } + +#if (ATA_MAX_NUM_OF_DEVICES==2) + /*select slave and make sure slave is ready*/ + if (pdev->wNumOfDevices >1) + { + DOCH_Error rc; +#ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + pdev->bLastDevNum=0;/*Master was the last one that was selected*/ +#endif /*DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES*/ + /* 3 accesses in each iteration */ + tries = (DOCH_SHORT_WAIT* (1000000UL / (gDochAccessNanosec*3))); + while (tries) + { + /*Set active ATA device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV1); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,1); + + /* Before trying to identify Dev1, check its CHIP_ID*/ + rc = doch_check_chipID(pdev->wSocketNo); /*caller responsibility to set device head register*/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if (rc == DOCH_OK) + { /*found chip ID - check readiness*/ + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("Socket #%d dev1"), pdev->wSocketNo)); + DBG_PRINT_FLOW(FLZONE_ATA, " - Found ChipID !\r\n"); + break; + } + } + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + tries--; + } + + if (!tries) + { + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\ndoch_reset(): Device#1 not ready (after reset): #0x%x \r\n"), status)); + return DOCH_TimedOut; + } + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + /*Set original ATA device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV(pdev->bAtaDevNum)); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,pdev->bAtaDevNum); + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + } +#endif /*(ATA_MAX_NUM_OF_DEVICES==2)*/ + DBG_PRINT_FLOW(FLZONE_ATA, "doch_reset() - exit (OK) \r\n"); +#endif /*DOCH_DISABLE_RESET*/ + return DOCH_OK; +} + +/****************************************************************************** + * * + * u p d a t e _ d e v i c e _ i n f o * + * * + * Update device structure based on diskOnChip device info structure * + * * + * Parameters : * + * pdev : DOCH_Socket * + * diskOnChipDeviceInfo : DOCH_DeviceInfo * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error update_device_info(DOCH_Socket* pdev, + DOCH_DeviceInfo* diskOnChipDeviceInfo, + FLSNative devNum) +{ + IOreq ioreq; + + /*TBD - BYTE???*/ + FLByte drqSize ; + + if((pdev == NULL) || (diskOnChipDeviceInfo == NULL)) + return DOCH_BadParameter; + drqSize = 1<<((FLByte)((diskOnChipDeviceInfo->dwCommandFlagsOrStatuses & DOCH_DCFSB_CURRENT_MULTI_SECTOR) >> DOCH_DCFSO_CURRENT_MULTI_SECTOR)); + + /*Update device structure*/ + /*=======================*/ + pdev->device[devNum].wNumOfPartitions = diskOnChipDeviceInfo->wTotalNumOfPartitions; + + pdev->device[devNum].dataTransferMode = + (DOCH_TransferMode)((diskOnChipDeviceInfo->dwCommandFlagsOrStatuses & DOCH_DCFSB_CURRENT_XFER_MODE) >> DOCH_DCFSO_CURRENT_XFER_MODE); + + /*Set XFER mode*/ + /*-------------*/ + doch_setTransferMode(pdev->wSocketNo, devNum, pdev->device[devNum].dataTransferMode, drqSize); + + if(pdev->wNumOfDevices == 0) + { + /*Retrieve device user attributes*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, pdev->wSocketNo); + ioreq.irData = &devUserAttr; + DOCHGetDiskUserAttributes(&ioreq); + + /*Extract span information from device attributes*/ + tffscpy(&pdev->sSpanData, &devUserAttr.sdkAttributes.sSpanInfo, sizeof(pdev->sSpanData)); + } + + return DOCH_OK; +} + +/*----------------------------------------------------------------------*/ +/* d o c h S e t M u t e x */ +/* */ +/* Notifies the start and end of a file-system operation. */ +/* */ +/* Parameters: */ +/* socketNum : Socket number */ +/* state : DOCH_ON (1) = operation entry */ +/* DOCH_OFF(0) = operation exit */ +/* partition : Partition number of the drive */ +/* */ +/*----------------------------------------------------------------------*/ +DOCH_Error dochSetMutex(FLByte socketNum, FLBoolean state, FLByte partition) +{ + DOCH_Socket* pdev; + + if(socketNum > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNum]; + + if (state == DOCH_ON) /* Set busy to ON */ + { + if (!flTakeMutex(&pdev->mutex)) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\ndochSetMutex Failed to set mutex\r\n"); + return DOCH_DriveNotAvailable; + } + } + else /* Set busy to OFF */ + { + flFreeMutex(&pdev->mutex); + } + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ f i n d _ b a s e _ a d d r e s s * + * * + * Calculate base address, try getting CHIP_ID from the device * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * dwAddress : Device address * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static +DOCH_Error doch_find_base_address(FLSNative socketNo, + FLDword dwAddress) +{ + void* win; + + /*Retreive socket pointer from devices array*/ + DOCH_Socket* pdev; + + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + /* Save the physical address */ + pdev->dwPhysicalAddress = dwAddress; + + /* Get pointer to base of DOCH register set */ + win = (void*)(dwAddress); + + pdev->bRegBase = (volatile FLByte FAR0*)physicalToPointer((FLDword)win,DOCH_MEM_WIN_SIZE,0); + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ f i n d _ b a s e _ a d d r e s s * + * * + * Calculate base address, try getting CHIP_ID from the device * + * caller responsibility to set device head register * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static +DOCH_Error doch_check_chipID(FLSNative socketNo) +{ + FLWord chipID1 = 0; + FLWord chipID2 = 0; + + /*Retreive socket pointer from devices array*/ + DOCH_Socket* pdev; + + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + +/* no need to set device head register here- caller responsibility*/ + + /*Check ChipID*/ + /*============*/ + /*Read Chip ID #1*/ + chipID1 = doch_getConfigReg16(pdev, HIB_CHIPID1_REG); + /*Read Chip ID #2*/ + chipID2 = doch_getConfigReg16(pdev, HIB_CHIPID2_REG); + + + /*Check that Chip IDs match*/ + if((chipID1 + chipID2) == 0xFFFF) + { + if((chipID1 != DOCH_CHIP_ID_H3) && (chipID1 != DOCH_CHIP_ID_H4) && (chipID1 != DOCH_CHIP_ID_H5)) + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nUnknown ChipID: #%d \r\n"), chipID1)); + } +/* else + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nSocket #%d - ChipID OK"), socketNo)); + DBG_PRINT_FLOW(FLZONE_ATA, "\r\nDevice Found: "); + if(chipID1 == DOCH_CHIP_ID_H3) + DBG_PRINT_FLOW(FLZONE_ATA, "H3"); + if(chipID1 == DOCH_CHIP_ID_H4) + DBG_PRINT_FLOW(FLZONE_ATA, "H4"); + if(chipID1 == DOCH_CHIP_ID_H5) + DBG_PRINT_FLOW(FLZONE_ATA, "H5"); + } +*/ + return DOCH_OK; + } + else + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nSocket #%d - ChipID Not Found -"), socketNo)); + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT(" ChipID#1 0x%x , ChipID#2 0x%x\r\n"), chipID1, chipID2 )); + } + + return DOCH_AdapterNotFound; +} + +DOCH_Error setConfigHWItem(DOCH_HwConfigType configHWItem) +{ + DOCH_Error rc; + IOreq ioreq; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + ioreq.irFlags = configHWItem; + ioreq.irLength = gConfigHWDefaults[configHWItem]; + rc = DOCHConfigHW(&ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "\r\nsetConfigHWItem(): Failed setting config Item "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("#%d "),configHWItem)); + DBG_PRINT_ERR(FLZONE_ATA, "\r\nwith status: "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("0x%x \r\n"),rc)); + + return rc; + } + + return DOCH_OK; +} +/****************************************************************************** + * * + * d o c h _ c o n f i g C o m m o n * + * * + * initializes config registers common to both floors * + * * + * Parameters : * + * pdev : device descriptor * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_configCommon(DOCH_Socket* pdev) +{ + + /*Dummy write to exit virtual mode*/ + /*(Don't worry about the value it is later updated by calling setConfigHWItem(DOCH_IPL_CTRL))*/ + DOCHWRITE_CTRL_REG (pdev->bRegBase, HIB_CHIPID2_REG, 0); + + /*The following registers effect both floors - no need to select each floor*/ + if (gSdkInitDone != DOCH_GLOBAL_BOOL_PATTERN) + { /*initialize - set defaults*/ + /*Set Endian Control Register */ + doch_setConfigReg16 (pdev,HIB_ENDIAN_CTRL_REG,gConfigHWDefaults[DOCH_ENDIAN_CTRL]); + + /*Set Power down register */ + doch_setConfigReg16 (pdev,HIB_POWER_DOWN_REG,gConfigHWDefaults[DOCH_POWER_DOWN]); + + /*Set S/W Lock Control register + (This will perform SW lock as needed) */ + doch_setConfigReg16 (pdev,HIB_SW_LOCK_REG,gConfigHWDefaults[DOCH_SLOCK]); + + /*Set Operation Mode Register */ + doch_setConfigReg16 (pdev,HIB_OPERATION_MODE_REG,gConfigHWDefaults[DOCH_OPERATION_MODE_CTRL]); + }else + { /*recover last values*/ + if(configRegValueSet.wEndianCtrlSet) + { + doch_setConfigReg16 (pdev,HIB_ENDIAN_CTRL_REG,configRegValue.wEndianCtrl); + } + if(configRegValueSet.wPowerDownSet) + { + doch_setConfigReg16 (pdev,HIB_POWER_DOWN_REG,configRegValue.wPowerDown); + } + if (configRegValueSet.wSWLockSet) + { + doch_setConfigReg16 (pdev,HIB_SW_LOCK_REG,configRegValue.wSWLock); + } + if (configRegValueSet.wOperationModeSet) + { + doch_setConfigReg16 (pdev,HIB_OPERATION_MODE_REG,configRegValue.wOperationMode); + } + } + + +#ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + /* clear lastDevNum before initializing floors*/ + pdev->bLastDevNum = 0xFF; +#endif /*DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES*/ + + + return DOCH_OK; + +} +/****************************************************************************** + * * + * d o c h _ c o n f i g F l o o r * + * * + * initializes config registers of specific floor * + * NOTE: caller responsibility to select floor * + * * + * Parameters : * + * pdev : device descriptor * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_configFloor(DOCH_Socket* pdev) +{ + /*The following registers should be set only after device was successfully selected*/ + + if (gSdkInitDone!= DOCH_GLOBAL_BOOL_PATTERN) + { /*initialize - set defaults*/ + /*Set IPL control register */ + doch_setConfigReg16 (pdev,HIB_IPL_CONTROL_REG,gConfigHWDefaults[DOCH_IPL_CTRL]); + + /*Set DMA Control register */ + doch_setConfigReg16 (pdev,HIB_DMA_CTRL_REG,gConfigHWDefaults[DOCH_DMA_CTRL]); + + /*Set DMA Negation register */ + doch_setConfigReg16 (pdev,HIB_DMA_NEGATION_REG,gConfigHWDefaults[DOCH_DMA_NEGATION_CTRL]); + + }else + { /*recover last values*/ + if(configRegValueSet.wIPLCtrlSet) + { + doch_setConfigReg16(pdev, HIB_IPL_CONTROL_REG, configRegValue.wIPLCtrl); + } + + if(configRegValueSet.wDMACtrlSet) + { + doch_setConfigReg16(pdev, HIB_DMA_CTRL_REG, configRegValue.wDMACtrl); + } + + if(configRegValueSet.wEndianNegationSet) + { + doch_setConfigReg16(pdev, HIB_DMA_NEGATION_REG, configRegValue.wEndianNegation); + } + } + + return DOCH_OK; + +} + +/****************************************************************************** + * * + * d o c h _ c o n f i g A n d I D * + * * + * Try finding a DOCH device on the requested address * + * initializes config registers that are common to both floors * + * reads chipID of floor 0 * + * initializes config registers of floor 0 * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * DOCH_InitSocket : runtime socket init data * + * pDev : device to act on * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static DOCH_Error doch_configAndID(DOCH_Socket* pdev, FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc; + + /*Try finding a DOCH device on the requested address*/ + /*==================================================*/ + gSdkDOCAddressObtained = 0; + + rc = doch_find_base_address(socketNo, initSocket.nDeviceAddress); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "Socket "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("#%d "), socketNo)); + DBG_PRINT_ERR(FLZONE_ATA, "NOT found !\r\n"); + + return rc; + } + + /* Global indication that the DOC address was obtained */ + gSdkDOCAddressObtained = DOCH_GLOBAL_BOOL_PATTERN; + + /*Set PCI/PortaDoc window offset register*/ + /*=======================================*/ + if(gAccessLayerType == DOCH_AL_NOR) + { + if(gMemWindowType == MEM_WIN_8KB) + { + + if (!DOCH_SET_WINDOW_OFFSET(TRUE, pdev->bRegBase)) + { + return DOCH_GeneralFailure; + } + + } + else + { + if (!DOCH_SET_WINDOW_OFFSET(FALSE, pdev->bRegBase)) + { + return DOCH_GeneralFailure; + } + } + } + + /* Set HW Config Items */ + /*=====================*/ + /*The following registers effect both floors - no need to select each floor*/ + doch_configCommon(pdev); + + /*Set device to master before checking CHIP ID*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + + /*initialize config registers of floor 0*/ + doch_configFloor(pdev); + + + /*Check ChipID*/ + /*============*/ + rc = doch_check_chipID(socketNo);/*caller responsibility to set device head register*/ + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_ATA, "Socket "); + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("#%d device#0"), socketNo)); + DBG_PRINT_ERR(FLZONE_ATA, " - ChipID FAILED !\r\n"); + + return rc; + } + + return DOCH_OK; + +} + +static DOCH_Error doch_init_8kb(DOCH_Socket* pdev, FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc; + + /*Set mem window type and size*/ + gMemWindowType = MEM_WIN_8KB; + gDochMemWinSize = DOCH_MEM_WIN_SIZE_8KB; + + /*Set addresses*/ + gHibContRegAreaAddress = HIB_CORE_ADDRESS_8KB+DOCH_CONT_REG_AREA_8KB_OFFSET; + gHibDataPortAreaAddress = HIB_CORE_ADDRESS_8KB+DOCH_DATA_PORT_AREA_8KB_OFFSET; + gHibConfigRegAreaAddress = HIB_CORE_ADDRESS_8KB+DOCH_CONFIG_REG_AREA_8KB_OFFSET; + + DBG_PRINT_FLOW(FLZONE_ATA, "Try 8KB window...\r\n"); + + /*Config HW and check ChipID*/ + rc = doch_configAndID(pdev, socketNo, initSocket); + + if(rc == DOCH_OK) + DBG_PRINT_FLOW(FLZONE_ATA, "Memory window is 8KB\r\n"); + + return rc; +} + +static DOCH_Error doch_init_128kb(DOCH_Socket* pdev, FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc; + + /*Set mem window type*/ + gMemWindowType = MEM_WIN_128KB; + gDochMemWinSize = DOCH_MEM_WIN_SIZE_128KB; + + /*Set addresses*/ + gHibContRegAreaAddress = HIB_CORE_ADDRESS_128KB+DOCH_CONT_REG_AREA_128KB_OFFSET; + gHibDataPortAreaAddress = HIB_CORE_ADDRESS_128KB+DOCH_DATA_PORT_AREA_128KB_OFFSET; + gHibConfigRegAreaAddress = HIB_CORE_ADDRESS_128KB+DOCH_CONFIG_REG_AREA_128KB_OFFSET; + + DBG_PRINT_FLOW(FLZONE_ATA, "Try 128KB window...\r\n"); + + /*Config HW and check ChipID*/ + rc = doch_configAndID(pdev, socketNo, initSocket); + + if(rc == DOCH_OK) + DBG_PRINT_FLOW(FLZONE_ATA, "Memory window is 128KB\r\n"); + + return rc; +} + +/****************************************************************************** + * * + * d o c h _ A T A s t d _ I D E N T I F Y _ D E V I C E * + * * + * Identify Device by using ATA standard IDENTIFY DEVICE command. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * DOCH_InitSocket : runtime socket init data * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +static DOCH_Error doch_ATAstd_IDENTIFY_DEVICE(FLSNative socketNo, FLSNative devNum) +{ + DOCH_Error rc; + DOCH_Registers in_regs; + DOCH_Registers out_regs; + + tffsset(&in_regs, 0, sizeof(in_regs)); + in_regs.bDriveHead = DOCH_SELECT_DEV(devNum); + in_regs.bCommandStatus = DOCH_CMD_IDENTIFY_DEV; + + gIgnoreErrorBit = 1; + + rc = doch_ata_passthru ( socketNo, + devNum, + DOCH_PASSTHRU_DATA_IN, + &in_regs, + &out_regs, + &sockets[socketNo].device[devNum].driveParameters, + 1); + + gIgnoreErrorBit = 0; + + if(rc != DOCH_OK) + return DOCH_DiskNotFound; + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ i n i t _ w i n d o w * + * * + * Initialize DOCH socket (only first floor is initialized) * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * DOCH_InitSocket : runtime socket init data * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_init_window (FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc; + DOCH_Socket* pdev; + FLByte j; + + /* args sanity check */ + if ((socketNo < 0) || (socketNo >= DOCH_MAX_SOCKETS)) + return DOCH_BadParameter; + + /*Retreive socket pointer from devices array*/ + pdev = &sockets[socketNo]; + + for(j=0; j < 2 ; j++) + { + /*Try identifying device on both 8KB and 128KB memory windows*/ + /*===========================================================*/ + + #ifdef DOCH_ASSUME_128KB_WINDOW + /*If 128KB window is assumed, skip checking 8KB window*/ + j = 1; + #endif /*DOCH_ASSUME_128KB_WINDOW*/ + + #ifdef DOCH_ASSUME_8KB_WINDOW + /*If 8KB window is assumed, do not continue checking 128KB window*/ + if(j == 1) + return DOCH_AdapterNotFound; + #endif /*DOCH_ASSUME_8KB_WINDOW*/ + + if(j==0) /*Try 8KB window*/ + { + rc = doch_init_8kb(pdev, socketNo, initSocket); + if(rc == DOCH_OK) + return DOCH_OK; + } + else /*Try 128KB window*/ + { + rc = doch_init_128kb(pdev, socketNo, initSocket); + if(rc != DOCH_OK) + return rc; + } + + } + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ i n i t _ f l o o r * + * * + * initialization sequence for each floor (MASTER \SLAVE) * + * makes sure floor is ready * + * in case of ATA_MAX_NUM_OF_DEVICES == 2 both floors should be initialized * + * * + * Parameters : * + * pdev : device to act on * + * bFloor : 0-MASTER , 1-SLAVE * + * bConfFloor : TRUE - config floor * + * FALSE - do not config floor * + * (Master might be already set during window search) * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_init_floors (DOCH_Socket* pdev,FLByte bConfFloor,FLByte * bFloorsNum) +{ + DOCH_Error rc =DOCH_OK; + FLDword dwTimes=0,i; + FLWord status; + + (*bFloorsNum) =0; + /* MASTER*/ + if (bConfFloor) + { + /* when function call is not from init sequence- */ + /* device head was not set yet and floor was not configured*/ + /*Set active ATA device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV0); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,0); + doch_configFloor(pdev); + } + /* during init - no need to rewrite device head register */ + /* it was set inside doch_init_xxkb */ + /* chip ID for device#0 was already checked */ + + /*Disable interrupts (will be enabled later per API decision)*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, DOCH_ATA_NIEN); + + dwTimes = (DOCH_MOUNT_WAIT* (1000000UL / gDochAccessNanosec)); + for(i=0; ibRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + break; + } + + if (i==dwTimes) + { + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("\r\nDoch_init_floors(): Device#0 not ready - status: 0x%x \r\n"),status)); + rc = DOCH_DiskNotFound; + } + else + { + (*bFloorsNum)++; + } + +#if (ATA_MAX_NUM_OF_DEVICES==2) + + if (rc==DOCH_OK) + { /* SLAVE*/ + FLSNative socketNo =pdev->wSocketNo; + dwTimes=0; + rc=DOCH_GeneralFailure; + /* SLAVE device cannot be selected until it becomes ready*/ + /* no way for checking slave readiness without selecting it first...*/ + /* Therefore make several trials to select it and read it's chip ID */ + while ((dwTimes < DOCH_CHIP_ID_TRIALS_FOR_SLAVE)) + { + /*Set active ATA device*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_DRIVE_HEAD_REG, DOCH_SELECT_DEV1); + DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,1); + + /* Before trying to identify Dev1, check its CHIP_ID*/ + rc = doch_check_chipID(socketNo); /*caller responsibility to set device head register*/ + + if (rc != DOCH_OK) + { + DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE; + }else + { + /*found chip ID - check readiness*/ + status = DOCHREAD_ATA_REG(pdev->bRegBase, DOCH_STATUS_REG); + if((status & (DOCH_READY | DOCH_BUSY)) == DOCH_READY) + break; + } + + dwTimes++; + } + + if(dwTimes == DOCH_CHIP_ID_TRIALS_FOR_SLAVE) /* no more trials..*/ + { /*SLAVE Failed*/ + DBG_PRINT_ERR_PRM(FLZONE_ATA, (FLTXT("Socket #%d dev1"), socketNo)); + DBG_PRINT_ERR(FLZONE_ATA, " - ChipID FAILED !\r\n"); + rc = DOCH_DiskNotFound; + } + else + { /*SLAVE Succeed*/ + (*bFloorsNum)++; + + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("Socket #%d dev1"), socketNo)); + DBG_PRINT_FLOW(FLZONE_ATA, " - Found ChipID !\r\n"); + /* initialize config registers of floor 1*/ + doch_configFloor(pdev); + + /*Disable interrupts (will be enabled later per API decision)*/ + DOCHWRITE_ATA_REG (pdev->bRegBase, DOCH_CONTROL_REG, DOCH_ATA_NIEN); + } + + } /*SLAVE*/ +#endif /*(ATA_MAX_NUM_OF_DEVICES==2)*/ + + if ((*bFloorsNum)>0 && rc!=DOCH_OK) + { + /* one floor succeed */ + rc = DOCH_OK; + } + /*Reset ATA protocol to ensure device is ready for the next ATA command*/ + /*Waiting to mount to complete before reset protocol*/ + /* need to add delay before reset (another access to DOCH_CONTROL_REG) */ + DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER; + + if (pdev->wNumOfDevices == 0) + { + /* during init sequence */ + pdev->wNumOfDevices = (*bFloorsNum); /* needed for reset routine*/ + doch_reset(pdev);/*reset both floors*/ + pdev->wNumOfDevices = 0; /* will be actually updated in init sequence*/ + + }else + { + /* during recover from power loss sequence*/ + if (pdev->wNumOfDevices != *bFloorsNum) + { + /*different number of floors was found*/ + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("originally number of floors was %d and found %d\r\n"), + pdev->wNumOfDevices,*bFloorsNum)); + return DOCH_GeneralFailure; + } + doch_reset(pdev);/*reset both floors*/ + } + return rc; +} +/****************************************************************************** + * * + * d o c h _ i n i t _ s o c k e t * + * * + * Initialize DOCH socket. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * DOCH_InitSocket : runtime socket init data * + * * + * Returns : * + * DOCH_OK in success, otherwise respective error code. * + * * + ******************************************************************************/ +DOCH_Error doch_init_socket (FLSNative socketNo, DOCH_InitSocket initSocket) +{ + DOCH_Error rc = DOCH_OK; + DOCH_Socket * pdev; + IOreq ioreq; + register FLSByte i; + FLByte bFloorsNum=0; + + /* args sanity check */ + if ((socketNo < 0) || (socketNo >= DOCH_MAX_SOCKETS)) + return DOCH_BadParameter; + + /*Clear "Ignore Error Bit" indication*/ + gIgnoreErrorBit = 0; + + /*Retreive socket pointer from devices array*/ + pdev = &sockets[socketNo]; + + /*Create a MUTEX for the socket*/ + flCreateMutex(&pdev->mutex); + + /*Clear socket structure*/ + clear_socket(pdev); + + /*Set socket number*/ + pdev->wSocketNo = socketNo; + + /*If no devices found - return failure + If 2 devices - check last partition of device #0 for partition span indication + ============================================================================*/ + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\nSearching devices on socket #%d...\r\n\n"), socketNo)); + + pdev->wTotalNumOfPartitions = 0; + pdev->nTotalCapacity = 0; + + /*Try identifying device on both 8KB and 128KB memory windows*/ + /*===========================================================*/ + rc = doch_init_window(socketNo,initSocket); + if(rc != DOCH_OK) + { + return rc; + } + + rc = doch_init_floors(pdev,FALSE,&bFloorsNum); + if(rc != DOCH_OK) + { + return rc; + } + + for(i=0; ibAtaDevNum = i; + + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, socketNo); + ioreq.irData = &gDiskOnChipDeviceInfo; + /*Identify command with very short timeout, and "option1" on" + (just check if the device responds, not all fields are valid!)*/ + ioreq.irCount = DOCH_IDENTIFY_EXISTANCE; + gUseShortWaitOnBusy = DOCH_SHORT_IDENTIFY_TIMEOUT; + rc = DOCHIdentifyDiskOnChipDeviceSingleFloor(&ioreq); + gUseShortWaitOnBusy = 0; + + /*If the device was NOT identified (e.g. not existing) - + try using ATA standard IDENTIFY DEVICE command*/ + if(rc != DOCH_OK) + { + /*Try Identifying using Standard ATA IDENTIFY DEVICE command*/ + gUseShortWaitOnBusy = DOCH_SHORT_IDENTIFY_TIMEOUT; + rc = doch_ATAstd_IDENTIFY_DEVICE(socketNo, i); + gUseShortWaitOnBusy = 0; + + /*Identifying using Standard ATA IDENTIFY DEVICE command - FAILED*/ + if(rc != DOCH_OK) + { + return DOCH_DiskNotFound; + } + + /*Identifying using Standard ATA IDENTIFY DEVICE command - SUCCEEDED*/ + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nDev%d identifid WITHOUT ETFFS...\r\n\n"), i)); + } + else + { + /*If the device was WAS identified (e.g. exists) - perform full retrieval of device info data + without "option1" and with a longer timeout*/ + ioreq.irCount = DOCH_IDENTIFY_FROM_FLASH; + gUseShortWaitOnBusy = DOCH_LONG_IDENTIFY_TIMEOUT; + rc = DOCHIdentifyDiskOnChipDeviceSingleFloor(&ioreq); + gUseShortWaitOnBusy = 0; + } + if(rc == DOCH_OK) + pdev->wNumOfDevices ++; +#endif /*CX_TOOLS_SUPPORT*/ + } /* End loop search for number of floors */ + + if(rc != DOCH_OK) + { + return DOCH_DiskNotFound; + } + + pdev->wTotalNumOfPartitions += pdev->device[i].wNumOfPartitions; + pdev->nTotalCapacity += gDiskOnChipDeviceInfo.dwUnformattedCapacity; + + /*Set ATA Device Number back to 0...*/ + pdev->bAtaDevNum = 0; + + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\nFound #%d device(s)...\r\n\n"), pdev->wNumOfDevices)); + + /*Set DPD mode as requested*/ + /*=========================*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + + /*If registered HAL is SPI, disable DPD*/ + if(gAccessLayerType == DOCH_AL_SPI) + { + gDpdSettings.activeMode = DOCH_WM_NORMAL; + gDpdSettings.inActiveMode = DOCH_IM_IDLE; + } + + if(pdev->device[0].ETFFS_Identified) + { + /*1. Set both modes + 2. If DOCH_IM_IDLE_2_DPD configured as Inactive mode, force ETFFS + to enter Inactive mode after the command completes*/ + ioreq.irFlags = DOCH_PM_SET_BOTH_MODES; + if(gDpdSettings.inActiveMode == DOCH_IM_IDLE_2_DPD) + ioreq.irFlags |= DOCH_PM_INACTIVE_MODE; + + /*3. Set Active/Inactive modes*/ + ioreq.irCount = (gDpdSettings.activeMode | gDpdSettings.inActiveMode); + /*4. Set Timeout*/ + ioreq.irLength = gDpdSettings.timeOut; + + /*5. Set Power Modes to device(s) that ETFFS was identified on*/ + /* no need to call flDOCHSetPowerMode twice for each floor - this is done inside flDOCHSetPowerMode*/ + + rc = flDOCHSetPowerMode(&ioreq); + if(rc != DOCH_OK) + return rc; + +#ifdef FL_REPORT_INTERNAL_ERRORS + /* Set DocH to report internal errors*/ + tffsset(&ioreq, 0, sizeof(ioreq)); + ioreq.irCount = DOCH_CP_REPORT_ECC_MODE; + ioreq.irSectorNo = (FLWord)(DOCH_ENABLE_REPORT_ECC_ERRORS); + ioreq.irFlags = DOCH_CUSTOM_PARAM_TEMP; + rc = DOCHSetCustomParameter(&ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_WRN_PRM(FLZONE_ATA, (FLTXT("\r\nWARNING: Failed setting mDoc to report internal errors with status %d \r\n"), rc)); + /*return rc;*/ /*do not fail - backward compatibility*/ + } +#endif /*FL_REPORT_INTERNAL_ERRORS*/ + + } + + return DOCH_OK; +} + + + +/*********************************************************/ +/* Function name : doch_release_socket*/ +/* Description : calls to appropriated function */ +/* to release all allocated memory / devices etc */ +/* Return type : DOCH_Error */ +/* Argument : int socketNo*/ +/*********************************************************/ +DOCH_Error doch_release_socket( int socketNo ) +{ +#ifdef DOCH_USE_FUNC + DOCH_Error status; + DOCH_Socket* pdev; + + if(socketNo > DOCH_MAX_SOCKETS - 1) + return DOCH_BadParameter; + + pdev = &sockets[socketNo]; + + /* Un-register the socket */ + status = (DOCH_Error)(pdev->halRoutines.hal_doch_release(socketNo)); + + /*Delete the mutex*/ + flDeleteMutex(&pdev->mutex); + + if(status != DOCH_OK) + return DOCH_GeneralFailure; +#endif /*DOCH_USE_FUNC*/ + + return DOCH_OK; +}/*doch_release_socket()*/ + + + + +/****************************************************************************** + * * + * d o c h _ g e t _ d i s k * + * * + * Return pointer to device, by device number. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * devNum : Device # (0,1) * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +DOCH* DOCH_get_disk(FLSNative socketNo, FLSNative devNum) +{ + if(socketNo > (DOCH_MAX_SOCKETS-1)) + return NULL; + else + return &sockets[socketNo].device[devNum]; +} + +/****************************************************************************** + * * + * d o c h _ s e t T r a n s f e r M o d e * + * * + * Sets data transfer mode * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * devNum : ATA Device [0..1] * + * tm : required data transfer mode: * + * DOCH_DATA_MODE_SINGLE * + * DOCH_DATA_MODE_MULT * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +DOCH_Error doch_setTransferMode (FLSNative socketNo, FLSNative devNum, DOCH_TransferMode tm, FLDword drqSize) +{ + if(socketNo > (DOCH_MAX_SOCKETS-1)) + return DOCH_BadParameter; + else + { + sockets[socketNo].device[devNum].dataTransferMode = tm; + sockets[socketNo].device[devNum].dwMulti_Current = drqSize; + + } + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ g e t T r a n s f e r M o d e * + * * + * Returns data transfer mode * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +DOCH_TransferMode doch_getTransferMode (FLSNative socketNo, FLSNative devNum) +{ + return sockets[socketNo].device[devNum].dataTransferMode; +} + +/****************************************************************************** + * * + * d o c h _ s e t C o n f i g R e g 1 6 * + * * + * Set DOCH 16Bit configuration register * + * Register values are maintained by a global structure of type * + * DOCH_ConfigRegsValue in order to allow recovery after power loss. * + * * + * Parameters : * + * pdev : device descriptor * + * registerOffset: Register offset * + * registerValue : Register Value * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +DOCH_Error doch_setConfigReg16(DOCH_Socket* pdev, FLDword registerOffset, FLNative registerValue) +{ + + if(registerOffset == (FLDword)HIB_BURST_WRITE_MODE_CTRL_REG) + { + configRegValue.wBurstWriteModeCtrl |= registerValue; + configRegValueSet.wBurstWriteModeCtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_BURST_READ_MODE_CTRL_REG) + { + configRegValue.wBurstReadModeCtrl |= registerValue; + configRegValueSet.wBurstReadModeCtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_IPL_CONTROL_REG) + { + configRegValue.wIPLCtrl |= (registerValue | DOCH_IPL_WRITE_READY); + configRegValueSet.wIPLCtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_POWER_DOWN_REG) + { + configRegValue.wPowerDown |= registerValue; + configRegValueSet.wPowerDownSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_DMA_CTRL_REG) + { + configRegValue.wDMACtrl |= registerValue; + configRegValueSet.wDMACtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_SW_LOCK_REG) + { + configRegValue.wSWLock |= registerValue; + configRegValueSet.wSWLockSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_ENDIAN_CTRL_REG) + { + configRegValue.wEndianCtrl |= registerValue; + configRegValueSet.wEndianCtrlSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_DMA_NEGATION_REG) + { + configRegValue.wEndianNegation |= registerValue; + configRegValueSet.wEndianNegationSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_OPERATION_MODE_REG) + { + configRegValue.wOperationMode |= registerValue; + configRegValueSet.wOperationModeSet = TRUE; + } + else if(registerOffset == (FLDword)HIB_POWER_MODE_REG) + { + /*Do nothing*/ + } + else + { + return DOCH_BadParameter; + } + + DOCHWRITE_CTRL_REG (pdev->bRegBase, registerOffset, registerValue); + + return DOCH_OK; +} + +/****************************************************************************** + * * + * d o c h _ g e t C o n f i g R e g 1 6 * + * * + * Returns DOCH 16Bit configuration register value * + * * + * Parameters : * + * pdev : device descriptor * + * registerOffset: Register offset * + * * + * Returns : * + * Pointer to DOCH structure. * + * * + ******************************************************************************/ +FLWord doch_getConfigReg16(DOCH_Socket* pdev, FLSNative registerOffset) +{ + /*Read 16Bit register*/ + return DOCHREAD_CTRL_REG(pdev->bRegBase, registerOffset); +} + + + +/****************************************************************************** + * * + * d e f _ d o c h D e l a y U s e c * + * * + * default implementation of delay according to access time * + * * + * Parameters : * + * FLDword usec: time to wait in uSec * + * dwAccessTime: access time in nano sec * + * * + * Returns : * + * 0 on success, otherwise error number. * + * * + ******************************************************************************/ +DOCH_Error def_dochDelayUsec(FLDword usec,FLDword dwAccessTime) +{ + volatile FLWord val; + FLDword dwCount = usec * (1000UL / dwAccessTime); +#ifdef DOCH_USE_FUNC + DOCH_Socket * pdev =&sockets[0]; +#endif /*DOCH_USE_FUNC*/ + + if (dwCount==0) + dwCount=1; + + /* read any register dwCount times; each time consumes gDochAccessNanosec*/ + while (dwCount-- > 0) + { + +#ifdef DOCH_USE_FUNC + val = DOCHREAD_CTRL_REG(pdev->bRegBase, HIB_CHIPID1_REG); +#else /*DOCH_USE_FUNC*/ + val = DOCHREAD_CTRL_REG(sockets[0].bRegBase, HIB_CHIPID1_REG); +#endif /*DOCH_USE_FUNC*/ + + } + + return DOCH_OK; + +} + + +#ifdef __cplusplus +} + +#endif diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_ata.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_ata.h new file mode 100755 index 00000000..bc9cfe43 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_ata.h @@ -0,0 +1,731 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/***********************************************************************************/ +/* */ +/* Header file for doch_ata module */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_ata.h-arc $ + * + * Rev 1.44 Dec 26 2007 10:13:36 einat.avidan + * doch_reset and doch_init_floors - changed parameters. + * + * Rev 1.43 Dec 11 2007 12:29:14 einat.avidan + * init sequence and DOCHConfigHW: change parameters of internal functions + * + * Rev 1.42 Dec 04 2007 17:32:42 einat.avidan + * Define max mount time + * def_dochDelayUsec - receives new parameter: access time. + * New functions declaration: doch_init_floor and doch_configCommon + * + * Rev 1.41 Oct 30 2007 17:01:42 einat.avidan + * replace dochEnableATAInterrupt function with macros + * + * Rev 1.40 Oct 23 2007 15:37:44 einat.avidan + * before reset wait for the longest operation to complete. + * + * Rev 1.39 Oct 23 2007 12:27:54 einat.avidan + * optimization: delay after setting head register only + * when switching floors + * + * Rev 1.38 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.37 Oct 21 2007 15:29:34 einat.avidan + * fix compilation warnings + * + * Rev 1.36 Oct 11 2007 18:48:42 Einat.Avidan + * update DOCH_VERY_LONG_WAIT + * in every write to drive head register set LBA bit. + * doch_reset resets both floor (no need of devNum parameter) + * caller responsible to set device head register + * when calling to dochEnableATAInterrupt (no need of devNum parameter) + * new function def_dochDelayUsec + * add compilation flags for SOTP and SLPP + * + * Rev 1.35 Sep 04 2007 15:40:28 einat.avidan + * bug fix: DOCH_VERY_LONG_WAIT definition was added + * (add_partition and secure_erase should have long waiting time) + * + * Rev 1.34 Mar 13 2007 13:47:20 einat.avidan + * add support for SLPP + * + * Rev 1.33 Feb 28 2007 09:58:42 einat.avidan + * No change + * + * Rev 1.32.1.1 Nov 12 2006 09:47:02 Yaniv.Iarovici + * 1. Added parameter 'FLBoolean waitOnBusy' to doch_reset(). + * 2. Added 'DOCH_SRST_WAIT' + * + * Rev 1.32.1.0 Oct 31 2006 12:23:36 yaniv.iarovici + * Added doch_init_window(). + * + * Rev 1.32 Oct 05 2006 11:00:42 yaniv.iarovici + * 1. Removed dwMulti_Read, dwMulti_Write. + * 2. Added dwMulti_MAX. + * 3. Removed DOCH_multReadOp structure. + * + * Rev 1.31 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.30 Aug 22 2006 13:23:54 Yaniv.Iarovici + * Add 'extern "c"' on flExit() definition + * - extern DOCH_Socket sockets [DOCH_MAX_SOCKETS] + * - DOCH_get_socket MACRO definition + * + * Rev 1.29 Aug 16 2006 08:46:10 Yaniv.Iarovici + * structure DOCH: + * - Remove wOtpToParition[] + * - Add ETFFS_Identified instead + * + * Rev 1.28 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef DOCH_ATA_H +#define DOCH_ATA_H + +#include "doch_sys.h" +#include "doch_api.h" + +#include "part_inf.h" + +/* + * macros + * (also customizable for internal purpose) + * + */ + +/* 'long' DOCH operations can take up to DOCH_LONG_WAIT milliseconds */ +#ifndef DOCH_LONG_WAIT + #define DOCH_LONG_WAIT 500 +#endif /*DOCH_LONG_WAIT*/ + +/* 'short' DOCH operations can take up to DOCH_SHORT_WAIT milliseconds */ +#ifndef DOCH_SHORT_WAIT + #define DOCH_SHORT_WAIT 450 +#endif /*DOCH_SHORT_WAIT*/ + +/* 'very long' DOCH operations can take up to DOCH_VERY_LONG_WAIT milliseconds */ +#ifndef DOCH_VERY_LONG_WAIT + #define DOCH_VERY_LONG_WAIT 180000 +#endif /*DOCH_VERY_LONG_WAIT*/ + +/* Wait for busy bit to clear before sending SRST to the device (milliseconds) */ +#ifndef DOCH_SRST_WAIT + #define DOCH_SRST_WAIT DOCH_SHORT_WAIT +#endif /*DOCH_SRST_WAIT*/ + +/* Wait for busy bit to clear during init sequence(milliseconds) */ +#ifndef DOCH_MOUNT_WAIT + #define DOCH_MOUNT_WAIT 3000 +#endif /*DOCH_SRST_WAIT*/ + +/* "Very short wait" used for identifying device = 50ms */ +#ifndef DOCH_SHORT_IDENTIFY_TIMEOUT + #define DOCH_SHORT_IDENTIFY_TIMEOUT (10L*1000000L/gDochAccessNanosec) +#endif /*DOCH_SHORT_IDENTIFY_TIMEOUT*/ + +/* "Longer" wait used for identifying device = 500ms */ +#ifndef DOCH_LONG_IDENTIFY_TIMEOUT + #define DOCH_LONG_IDENTIFY_TIMEOUT (500L*1000000L/gDochAccessNanosec) +#endif /*DOCH_LONG_IDENTIFY_TIMEOUT*/ + +#ifndef DOCH_DEFAULT_SLEEP_PERIOD + #define DOCH_DEFAULT_SLEEP_PERIOD 3000 +#endif /* DOCH_DEFAULT_SLEEP_PERIOD */ + +/*#define ONE_SEC_IN_NANO_SEC (1000000000 / gDochAccessNanosec)*/ + +/* maximum number of sectors which could be read from / written to DOCH at once */ +#define DOCH_MAX_SECTORS 256 + +/*ATA device definitions*/ +#define DOCH_ATA_MASTER_DEV 0 /* master device only */ +#define DOCH_ATA_SLAVE_DEV 1 /* slave device only */ +#define DOCH_ATA_ALL_DEVS 0xff /* all devices */ + +#define ATA_NO_ERR 0 /* no error on ATA command */ + +#define DOCH_ATA_MAX_TIMEOUT 0xFFFFFFFF + +/* Access Layer Types */ +typedef enum { + DOCH_AL_NONE = 0xCAF0, + DOCH_AL_NOR = 0xCAF1, + DOCH_AL_SPI = 0xCAF2, + DOCH_AL_USER = 0xCAF3, + DOCH_AL_SIM = 0xCAF4 +} DOCH_AccessLayerType; + +/* Optional bits in DOCH_DRIVE_HEAD_REG */ +#define DRIVE_HEAD_OPT1 0x80 +#define DRIVE_HEAD_OPT2 0x20 + +/* Pattern to add to DOCH_DRIVE_HEAD_REG to */ +/*Option1*/ +#define CUSTOM_PARAM_TEMP DRIVE_HEAD_OPT1 /*Temporary value*/ +#define CUSTOM_PARAM_DEFAULT 0 /*DEFAULT value*/ +#define PERM_DEFAULT_PART_OP DRIVE_HEAD_OPT1 /*Permanently set default partition number*/ +#define PREPARE_FOR_WRITE_OP 0 +#define REWRITE_NORMAL_OP DRIVE_HEAD_OPT1 +#define WRITE_NORMAL_OP DRIVE_HEAD_OPT1 +#define HASH_AS_IS 0 +#define HASH_BY_KEY DRIVE_HEAD_OPT1 +#define DELETE_PARTITIONS_FAST 0 +#define DELETE_PARTITIONS_COMPLETE DRIVE_HEAD_OPT1 +/*Option2*/ +#define ERASE_NORMAL 0 +#define ERASE_IMMEDIATE DRIVE_HEAD_OPT2 + + +typedef enum { DOCH_4BITS = 0, /*TBD*/ + DOCH_ATA_NIEN = 2, + DOCH_ATA_SRST = 4 +} DOCH_control_reg; + +/* Data transfer modes */ +typedef enum { DOCH_DATA_MODE_SINGLE = 0x00, + DOCH_DATA_MODE_MULT = 0x01 +} DOCH_TransferMode; + +/* Atomic write sequence control */ +typedef enum { DOCH_START_ATOMIC_WRITE = 0x00, + DOCH_FINISH_ATOMIC_WRITE = 0x01, + DOCH_ABORT_ATOMIC_WRITE = 0x02 +} DOCH_AtomicSeqCtrl; + +/* set of DOCH Vendor-Specific ATA Commands */ +typedef enum { + /*I/O*/ + DOCH_VSCMD_READ_PARTITION = 0x82, + DOCH_VSCMD_WRITE_PARTITION = 0x83, + DOCH_VSCMD_WRITE_FLEXI = 0x84, + + /*Sectors Operations*/ + DOCH_VSCMD_OPTIMIZE_PARTITION_SECTORS = 0x86, + DOCH_VSCMD_ERASE_PARTITION_SECTORS = 0x88, + + /*Hash*/ + DOCH_VSCMD_READ_CALCULATED_HASH = 0x8A, + DOCH_VSCMD_WRITE_CALCULATED_HASH = 0x8B, + DOCH_VSCMD_READ_ORIGINAL_HASH = 0x8C, + DOCH_VSCMD_WRITE_GIVEN_HASH = 0x8D, + + /*Sub-commanded commands*/ + DOCH_VSCMD_PARTITION_MANAGEMENT = 0xFA, + DOCH_VSCMD_ACCESS_CONTROL = 0xFB, + DOCH_VSCMD_EXT_DEVICE_CTRL = 0xFC, + DOCH_VSCMD_EXT_SECURITY_CTRL = 0xFD, + + /*Supported standard ATA commands*/ + DOCH_CMD_IDENTIFY_DEV = 0xEC, + DOCH_DOWNLOAD_MICROCODE = 0x92 + +} DOCH_Command; + +/* set of operation codes for DOCH_VSCMD_PARTITION_MANAGEMENT command */ +typedef enum { + DOCH_GET_PARTITION_INFO = 0x00, + DOCH_SET_DEFAULT_PARTITION = 0x11, + DOCH_SET_PARTITION_PROTECTION = 0x18, + DOCH_GET_PARTITION_USER_ATTR = 0x70, + DOCH_SET_PARTITION_USER_ATTR = 0x71, + DOCH_DELETE_PARTITIONS = 0xB0, + DOCH_ADD_PARTITION = 0xB4, + DOCH_SECURE_ERASE = 0xB8 +} DOCH_PartitionManageOp; + +/* set of operation codes for DOCH_VSCMD_ACCESS_CONTROL command */ +typedef enum { + DOCH_EN_ACCESS_WPWD = 0x30, + DOCH_DISABLE_ACCESS = 0x31, + + /*Enable access with challange/response protocol*/ + DOCH_TX_HOST_PUBLICKEY = 0x32, + DOCH_RX_DOCH_PUBLICKEY = 0x33, +#ifndef FL_SLPP + DOCH_VERIFY_HOST_KEY = 0x34 +#else/* FL_SLPP */ + DOCH_VERIFY_HOST_KEY = 0x34, + /*SLPP Specific*/ + DOCH_SLPP_UNLOCK_RANGE = 0x40, + DOCH_SLPP_UNLOCK_ENTIRE_PARTITION = 0x41, + DOCH_SLPP_LOCK_RANGE = 0x42, + DOCH_SLPP_STICKY_LOCK_RANGE = 0x43, + DOCH_SLPP_REPORT_LOCKED_RANGES = 0x44 +#endif /*FL_SLPP*/ +} DOCH_AccessCtrlOp; + +/* set of operation codes for DOCH_VSCMD_EXT_DEVICE_CTRL command */ +typedef enum { + DOCH_IDENTIFY_DISKONCHIP_DEVICE = 0x00, + DOCH_GET_EXTENDED_DEVICE_INFO = 0x01, + DOCH_SET_DATA_XFER_MODE = 0x10, + DOCH_ATOMIC_WRITE_SEQUENCE = 0x20, + DOCH_OPTIMIZE_MEDIA = 0x30, + DOCH_GET_CUSTOM_PARAM = 0x40, + DOCH_SET_CUSTOM_PARAM = 0x41, + DOCH_CALIBRATE_CLOCK = 0x50, + DOCH_GET_POWER_MODE = 0x60, + DOCH_SET_POWER_MODE = 0x61, + DOCH_GET_DISK_USER_ATTR = 0x70, + DOCH_SET_DISK_USER_ATTR = 0x71, + DOCH_GET_CONFIGURATION_DATA = 0x72, + DOCH_SET_CONFIGURATION_DATA = 0x73, + DOCH_ACTIVATE_DEBUG_MODE = 0x7C, + DOCH_RETRIEVE_DBG_MSG = 0x7E, + DOCH_SET_ALERT_LEVEL = 0x7F, + DOCH_GET_RESET_STATUS = 0x80, + DOCH_NOTIFY_PLATFORM_RESUMED = 0x8E, + DOCH_NOTIFY_RESET = 0x8F +} DOCH_DeviceCtrlOp; + +/* set of operation codes for DOCH_VSCMD_EXT_SECURITY_CTRL command */ +typedef enum { + DOCH_REPORT_SUPPORTED_ALGORITHMS = 0x00, + DOCH_GET_ALGORITHM_CAPABILITIES = 0x01, + DOCH_SET_ALGORITHM_MODE = 0x02, + DOCH_RETURN_RANDOM_NUMBERS = 0x10, + DOCH_AUTO_HASH_CONTROL = 0x40, + DOCH_SET_KEYS = 0x48, + DOCH_START_HASH_STREAM_CALC = 0x50, + DOCH_READ_STOP_HASH_STREAM_CALC = 0x51 +} DOCH_SecurityCtrlOp; + +/* set of operation codes for DOCH_VSCMD_CRYPTO_CONTROL command */ +typedef enum { DOCH_HASH_NO_ENCRYPTION = 0x00, + DOCH_HASH_ENCRYPT_BY_KEY = 0x01 +} DOCH_HashEncrypt_Op; + +/* bits in DOCH_STATUS_REG and DOCH_ALT_STATUS_REG registers */ +#define DOCH_ERROR 0x01 +#define DOCH_DRQ 0x08 +#define DOCH_DSC 0x10 +#define DOCH_READY 0x40 +#define DOCH_BUSY 0x80 + +/* bits in DOCH_STATUS_REG and DOCH_ALT_STATUS_REG registers */ +#define DOCH_ERR_REG_BIT0 0x01; +#define DOCH_ERR_REG_BIT1 0x02; +#define DOCH_ERR_REG_ABRT 0x04; +#define DOCH_ERR_REG_BIT3 0x08; +#define DOCH_ERR_REG_BIT4 0x10; +#define DOCH_ERR_REG_BIT5 0x20; +#define DOCH_ERR_REG_BIT6 0x40; +#define DOCH_ERR_REG_BIT7 0x80; + +/* bits for DOCH_DRIVE_HEAD_REG register */ +#define DOCH_DEVICE 0x10 +#define DOCH_LBA 0x40 +#define DOCH_DRIVE_HEAD 0xA0 + +#define DOCH_SELECT_DEV0 DOCH_LBA +#define DOCH_SELECT_DEV1 (DOCH_DEVICE|DOCH_LBA) +#define DOCH_SELECT_DEV(devNum) ((devNum*DOCH_DEVICE)|DOCH_LBA) + +/* DOCH configuration bits (IDENTIFY_DEVICE Word#0) */ +#define DOCH_ATAPI 0x8000 +#define DOCH_REMOVABLE 0x0080 +#define DOCH_FIXED 0x0040 + +/* IDENTIFY DEVICE data */ +/*==========================*/ +typedef struct { + FLWord wGeneralConfiguration; + FLWord wDefaultNumberOfCylinders; /*1*/ + FLWord wSpecificConfiguration; /*ATA-5*/ + FLWord wDefaultNumberOfHeads; /*3*/ + FLDword dwReserved2; + FLWord wDefaultSectorsPerTrack; /*6*/ + FLWord wReserved1[3]; + FLByte bSerialNumber[20]; /*10*/ + FLWord wReserved4[2]; + FLWord wVsFLBytesInReadWriteLONG; /*obsolete in ata-5*/ + FLByte bFirmwareRevision[8]; /*23*/ + FLByte bModelNumber[40]; /*27*/ + + FLByte bReserved3; /*47 ata-4+ : must be 0x80*/ + FLByte bMaxSectorsPerMulti; + + FLWord wReserved5; + FLWord wCapabilities; /*49*/ + FLWord wCapabilities2; /*ata-4*/ + + FLByte bPIOTransferTiming; /*51 obsolete in ATA-5*/ + FLByte bReserved6a; + + FLWord wReserved7; /*was (single-word?) DMA Timing in ATA-2*/ + FLWord wWordSupported; /*53*/ + FLWord wCurrentNumberOfCylinders; /*54*/ + FLWord wCurrentNumberOfHeads; /*55*/ + FLWord wCurrentSectorPerTrack; /*56*/ + + FLWord wCurrentCapacityInSectorsLow; /*57*/ + FLWord wCurrentCapacityInSectorsHigh; /*58*/ + + FLByte bMultipleSectorSettingValid; /*59*/ + FLByte bMultipleSectorCurrentNumber; + + FLWord wTotalNumberOfSectorsLow; /*60*/ + FLWord wTotalNumberOfSectorsHigh; /*61*/ + + FLWord wReserved8; /*was singlewordDMASelect+Support in ATA-2*/ + + FLByte bMultiwordDMASelected; /*63*/ + FLByte bMultiwordDMASupported; + + FLByte bReserved9; /*64*/ + FLByte bAdvancedPIOsupported; + + FLWord wMinDMACycleTimePerWord; + FLWord wRecommndedMinDMACycleTimePerWord; + FLWord wMinPIOCycleTimeWithoutFlowControl; + FLWord wMinPIOCycleTimeWithIORDY; + FLWord wReserved10[6]; + + FLWord wQueueDepth; /*75 ata-4*/ + FLWord wReserved11[4]; + + FLWord wMajorVersionNumber; /*80*/ + FLWord wMinorVersionNumber; + FLWord wCommandSetsupported1; /*82*/ + FLWord wCommandSetsupported2; + + FLWord wCommandSetFeatureExtension; /*84 ata-4*/ + FLWord wCommandSetFeatureEnabled1; /*ata-4*/ + FLWord wCommandSetFeatureEnabled2; /*86 ata-4*/ + FLWord wCommandSetFeatureDefault; /*ata-4*/ + + FLByte bUltraDMASelected; /*88 ata-4*/ + FLByte bUltraDMASupported; + + FLWord wTimeForSecurityEraseCompletion; /*ata-4*/ + FLWord wTimeForEnhancedSecurityEraseCompletion; /*90 ata-4*/ + + FLWord wCurrentAdvancedPowerManagementValue; /*ata-4*/ + + FLWord wMasterPasswordRevision; /*92 ata-5*/ + FLWord wHardwareResetResult; /*ata-5*/ + + FLWord wReserved12[33]; + + FLWord wRemovableMediaNotificationSupport; /*127 ata-4*/ + + FLWord wSecurityStatus; /*128, i.e. 127 words left*/ + FLWord wVendorSpecific[31]; /*129-159*/ + FLWord wCFApowermode1; + FLWord wCFAreserved[15]; + FLWord wCurrentMediaSerialNumber[30]; + + FLWord wReserved13[49]; + + FLWord wIntegrityWord; +} DOCH_DriveParameters; + +typedef struct { + FLSDword activeMode; + FLSDword inActiveMode; + FLSDword timeOut; +} DOCH_DpdSettings; + + +/*IDENTIFY DEVICE information bits*/ +/*================================*/ + +/*for generalConfiguration*/ +#define GENERAL_CONFIG_ATAPI 0x8000 /*otherwise ATA*/ +#define GENERAL_CONFIG_REMOVABLE_MEDIA 0x80 /*otherwise not*/ +#define GENERAL_CONFIG_NON_REMOVABLE_DRIVE 0x40 /*and/or device*/ +#define GENERAL_CONFIG_RESPONSE_INCOMPLETE 0x04 /*ATA-5*/ + +/*for specificConfiguration*/ +#define DEVICE_REQUIRES_SET_FEATURES_ID_INCOMPLETE 0x37C8 +#define DEVICE_REQUIRES_SET_FEATURES_ID_COMPLETE 0x738C +#define DEVICE_NOT_REQUIRE_SET_FEATURES_ID_INCOMPLETE 0x8C73 +#define DEVICE_NOT_REQUIRE_SET_FEATURES_ID_COMPLETE 0xC837 + +/*for capabilities*/ +#define CAPABILITY_STANDBY_TIMER_AS_IN_STANDARD 0x2000 /*1<<13*/ +#define CAPABILITY_IORDY_SUPPORTED 0x0800 /*1<<11*/ +#define CAPABILITY_IORDY_CAN_BE_DISABLED 0x0400 /*1<<10*/ +#define CAPABILITY_MUST 0x0300 /*just must be*/ + +/*for capabilities2*/ +#define CAPABILITY2_MUST 0x4000 +#define CAPABILITY2_DEVICE_HAS_STANDBY_TIMER_MINIMUM 0x0001 + +/*for wordSupported*/ +#define FIELDS54_58_VALID 1 /*geometry*/ +#define FIELDS64_70_VALID 2 /*timing*/ +#define FIELD88_VALID 4 /*ATA-4: Ultra-DMA modes*/ + +/*for multipleSectorSetting*/ +/*#define MULTI_SECTOR_SETTING_CORRECT 0x100*/ + +/*for multiwordDma*/ +#define MULTI_WORD_DMA_0 1 +#define MULTI_WORD_DMA_1 2 +#define MULTI_WORD_DMA_2 4 /*ATA-4*/ +/*dma 'selected' - one bit*/ +/*dma 'supported' - also one bit, but with ATA-4/5 it MUST support*/ +/*all modes below. AND must have their bits in 1 too.*/ + +/*for advancedPIOsupported; 1 for pio3 3 for pio4*/ +#define ADVANCED_PIO_3_SUPPORTED 1 +#define ADVANCED_PIO_4_SUPPORTED 2 + + +/*for majorVersionNumber*/ +#define SUPPORTS_ATA_1 2 +#define SUPPORTS_ATA_2 4 +#define SUPPORTS_ATA_3 8 +#define SUPPORTS_ATA_4 0x10 +#define SUPPORTS_ATA_5 0x20 + +/*for minorVersionNumber*/ +#define ATA3_PUBLISHED 0x0A +#define ATA_ATAPI4_PUBLISHED 0x12 +#define ATA_ATAPI5_PUBLISHED 0x18 +/*#error download last draft & find out!*/ + +/*for commandSetsupported1, commandSetFeatureEnabled1*/ +#define SUPPORTS1_SMART 0x01 +#define SUPPORTS1_SECURITY 0x02 +#define SUPPORTS1_REMOVABLE 0x04 +#define SUPPORTS1_POWER_MANAGEMENT 0x08 +#define SUPPORTS1_PACKET_COMMAND 0x10 /*ATA-4. ATA-5: must be zero*/ +#define SUPPORTS1_WRITE_CACHE 0x20 /*ATA-4*/ +#define SUPPORTS1_LOOK_AHEAD 0x40 /*ATA-4*/ +#define SUPPORTS1_RELEASE_INTERRUPT 0x80 /*ATA-4*/ +#define SUPPORTS1_SERVICE_INTERRUPT 0x100 /*ATA-4*/ +#define SUPPORTS1_DEVICE_RESET_CMD 0x200 /*ATA-4*/ +#define SUPPORTS1_HOST_PROTECTED_AREA_FEATURE 0x400 /*ATA-4*/ +#define SUPPORTS1_WRITE_BUFFER 0x1000 /*ATA-4*/ +#define SUPPORTS1_READ_BUFFER 0x2000 /*ATA-4*/ +#define SUPPORTS1_NOP 0x4000 /*ATA-4*/ +/*1<<11 obsolete*/ +/*1<<15 obsolete*/ + +/*for commandSetsupported2, commandSetFeatureEnabled2*/ +#define SUPPORTS2_MUST 0x4000 +#define SUPPORTS2_DOWNLOAD_MICROCODE 0x01 /*ATA-4*/ +#define SUPPORTS2_READ_WRITE_DMA_QUEUED 0x02 /*ATA-4*/ +#define SUPPORTS2_CFA_FEATURE 0x04 /*ATA-4*/ +#define SUPPORTS2_ADVANCED_POWER_MANAGEMENT 0x08 /*ATA-4*/ +#define SUPPORTS2_REMOVABLE_MEDIA_NOTIFICATION 0x10 /*ATA-4*/ +#define SUPPORTS2_POWERUP_IN_STANDBY 0x20 /*ATA-5*/ +#define SUPPORTS2_NEEDS_SET_FEATURES_TO_SPIN 0x40 /*ATA-5*/ +#define SUPPORTS2_ADDRESS_OFFSET_RESERVED_BOOT 0x80 /*ATA-5*/ +#define SUPPORTS2_SET_MAX_SECURITY_EXTENSION 0x100 /*ATA-5*/ + +/*for commandSetFeatureExtension, commandSetFeatureDefault*/ +#define CMDSET_EXTENSION_MUST 0x4000 + +/*for ultraDma*/ +#define ULTRA_DMA_0 1 +#define ULTRA_DMA_1 2 +#define ULTRA_DMA_2 4 +#define ULTRA_DMA_3 8 /*ATA-5*/ +#define ULTRA_DMA_4 0x10 /*ATA-5*/ +/*selected: one, supported: one and below*/ + +/*for hardwareResetResult (ATA-5)*/ +#define HARDRESET_RESULT_MUST 0x4101 + +#define HARDRESET_CBLID_ABOVE_VIH 0x2000 + +#define HARDRESET_DEVICE_0_JUMPER 0x02 +#define HARDRESET_DEVICE_0_CSEL 0x04 +#define HARDRESET_DEVICE_0_OTHER 0x06 + +#define HARDRESET_DEVICE_0_PASSED_DIAGNOSTICS 0x08 +#define HARDRESET_DEVICE_0_DETECTED_PDIAG 0x10 +#define HARDRESET_DEVICE_0_DETECTED_DASP 0x20 +#define HARDRESET_DEVICE_0_RESPONDS_FOR_1 0x40 + +#define HARDRESET_DEVICE_1_JUMPER 0x200 +#define HARDRESET_DEVICE_1_CSEL 0x400 +#define HARDRESET_DEVICE_1_OTHER 0x600 + +#define HARDRESET_DEVICE_1_ASSERTED_PDIAG 0x800 + +/*for removableMediaNotificationSupport*/ +#define REMOVABLE_MEDIA_STATUS_NOTIFICATION_SUPPORTED 1 + +/*for securityStatus*/ +#define SECURITY_MAXIMUM 0x100 /*otherwise HIGH*/ +#define SECURITY_ENCHANCED_ERASE_SUPPORTED 0x20 /*ATA-4*/ +#define SECURITY_COUNT_EXPIRED 0x10 +#define SECURITY_FROZEN 0x08 +#define SECURITY_LOCKED 0x04 +#define SECURITY_ENABLED 0x02 +#define SECURITY_SUPPORTED 0x01 + +typedef struct { + FLByte bReserved[0x200]; +} DOCH_DeviceAttributes; + +/* long-word-aligned buffer */ +typedef union { unsigned char cbuf [DOCH_SECTOR_SIZE]; + unsigned short sbuf [DOCH_SECTOR_SIZE / sizeof(short)]; + unsigned long lbuf [DOCH_SECTOR_SIZE / sizeof(long)]; +} DOCH_Buf; + +#define DOCH_CHIP_ID_H3 0x4833 +#define DOCH_CHIP_ID_H4 0x4834 +#define DOCH_CHIP_ID_H5 0x4835 + +/* Runtime configuration flags*/ +/*DOCH Flags Offsets*/ +#define DOCH_FLAGSO_USE_CHS 0 +#define DOCH_FLAGSO_USE_DMA_READ 1 +#define DOCH_FLAGSO_USE_DMA_WRITE 2 +#define DOCH_FLAGSO_USE_INTERRUPT 3 + +/*DOCH Flags Bits*/ +#define DOCH_FLAGSB_USE_CHS 0x00000001 /* use Cyl/Head/Sector block addressing */ +#define DOCH_FLAGSB_USE_DMA_READ 0x00000002 /* use h/w DMA when reading sectors */ +#define DOCH_FLAGSB_USE_DMA_WRITE 0x00000004 /* use h/w DMA when writing sectors */ +#define DOCH_FLAGSB_USE_INTERRUPT 0x00000008 /* use DOCH interrupt */ + +/* single DOCH device */ +typedef struct { + DOCH_DriveParameters driveParameters; /* ATA::IDENTIFY DEVICE data */ + FLWord wNumOfPartitions; + FLWord ETFFS_Identified; /*ETFFS exists on device*/ + FLDword flags; + FLDword dwMulti_MAX; + FLDword dwSpare1; + FLDword dwMulti_Current; + DOCH_TransferMode dataTransferMode; +} DOCH; + +typedef struct { + volatile FLByte * bRegBase; + FLByte bAtaDevNum; /* Indicates which ATA device to send command to (0..1)*/ +#ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + FLByte bLastDevNum; /* Indicates which ATA device was recently accessed */ +#endif /*DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES*/ + FLDword dwPhysicalAddress; /* NOT USED, returned by the SDK by a specific API */ + FLWord wSocketNo; /* [0.. DOCH_MAX_SOCKETS-1] */ + FLMutex mutex; /* Mutex for the socket*/ + FLBoolean bUseInterrupt; /* Wait on interrupt */ + FLBoolean bUseDMA; /* Use DMA for current data xfer */ + FLBoolean bUseBurst; /* Use Burst for current data xfer */ + FLWord wNumOfDevices; /* 2 if device #1 exists */ + FLNative nTotalCapacity; + FLWord wTotalNumOfPartitions; /* In both devices */ + DOCH_PartitionAttr partitionAttr[DOCH_MAX_PARTITIONS]; /* Partitions attributes */ + FLWord wLastPartitionSpanned; /* Last partition of device #0 spans to device #1 */ + DOCH device[ATA_MAX_NUM_OF_DEVICES]; /* ATA device #0, #1 */ + DOCH_HALRoutnies halRoutines; /* HAL routines structure*/ + DOCH_PartitionSpanData sSpanData; /*Span data as retrieved from Device User Attributes sector*/ +} DOCH_Socket; + +/* structure that holds addressing data (CHS/LBA) */ +typedef struct { + FLByte bSecNum; + FLByte bCylLow; + FLByte bCylHi; + FLByte bDevHead; +} Addressing_Values_s; + + +#ifdef __cplusplus +extern "C" { +#endif +extern DOCH_Socket sockets [DOCH_MAX_SOCKETS]; + +#define DOCH_get_socket(pdev, socketNo) \ + if(socketNo > (DOCH_MAX_SOCKETS-1)) \ + pdev = NULL; \ + else \ + pdev = &sockets[socketNo]; + + +/* API routines */ +extern DOCH* DOCH_get_disk(FLSNative socketNo, FLSNative devNum); +extern DOCH_Error doch_init_window (FLSNative socketNo, DOCH_InitSocket initSocket); +extern DOCH_Error doch_init_floors (DOCH_Socket* pdev,FLByte bConfFloor,FLByte * bFloorsNum); +extern DOCH_Error doch_init_socket (FLSNative socketNo, DOCH_InitSocket); +extern DOCH_Error doch_get_flags (FLSNative socketNo, FLSNative devNum, FLDword* flags); +extern DOCH_Error doch_set_flags (FLSNative socketNo, FLSNative devNum, FLDword flags); +extern DOCH_Error doch_command (FLSNative socketNo, FLSNative devNum, DOCH_Registers* in_regs, DOCH_Registers* out_regs, void* buf, FLNative secNum); +extern DOCH_Error doch_reset (DOCH_Socket* pdev); +extern DOCH_Error doch_setTransferMode (FLSNative socketNo, FLSNative devNum, DOCH_TransferMode tm, FLDword drqSize); +extern DOCH_TransferMode doch_getTransferMode (FLSNative socketNo, FLSNative devNum); +extern DOCH_Error doch_setConfigReg16(DOCH_Socket* pdev, FLDword registerOffset, FLNative registerValue); +extern FLWord doch_getConfigReg16(DOCH_Socket* pdev, FLSNative registerOffset); +extern DOCH_Error doch_configCommon(DOCH_Socket* pdev); +extern DOCH_Error clearATAInterrupt(FLSNative socketNo); + + +extern DOCH_Error doch_ata_passthru ( FLSNative socketNo, + FLSNative devNum, + DOCH_PassThru_Op ptOP, + DOCH_Registers * in_regs, + DOCH_Registers * out_regs, + void * buf, + FLNative secNum + ); + +extern DOCH_Error update_device_info(DOCH_Socket* pdev, + DOCH_DeviceInfo* diskOnChipDeviceInfo, + int devNum); + +DOCH_Error dochCheckPFSymptom(FLSNative socketNo, FLByte devNum, FLBoolean beforOrAfterCommand /* Used for debug prints */); + +DOCH_Error def_dochDelayUsec(FLDword usec,FLDword dwAccessTime); + +#define WAIT_FOR_UPLOAD_MAX_CYCLES 100 +#define DOCH_MINIMAL_PAGE_SIZE 0x4 /*2KB in sectors*/ +#define DOCH_MINIMAL_UNIT_SIZE 0x800 /*1MB in sectors*/ +#ifdef __cplusplus +} +#endif + +#endif /* DOCH_ATA_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_func.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_func.h new file mode 100755 index 00000000..672225c6 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_func.h @@ -0,0 +1,171 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_func.h-arc $ + * + * Rev 1.24 Dec 04 2007 17:33:22 einat.avidan + * Remove flDOCHWipeSectorsByWriting + * + * Rev 1.23 Oct 30 2007 17:02:56 einat.avidan + * add new function DOCHWipeSectorsByWriting + * + * Rev 1.22 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.21 Oct 11 2007 18:48:58 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * + * Rev 1.20 Mar 13 2007 13:47:20 einat.avidan + * add support for SLPP + * + * Rev 1.19 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.18 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef DOCH_FUNC_H +#define DOCH_FUNC_H + +#include "flcommon.h" +#include "doch_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*Get Info*/ +DOCH_Error DOCHIdentifyDiskOnChipDevice(IOreq* ioreq); +DOCH_Error DOCHGetResetStatus(IOreq* ioreq); +DOCH_Error DOCHNotifyReset(IOreq* ioreq); +DOCH_Error DOCHNotifyPlatformResumed(IOreq* ioreq); +DOCH_Error DOCHPartitionInfo(IOreq* ioreq); +DOCH_Error DOCHSetDiskUserAttributes(IOreq* ioreq); +DOCH_Error DOCHGetDiskUserAttributes(IOreq* ioreq); +DOCH_Error DOCHGetConfigurationData(IOreq* ioreq); +DOCH_Error DOCHSetConfigurationData(IOreq* ioreq); + +/*Media*/ +DOCH_Error DOCHSetDefaultPartition(IOreq* ioreq); +DOCH_Error DOCHSetDataTransferMode(IOreq* ioreq); +DOCH_Error DOCHOptimizeMedia(IOreq* ioreq); +DOCH_Error DOCHDeletePartitions(IOreq* ioreq); +DOCH_Error DOCHAddPartition(IOreq* ioreq); +DOCH_Error DOCHUnformatDevice(IOreq* ioreq); +DOCH_Error DOCHWriteIPL(IOreq* ioreq); +DOCH_Error DOCHReadIPL(IOreq* ioreq); + +/*IO*/ +DOCH_Error DOCHReadPartitionSectors(IOreq* ioreq); +DOCH_Error DOCHWritePartitionSectors(IOreq* ioreq); +DOCH_Error DOCHWriteAndLock(IOreq* ioreq); +DOCH_Error DOCHWipeSectors(IOreq* ioreq); +DOCH_Error DOCHFreeSectors(IOreq* ioreq); +DOCH_Error DOCHPrepareForWrite(IOreq* ioreq); + + +/*Flexi-Flash*/ +DOCH_Error DOCHWriteFlexiFast(IOreq* ioreq); +DOCH_Error DOCHWriteFlexiNormal(IOreq* ioreq); +DOCH_Error DOCHReWriteFlexiNormal(IOreq* ioreq); + +/*Protection*/ +DOCH_Error DOCHAccessPartWithPwd(IOreq* ioreq); +DOCH_Error DOCHDisablePartAccess(IOreq* ioreq); +DOCH_Error DOCHSetParitionProtection(IOreq* ioreq); + +/*PKI*/ +DOCH_Error DOCHSendHostPublicKey(IOreq* ioreq); +DOCH_Error DOCHReceiveDochPublicKey(IOreq* ioreq); +DOCH_Error DOCHVerifyHostKey(IOreq* ioreq); + +/*Custom Parameters*/ +DOCH_Error DOCHGetCustomParameter(IOreq* ioreq); +DOCH_Error DOCHSetCustomParameter(IOreq* ioreq); + +/*Atomic Read/Write Sequence*/ +DOCH_Error DOCHManageAtomicWriteSeq(IOreq* ioreq); + +/*Algorithms*/ +DOCH_Error DOCHReportSupportedAlgorithms(IOreq* ioreq); +DOCH_Error DOCHGetAlgorithmCapabilities(IOreq* ioreq); +DOCH_Error DOCHSetAlgorithmMode(IOreq* ioreq); + +/*Hash*/ +DOCH_Error DOCHAutoHashControl(IOreq* ioreq); +DOCH_Error DOCHReadCalculatedHash(IOreq* ioreq); +DOCH_Error DOCHWriteCalculatedHash(IOreq* ioreq); +DOCH_Error DOCHReadOriginalHash(IOreq* ioreq); +DOCH_Error DOCHWriteGivenHash(IOreq* ioreq); +DOCH_Error DOCHStartHashStreamCalculation(IOreq* ioreq); +DOCH_Error DOCHReadStopHashStreamCalc(IOreq* ioreq); +DOCH_Error DOCHReturnRandomNumbers(IOreq* ioreq); +DOCH_Error DOCHSetHashKey(IOreq* ioreq); + +/*General*/ +DOCH_Error DOCHSetParitionUserAttributes(IOreq* ioreq); +DOCH_Error DOCHGetParitionUserAttributes(IOreq* ioreq); +DOCH_Error DOCHSetPowerMode(IOreq* ioreq); +DOCH_Error DOCHGetPowerMode(IOreq* ioreq); +DOCH_Error DOCHConfigHW(IOreq* ioreq); +DOCH_Error DOCHRecoverFromPowerLoss(IOreq* ioreq); +DOCH_Error DOCHClearIRQ(IOreq* ioreq); +DOCH_Error DOCHGetPhysicalAddress(IOreq* ioreq); + +#ifdef FL_SLPP +/*SLPP Specific*/ +DOCH_Error DOCHSLPPUnlockRange(IOreq* ioreq); +DOCH_Error DOCHSLPPUnlockEntirePartition(IOreq* ioreq); +DOCH_Error DOCHSLPPLockRange(IOreq* ioreq); +DOCH_Error DOCHSLPPStickyLockRange(IOreq* ioreq); +DOCH_Error DOCHSLPPReportLockedRanges(IOreq* ioreq); +#endif /*FL_SLPP*/ +#ifdef __cplusplus +} +#endif + +#endif /*DOCH_FUNC_H*/ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_sys.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_sys.h new file mode 100755 index 00000000..0b47786b --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/doch_sys.h @@ -0,0 +1,120 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/***********************************************************************************/ +/* */ +/* Header file for doch_sys module */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/doch_sys.h-arc $ + * + * Rev 1.17 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.16 Feb 28 2007 09:58:42 einat.avidan + * No change + * + * Rev 1.15.1.0 Oct 31 2006 12:23:42 yaniv.iarovici + * Fix compilation warnings. + * + * Rev 1.15 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.14 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.13.1.0 Aug 08 2006 15:55:26 Polina.Marimont + * DOC Driver 1.0 initial + * + * Rev 1.13 May 18 2006 14:41:20 polina.marimont + * v1.40Fin1, PVCS log inside + */ + +#ifndef DOCH_SYS_H +#define DOCH_SYS_H + +#include "flcustom.h" + + +/* + * Access Layer API + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + unsigned char (*hal_get_ata_reg) (volatile unsigned char *base, int reg); + void (*hal_set_ata_reg) (volatile unsigned char *base, int reg, unsigned int val); + unsigned short (*hal_get_ctrl_reg) (volatile unsigned char *base, int reg); + void (*hal_set_ctrl_reg) (volatile unsigned char *base, int reg, unsigned int val); + int (*hal_blk_read) (volatile unsigned char *base, unsigned char *buf, int sectors); + int (*hal_blk_write) (volatile unsigned char *base, unsigned char *buf, int sectors); + int (*hal_doch_release) (int socketNo); +} DOCH_HALRoutnies; + +#ifdef __cplusplus +} +#endif +#ifdef FL_MIGRATION_VERSION + +#ifndef DOCH_USE_FUNC +#include "defs.h" +#ifdef __cplusplus +extern "C" { +#endif +extern FLFlash * DOCHFlash; +#ifdef __cplusplus +} +#endif +#endif /* DOCH_USE_FUNC */ + +#endif /*FL_MIGRATION_VERSION*/ + +#endif /* DOCH_SYS_H */ + + + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochstub.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochstub.c new file mode 100755 index 00000000..6aff137e --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochstub.c @@ -0,0 +1,121 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/*This file holds necessary routines for integrating sureFS over DOCH SDK*/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 7.0/TrueFFS FS/src/h3/dochstub.c-arc $ + * + * Rev 1.12 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.11 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.10 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.9.1.0 Aug 08 2006 15:55:26 Polina.Marimont + * DOC Driver 1.0 initial + */ + +#include "flbase.h" +#include "flstruct.h" +#ifdef FL_MIGRATION_VERSION +#include "bddefs.h" +#else /*FL_MIGRATION_VERSION*/ +#include "fsdefs.h" +#endif /*FL_MIGRATION_VERSION*/ +#include "dochtl.h" +#include "doch_sys.h" +#include "doch_api.h" + + +FLMutex busy[DOCH_MAX_SOCKETS]; +FLBoolean dochStubInitialized = 0; +/*===========================*/ + +FLStatus dochSetBusy(FLByte socket, FLBoolean state, FLByte partition) +{ + FLStatus status = flOK; + + if (state == FL_ON) /* Set busy to ON */ + { + if (!flTakeMutex(&busy[socket])) + { + DBG_PRINT_FLOW_PRM(FLZONE_ATA, (FLTXT("\r\ndochSetMutex Failed to set mutex\r\n"))); + return flDriveNotAvailable; + } + } + else /* Set busy to OFF */ + { + flFreeMutex(&busy[socket]); + } + + return status; +} + +void setTL(FLByte socket, FLByte partition, TL * tl) +{ + FLNative i; + if (dochStubInitialized != TRUE) + { + dochStubInitialized = TRUE; + for (i = 0; i < DOCH_MAX_SOCKETS ; i ++) + flCreateMutex(&busy[i]); + } + getDochTL(tl, partition); +} + +#ifndef FL_MIGRATION_VERSION + +/* ----------------------------------------------------------------------------------- */ +FLStatus lockForIO(FLByte socket, FLByte partition, FLBoolean onOff) { + +checkStatus(dochSetBusy(socket, onOff, partition)); /* take BD mutex */ + +return flOK; +} +#endif /*FL_MIGRATION_VERSION*/ +/* ----------------------------------------------------------------------------------- */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochstub.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochstub.h new file mode 100755 index 00000000..e156cf7e --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochstub.h @@ -0,0 +1,72 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 7.0/TrueFFS FS/src/h3/dochstub.h-arc $ + * + * Rev 1.9 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.8 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.7 Aug 09 2006 17:26:54 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.6.1.0 Aug 08 2006 15:55:28 Polina.Marimont + * DOC Driver 1.0 initial + */ + +#ifndef DOCHSTUB +#define DOCHSTUB + +#ifndef FL_MIGRATION_VERSION +void setTL(FLByte socket, FLByte partition, TL * tl) ; +#else /*FL_MIGRATION_VERSION */ +void DOCH_setTL(FLByte socket, FLByte partition, TL* tl); +FLStatus dochSetBusy(FLByte socket, FLBoolean state, FLByte partition); +#endif /*FL_MIGRATION_VERSION*/ + +FLStatus DOCH_lockForIO(FLByte socket, FLByte partition, FLBoolean onOff); + +#endif /*DOCHSTUB*/ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochtl.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochtl.c new file mode 100755 index 00000000..af0ec2b2 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochtl.c @@ -0,0 +1,642 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/dochtl.c-arc $ + * + * Rev 1.30 Dec 25 2007 11:18:24 einat.avidan + * bug fix: multiple mount on the same partition caused memory leak. + * + * Rev 1.29 Dec 04 2007 17:35:20 einat.avidan + * bug fix: gDeviceTurnedOff defined as byte and not as boolean + * + * Rev 1.28 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.27 Oct 11 2007 18:53:30 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * + * Rev 1.26 Jun 20 2007 12:04:52 einat.avidan + * Enable burst without DMA when dochTl is used + * + * Rev 1.25 Jan 07 2007 17:53:56 Einat.Avidan + * adjustment for a change in mDoc H3: + * flGetPartitionInfo now returns flOK when partition is both read and write protected. therefore need to check protection attributes of the partition during absMount. + * + * Rev 1.23.1.0 Oct 22 2006 14:53:42 yaniv.iarovici + * Fixed compilation warnings. + * + * Rev 1.23 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.22 Sep 10 2006 10:03:42 Yaniv.Iarovici + * Fix compilation warning: Initialize tlRecTable[] and tlTable[] upon first entry to dochMountTL(). + * + * Rev 1.21 Aug 24 2006 11:39:46 Yaniv.Iarovici + * Change error returned by dochMountTL() in case DOCHPartitionInfo() failed to: + * - flHWProtection if the operation failed due to protection error + * - flGeneralFailure otherwise + * + * Rev 1.20 Aug 17 2006 15:20:36 Yaniv.Iarovici + * Zerioze partition info structure. + * + * Rev 1.18 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#include "dochtl.h" +#include "doch_ata.h" +#include "doch_func.h" + +#ifdef FL_MIGRATION_VERSION +#include "tffs_api.h" +#endif /*FL_MIGRATION_VERSION*/ + +static DocTLRec tlRecTable[DOCH_MAX_PARTITIONS]; +static TL tlTable[DOCH_MAX_PARTITIONS]; + + +extern FLByte gIsDMAEnabled; /*DMA is Enabled/Disabled*/ + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +extern FLByte gDeviceTurnedOff; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#ifndef FL_MIGRATION_VERSION +bdCallType bdCall = bdCallSureFS; +#endif /*FL_MIGRATION_VERSION*/ + +static FLStatus dochMapSector(TLrec * tlRec, SectorNo sectorNo, void * *retBuffer) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = 1; + ioreq.irData = tlRec->mappedSector; + + rc = flDOCHReadPartitionSectors(&ioreq); + + *retBuffer = tlRec->mappedSector; + + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochWriteSector(TLrec *tlRec, SectorNo sectorNo, void FAR1 *fromAddress) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = 1; + ioreq.irData = fromAddress; + + rc = flDOCHWritePartitionSectors(&ioreq); + + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + if( (rc == DOCH_ATA_ERROR_TRACK_0_NOT_FOUND) || (rc == DOCH_ProtectionFault)) + return flHWProtection; + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochWriteMultiSector(TLrec *tlRec, SectorNo sectorNo, void FAR1 *fromAddress,SectorNo sectorCount) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = sectorCount; + ioreq.irData = fromAddress; + +#ifdef FL_MIGRATION_VERSION + #ifdef FL_USE_DMA_ON_WRITE +#endif /*FL_MIGRATION_VERSION*/ + +#ifdef DOCH_DMA_CONFIG + /*Check if to enable DMA*/ + if((((FLDword)fromAddress & 0x3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN)) + ioreq.irFlags |= DOCH_USE_DMA; +#endif /*DOCH_DMA_CONFIG*/ + +#ifdef FL_MIGRATION_VERSION + #endif /*FL_USE_DMA_ON_WRITE*/ +#endif /*FL_MIGRATION_VERSION*/ + +#ifdef DOCH_USE_BURST_MODE_WRITE + ioreq.irFlags |= DOCH_USE_BURST; +#endif /*DOCH_USE_BURST_MODE_WRITE*/ + + rc = flDOCHWritePartitionSectors(&ioreq); + + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochReadSectors(TLrec *tlRec, SectorNo sectorNo, void FAR1 *dest,SectorNo sectorCount) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = sectorCount; + ioreq.irData = dest; + +#ifdef DOCH_DMA_CONFIG + /*Check if to enable DMA*/ + if((((FLDword)dest & 0x3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN)) + { + ioreq.irFlags |= DOCH_USE_DMA; + } +#endif /*DOCH_DMA_CONFIG*/ + +#ifdef FL_USE_BURST_MODE_READ + if( ((FLDword)ioreq.irData & 3) == 0 ) + { + ioreq.irFlags |= DOCH_USE_BURST; + } +#endif /* FL_USE_BURST_MODE_READ */ + + rc = flDOCHReadPartitionSectors(&ioreq); + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochDeleteSector(TLrec *tlRec, SectorNo sectorNo, SectorNo noOfSectors) +{ + DOCH_Error rc; + IOreq ioreq; + DOCH_Socket* pdev; + DOCH_get_socket(pdev, tlRec->socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + tffsset(&ioreq, 0, sizeof(ioreq)); + + pdev->bAtaDevNum = 0; + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, tlRec->socketNo); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, tlRec->partitionNo); + ioreq.irSectorNo = sectorNo; + ioreq.irSectorCount = noOfSectors; + + rc = flDOCHFreeSectors(&ioreq); + + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + else + return flOK; +} + +static FLStatus dochTlSetBusy(TLrec *tlRec, FLBoolean state) +{ + return flOK; +} + +static void dochDismount(TLrec *tlRec) +{ + FL_FREE(tlRec->mappedSector); +} + +static FLStatus dochDefragment(TLrec *tlRec, FLSDword FAR2 *sectorsNeeded, FLDword normalSpace) +{ + /*optimize*/ + return flOK; +} + +static FLStatus dochCheckVolume(TLrec *tlRec) +{ + return flOK; +} + +static SectorNo dochSectorsInVolume(TLrec *tlRec) +{ + SectorNo secNo = tlRec->virtualSectors; + + return secNo; +} + +static FLStatus dochGetTLInfo(TLrec *tlRec, TLInfo *tlInfo) +{ + return flOK; +} + +static void dochRecommendedClusterInfo(TLrec *tlRec, FLDword *sectorsPerCluster, FLDword *clusterAlignment) +{ + *sectorsPerCluster = tlRec->maxRelatedSectors; + *clusterAlignment = ((FLDword)tlRec->sectorsInUnit<socketNo); +#endif /*FL_MIGRATION_VERSION*/ + + tffscpy(tl, &tlTable[partition], sizeof(TL)); + + return flOK; +} + +FLStatus dochMountTL(FLNative partition, FLNative socket) +{ + static FLBoolean bStaticArraysInit = FALSE; + + IOreq ioreq; + DOCH_PartitionInfo partInfo; + DOCH_Error rc; + TL* tl; + DOCH_Socket* pdev; + FLByte protectionType,guestAccessMode,authenticated; + + /*Initialize static arrays*/ + if(!bStaticArraysInit) + { + tffsset(tlRecTable, 0, sizeof(tlRecTable)); + tffsset(tlTable, 0, sizeof(tlTable)); + bStaticArraysInit = TRUE; + } + + DOCH_get_socket(pdev, socket); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return flAdapterNotFound; + + /*Retrieve partition info*/ + tffsset(&partInfo, 0, sizeof(partInfo)); + tffsset(&ioreq, 0, sizeof(ioreq)); + DOCH_SET_SOCKET_TO_IOREQ_HANDLE(&ioreq, socket); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&ioreq, partition); + pdev->bAtaDevNum = 0; + ioreq.irData = &partInfo; + rc = DOCHPartitionInfo(&ioreq); + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + + return flGeneralFailure; + } + protectionType = (FLByte)(partInfo.partitionAttributes2 & DOCH_PA2B_PROTECTION_TYPE); + guestAccessMode = (FLByte)((partInfo.partitionAttributes2 & DOCH_PA2B_GUEST_MODE) >> DOCH_PA2O_GUEST_MODE); + authenticated = (FLByte)((partInfo.dwCommandFlagsOrStatuses & DOCH_CFSB_USER_AUTHENTICATED) >> DOCH_CFSO_USER_AUTHENTICATED); + + if ((protectionType != DOCH_PARTITION_NOT_PROTECTED) && (guestAccessMode == DOCH_PART_ACCESS_MODE_NONE)) + { + /* partition is READ_PROTECTED and WRITE_PROTECTED*/ + if (!(authenticated && protectionType != DOCH_PARTITION_NOT_PROTECTED)) + { + /*key is not inserted*/ + return flHWProtection; + } + + } + tl = &tlTable[partition]; + + /*Set tlRec*/ + /*=========*/ + tlRecTable[partition].partitionNo = partition; + tlRecTable[partition].socketNo = socket; + tlRecTable[partition].virtualSectors = partInfo.nPartitionSize; + tl->rec = &tlRecTable[partition]; + + /*Allocate 1 sector for mapping*/ + /*=============================*/ + /* allocate mappedSector only if not already allocated*/ + if (tl->rec->mappedSector==NULL) + tl->rec->mappedSector = FL_MALLOC(DOCH_SECTOR_SIZE); + + /*Fill TL parameters*/ + /*==================*/ + tl->cylinders = 0; + tl->heads = 0; + tl->sectorsPerTrack = 0; + tl->recommendedSectorsInCluster = partInfo.wRecommendedSectorsPerCluster; + tl->normalArea_SectorsInUnit_Bits = partInfo.wNormalAreaSectorsInErasableUnit; + tl->riskZoneSectors = 8; + + /*Fill TL routines*/ + /*================*/ + tl->mapSector = dochMapSector; + tl->writeSector = dochWriteSector; + tl->writeMultiSector = dochWriteMultiSector; + tl->readSectors = dochReadSectors; + tl->deleteSector = dochDeleteSector; + tl->tlSetBusy = dochTlSetBusy; + tl->dismount = dochDismount; + tl->defragment = dochDefragment; + tl->checkVolume = dochCheckVolume; + tl->sectorsInVolume = dochSectorsInVolume; + tl->getTLInfo = dochGetTLInfo; + tl->recommendedClusterInfo = dochRecommendedClusterInfo; + tl->readBBT = dochReadBBT; + tl->notifyChange = dochNotifyChange; + tl->completeOperation = dochCompleteOperation; + tl->getLastMappedSectorAddress = dochGetLastMappedSectorAddress; + tl->ensureFreeSectorsInUnit = dochEnsureFreeSectorsInUnit; + + return flOK; +} + + +#ifndef FL_MIGRATION_VERSION +TFFS_DLL_API FLStatus bdCallSureFS(FLFunctionNo functionNo, IOreq FAR2 *ioreq) +{ + switch(functionNo) + { + case FL_ABS_MOUNT: + return dochMountTL(FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq), FL_GET_SOCKET_FROM_HANDLE(ioreq)); + + case FL_DISMOUNT_VOLUME: + return flOK; + + default: + return flFeatureNotSupported; + } + +} + +TFFS_DLL_API FLStatus NAMING_CONVENTION flInit(void) +{ + DOCH_Error rc; + + rc = DochSDKInit(); + if(rc != DOCH_OK) + { + #ifdef CHECK_POWER_ON_EVERY_COMMAND + /*In case Power Fail was detected, return DOCH_DeviceTurnedOff*/ + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + { + gDeviceTurnedOff = FALSE; + +#ifdef FL_MIGRATION_VERSION + return flSuspendModeDetected; +#else /*FL_MIGRATION_VERSION*/ + return DOCH_DeviceTurnedOff; +#endif /*FL_MIGRATION_VERSION*/ + } + #endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + + return flBadFunction; + } + + return flOK; +} + +TFFS_DLL_API void NAMING_CONVENTION flExit(void) +{ + doch_release_socket(0); +} + +#else /* FL_MIGRATION_VERSION not defined */ + +/******************************************/ +/* Function name : dochDismountTL */ +/* Description : */ +/* Return type : FLStatus */ +/* Argument : FLNative partition */ +/******************************************/ +FLStatus dochDismountTL(FLNative partition) +{ + TL* tl; + + tl = &tlTable[partition]; + + if( tl->rec->mappedSector != NULL ) + { + FL_FREE(tl->rec->mappedSector); + tl->rec->mappedSector = NULL; + } + + return flOK; +}/* dochDismountTL() */ + +#endif /*FL_MIGRATION_VERSION*/ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochtl.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochtl.h new file mode 100755 index 00000000..e277a78e --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dochtl.h @@ -0,0 +1,84 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/dochtl.h-arc $ + * + * Rev 1.15 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.14 Sep 11 2006 13:45:16 yaniv.iarovici + * Legal header added + * + * Rev 1.13 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef DOCHTL_H +#define DOCHTL_H + +#include "fltl.h" + + +struct tTLrec{ + FLByte socketNo; /* Socket number of the volume */ + FLByte partitionNo; /* Partition number of the volume */ + FLDword virtualSectors; /* No of sectors exported by the TL */ + FLByte maxRelatedSectors; /* Max number of sectors that might be written together */ + FLWord sectorsInUnit; /* No of sectors in a logical unit */ + + void FAR0 * mappedSector; +}; + +typedef TLrec DocTLRec; + +FLStatus getDochTL(TL* tl, FLByte partition); +FLStatus dochMountTL(FLNative partition, FLNative socket); + +#ifndef FL_MIGRATION_VERSION +TFFS_DLL_API FLStatus bdCallSureFS(FLFunctionNo functionNo, IOreq FAR2 *ioreq); +#else /*FL_MIGRATION_VERSION*/ +FLStatus dochDismountTL(FLNative partition); +#endif /*FL_MIGRATION_VERSION*/ +#endif /*DOCHTL_H*/ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docsys.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docsys.c new file mode 100755 index 00000000..02104c2f --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docsys.c @@ -0,0 +1,1304 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/docsys.c-arc $ + * + * Rev 1.9 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.8 Mar 11 2007 16:37:30 einat.avidan + * bug fix: working on x86 requires read buffer not to be paged out + * replace the former solution (access to the begining and the end of the buffer) + * with full solution: usage of a buffer that is locked on RAM + * + * Rev 1.7 Feb 28 2007 09:53:44 einat.avidan + * No change + * + * Rev 1.6.1.0 Nov 13 2006 15:13:50 Yaniv.Iarovici + * Added environment variable - 'FL_DISABLE_MEMCPY'. + * + * Rev 1.6 Oct 05 2006 11:00:48 yaniv.iarovici + * Removed support for flUse8Bit. + * + * Rev 1.5 Sep 11 2006 13:45:18 yaniv.iarovici + * Legal header added + * + * Rev 1.4 Aug 09 2006 16:52:44 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#include "docsys.h" +#ifdef FL_PARALLEL_MTD_SUPPORT +#include "pacclayr.h" +#endif /* FL_PARALLEL_MTD_SUPPORT */ + +FLBoolean flPreventMemcpy = 0; + +#ifndef FL_NO_USE_FUNC + +/*********************************************************/ +/* Report DiskOnChip Memory size */ +/*********************************************************/ + +/*---------------------------------------------------------------------- + f l D o c M e m W i n S i z e N o S h i f t + + This routine is called from MTD to quary the size of the DiskOnChip + memory window for none shifted DiskOnChip. +------------------------------------------------------------------------*/ + +FLDword FAR1 flDocMemWinSizeNoShift(void) +{ + return 0x2000; +} + +/*---------------------------------------------------------------------- + f l D o c M e m W i n S i z e S i n g l e S h i f t + + This routine is called from MTD to quary the size of the DiskOnChip + memory window for DiskOnChip connected with a single addres shift. +------------------------------------------------------------------------*/ + +FLDword FAR1 flDocMemWinSizeSingleShift(void) +{ + return 0x4000; +} + +/*---------------------------------------------------------------------- + f l D o c M e m W i n S i z e D o u b l e S h i f t + + This routine is called from MTD to quary the size of the DiskOnChip + memory window for DiskOnChip connected with a double addres shift. +------------------------------------------------------------------------*/ + +FLDword FAR1 flDocMemWinSizeDoubleShift(void) +{ + return 0x8000; +} + +/*********************************************************/ +/* Write 16 bits to DiskOnChip memory window */ +/*********************************************************/ + + +/*---------------------------------------------------------------------- + f l W r i t e 16 b i t U s i n g 8 b i t s N o S h i f t + + Write 16-bits Using 8-bits operands and 8 bit data + With no address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing8bitsNoShift(volatile FLByte FAR0 * win, FLWord offset,FLWord val) +{ +#ifndef FL_BIG_ENDIAN + FLWRITE_IO_BYTE((FLByte)val,(win + offset)); + FLWRITE_IO_BYTE((FLByte)(val>>0x8),(win + offset+1)); +#else + FLWRITE_IO_BYTE((FLByte)(val>>0x8),(win + offset)); + FLWRITE_IO_BYTE((FLByte)val,(win + offset + 1)); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 1 6 b i t U s i n g 1 6 b i t s N o S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 16 when using address shift. + + Write 16-bit Using 16-bits operands and 16-bits of data + with no address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing16bitsNoShift(volatile FLByte FAR0 * win, FLWord offset,Reg16bitType val) +{ + FLWRITE_IO_WORD(val,((volatile FLWord FAR0 *)win + (offset>>1))); +} + +/*---------------------------------------------------------------------- + f l W r i t e 1 6 b i t U s i n g 3 2 b i t s S i n g l e S h i f t + + Note : offset must be 16-bits aligned. + + Write 16-bit Using 32-bits operands and 16-bits of data + With a single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing32bitsSingleShift(volatile FLByte FAR0 * win, FLWord offset,Reg16bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD((FLDword)(((FLDword)val)<<16),(((volatile FLDword FAR0 *)win)+(offset>>1))); +#else + FLWRITE_IO_DWORD((FLDword)val,(((volatile FLDword FAR0 *)win)+(offset>>1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 1 6 b i t U s i n g 1 6 b i t s S i n g l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 8 when using address shift. + + Write 16-bit Using 16-bits operands and 8-bits of data + with a single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing16bitsSingleShift(volatile FLByte FAR0 * win, FLWord offset,Reg16bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_WORD((FLWord)(val>>8),(((volatile FLWord FAR0 *)win) + offset)); + FLWRITE_IO_WORD((FLWord)(val),(((volatile FLWord FAR0 *)win) + (offset+1))); +#else + FLWRITE_IO_WORD(val,(((volatile FLWord FAR0 *)win) + offset)); + FLWRITE_IO_WORD((FLWord)(val>>8),(((volatile FLWord FAR0 *)win) + (offset + 1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 1 6 b i t U s i n g 3 2 b i t s D o u b l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 8 when using address shift. + + Write 16-bit Using 32-bits operands and 8-bits of data + with a single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite16bitUsing32bitsDoubleShift(volatile FLByte FAR0 * win, FLWord offset,Reg16bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD(((FLDword)(val>>8)),(((volatile FLDword FAR0 *)win) + offset)); + FLWRITE_IO_DWORD(((FLDword)((FLByte)val)),(((volatile FLDword FAR0 *)win) + (offset + 1))); +#else + FLWRITE_IO_DWORD(((FLDword)((FLByte)val)),(((volatile FLDword FAR0 *)win) + offset)); + FLWRITE_IO_DWORD(((FLDword)(val>>8)),(((volatile FLDword FAR0 *)win) + (offset + 1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*********************************************************/ +/* Read 16 bits from DiskOnChip memory window */ +/*********************************************************/ + + +/*---------------------------------------------------------------------- + f l R e a d 16 b i t U s i n g 8 b i t s N o S h i f t + + Read 16-bits Using 8-bits operands and 8-bits of data + With no address shifted. +------------------------------------------------------------------------*/ + +FLWord FAR1 flRead16bitUsing8bitsNoShift(volatile FLByte FAR0 * win,FLWord offset) +{ +#ifndef FL_BIG_ENDIAN + register FLWord val = (FLWord)FLREAD_IO_BYTE((win+offset)); + return val | (((FLWord)FLREAD_IO_BYTE((win+offset+1)))<<8); +#else + register FLWord val = ((FLWord)FLREAD_IO_BYTE(win+offset))<<8; + return val | ((FLWord)FLREAD_IO_BYTE(win+offset+1)); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l R e a d 1 6 b i t U s i n g 1 6 b i t s N o S h i f t + + Note : offset must be 16-bits aligned. + + Read 16-bit Using 16-bits operands and 16-bits of data + With no address shifted. +------------------------------------------------------------------------*/ + +Reg16bitType FAR1 flRead16bitUsing16bitsNoShift(volatile FLByte FAR0 * win,FLWord offset) +{ + return( FLREAD_IO_WORD(((volatile FLWord FAR0 *)win + (offset>>1))) ); +} + +/*---------------------------------------------------------------------- + f l R e a d 1 6 b i t U s i n g 3 2 b i t s S i n g l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 16 when using address shift. + + Read 16-bit Using 32-bits operands and 16-bits of data + With single address shifted. +------------------------------------------------------------------------*/ + +Reg16bitType FAR1 flRead16bitUsing32bitsSingleShift(volatile FLByte FAR0 * win,FLWord offset) +{ +#ifdef FL_BIG_ENDIAN + return (Reg16bitType) (FLREAD_IO_DWORD(((volatile FLDword FAR0*)win)+(offset>>1))>>16); +#else + return((Reg16bitType)FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l R e a d 1 6 b i t U s i n g 1 6 b i t s S i n g l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 8 when using address shift. + + Read 16-bit Using 16-bits operands and 8-bits of data + With single address shifted. +------------------------------------------------------------------------*/ + +Reg16bitType FAR1 flRead16bitUsing16bitsSingleShift(volatile FLByte FAR0 * win,FLWord offset) +{ + FLByte val[2]; + + val[0] = ((Reg8bitType)(FLREAD_IO_WORD(((volatile FLWord FAR0 *)win)+offset))); + val[1] = ((Reg8bitType)(FLREAD_IO_WORD(((volatile FLWord FAR0 *)win)+(offset+1)))); + + return *((Reg16bitType *)val); +} + +/*---------------------------------------------------------------------- + f l R e a d 1 6 b i t U s i n g 3 2 b i t s D o u b l e S h i f t + + Note : offset must be 16-bits aligned. + + Note2 : Used for if_cfg = 8 when using address shift. + + Read 16-bit Using 32-bits operands and 8-bits of data + With double address shifted. +------------------------------------------------------------------------*/ + +Reg16bitType FAR1 flRead16bitUsing32bitsDoubleShift(volatile FLByte FAR0 * win,FLWord offset) +{ + FLByte val[2]; + + val[0] = ((Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+offset))); + val[1] = ((Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset+1)))); + + return *((Reg16bitType *)val); +} + + +/*********************************************************/ +/* Write 8 bits to DiskOnChip memory window */ +/*********************************************************/ + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 8 b i t s N o S h i f t + + Write 8-bits Using 8-bits operands with no address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing8bitsNoShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ + FLWRITE_IO_BYTE(val,win + offset); +} + + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 16 b i t s N o S h i f t + + Note : DiskOnChip is connected with 16-bit data bus. + Note : Data is written only to lower memory addresses. + + Write 8-bits Using 16-bits operands with no address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing16bitsNoShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_WORD(((FLWord)val)<<8,((volatile FLWord FAR0 *)win)+(offset>>1)); +#else + FLWRITE_IO_WORD((FLWord)val,(((volatile FLWord FAR0 *)win)+(offset>>1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 16 b i t s S i n g l e S h i f t + + Note : Data is written only to 8-LSB. + + Write 8-bits Using 16-bits operands with Single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing16bitsSingleShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ + FLWRITE_IO_WORD((FLWord)val,(((volatile FLWord FAR0 *)win)+offset)); +} + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 32 b i t s S i n g l e S h i f t + + Note : DiskOnChip is connected with 16-bit data bus. + Note : Data is written to both data bus 8-bits + + Write 8-bits Using 32-bits operands with single address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing32bitsSingleShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD(((FLDword)((FLDword)val*0x01010101L)),(((volatile FLDword FAR0 *)win)+(offset>>1))); +#else + FLWRITE_IO_DWORD((FLDword)val,(((volatile FLDword FAR0 *)win)+(offset>>1))); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l W r i t e 8 b i t U s i n g 32 b i t s D o u b l e S h i f t + + Note : Data is written only to 8-LSB. + + Write 8-bits Using 32-bits operands with Double address shifted. +------------------------------------------------------------------------*/ + +void FAR1 flWrite8bitUsing32bitsDoubleShift(volatile FLByte FAR0 * win, FLWord offset,Reg8bitType val) +{ + FLWRITE_IO_DWORD((FLDword)val,(((volatile FLDword FAR0 *)win)+offset)); +} + +/*********************************************************/ +/* Read 8 bits to DiskOnChip memory window */ +/*********************************************************/ + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 8 b i t s N o S h i f t + + Read 8-bits Using 8-bits operands with no address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing8bitsNoShift(volatile FLByte FAR0 * win,FLWord offset) +{ + return FLREAD_IO_BYTE(((volatile void FAR0 *)(win + offset))); +} + + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 16 b i t s N o S h i f t + + Note : DiskOnChip is connected with 16-bit data bus. + + Read 8-bits Using 16-bits operands with no address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing16bitsNoShift(volatile FLByte FAR0 * win,FLWord offset) +{ +#ifdef FL_BIG_ENDIAN + return (((offset & 0x1) == 0) ? +#else + return (( offset & 0x1 ) ? +#endif /* FL_BIG_ENDIAN */ + (Reg8bitType)(FLREAD_IO_WORD(((volatile FLWord FAR0 *)win + (offset>>1))) >> 8) : + (Reg8bitType)(FLREAD_IO_WORD(((volatile FLWord FAR0 *)win + (offset>>1)))) ); + +} + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 16 b i t s S i n g l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Read 8-bits Using 16-bits operands with Single address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing16bitsSingleShift(volatile FLByte FAR0 * win,FLWord offset) +{ + return( (Reg8bitType)FLREAD_IO_WORD((((volatile FLWord FAR0 *)win)+offset)) ); +} + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 32 b i t s S i n g l e S h i f t + + Note : DiskOnChip is connected with 16-bit data bus. + + Read 8-bits Using 16-bits operands with Single address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing32bitsSingleShift(volatile FLByte FAR0 * win,FLWord offset) +{ +#ifdef FL_BIG_ENDIAN + return (((offset & 0x1) == 0) ? + (Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))>>24) : + (Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))>>16)); +#else + return (( offset & 0x1 ) ? + (Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))>>8) : + (Reg8bitType)(FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+(offset>>1))) ); +#endif /* FL_BIG_ENDIAN */ +} + +/*---------------------------------------------------------------------- + f l R e a d 8 b i t U s i n g 32 b i t s D o u b l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Read 8-bits Using 16-bits operands with Single address shifted. +------------------------------------------------------------------------*/ + +Reg8bitType FAR1 flRead8bitUsing32bitsDoubleShift(volatile FLByte FAR0 * win,FLWord offset) +{ + return((Reg8bitType)FLREAD_IO_DWORD(((volatile FLDword FAR0 *)win)+offset)); +} + +/*********************************************************/ +/*********************************************************/ +/*** Operation on several bytes (read/write/set) ***/ +/*********************************************************/ +/*********************************************************/ + +/*************************************************/ +/* 8-Bit DiskOnChip - No Shift */ +/*************************************************/ + +/*---------------------------------------------------------------------- + f l 8 b i t D o c R e a d N o S h i f t + + Read 'count' bytes, from a none shifted address bus using tffscpy. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocReadNoShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* dest,FLWord count) +{ +#ifdef FL_ENVIRONMENT_VARS + if(flPreventMemcpy == 1) + { + register int i ; + + for(i = 0 ; i < count ; i++) + dest[i] = FLREAD_IO_BYTE(win + offset + i); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + TFFSCPY_FROM_IO_8_BITS(dest,win+offset,count); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c W r i t e N o S h i f t + + Write 'count' bytes, from a none shifted address bus using tffscpy. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocWriteNoShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* src,FLWord count) +{ +#ifdef FL_ENVIRONMENT_VARS + if(flPreventMemcpy == 1) + { + register int i ; + + for(i = 0 ; i < count ; i++) + FLWRITE_IO_BYTE(src[i],win + offset + i); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + TFFSCPY_TO_IO_8_BITS(win+offset,src,count); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c S e t N o S h i f t + + Set 'count' bytes, from a none shifted address bus using tffsset. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocSetNoShift(volatile FLByte FAR0 * win,FLWord offset,FLWord count, FLByte val) +{ +#ifdef FL_ENVIRONMENT_VARS + if(flPreventMemcpy == 1) + { + register int i ; + for(i = 0 ; i < count ; i++) + FLWRITE_IO_BYTE(val,win + offset + i); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + TFFSSET_IO_8_BITS(win+offset,val,count); +} + +/*************************************************/ +/* 8-Bit DiskOnChip - Single Shift */ +/*************************************************/ + +/*---------------------------------------------------------------------- + f l 8 b i t D o c R e a d S i n g l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Read 'count' bytes, from data bus's LSB lane with 1 address shifted +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocReadSingleShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* dest,FLWord count) +{ + volatile FLWord FAR0 * doc = ((volatile FLWord FAR0 *)win) + offset; + register int i; + + + for(i=0;( i < count );i++) + dest[i] = (Reg8bitType)FLREAD_IO_WORD(doc+i); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c W r i t e S i n g l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Write 'count' bytes, to data bus's LSB lane with 1 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocWriteSingleShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* src,FLWord count) +{ + volatile FLWord FAR0 * doc = ((volatile FLWord FAR0 *)win) + offset; + register int i; + + for(i=0;( i < count );i++) + FLWRITE_IO_WORD((FLWord)(src[i]),doc+i); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c S e t S i n g l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Set 'count' bytes, of data bus's LSB lane with 1 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocSetSingleShift(volatile FLByte FAR0 * win,FLWord offset,FLWord count, FLByte val) +{ + volatile FLWord FAR0 * doc = ((volatile FLWord FAR0 *)win) + offset; + register int i; + + for(i=0;( i < count );i++) + FLWRITE_IO_WORD((FLWord)val,doc+i); +} + +/*************************************************/ +/* 8-Bit DiskOnChip - Double Shift */ +/*************************************************/ + +/*---------------------------------------------------------------------- + f l 8 b i t D o c R e a d D o u b l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Read 'count' bytes, from data bus's LSB lane with 2 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocReadDoubleShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* dest,FLWord count) +{ + volatile FLDword FAR0 *doc = ((volatile FLDword FAR0 *)win) + offset; + register int i; + + + for(i=0;( i < count );i++) + dest[i] = (Reg8bitType)FLREAD_IO_DWORD(doc+i); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c W r i t e D o u b l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Write 'count' bytes, to data bus's LSB lane with 2 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocWriteDoubleShift(volatile FLByte FAR0 * win,FLWord offset,FLByte FAR1* src,FLWord count) +{ + volatile FLDword FAR0 * doc = ((volatile FLDword FAR0 *)win) + offset; + register int i; + + for(i=0;( i < count );i++) + FLWRITE_IO_DWORD((FLDword)(src[i]),doc+i); +} + +/*---------------------------------------------------------------------- + f l 8 b i t D o c S e t D o u b l e S h i f t + + Note : Assume data is found in 8-LSB of DiskOnChip + + Set 'count' bytes, of data bus's LSB lane with 2 address shifted. +------------------------------------------------------------------------*/ + +void FAR1 fl8bitDocSetDoubleShift(volatile FLByte FAR0 * win,FLWord offset,FLWord count, FLByte val) +{ + volatile FLDword FAR0 * doc = ((volatile FLDword FAR0 *)win)+offset; + register int i; + + for(i=0;( i < count );i++) + FLWRITE_IO_DWORD((FLDword)val,doc+i); +} + +/*************************************************/ +/* 16-Bit DiskOnChip - No Shift */ +/*************************************************/ + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c R e a d N o S h i f t + + Note - this routine can read only even number of bytes + + Read 'count' bytes from M+ DiskOnChip with none shifted address bus. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocReadNoShift (volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + register FLWord tmp; + + + if( (FLDword)dest & 0x1 ) + { + /* rare case: unaligned target buffer */ + for (i = 0; i < (int)count; ) + { + tmp = FLREAD_IO_WORD(swin); +#ifdef FL_BIG_ENDIAN + dest[i++] = (FLByte)(tmp>>8); + dest[i++] = (FLByte)tmp; +#else + dest[i++] = (FLByte)tmp; + dest[i++] = (FLByte)(tmp>>8); +#endif /* FL_BIG_ENDIAN */ + } + } + else + { /* mainstream case */ +#ifdef FL_ENVIRONMENT_VARS + /* Some memcpy implementations from none 4 bytes aligned destination + * buffer may use a for loop of single byte calls to the first 2 + * bytes. This implementation may be good for RAM, but will be + * problematic to 16bit DiskOnChip that does not have a BHE signal. + * so if the buffer is not dword aligned we would not perform memcpy */ + + if ((flPreventMemcpy == 0) && (((FLDword)dest&0x3)==0) ) + { + TFFSCPY_FROM_IO_16_BITS( dest,win + offset, count); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + { /* read in short words */ + for (i = 0, count = count >> 1; i < (int)count; i++) +#ifndef FL_XSCALE_BOOT_MODE + /* while incrementing DiskOnChip offset */ + ((FLWord FAR1 *)dest)[i] = FLREAD_IO_WORD(swin+i); +#else + /* but do not increment DiskOnChip offset */ + ((FLWord FAR1 *)dest)[i] = FLREAD_IO_WORD(swin); +#endif /* FL_XSCALE_BOOT_MODE */ + } + } +} + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c W r i t e N o S h i f t + + Note - this routine can write only even number of bytes + + Write 'count' bytes to M+ DiskOnChip with none shifted address bus. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocWriteNoShift ( volatile FLByte FAR0 * win , FLWord offset , + FLByte FAR1 * src, FLWord count ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + register FLWord tmp; + + if( (FLDword)src & 0x1 ) /* rare case: unaligned source buffer */ + { + for (i = 0; i < (int)count; i+=2) + { + /* tmp variable is just a precation from compiler optimizations */ +#ifdef FL_BIG_ENDIAN + tmp = ((FLWord)src[i]<<8) + (FLWord)src[i+1]; +#else + tmp = (FLWord)src[i] + ((FLWord)src[i+1]<<8); +#endif /* FL_BIG_ENDIAN */ + FLWRITE_IO_WORD(tmp,swin); + } + } + else /* mainstream case */ + { +#ifdef FL_ENVIRONMENT_VARS + if ((flPreventMemcpy == 0) && (((FLDword)src&0x3)==0)) + { + TFFSCPY_TO_IO_16_BITS(win + offset,src,count); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + { + /* write in short words */ + for (i = 0, count = count >> 1; i < (int)count; i++) + /* while incrementing DiskOnChip offset */ + /* but do not increament DiskOnChip offset */ + FLWRITE_IO_WORD(((FLWord FAR1 *)src)[i],swin); + } + } +} + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c S e t N o S h i f t + + Note - this routine can write only even number of bytes + + Set 'count' bytes of M+ DiskOnChip with none shifted address bus +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocSetNoShift ( volatile FLByte FAR0 * win , FLWord offset , + FLWord count , FLByte val) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + register FLWord tmpVal = (FLWord)val * 0x0101; + +#ifdef FL_ENVIRONMENT_VARS + if (flPreventMemcpy == 0) + { + TFFSSET_IO_16_BITS(win + offset, val, count ); + } + else +#endif /* FL_ENVIRONMENT_VARS */ + { /* write in short words */ + for (i = 0; i < (int)count; i+=2) + FLWRITE_IO_WORD(tmpVal,swin); + } +} + +/*************************************************************/ +/* 16-Bit DiskOnChip - No Shift - Only 8 bits are valid */ +/*************************************************************/ + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c R e a d N o S h i f t I g n o r e H i g h e r 8 B i t s + + Note : offset must be 16-bits aligned. + + Read 'count' bytes from M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8 bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocReadNoShiftIgnoreHigher8bits(volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + + + for (i = 0; i < (int)count; i++) + { +#ifndef FL_XSCALE_BOOT_MODE + /* Read while incrementing DiskOnChip window offset */ +#ifdef FL_BIG_ENDIAN + dest[i] = (FLByte)(FLREAD_IO_WORD((volatile void FAR0 *)(swin+i))>>8); +#else + dest[i] = (FLByte)FLREAD_IO_WORD((volatile void FAR0 *)(swin+i)); +#endif /* FL_BIG_ENDIAN */ +#else + /* Read while not incrementing DiskOnChip window offset */ +#ifdef FL_BIG_ENDIAN + dest[i] = (FLByte)(FLREAD_IO_WORD(swin)>>8); +#else + dest[i] = (FLByte)(FLREAD_IO_WORD(swin)); +#endif /* FL_BIG_ENDIAN */ +#endif /* FL_XSCALE_BOOT_MODE */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 D o c W r i t e N o S h i f t I g n o r e H i g h e r 8 b i t s + + Note : offset must be 16-bits aligned. + + Write 'count' bytes to M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocWriteNoShiftIgnoreHigher8bits ( volatile FLByte FAR0 * win , FLWord offset , + FLByte FAR1 * src, FLWord count ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset); + register int i; + + for (i = 0; i < (int)count; i++) + { + /* Write while not incrementing DiskOnChip window offset */ +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_WORD((((FLWord)src[i])<<8),swin); +#else + FLWRITE_IO_WORD((FLWord)src[i],swin); +#endif /* FL_BIG_ENDIAN */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 D o c S e t N o S h i f t I g n o r e H i g h e r 8 b i t s + + Note : offset must be 16-bits aligned. + + Set 'count' bytes to M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocSetNoShiftIgnoreHigher8bits ( volatile FLByte FAR0 * win , FLWord offset , + FLWord count , FLByte val) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)( win + offset ); + register int i; + register FLWord tmpVal = val * 0x0101; + + for (i = 0; i < (int)count; i++) + FLWRITE_IO_WORD(tmpVal,swin); +} + +/****************************************/ +/* 16-Bit DiskOnChip - Single Shift */ +/****************************************/ + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c R e a d S i n g l e S h i f t + + Read 'count' bytes from M+ DiskOnChip with none shifted address bus. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocReadSingleShift (volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win) + (offset>>1); + register int i; + register FLDword tmp; + + + if( (FLDword)dest & 0x1 ) + { + /* rare case: unaligned target buffer */ + for (i = 0; i < (int)count; ) + { + tmp = FLREAD_IO_DWORD(swin); +#ifdef FL_BIG_ENDIAN + dest[i++] = (FLByte)(tmp>>24); + dest[i++] = (FLByte)(tmp>>16); +#else + dest[i++] = (FLByte)tmp; + dest[i++] = (FLByte)(tmp>>8); +#endif /* FL_BIG_ENDIAN */ + } + } + else + { /* mainstream case */ + for (i = 0, count = count >> 1; i < (int)count; i++) + { +#ifdef FL_BIG_ENDIAN + ((FLWord FAR1 *)dest)[i]=(FLWord)(FLREAD_IO_DWORD(swin+i)>>16); +#else + ((FLWord FAR1 *)dest)[i] = (FLWord)FLREAD_IO_DWORD(swin+i); +#endif /* FL_BIG_ENDIAN */ + } + } +} + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c W r i t e S i n g l e S h i f t + + Write 'count' bytes to M+ DiskOnChip with none shifted address bus. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocWriteSingleShift ( volatile FLByte FAR0 * win , FLWord offset , + FLByte FAR1 * src, FLWord count ) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win)+ (offset>>1); + register int i; + register FLDword tmp; + + if( (FLDword)src & 0x1 ) /* rare case: unaligned source buffer */ + { + for (i = 0; i < (int)count; i+=2) + { +#ifdef FL_BIG_ENDIAN + tmp = (((FLDword)src[i])<<24) + (((FLDword)src[i+1])<<16); +#else + tmp = (FLDword)src[i] + (((FLDword)src[i+1])<<8); +#endif /* FL_BIG_ENDIAN */ + FLWRITE_IO_DWORD(tmp,swin); + } + } + else /* mainstream case */ + { + for (i = 0, count = count >> 1; i < (int)count; i++) +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD(((FLDword)((FLWord FAR1 *)src)[i])<<16,swin); +#else + FLWRITE_IO_DWORD(((FLDword)((FLWord FAR1 *)src)[i]),swin); +#endif /* FL_BIG_ENDIAN */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c S e t S i n g l e S h i f t + + Set 'count' bytes of M+ DiskOnChip with none shifted address bus +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocSetSingleShift ( volatile FLByte FAR0 * win , FLWord offset , + FLWord count , FLByte val) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win)+ (offset>>1); + register int i; + register FLDword tmpVal = (FLDword)val * 0x01010101L; + + for (i = 0; i < (int)count; i+=2) + FLWRITE_IO_DWORD(tmpVal,swin); +} + + +/**************************************************************/ +/* 16-Bit DiskOnChip - Single Shift - Only 8 bits are valid */ +/**************************************************************/ + +/*---------------------------------------------------------------------- + f l 1 6 b i t D o c R e a d S i n g l e S h i f t I g n o r e H i g h e r 8 B i t s + + Note : offset must be 16-bits aligned. + + Read 'count' bytes from M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8 bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocReadSingleShiftIgnoreHigher8bits(volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ) +{ + volatile FLDword FAR0* swin = ((volatile FLDword FAR0 *)win)+ (offset>>1); + register int i; + + + for (i = 0; i < (int)count; i++) + { +#ifdef FL_BIG_ENDIAN + dest[i] = (FLByte)(FLREAD_IO_DWORD(swin+i)>>24); +#else + dest[i] = (FLByte)FLREAD_IO_DWORD(swin+i); +#endif /* FL_BIG_ENDIAN */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 D o c W r i t e S i n g l e S h i f t I g n o r e H i g h e r 8 b i t s + + Note : offset must be 16-bits aligned. + + Write 'count' bytes to M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocWriteSingleShiftIgnoreHigher8bits ( volatile FLByte FAR0 * win , FLWord offset , + FLByte FAR1 * src, FLWord count ) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win)+ (offset>>1); + register int i; + + for (i = 0; i < (int)count; i++) + { +#ifdef FL_BIG_ENDIAN + FLWRITE_IO_DWORD(((FLDword)src[i]<<24),swin); +#else + FLWRITE_IO_DWORD(((FLDword)src[i]),swin); +#endif /* FL_BIG_ENDIAN */ + } +} + +/*---------------------------------------------------------------------- + f l 1 6 D o c S e t S i n g l e S h i f t I g n o r e H i g h e r 8 b i t s + + Note : offset must be 16-bits aligned. + + Set 'count' bytes to M+ DiskOnChip connected with all 16 data bits, but + in interleave-1 mode , therefore only one of the 8bits contains actual data. + The DiskOnChip is connected without an address shift. +------------------------------------------------------------------------*/ + +void FAR1 fl16bitDocSetSingleShiftIgnoreHigher8bits ( volatile FLByte FAR0 * win , FLWord offset , + FLWord count , FLByte val) +{ + volatile FLDword FAR0 * swin = ((volatile FLDword FAR0 *)win) + (offset>>1); + register int i; + register FLDword tmpVal = (FLDword)val * 0x01010101L; + + for (i = 0; i < (int)count; i++) + FLWRITE_IO_DWORD(tmpVal,swin); +} + + +/**********************************************************/ +/* Set proper access type routines into the proper record */ +/**********************************************************/ + +/*----------------------------------------------------------------------*/ +/* s e t B u s T y p e O f F l a s h */ +/* */ +/* Set DiskOnChip socket / flash memory access routine. */ +/* This routine must be called by the MTD prior to any access to the */ +/* DiskOnChip */ +/* */ +/* Parameters: */ +/* flflash : Pointer to sockets flash record. */ +/* access : Type of memory access routines to install */ +/* */ +/* Note: The possible type of memory access routine are comprised of: */ +/* */ +/* Address shift: */ +/* FL_NO_ADDR_SHIFT - No address shift */ +/* FL_SINGLE_ADDR_SHIFT - Single address shift */ +/* FL_DOUBLE_ADDR_SHIFT - Double address shift */ +/* */ +/* Platform bus capabilities (access width): */ +/* FL_BUS_HAS_8BIT_ACCESS - Bus can access 8-bit */ +/* FL_BUS_HAS_16BIT_ACCESS - Bus can access 16-bit */ +/* FL_BUS_HAS_32BIT_ACCESS - Bus can access 32-bit */ +/* */ +/* Number of data bits connected to the DiskOnChip (if_cfg): */ +/* FL_8BIT_DOC_ACCESS - DiskOnChip has 8 data bits */ +/* FL_16BIT_DOC_ACCESS - DiskOnChip has 16 data bits */ +/* */ +/* Flash data bits that can be accessed in a bus cycle (interleave): */ +/* FL_8BIT_FLASH_ACCESS - 8 bits of flash per cycle */ +/* FL_16BIT_FLASH_ACCESS - 16 bits of flash per cycle */ +/* */ +/* Ignore all of the above and use user defined access routines: */ +/* FL_ACCESS_USER_DEFINED - Do not install any routine since */ +/* user already installed customer made*/ +/* routines */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +FLStatus FAR1 setBusTypeOfFlash(FLFlash * flash,FLDword access) +{ + /* sanity checks here if needed */ + if(flash==NULL) + { + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: Flash record passed to setBusTypeOfFlash is NULL.\r\n"); + return flBadParameter; + } + + /* check if user already defined the memory access routines */ + if ((access & FL_ACCESS_USER_DEFINED) != 0) + return flOK; + + /************************************/ + /* install requested access methods */ + /************************************/ + + switch(access & FL_XX_ADDR_SHIFT_MASK) + { + case FL_NO_ADDR_SHIFT: + + flash->memWindowSize = flDocMemWinSizeNoShift; + switch(access & FL_XX_DATA_BITS_MASK) + { + case FL_8BIT_DOC_ACCESS: /* if_cfg set to 8-bits */ + + /* Make sure bus supports 8 bit access */ + if((access & FL_BUS_HAS_8BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 8-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 8-bit DiskOnChip connected with no address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing8bitsNoShift; + flash->memRead8bit = flRead8bitUsing8bitsNoShift; + flash->memRead16bit = flRead16bitUsing8bitsNoShift; + flash->memWrite16bit = flWrite16bitUsing8bitsNoShift; + flash->memRead = fl8bitDocReadNoShift; + flash->memWrite = fl8bitDocWriteNoShift; + flash->memSet = fl8bitDocSetNoShift; + break; + + case FL_16BIT_DOC_ACCESS: /* if_cfg set to 16-bits (Plus family) */ + + /* Make sure bus supports 16 bit access */ + if((access & FL_BUS_HAS_16BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 16-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 16-bit DiskOnChip connected with no address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing16bitsNoShift; + flash->memRead8bit = flRead8bitUsing16bitsNoShift; + flash->memRead16bit = flRead16bitUsing16bitsNoShift; + flash->memWrite16bit = flWrite16bitUsing16bitsNoShift; + + switch(access & FL_XX_FLASH_ACCESS_MASK) /* Interleave */ + { + case FL_8BIT_FLASH_ACCESS: /* Interleave - 1 */ + flash->memRead = fl16bitDocReadNoShiftIgnoreHigher8bits; + flash->memWrite = fl16bitDocWriteNoShiftIgnoreHigher8bits; + flash->memSet = fl16bitDocSetNoShiftIgnoreHigher8bits; + break; + case FL_16BIT_FLASH_ACCESS: /* Interleave - 2 */ + flash->memRead = fl16bitDocReadNoShift; + flash->memWrite = fl16bitDocWriteNoShift; + flash->memSet = fl16bitDocSetNoShift; + break; + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this flash access type (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this number of DiskOnChip data bits (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + case FL_SINGLE_ADDR_SHIFT: + + /* Install memory window size routine */ + flash->memWindowSize = flDocMemWinSizeSingleShift; + switch(access & FL_XX_DATA_BITS_MASK) + { + case FL_8BIT_DOC_ACCESS: /* if_cfg set to 8bits (or none plus family) */ + + /* Make sure bus supports 16 bit access */ + if((access & FL_BUS_HAS_16BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 16-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 8-bit DiskOnChip connected with a single address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing16bitsSingleShift; + flash->memRead8bit = flRead8bitUsing16bitsSingleShift; + flash->memWrite16bit = flWrite16bitUsing16bitsSingleShift; + flash->memRead16bit = flRead16bitUsing16bitsSingleShift; + flash->memRead = fl8bitDocReadSingleShift; + flash->memWrite = fl8bitDocWriteSingleShift; + flash->memSet = fl8bitDocSetSingleShift; + break; + + case FL_16BIT_DOC_ACCESS: /* if_cfg set to 16bits */ + + /* Make sure bus supports 32 bit access */ + if((access & FL_BUS_HAS_32BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 32-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 16-bit DiskOnChip connected with a single address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing32bitsSingleShift; + flash->memRead8bit = flRead8bitUsing32bitsSingleShift; + flash->memRead16bit = flRead16bitUsing32bitsSingleShift; + flash->memWrite16bit = flWrite16bitUsing32bitsSingleShift; + + switch(access & FL_XX_FLASH_ACCESS_MASK) /* Interleave */ + { + case FL_8BIT_FLASH_ACCESS: /* Interleave - 1 */ + flash->memRead = fl16bitDocReadSingleShiftIgnoreHigher8bits; + flash->memWrite = fl16bitDocWriteSingleShiftIgnoreHigher8bits; + flash->memSet = fl16bitDocSetSingleShiftIgnoreHigher8bits; + break; + case FL_16BIT_FLASH_ACCESS: /* Interleave - 2 */ + flash->memRead = fl16bitDocReadSingleShift; + flash->memWrite = fl16bitDocWriteSingleShift; + flash->memSet = fl16bitDocSetSingleShift; + break; + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this flash access type (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this number of DiskOnChip data bits (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + case FL_DOUBLE_ADDR_SHIFT: + + /* Install memory window size routine */ + flash->memWindowSize = flDocMemWinSizeDoubleShift; + switch(access & FL_XX_DATA_BITS_MASK) + { + case FL_8BIT_DOC_ACCESS: /* if_cfg set to 8bits or none plus family */ + + /* Make sure bus supports 32 bit access */ + if((access & FL_BUS_HAS_32BIT_ACCESS) == 0) + { + DBG_PRINT_WRN(FLZONE_MTD,"Warning: TrueFFS requires 32-bit access to DiskOnChip memory window\r\n"); + DBG_PRINT_WRN(FLZONE_MTD," for 8-bit DiskOnChip connected with a double address shift.\r\n"); + return flBadParameter; + } + + flash->memWrite8bit = flWrite8bitUsing32bitsDoubleShift; + flash->memRead8bit = flRead8bitUsing32bitsDoubleShift; + flash->memWrite16bit = flWrite16bitUsing32bitsDoubleShift; + flash->memRead16bit = flRead16bitUsing32bitsDoubleShift; + flash->memRead = fl8bitDocReadDoubleShift; + flash->memWrite = fl8bitDocWriteDoubleShift; + flash->memSet = fl8bitDocSetDoubleShift; + break; + + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this number of DiskOnChip data bits\r\n"); + DBG_PRINT_ERR(FLZONE_MTD," when connected with a double address shift (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + break; + + default: + DBG_PRINT_ERR(FLZONE_MTD,"ERROR in setBusTypeOfFlash: TrueFFS does not support this kind of address shifting (setBusTypeOfFlash).\r\n"); + return flBadParameter; + } + + /* Store access type in flash record */ + flash->busAccessType = access; + return flOK; +} + +#endif /* FL_NO_USE_FUNC */ + + + + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docsys.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docsys.h new file mode 100755 index 00000000..00f46100 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/docsys.h @@ -0,0 +1,88 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/docsys.h-arc $ + * + * Rev 1.5 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.4 Sep 11 2006 13:45:18 yaniv.iarovici + * Legal header added + * + * Rev 1.3 Aug 09 2006 16:52:46 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +/************************************************************************/ +/* I M P O R T A N T */ +/* */ +/* The file contains DiskOnChip memory access routines and macros */ +/* defintions. */ +/* */ +/* In order to use the complete set of TrueFFS memory access routine */ +/* that allows runtime configuration of each socket access type make */ +/* sure the FL_NO_USE_FUNC is not defined in FLCUSTOM.H. */ +/* */ +/* If you know the exact configuration of your application you can */ +/* uncomment the FL_NO_USE_FUNC definition and set the proper access */ +/* type using the macroe defintion bellow. */ +/************************************************************************/ + +#ifndef DOCSYS_H +#define DOCSYS_H + + +#ifndef FL_NO_USE_FUNC + +/* (public) types of DiskOnChip access configurations */ + +#define FL_BUS_HAS_XX_ACCESS_MASK 0x0000000FL /* Bus can access mask */ + +#define FL_XX_ADDR_SHIFT_MASK 0x000000F0L /* Address shift mask */ + +#endif /* FL_NO_USE_FUNC */ + +#include "_docsys.h" + +#endif /* DOCSYS_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dosformt.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dosformt.h new file mode 100755 index 00000000..0bc1aea9 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/dosformt.h @@ -0,0 +1,443 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/dosformt.h-arc $ + * + * Rev 1.12 Oct 22 2007 11:34:50 einat.avidan + * update copyrights header + * + * Rev 1.11 Feb 28 2007 09:53:46 einat.avidan + * No change + * + * Rev 1.10.1.0 Nov 12 2006 09:47:10 Yaniv.Iarovici + * Added FAT 32 support. + * + * Rev 1.10 Sep 11 2006 13:45:18 yaniv.iarovici + * Legal header added + * + * Rev 1.9 Aug 09 2006 16:52:48 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef DOSFORMT_H +#define DOSFORMT_H + +#include "flbase.h" +#include "fltl.h" + + +#define DRIVE_NUMBER 0x80 +#define EXTENDED_BOOT_SIGNATURE 0x29 +#define BACKUP_OF_BOOT_SECTOR 6 +#define FSI_LEADING_SIGNATURE 0x41615252 +#define FSI_STRUCTURE_SIGNATURE 0x61417272 + +#ifndef FL_ROOT_DIR_ENTRIES +#define FL_ROOT_DIR_ENTRIES 512 +#endif /* FL_ROOT_DIR_ENTRIES */ + + +/* The BIOS parameter block (a part of the boot sector) */ +/* Note that this is NOT the customary definition of the BPB */ +/* (customary is to start it on 'bytesPerSector'). To avoid the */ +/* nuisance of a structure that starts at an odd offset, we add */ +/* the first 11 bytes of the boot sector here. */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +#ifdef FL_WINDOWS_PACKING +#pragma pack(push, 1) +#endif /* FL_WINDOWS_PACKING */ + + +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +typedef struct +{ + FLDword size; + FLByte clusterSize; +}DiskParamsTable; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + BPB bpb; + FLByte physicalDriveNo; + FLSByte reserved0; + FLSByte extendedBootSignature; + FLSByte volumeId[4]; + FLSByte volumeLabel[11]; + FLSByte systemId[8]; + FLSByte bootstrap[448]; + LEushort signature; +} DOSBootSector; +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + BPB bpb; + LEulong FAT32Size; + LEushort extFlags; + LEushort FSVer; + LEulong RootClus; + LEushort FSInfo; + LEushort bckUpBootSect; + FLByte reserved[12]; + FLByte physicalDriveNo; + FLSByte reserved0; + FLSByte extendedBootSignature; + FLSByte volumeId[4]; + FLSByte volumeLabel[11]; + FLSByte systemId[8]; + FLSByte bootstrap[420]; + LEushort signature; +} FAT32BootSector; + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + LEulong FSI_LeadSig; + FLByte FSI_Reserved1[480]; + LEulong FSI_StructSig; + LEulong FSI_Free_Count; + LEulong FSI_Nxt_Free; + FLByte FSI_Reserved2[14]; + LEushort signature; +}FAT32FSInfo; +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define FL_DOSBOOTSECTOR_BPB_OFFSET 0 /* size 36 */ +#define FL_DOSBOOTSECTOR_PHYSICAL_DRIVE_NO_OFFSET 36 /* size 1 */ +#define FL_DOSBOOTSECTOR_RESERVED0_OFFSET 37 /* size 1 */ +#define FL_DOSBOOTSECTOR_EXTENDED_BOOT_SIGNATURE_OFFSET 38 /* size 1 */ +#define FL_DOSBOOTSECTOR_VOLUME_ID_OFFSET 39 /* size 4, array */ +#define FL_DOSBOOTSECTOR_VOLUME_LABEL_OFFSET 43 /* size 11, array */ +#define FL_DOSBOOTSECTOR_SYSTEM_ID_OFFSET 54 /* size 8, array */ +#define FL_DOSBOOTSECTOR_BOOTSTRAP_OFFSET 62 /* size 448, array */ +#define FL_DOSBOOTSECTOR_SIGNATURE_OFFSET 510 /* size 2 */ +#define FL_DOSBOOTSECTOR_SIZE 512 + +#define FL_FAT32BOOTSECTOR_BPB_OFFSET 0 /* size 36 */ +#define FL_FAT32BOOTSECTOR_FAT32SIZE_OFFSET 36 /* size 4 */ +#define FL_FAT32BOOTSECTOR_EXTFLAGS_OFFSET 40 /* size 2 */ +#define FL_FAT32BOOTSECTOR_FSVER_OFFSET 42 /* size 2 */ +#define FL_FAT32BOOTSECTOR_ROOTCLUSTER_OFFSET 44 /* size 4 */ +#define FL_FAT32BOOTSECTOR_FSINFO_OFFSET 48 /* size 2 */ +#define FL_FAT32BOOTSECTOR_BCKUPBOOTSECT_OFFSET 50 /* size 2*/ +#define FL_FAT32BOOTSECTOR_RESERVED_OFFSET 52 /* size 12, array */ +#define FL_FAT32BOOTSECTOR_PHYDRIVENO_OFFSET 64 /* size 1 */ +#define FL_FAT32BOOTSECTOR_RESERVED0_OFFSET 65 /* size 1*/ +#define FL_FAT32BOOTSECTOR_EXTSIGNATURE_OFFSET 66 /* size 1 */ +#define FL_FAT32BOOTSECTOR_VOLUMEID_OFFSET 67 /* size 4, array */ +#define FL_FAT32BOOTSECTOR_VOLUMELABEL_OFFSET 71 /* size 11, array */ +#define FL_FAT32BOOTSECTOR_SYSTEMID_OFFSET 82 /* size 8 */ +#define FL_FAT32BOOTSECTOR_BOOTSTRAP_OFFSET 90 /* size 420, array */ +#define FL_FAT32BOOTSECTOR_SIGNATURE_OFFSET 510 /* size 2 */ +#define FL_FAT32BOOTSECTOR_SIZE 512 + + + +#define FL_FAT32_FSINFO_LEADSIGNATURE_OFFSET 0 /* size 4*/ +#define FL_FAT32_FSINFO_RESERVED1_OFFSET 4 /* size 480, array*/ +#define FL_FAT32_FSINFO_STRUCTSIGNATURE_OFFSET 484 /* size 4*/ +#define FL_FAT32_FSINFO_FREECOUNT_OFFSET 488 /* size 4*/ +#define FL_FAT32_FSINFO_NEXTFREE_OFFSET 492 /* size 4*/ +#define FL_FAT32_FSINFO_RESERVED2_OFFSET 496 /* size 4*/ +#define FL_FAT32_FSINFO_SIGNATURE_OFFSET 510 /* size 14, array*/ +#define FL_FAT32_FSINFO_SIZE 512 + +typedef FLByte DOSBootSector[FL_DOSBOOTSECTOR_SIZE]; +typedef FLByte FAT32BootSector[FL_FAT32BOOTSECTOR_SIZE]; +typedef FLByte FAT32FSInfo[FL_FAT32_FSINFO_SIZE]; +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + + + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + FLByte orderNum; /* 6 significant bits of LFN order number */ + Unaligned name1[5]; /* part 1 of scattered name */ + FLByte attributes; /* file attributes, must be RO, System, Hidden, Volume */ + FLByte reserved; /* must be 0 */ + FLByte checksum; /* checksum created from short form name */ + LEushort name2[6]; /* part 2 of scattered name */ + LEushort startingCluster; /* must be 0 */ + LEushort name3[2]; /* part 3 of scattered name */ +} LfnDirectoryEntry; +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define FL_LFN_DIRECTORY_ENTRY_ORDER_NUM_OFFSET 0 /* size 1 */ +#define FL_LFN_DIRECTORY_ENTRY_NAME1_OFFSET 1 /* size 10, unaligned array of 2 */ +#define FL_LFN_DIRECTORY_ENTRY_ATTRIBUTES_OFFSET 11 /* size 1 */ +#define FL_LFN_DIRECTORY_ENTRY_RESERVED_OFFSET 12 /* size 1 */ +#define FL_LFN_DIRECTORY_ENTRY_CHECKSUM_OFFSET 13 /* size 1 */ +#define FL_LFN_DIRECTORY_ENTRY_NAME2_OFFSET 14 /* size 12, array of 2 */ +#define FL_LFN_DIRECTORY_ENTRY_STARTING_CLUSTER_OFFSET 26 /* size 2 */ +#define FL_LFN_DIRECTORY_ENTRY_NAME3_OFFSET 28 /* size 4, array of 2 */ +#define FL_LFN_DIRECTORY_ENTRY_SIZE 32 + +typedef FLByte LfnDirectoryEntry[FL_LFN_DIRECTORY_ENTRY_SIZE]; +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +/* Directory entry attribute bits */ + + + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + /* First partition entry starts here. We do not map it as a */ + /* separate structure because it is not longword aligned */ + FLByte activeFlag; /* 80h = bootable */ + FLByte startingHead; + LEushort startingCylinderSector; + FLSByte type; + FLByte endingHead; + LEushort endingCylinderSector; + Unaligned4 startingSectorOfPartition; + Unaligned4 sectorsInPartition; + /* Partition entries 2,3 and 4 are structured as the 1st partition */ +} Partition; +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define FL_PARTITION_ACTIVE_FLAG_OFFSET 0 /* size 1 */ +#define FL_PARTITION_STARTING_HEAD_OFFSET 1 /* size 1 */ +#define FL_PARTITION_STARTING_CYLINDER_SECTOR_OFFSET 2 /* size 2 */ +#define FL_PARTITION_TYPE_OFFSET 4 /* size 1 */ +#define FL_PARTITION_ENDING_HEAD_OFFSET 5 /* size 1 */ +#define FL_PARTITION_ENDING_CYLINDER_SECTOR_OFFSET 6 /* size 2 */ +#define FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET 8 /* size 4 */ +#define FL_PARTITION_SECTORS_IN_PARTITION_OFFSET 12 /* size 4 */ +#define FL_PARTITION_SIZE 16 + +typedef FLByte Partition[FL_PARTITION_SIZE]; +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +typedef FL_PACKED_STRUCTURES_BEFORE struct FL_PACKED_STRUCTURES_AFTER { + FLSByte reserved1[0x1A6]; + Unaligned4 passwordInfo[3]; /* M-Systems proprietary */ + FLSByte reserved2[0xC]; /* NT4 or NT5 signature place */ + + /* First partition entry starts here. We do not map it as a */ + /* separate structure because it is not longword aligned */ + Partition ptEntry[4]; + LEushort signature; /* = PARTITION_SIGNATURE */ +} PartitionTable; +#else /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define FL_PARTITION_TABLE_RESERVED1_OFFSET 0 /* size 0x1A6 */ +#define FL_PARTITION_TABLE_PASSWORD_INFO_OFFSET 422 /* size 12, unaligned array of 4 */ +#define FL_PARTITION_TABLE_RESERVED2_OFFSET 434 /* size 12, array */ +#define FL_PARTITION_TABLE_PT_ENTRY_OFFSET 446 /* size 4x16, array of partition entries */ +#define FL_PARTITION_TABLE_SIGNATURE_OFFSET 510 /* size 2 */ +#define FL_PARTITION_TABLE_SIZE 512 + +typedef FLByte PartitionTable[FL_PARTITION_TABLE_SIZE]; +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + +#ifdef FL_WINDOWS_PACKING +#pragma pack(pop) +#endif /* FL_WINDOWS_PACKING */ + +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + +#define PARTITION_ENTRIES 4 + + +/** Values of irFlags for flOpenFile: */ + +#define ACCESS_MODE_MASK 3 /* Mask for access mode bits */ + +/* Individual flags */ + +#define FL_ACCESS_CREATE 2 /* Create new file */ + +/* commands to flGetSetFileInfo (in addition to above) */ +#define FL_GET_DATETIME -1 /* Get date/time */ +#define FL_GET_ATTRIBUTES -2 /* Get attributes */ +#define FL_GET_CREATE_DATETIME -8 /* Get creation date/time */ + + +#ifndef LFN_NAME_MAX_CHARACTERS +#define LFN_NAME_MAX_CHARACTERS 255 +#endif /* LFN_NAME_MAX_CHARACTERS */ + +#ifndef PATH_SEGMENTS_MAX_NUM +#define PATH_SEGMENTS_MAX_NUM 10 +#endif /* PATH_SEGMENTS_MAX_NUM */ + +#ifndef PATH_CHARACTERS_MAX_NUM +#define PATH_CHARACTERS_MAX_NUM LFN_NAME_MAX_CHARACTERS +#endif /* PATH_CHARACTERS_MAX_NUM */ + +#ifndef FL_MAX_TREE_LEVELS +#define FL_MAX_TREE_LEVELS ( PATH_CHARACTERS_MAX_NUM / 2 + 1 ) +#endif /* FL_MAX_TREE_LEVELS */ + +#ifndef FL_ROOT_DIR_ENTRIES +#define FL_ROOT_DIR_ENTRIES(socket,partition) 512 +#endif /* FL_ROOT_DIR_ENTRIES */ + +#define UNICODE_CHAR_PER_LFN_ENTRY 13 + +#define SHORT_NAME_MAX_LENGTH 8 +#define EXTENSION_MAX_LENGTH 3 +#define NAME_8_3_MAX_LENGTH 12 /* "tttttttt.xxx" */ + +/* Directory entry attribute bits for internal use */ +#define ATTR_SUREFS_GEN_ATTENTION_FLAG 0x40 +#define ATTR_SUREFS_REN_ATTENTION_FLAG 0x80 +#define ATTR_SUREFS_ATTENTION_FLAG_MASK (ATTR_SUREFS_GEN_ATTENTION_FLAG | \ + ATTR_SUREFS_REN_ATTENTION_FLAG) + +#define ATTR_MASK ((unsigned char)(FL_ATTR_READ_ONLY | FL_ATTR_HIDDEN | FL_ATTR_SYSTEM | \ + FL_ATTR_VOL_LABEL | FL_ATTR_DIRECTORY | FL_ATTR_ARCHIVE)) +#define LFN_ATTRIBUTES ((unsigned char)(FL_ATTR_READ_ONLY | FL_ATTR_HIDDEN | \ + FL_ATTR_SYSTEM | FL_ATTR_VOL_LABEL)) + +#define DIRECTORY_ENTRY_SIZE 32 + +#define DIRECTORY_ENTRIES_PER_SECTOR (FL_SECTOR_SIZE / DIRECTORY_ENTRY_SIZE) +#define MAX_ROOT_DIR_SECTORS ((0x10000/DIRECTORY_ENTRIES_PER_SECTOR) - 1) + +#ifdef FS_EXP_FAT32 +/* setting this to 0xffffffff may improve performance * + * setting this to 0x0fffffff improves compatibility */ +#define FAT32_ENTRY_BITS_COMP 0x0fffffff +#endif /*FS_EXP_FAT32*/ + +#define SET_GLOBAL_ATTENTION_FLAG 0 +#ifdef FS_EXP_FAT32 +#define RESET_GLOBAL_ATTENTION_FLAG 0x0fffffff +#else /*FS_EXP_FAT32*/ +#define RESET_GLOBAL_ATTENTION_FLAG 0xffff +#endif /*FS_EXP_FAT32*/ +#define GLOBAL_ATT_FLAG_FAT_ENTRY 1 + +#define NEVER_USED_DIR_ENTRY 0 + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED +#define DELETED_DIR_ENTRY ((FLSByte) 0xe5) +#else /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +#define DELETED_DIR_ENTRY ((FLByte) 0xe5) +#endif /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ + +/* FAT definitions */ + +#define FAT_FREE 0 +#define FAT_BAD_CLUSTER 0xfff7 +#ifdef FS_EXP_FAT32 +#define FAT_LAST_CLUSTER 0x0fffffff /* FAT16 values are converted */ +#else /*FS_EXP_FAT32*/ +#define FAT_LAST_CLUSTER 0xffff /* actually any of 0xfff8-0xffff */ +#endif /*FS_EXP_FAT32*/ + +/* Partition table definitions */ + +#define PARTITION_SIGNATURE 0xaa55 + +#define CYLINDER_SECTOR(cylinder,sector) ((sector) + ((cylinder & 0xff) << 8) + ((cylinder & 0x300) >> 2)) + + +#ifndef FL_MAX_PARTITION_DEPTH +#define FL_MAX_PARTITION_DEPTH 0x08 +#endif /* FL_MAX_PARTITION_DEPTH */ + +#define LFN_SHORT_NAME 0 /* for 8.3 short file name */ +#define LFN_LONG_NAME 1 /* for long file name */ +#define LFN_INVALID_SET 2 /* found invalid file name characters */ +#define SFN_LOWERCASE_NAME8 0x08 /* these 2 bit-flags are to support */ +#define SFN_LOWERCASE_EXT3 0x10 /* NT VFAT lowercase bits */ + +/*------------------------------------------------------------------------------------------- +* F L P a t h S e g m e n t +* The structure is used when analyzing path string. +* Parameters: name - address of first character of the path segment (unicode null terminated +* string. For example, for first segment of /first/second/third.ext it +* will point on "first". +* length - number of characters of the path segment +* buffSize - in case of retrieving file name this field contains size of supplied buffer +* in characters. +* get - if TRUE, this structure is used to retrieve found file name +* (getFirstFileName()). If FALSE, this structure contains file name to +* be opened/created/found (findFileName()). +*------------------------------------------------------------------------------------------*/ +typedef struct { + FLWchar FAR1 *name; + short length; + short buffSize; + FLBoolean get; + FLBoolean reserved; +} FLPathSegment; + +/*-------------------------------------------------------------------------- +* F L L f n S e a r c h +* The FLLfnSearch structer is used when searching directory by specified +* file name. +* Parameters: +* neverUsed - indicates that found at least one directory entry in sector +* that was never used. +* verifiedChars - Number of characters that successfully compared with +* file name or found in free entries in previous sector +* checksum - LFN checksum found in previous sector +* lastNum - LFN order number of last LFN entry found in previous sector +* idx - directory entry index of found entry +* status - LFN_SHORT_NAME, LFN_LONG_NAME, LFN_UPPERCASE_FOR_SHORT, +* LFN_INVALID_SET +*---------------------------------------------------------------------------*/ +typedef struct { + unsigned verifiedChars; + unsigned lastNum; + unsigned idx; + int status; + unsigned char checksum; + FLBoolean neverUsed; +} FLLfnSearch; + + + +#endif /* DOSFORMT_H */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/extfiltr.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/extfiltr.c new file mode 100755 index 00000000..e87d5f1d --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/extfiltr.c @@ -0,0 +1,717 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.4 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.4. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + +#include "tffsdrv.h" + + +#ifndef TFFS_DEBUG_EXTFILTER +# undef TFFS_DEBUG_DRIVER +#endif + +/* min: 0x40000 == sect>>9 == 256 blocks/group * 1024 bytes/block +typical: 0x800000 == sect>>15 == 8192 blocks/group * 1024 bytes/block +default: 0x100000 == sect>>12 == 1M */ +# define TFFS_EXTF_CACHE_STEP 12 + +#define EXTF_CACHE_MASK ((1<= 256, <= 8*blocksize */ +/* all offsets of SB/GD are including first empty block, block bitmap doesn't */ + +#ifdef TFFS_USE_RAM +# include "tffsram.h" +#else +# include "blockdev.h" +#endif + +static unsigned char pTmp[512]; + +#ifdef TFFS_DEBUG_DRIVER +static unsigned long dwSearches=0,dwSteps=0; +#endif + +unsigned char ExtReadSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char*p); +unsigned char ExtDelSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char bSectors); + +void AddSect(DeviceInfo*pDevice,SectInfo*pSect); +SectInfo*DelSect(DeviceInfo*pDevice,SectInfo*pSect); + +void CacheSect(DeviceInfo*pDevice,SectInfo*pSect); +void UncacheSect(DeviceInfo*pDevice,SectInfo*pSect); + +#define PTChanged(pSect,pData) 1 +void AddPT(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pBuff); +void DelPT(DeviceInfo*pDevice,SectInfo*pPT); + +#ifdef TFFS_DEBUG_DRIVER +unsigned char SBChanged(SectInfo*pSect,struct ext2_super_block*pSB) +{ + if(le32_to_cpu(pSB->s_log_block_size) != pSect->bSect2BlockShift-1) + { + PrintkDebug("SBChanged: s_log_block_size different: %d -> %d",(int)pSect->bSect2BlockShift-1,(int)pSB->s_log_block_size); + return 1; + } + if(le32_to_cpu(pSB->s_blocks_per_group) != pSect->dwBlocksPerBitmap) + { + PrintkDebug("SBChanged: s_blocks_per_group different: %d -> %d",(int)pSect->dwBlocksPerBitmap,(int)pSB->s_blocks_per_group); + return 1; + } + if(pSB->s_feature_compat != pSect->dwExt3Flags) + { + PrintkDebug("SBChanged: s_feature_compat different: %d -> %d",(int)pSect->dwExt3Flags,(int)pSB->s_feature_compat); + return 1; + } + PrintkDebug("SBChanged: not changed"); + return 0; +} +#else +# define SBChanged(pSect,pSB) ( ( le32_to_cpu((pSB)->s_log_block_size) != (pSect)->bSect2BlockShift-1 ) || ( le32_to_cpu((pSB)->s_blocks_per_group) != (pSect)->dwBlocksPerBitmap ) || ((pSB)->s_feature_compat!=(pSect)->dwExt3Flags)) +#endif + +void AddSB(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_super_block*pSB); +void DelSB(DeviceInfo*pDevice,SectInfo*pPart); + +void AddGD(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_group_desc*pGD,unsigned char bOffset); +void ProcessBB(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pOld,unsigned char*pNew,unsigned char bOffset); + +#ifdef TFFS_DEBUG_DRIVER + +void PrintSect(SectInfo*pSect,char*p) +{ + char*str; + switch(pSect->bFlag) + { + case EXTF_PT: + str="PT empty"; + break; + case EXTF_HAS_PT: + str="PT"; + break; + case EXTF_SB: + str="SB empty"; + break; + case EXTF_HAS_SB: + str="SB"; + break; + case EXTF_HAS_GD: + str="SB&GD"; + break; + case EXTF_BB: + str="BB not adjusted"; + break; + case EXTF_HAS_BB: + str="BB"; + break; + case 0: + str="last sect"; + break; + default: + str="BAD FLAG"; + } + PrintkDebug("%s: %s part %d sect %lu len %u flag %d",p,str,pSect->no,pSect->dwSector,pSect->bSectors,pSect->bFlag); +} + +void PrintAllSect(DeviceInfo*pDevice) +{ + SectInfo*pSect=&pDevice->sect[0]; + do{ + PrintSect(pSect,"LIST"); + pSect=pSect->pNext; + }while(pSect!=&pDevice->sect[0]); +} + +void Printp(unsigned char*p) +{ + int i,k; + for(i=0;i<32;i++) + { + for(k=0;k<16;k++) + printk("%2x ",*(p+((i<<4)+k))); + printk("\n"); + } +} + +#else +# define PrintAllSect(pDevice) +# define PrintSect(pSect,p) +# define Printp(p) +#endif + +void ExtFilter(DeviceInfo*pDevice,unsigned char*pBuff,unsigned long dwSector,unsigned long dwSectors) +{ + SectInfo*pSect=pDevice->pCache[dwSector>>TFFS_EXTF_CACHE_STEP]; + unsigned long dwSect=dwSector; + + PrintkDebug("ExtFilter: dev %d sec 0x%lx + 0x%lx",pDevice->diskNo,dwSector,dwSectors); + + while(dwSect=pSect->dwSector+pSect->bSectors) + pSect=pSect->pNext; + + if(dwSect>=pSect->dwSector+pSect->bSectors || dwSect+dwSectors<=pSect->dwSector) + return; + + if(dwSectdwSector) + dwSect=pSect->dwSector; + + PrintkDebug("ExtFilter: sec 0x%lx",dwSect); + +/* PrintkDebug("ExtFilter sec %lu + %lu: found %lu of %lu + %d",dwSector,dwSectors,dwSect,pSect->dwSector,pSect->bSectors); */ +/* PrintSect(pSect,"ExtFilter: found"); */ + + pData=pBuff+((dwSect-dwSector)<<9); + + switch(pSect->bFlag) + { + case EXTF_PT: + PrintkDebug("ExtFilter: EXTF_PT"); + AddPT(pDevice,pSect,pData); + dwSect=pSect->pNext->dwSector; + break; + case EXTF_HAS_PT: + PrintkDebug("ExtFilter: EXTF_HAS_PT"); + if(PTChanged(pSect,pData)) + { + DelPT(pDevice,pSect); + AddPT(pDevice,pSect,pData); + } + dwSect=pSect->pNext->dwSector; + break; + case EXTF_SB: + PrintkDebug("ExtFilter: EXTF_SB"); + AddSB(pDevice,pSect,(struct ext2_super_block*)pData); + dwSect++; + break; + case EXTF_HAS_SB: + PrintkDebug("ExtFilter: EXTF_HAS_SB"); + if(dwSect==pSect->dwSector) /* SB changed */ + { + if(SBChanged(pSect,(struct ext2_super_block*)pData)) + AddSB(pDevice,pSect,(struct ext2_super_block*)pData); + dwSect+=2; + } + else + { + if(dwSect>=pSect->dwSector+(pSect->bSect2BlockShift==3?6:2)) /* GD added */ + { + AddGD(pDevice,pSect,(struct ext2_group_desc*)pData,dwSect-(pSect->dwSector+(pSect->bSect2BlockShift==3?6:2))); + } + dwSect++; + } + break; + case EXTF_HAS_GD: /* ignore GD changes */ + PrintkDebug("ExtFilter: EXTF_HAS_GD"); + if(SBChanged(pSect,(struct ext2_super_block*)pData)) + { + DelSB(pDevice,pSect); + AddSB(pDevice,pSect,(struct ext2_super_block*)pData); + } + dwSect=pSect->pNext->dwSector; + break; + case EXTF_BB: + PrintkDebug("ExtFilter: EXTF_BB"); + /* do nothing */ + dwSect=pSect->pNext->dwSector; + break; + return; + case EXTF_HAS_BB: + PrintkDebug("ExtFilter: EXTF_HAS_BB"); + if(ExtReadSector(pDevice,dwSect,pTmp)) + ProcessBB(pDevice,pSect,pTmp,pData,dwSect-pSect->dwSector); + dwSect++; + break; +#ifdef TFFS_DEBUG_DRIVER + default: + PrintkDebug("ExtFilter: wrong case %d",pSect->bFlag); + dwSect++; +#endif + } + } + PrintkDebug("ExtFilter:exit"); +} + +void ExtFilterInit(DeviceInfo*pDevice) +{ + unsigned short wCache,wCacheSize; + + PrintkDebug("ExtFilterInit"); + + /* init first and last sectors */ + pDevice->sect[0].dwSector=0; + pDevice->sect[0].bSectors=1; + pDevice->sect[0].pParent=NULL; + pDevice->sect[0].pPrev=pDevice->sect[0].pNext=&pDevice->sect[1]; + pDevice->sect[0].bFlag=EXTF_PT; + pDevice->sect[0].dwOffset=0; + pDevice->sect[1].dwSector=0xffffffff; + pDevice->sect[1].bSectors=0; + pDevice->sect[1].pParent=NULL; + pDevice->sect[1].pPrev=pDevice->sect[1].pNext=&pDevice->sect[0]; + pDevice->sect[1].bFlag=0; + pDevice->sect[1].dwOffset=0; +#ifdef TFFS_DEBUG_DRIVER + pDevice->sect[0].no=0; + pDevice->sect[1].no=0; +#endif + + /* init hash */ + wCacheSize=(pDevice->dwSize >> TFFS_EXTF_CACHE_STEP) + 1; + PrintkDebug("ExtFilterInit: cache len %u",wCacheSize); + pDevice->pCache=KMalloc(sizeof(SectInfo*)*wCacheSize); + if(pDevice->pCache==NULL) + return; + pDevice->pCache[0]=&pDevice->sect[0]; + for(wCache=1;wCachepCache[wCache]=&pDevice->sect[1]; + + ExtReadSector(pDevice,0,pTmp); + AddPT(pDevice,&pDevice->sect[0],pTmp); + + PrintAllSect(pDevice); +} + +void ExtFilterRelease(DeviceInfo*pDevice) +{ + PrintkDebug("ExtFilterRelease: %lu times, %lu steps, average %lu",dwSearches,dwSteps,(dwSearches!=0)?dwSteps/dwSearches:0); + PrintAllSect(pDevice); + DelPT(pDevice,&pDevice->sect[0]); + if(pDevice->pCache!=NULL) + { + kfree(pDevice->pCache); + pDevice->pCache=NULL; + } +} + +void AddPT(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pBuff) +{ + SectInfo*pPT=pSect; + unsigned char*pPTData,*pPartData; + + pPTData=KMalloc(1024); + if(pPTData==NULL) + return; + memcpy(pPTData,pBuff,512); + pPartData=pPTData+512; + + while(pPT!=NULL) + { + unsigned char bPart; + SectInfo*pNextPT=NULL; + + PrintkDebug("AddPT %d",pPT->no); + + if(pPTData[510]!=0x55 || pPTData[511]!=0xaa) + { + PrintkDebug("AddPT %d: no signature",pPT->no); + pPT->bFlag=EXTF_PT; + return; + } + PrintkDebug("AddPT %d: signature found",pPT->no); + pPT->bFlag=EXTF_HAS_PT; + + for(bPart=0;bPart<4;bPart++) + { + SectInfo*pPart; + unsigned char*pData=pPTData+(446+bPart*16); + + if(*(pData+4)==0) + { + PrintkDebug("AddPT %d: empty partition %d",pPT->no,bPart); + continue; + } + + pPart=KMalloc(sizeof(SectInfo)); + if(pPart==NULL) + return; + memset(pPart,0,sizeof(SectInfo)); + + pPart->pParent=pPT; + + pPart->dwSector=*(pData+11); + pPart->dwSector<<=8; + pPart->dwSector+=*(pData+10); + pPart->dwSector<<=8; + pPart->dwSector+=*(pData+9); + pPart->dwSector<<=8; + pPart->dwSector+=*(pData+8); + + #ifdef TFFS_DEBUG_DRIVER + if(pPT->no==0) + pPart->no=bPart+1; + else + if(pPT->no<4) + pPart->no=5; + else + pPart->no=pPT->no+1; + #endif + + switch(*(pData+4)) + { + case 5: + case 0xf: + case 0x85: + /* extended partition */ + pPart->dwSector+=pPart->pParent->dwOffset; + pNextPT=pPart; /* save next extended partition */ + pPart->bSectors=1; /* partition table */ + pPart->bFlag=EXTF_PT; + pPart->dwOffset=pPT->dwOffset; + if(pPart->dwOffset==0) + pPart->dwOffset=pPart->dwSector; + AddSect(pDevice,pPart); + break; + default: + /* data partition */ + pPart->dwSector+=pPart->pParent->dwSector+2; /* offset from PT + superblock */ + pPart->bSectors=1; /* only first sector of superblock */ + pPart->bFlag=EXTF_SB; + AddSect(pDevice,pPart); + + /* add superblock */ + PrintkDebug("AddPT %d: read sector %lu for SB",pPart->no,pPart->dwSector); + ExtReadSector(pDevice,pPart->dwSector,pPartData); + AddSB(pDevice,pPart,(struct ext2_super_block*)pPartData); + + /* add group descriptors */ + if(pPart->bFlag&EXTF_HAS_SB) + { + unsigned short wGroup; + for(wGroup=0;wGroupwGroups;wGroup+=16) + { + PrintkDebug("AddPT %d: read sector %lu for GD",pPT->no,pPart->dwSector+2+(wGroup>>4)); + ExtReadSector(pDevice,pPart->dwSector+(pPart->bSect2BlockShift==3?6:2)+(wGroup>>4),pPartData); + AddGD(pDevice,pPart,(struct ext2_group_desc*)pPartData,(wGroup>>4)); + } + } + } + + PrintkDebug("AddPT: part %d added, %lu",pPart->no,pPart->dwSector); + } + pPT=pNextPT; + if(pPT!=NULL) + { + PrintkDebug("AddPT %d: read sector %lu for next PT",pPT->no,pPT->dwSector); + ExtReadSector(pDevice,pPT->dwSector,pPTData); + } + } + + kfree(pPTData); +} + +void DelPT(DeviceInfo*pDevice,SectInfo*pPT) +{ + SectInfo*pCurPT=pPT; + + while(pCurPT!=NULL) + { + SectInfo*pCurSect=pCurPT->pNext,*pNextPT=NULL;; + PrintkDebug("DelPT: part %d",pCurPT->no); + while(pCurSect!=pCurPT) + { + if(pCurSect->pParent==pCurPT) + { + PrintkDebug("DelPT: part %d flag %d",pCurSect->no,pCurSect->bFlag); + switch(pCurSect->bFlag) + { + case EXTF_PT: + case EXTF_SB: + pCurSect=DelSect(pDevice,pCurSect); + break; + case EXTF_HAS_PT: + pNextPT=pCurSect; /* save next PT */ + pCurSect=pCurSect->pNext; + break; + case EXTF_HAS_SB: + case EXTF_HAS_GD: + DelSB(pDevice,pCurSect); + pCurSect=DelSect(pDevice,pCurSect); + break; +#ifdef TFFS_DEBUG_DRIVER + default: + PrintkDebug("DelPT: wrong case"); +#endif + } + } + else + pCurSect=pCurSect->pNext; + } + if(pCurPT!=pPT) + DelSect(pDevice,pCurPT); + pCurPT=pNextPT; + } + pPT->bFlag=EXTF_PT; +} + +void AddSB(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_super_block*pSB) +{ + unsigned short wGroup; + SectInfo*pBBSect; + + PrintkDebug("AddSB %d: sector %lu",pSect->no,pSect->dwSector); + /* check that is superblock */ + if( (le16_to_cpu(pSB->s_magic)!=0xef53) || (le32_to_cpu(pSB->s_creator_os)!=0) || (le32_to_cpu(pSB->s_rev_level)!=0 && le32_to_cpu(pSB->s_rev_level)!=1) ) + { + PrintkDebug("AddSB: no superblock: magic 0x%x os %d, rev %d",le16_to_cpu(pSB->s_magic),le32_to_cpu(pSB->s_creator_os),le32_to_cpu(pSB->s_rev_level)); + pSect->bFlag=EXTF_SB; + return; + } + pSect->bFlag=EXTF_HAS_SB; + + pSect->dwExt3Flags=pSB->s_feature_compat; + pSect->bSect2BlockShift=le32_to_cpu(pSB->s_log_block_size)+1; + pSect->dwBlocksPerBitmap=le32_to_cpu(pSB->s_blocks_per_group); + + /* calc no of groups */ + pSect->wGroups=(le32_to_cpu(pSB->s_blocks_count)-le32_to_cpu(pSB->s_first_data_block))/le32_to_cpu(pSB->s_blocks_per_group); + if(pSect->wGroups*le32_to_cpu(pSB->s_blocks_per_group) < le32_to_cpu(pSB->s_blocks_count)-le32_to_cpu(pSB->s_first_data_block)) + pSect->wGroups++; + PrintkDebug("AddSB %d: %u groups",pSect->no,pSect->wGroups); + + pSect->bSectors=pSect->wGroups>>4; + if(((unsigned short)pSect->bSectors)<<4 < pSect->wGroups) + pSect->bSectors++; + pSect->bSectors+=pSect->bSect2BlockShift==3?6:2; /* group descriptors sectors + 2 or 6 sect. of superblock */ + + pBBSect=KMalloc(pSect->wGroups*sizeof(SectInfo)); + if(pBBSect==NULL) + { + PrintkDebug("AddSB: kmalloc failed"); + return; + } + memset(pBBSect,0,pSect->wGroups*sizeof(SectInfo)); + pSect->bFlag=EXTF_HAS_SB; + for(wGroup=0;wGroupwGroups;wGroup++,pBBSect++) + { + pBBSect->pParent=pSect; + pBBSect->bFlag=EXTF_BB; + pBBSect->dwSector=pSect->dwSector+wGroup*((le32_to_cpu(pSB->s_blocks_per_group))<bSect2BlockShift)+1; /* the value shoul be updated in AddGD */ +#ifdef TFFS_DEBUG_DRIVER + pBBSect->no=pSect->no; +#endif + + if(wGroupwGroups-1) + { + pBBSect->dwBlocksPerBitmap=le32_to_cpu(pSB->s_blocks_per_group); + } + else /* last group */ + { + pBBSect->dwBlocksPerBitmap=le32_to_cpu(pSB->s_blocks_count)-le32_to_cpu(pSB->s_first_data_block)-le32_to_cpu(pSB->s_blocks_per_group)*(pSect->wGroups-1); + } + pBBSect->bSectors=pBBSect->dwBlocksPerBitmap>>12; + if( ((pBBSect->dwBlocksPerBitmap>>12)<<12) != pBBSect->dwBlocksPerBitmap) + pBBSect->bSectors++; + + pBBSect->dwFirstSectorOfBitmap=pSect->dwSector-2+((le32_to_cpu(pSB->s_first_data_block)+le32_to_cpu(pSB->s_blocks_per_group)*wGroup)<bSect2BlockShift); + + AddSect(pDevice,pBBSect); + } + PrintkDebug("SB %d added: sector %lu sectors %u",pSect->no,pSect->dwSector,pSect->bSectors); +} + +void DelSB(DeviceInfo*pDevice,SectInfo*pPart) +{ + SectInfo*pTmp=pPart->pNext; + + PrintkDebug("DelSB part %d",pPart->no); + + while(pTmp->bFlag&EXTF_HAS_BB || pTmp->bFlag&EXTF_BB) + { + UncacheSect(pDevice,pTmp); + pTmp=pTmp->pNext; + } + kfree(pPart->pNext); + pPart->pNext=pTmp; + pPart->bFlag=EXTF_SB; +} + + +void AddGD(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_group_desc*pGD,unsigned char bOffset) +{ + unsigned short wGroup,wGroups; + SectInfo*pCurSect=pSect->pNext; + + PrintkDebug("AddGD: part %d offset %u",pSect->no,bOffset); + + wGroups=(((unsigned short)bOffset)<<4); + while(wGroups) + { + pCurSect=pCurSect->pNext; + wGroups--; + } + wGroups=pSect->wGroups-(((unsigned short)bOffset)<<4); + if(wGroups>16) + wGroups=16; + + for(wGroup=0;wGrouppNext) + { + UncacheSect(pDevice,pCurSect); + pCurSect->dwSector=((unsigned long)le32_to_cpu(pGD[wGroup].bg_block_bitmap)<bSect2BlockShift)+pSect->dwSector-2; + CacheSect(pDevice,pCurSect); + pCurSect->bFlag=EXTF_HAS_BB; + PrintkDebug("AddGD: added group %d (%d) sect %lu",wGroup,wGroup+(bOffset<<4),pCurSect->dwSector); + PrintkDebug("AddGD: 0x%lx 0x%x 0x%lx",(unsigned long)le32_to_cpu(pGD[wGroup].bg_block_bitmap),pSect->bSect2BlockShift,pSect->dwSector); + } + + /* set EXTF_HAS_GD flag to the parent sector, if it's last GD sector */ + if(((bOffset+1)<<4)>=pSect->wGroups) + { + PrintkDebug("AddGD: end group descriptors"); + pSect->bFlag=EXTF_HAS_GD; + pSect->bSectors=1; + } +} + +void ProcessBB(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pOld,unsigned char*pNew,unsigned char bOffset) +{ + unsigned long dwSectorShift=pSect->dwFirstSectorOfBitmap+(((unsigned long)bOffset)<<(pSect->pParent->bSect2BlockShift+12)); + unsigned short wBlock; + unsigned short wLastBlockInSector=pSect->dwBlocksPerBitmap-(((unsigned short)bOffset)<<12); + + /* PrintkDebug("ProcessBB %d: %lu",pSect->no,pSect->dwSector); */ + + for(wBlock=0;wBlock>5],n=((unsigned long*)pNew)[wBlock>>5]; + if(o!=n) + { + unsigned char b; + + for(b=0;b<32 && wBlock+b (n&(1L<pParent->bSect2BlockShift)+dwSectorShift,1<pParent->bSect2BlockShift); + } + } + } +} + +unsigned char ExtReadSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char*p) +{ + IOreq ioreq; + + ioreq.irHandle=pDevice->bHandle; + ioreq.irData=p; + ioreq.irLength=dwSector; + ioreq.irCount=1; + + if(flAbsRead(&ioreq)==flOK) + return 1; + else + { + PrintkDebug("ExtReadSector->flAbsRead error"); + return 0; + } +} + +unsigned char ExtDelSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char bSectors) +{ + IOreq ioreq; + + PrintkDebug("ExtDelSector: del %lu %u",dwSector,bSectors); + + ioreq.irHandle=pDevice->bHandle; + ioreq.irLength=dwSector; + ioreq.irCount=bSectors; +#ifdef DRIVER_DEBUG + if(dwSector>=pDevice->dwSize) + PrintkDebug("ExtDelSector: achtung: wrong sector 0x%lx of 0x%lx",dwSector,pDevice->dwSize); +#endif + if(flAbsDelete(&ioreq)!=flOK) + { + PrintkDebug("ExtDelSector:flAbsDelete fails"); + return 0; + } + return 1; +} + +void AddSect(DeviceInfo*pDevice,SectInfo*pSect) +{ + SectInfo*pCurSect=&pDevice->sect[1]; + +/* PrintSect(pSect,"AddSect"); */ + + while(pCurSect->pNext!=&pDevice->sect[1] && pCurSect->pNext->dwSectordwSector) + pCurSect=pCurSect->pNext; + pSect->pNext=pCurSect->pNext; + pSect->pPrev=pCurSect; + pCurSect->pNext->pPrev=pSect; + pCurSect->pNext=pSect; + CacheSect(pDevice,pSect); +} + +SectInfo*DelSect(DeviceInfo*pDevice,SectInfo*pSect) +{ + SectInfo*p=pSect->pNext; + + PrintkDebug("DelSect: %lu flag 0x%x",pSect->dwSector,pSect->bFlag); + + UncacheSect(pDevice,pSect); + pSect->pPrev->pNext=pSect->pNext; + pSect->pNext->pPrev=pSect->pPrev; + kfree(pSect); + return p; +} + +void CacheSect(DeviceInfo*pDevice,SectInfo*pSect) +{ + unsigned short wCache=pSect->dwSector>>TFFS_EXTF_CACHE_STEP; + +/* PrintkDebug("CacheSect %lu to %lu",pSect->dwSector,pSect->dwSector>>TFFS_EXTF_CACHE_STEP); */ + + while(pDevice->pCache[wCache]==pSect->pNext) + { +/* PrintkDebug("CacheSect: pCache[%u]=%lu",wCache,pSect->dwSector); */ + pDevice->pCache[wCache]=pSect; + wCache--; + } +} + +void UncacheSect(DeviceInfo*pDevice,SectInfo*pSect) +{ + unsigned short wCache=pSect->dwSector>>TFFS_EXTF_CACHE_STEP; + +/* PrintkDebug("UncacheSect %lu to %lu",pSect->dwSector,pSect->dwSector>>TFFS_EXTF_CACHE_STEP); */ + + while(pDevice->pCache[wCache]==pSect) + { +/* PrintkDebug("UncacheSect: pCache[%u]=%lu",wCache,pSect->pNext->dwSector); */ + pDevice->pCache[wCache]=pSect->pNext; + wCache--; + } +} + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/extfiltr.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/extfiltr.h new file mode 100755 index 00000000..3dd6182d --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/extfiltr.h @@ -0,0 +1,43 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.4 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.4. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + +#ifndef __EXTFILTR__H__ +#define __EXTFILTR__H__ + +void ExtFilterInit(DeviceInfo*pDevice); +void ExtFilterRelease(DeviceInfo*pDevice); +void ExtFilter(DeviceInfo*pDevice,unsigned char*pBuff,unsigned long dwSector,unsigned long dwSectors); + +#endif /* __EXTFILTR__H__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fatfilt.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fatfilt.c new file mode 100755 index 00000000..e3958683 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fatfilt.c @@ -0,0 +1,1949 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/fatfilt.c-arc $ + * + * Rev 1.10 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.9 Feb 28 2007 09:53:46 einat.avidan + * No change + * + * Rev 1.8.1.1 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.8.1.0 Aug 08 2006 15:55:28 Polina.Marimont + * DOC Driver 1.0 initial + */ + +/******************************************************************************* + * * + * * + * Module: FATFILT * + * * + * This module implements installable FAT12/16 filters. It supports up to * + * SOCKETS sockets, with up to FL_MAX_TL_PARTITIONS disks per socket. * + * Each disk can contain up to FL_MAX_PARTS_PER_DISK partitions on it, with * + * maximum depth of partition nesting in extended partitions equal to * + * MAX_PARTITION_DEPTH. * + * * + * In order for this module to work, disks must be abs.mounted rather then * + * mounted. In latter case, this module won't detect any of disk's * + * partitions, and won't install FAT filters. * + * * + * This module uses more then 512 bytes of stack space in case if MALLOC is * + * not enabled. * + * * + *******************************************************************************/ + +/* + * Includes + */ + +#include "fatfilt.h" +#include "blockdev.h" +#include "defs.h" + + +#if defined(FL_ABS_READ_WRITE) && !defined(FL_READ_ONLY) + + + +/* + * Module configuration + */ + +#define FL_INCLUDE_FAT_MONITOR /* undefine it to remove FAT filter code */ +#undef FL_INCLUDE_FAT32 /* define after support for FAT32 is added */ +#define FL_DEL_SECTOR_SETS /* undefine to delete single cluster at a time */ +#undef FL_DEL_SECTOR_STATS /* gather sector deletion statistics */ + + + +/* + * Defines + */ + +/* extract pointer to user's buffer from IOreq */ + +#ifdef SCATTER_GATHER +#define FLBUF(ioreq,i) (*((FLSByte FAR1 **)((ioreq)->irData) + (int)(i))) +#else +#define FLBUF(ioreq,i) ((FLSByte FAR1 *)(ioreq->irData) + (FL_SECTOR_SIZE * ((int)(i)))) +#endif + +/* extract socket# and disk# from TFFS handle */ + +#define H2S(handle) (((int)(handle)) & 0xf) +#define H2D(handle) ((((int)(handle)) >> 4) & 0xf) + +/* construct TFFS handle from socket# and disk# */ + +#define SD2H(socNo,diskNo) ((int)((((diskNo) & 0xf) << 4) | ((socNo) & 0xf))) + +/* unformatted ("raw") disk partition */ + +#define FL_RAW_PART (-1) + + + +/* + * Global vars + */ + +#ifdef FL_DEL_SECTOR_SETS +FLBoolean del_sect_sets = TRUE; /* try to delete sectors in larger sets */ +#endif + + + + +/* + * Local routines + */ + +static FLStatus reset (void); +static FLStatus discardDisk (int handle); +static FLStatus newDisk (int handle); +static FLStatus parseDisk (int handle); +static FLStatus discardDiskParts (FLffDisk *pd); +static FLStatus addDiskPart (FLffDisk *pd, int partNo); +static FLStatus addNewDiskPart (FLffDisk *pd); +static FLBoolean isPartTableWrite (FLffDisk *pd, IOreq FAR2 *ioreq); +static FLStatus isExtPartPresent (FLSByte FAR1 *buf, SectorNo *nextExtPartSec); +static FLBoolean isBPBchanged (FLffVol *pv, FLSByte FAR1 *buf); + + +#ifdef FL_INCLUDE_FAT_MONITOR + +static FLStatus partEnableFF (FLffVol* pv); +static FLStatus partFreeDelClusters (FLffVol *pv, SectorNo secNo, + FLSByte FAR1 *newFAT, IOreq *ioreq_delete); + +#endif + + + + +/* + * Local data + */ + +/* module reset flag */ + +static FLBoolean resetDone = FALSE; + +/* disks (BDTL partitions in OSAK terminology) */ + +static FLffDisk* ffDisk[FL_SOCKETS][FL_MAX_TL_PARTITIONS] = { { NULL } }; + + +#ifndef FL_MALLOC + +/* + * WARNING: Large static arrays ! + * + * sizeof(ffAllDisks[x][y]) is 64 bytes. + * sizeof(ffAllParts[x][y][z]) is 40 bytes. + * + */ + +static FLffDisk ffAllDisks[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +static FLffVol ffAllParts[FL_SOCKETS][FL_MAX_TL_PARTITIONS][FL_MAX_PARTS_PER_DISK]; + +#endif /* FL_MALLOC */ + +static const FLSByte zeroes[FL_SECTOR_SIZE] = {0}; + +#if (defined(FL_DEL_SECTOR_SETS) && defined(FL_DEL_SECTOR_STATS)) +static FLDword del_sect_stats[16] = {0}; /* sector deletion statistics */ +#endif + + + + +/* --------------------------------------------------------------------------- * + * * + * d i s c a r d D i s k P a r t s * + * * + * Discard all the partition info (if any) associated with particular disk. * + * * + * Parameters: * + * pd : disk (BDTL volume) * + * * + * Returns: * + * Always flOK. * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus discardDiskParts ( FLffDisk * pd ) +{ + register int i; + + if (pd != NULL) { + + for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) { + +#ifdef FL_MALLOC + + if (pd->part[i] != NULL) { + + FL_FREE(pd->part[i]); + } +#endif + + pd->part[i] = NULL; + } + + pd->parts = 0; + } + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * a d d D i s k P a r t * + * * + * If there is partition record #partNo associated with the disk, discard * + * this info. Attach new partition record #partNo. * + * * + * Parameters: * + * pd : disk (BDTL volume) * + * partNo : partition (0 ... FL_MAX_PARTS_PER_DISK-1) * + * * + * Returns: * + * flOK if success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus addDiskPart ( FLffDisk * pd, + int partNo ) +{ + FLffVol * pv; + FLStatus status; + int socNo, diskNo; + + /* arg. sanity check */ + + if ((pd == NULL) || (partNo >= FL_MAX_PARTS_PER_DISK)) + return flBadDriveHandle; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(pd->handle); + diskNo = H2D(pd->handle); + + if ((socNo >= FL_SOCKETS) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + status = flNotEnoughMemory; + +#ifdef FL_MALLOC + pv = (FLffVol *)FL_MALLOC( sizeof(FLffVol) ); +#else + pv = &ffAllParts[socNo][diskNo][partNo]; +#endif + + if (pv != NULL) { + + /* initialize fields in struct FLffDisk to safe values */ + + pv->handle = pd->handle; + pv->type = FL_RAW_PART; + pv->flags = 0; + pv->ffEnabled = FALSE; /* turn off FAT minitor */ + pv->sectors = (SectorNo) 0; + pv->firstFATsecNo = (SectorNo) -1; /* none */ + pv->lastFATsecNo = pv->firstFATsecNo; /* none */ + pv->firstDataSecNo = (SectorNo) 0; + pv->clusterSize = (unsigned) 0; + +#ifdef FL_MALLOC + if( pd->part[partNo] != NULL ) { + + FL_FREE(pd->part[partNo]); + pd->part[partNo] = NULL; + } +#endif + pd->part[partNo] = pv; + + status = flOK; + } + + return status; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * a d d N e w D i s k P a r t * + * * + * Add one more partition record to the disk. * + * * + * Parameters: * + * pd : disk (BDTL volume) * + * * + * Returns: * + * flOK if success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus addNewDiskPart ( FLffDisk * pd ) +{ + if (pd->parts < FL_MAX_PARTS_PER_DISK) { + + checkStatus( addDiskPart (pd, pd->parts) ); + pd->parts++; + } + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * d i s c a r d D i s k * + * * + * Remove disk record (with all the associated partition records). * + * * + * Parameters: * + * handle : TFFS handle * + * * + * Returns: * + * flOK if success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus discardDisk ( int handle ) +{ + int socNo, diskNo; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= FL_SOCKETS) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + if( ffDisk[socNo][diskNo] != NULL ) { + + /* discard associated partition info */ + + (void) discardDiskParts( ffDisk[socNo][diskNo] ); + +#ifdef FL_MALLOC + + /* release disk's scratch buffer */ + + if( (ffDisk[socNo][diskNo])->buf != NULL) { + + FL_FREE( (ffDisk[socNo][diskNo])->buf ); + (ffDisk[socNo][diskNo])->buf = NULL; + } + + FL_FREE( ffDisk[socNo][diskNo] ); +#endif + + ffDisk[socNo][diskNo] = NULL; + } + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * n e w D i s k * + * * + * Discard existing disk record (if any), and create new one. * + * * + * Parameters: * + * handle : TFFS handle * + * * + * Returns: * + * flOK if success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus newDisk ( int handle ) +{ + int socNo, diskNo; + int i; + FLffDisk * pd; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= FL_SOCKETS) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* discard current disk and associated partition info (if any) */ + + checkStatus( discardDisk(handle) ); + +#ifdef FL_MALLOC + + pd = (FLffDisk *) FL_MALLOC( sizeof(FLffDisk) ); + + if (pd == NULL) + return flNotEnoughMemory; + + /* allocate and attach disk's scratch buffer */ + + pd->buf = (FLSByte *)FL_MALLOC( FL_SECTOR_SIZE ); + + if (pd->buf == NULL) { + + FL_FREE (pd); + pd = NULL; + return flNotEnoughMemory; + } + +#else /* !FL_MALLOC */ + + pd = &ffAllDisks[socNo][diskNo]; + +#endif /* FL_MALLOC */ + + + pd->handle = handle; + pd->ffstate = flStateNotInitialized; + + /* don't know partition layout yet */ + + pd->parts = 0; + for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) + pd->part[i] = NULL; + + /* watch Master Boot Record for update */ + + pd->secToWatch = (SectorNo) 0; + + ffDisk[socNo][diskNo] = pd; + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * i s P a r t T a b l e W r i t e * + * * + * Check if any of the sectors specified by 'ioreq' points to Master Boot * + * Record or next extended partition in the extended partitions list. * + * * + * Parameters: * + * pd : pointer to disk structure * + * ioreq : standard I/O request * + * * + * Returns: * + * TRUE if write to MBR or extended partition list is detected, otherwise * + * FALSE * + * * + * --------------------------------------------------------------------------- */ + +static FLBoolean isPartTableWrite ( FLffDisk * pd, + IOreq FAR2 * ioreq ) +{ + register FLSDword i; + + if (pd != NULL) { + + for (i = (FLSDword)0; i < ioreq->irSectorCount; i++) { + + if( (ioreq->irSectorNo + i) == (FLSDword)pd->secToWatch ) + return TRUE; + } + } + + return FALSE; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * i s E x t P a r t P r e s e n t * + * * + * Check if extended partition persent in the partition table. If it is, * + * calculate the sector # where next partition table will be written to. * + * * + * Parameters: * + * buf : partition table * + * nextExtPartSec : sector where next partition table will be written to * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus isExtPartPresent ( FLSByte FAR1 * buf, + SectorNo * nextExtPartSec ) +{ + Partition FAR1 * p; + register int i; + + /* does it look like partition table ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (LE2(((PartitionTable FAR1 *) buf)->signature) != PARTITION_SIGNATURE) +#else + if (FL_GET_LE2(buf, FL_PARTITION_TABLE_SIGNATURE_OFFSET) != PARTITION_SIGNATURE) +#endif + return flBadFormat; + + /* if extended. part. present, get sector# that will contain next part. in list */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + p = &( ((PartitionTable FAR1 *) buf)->ptEntry[0] ); +#else + p = (Partition *) &FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET ); +#endif + + for (i = 0; i < FL_PART_TBL_ENTRIES; i++) { + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (p->type == EX_PARTIT) { + *nextExtPartSec = (SectorNo) UNAL4( p[i].startingSectorOfPartition ); +#else + if (FL_REF_1(p, FL_PARTITION_TYPE_OFFSET) == EX_PARTIT) { + *nextExtPartSec = (SectorNo) FL_GET_UNAL4(p, i* FL_PARTITION_SIZE + FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET ); +#endif + return flOK; + } + } + + /* no extended partition found */ + + return flFileNotFound; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * i s B P B c h a n g e d * + * * + * Check if critical fields in partition's boot sector have been changed. * + * * + * Parameters: * + * pv : disk partition (filesystem volume) * + * buf : new contents of partition's boot sector * + * * + * Returns: * + * TRUE if critical fields in BPB have been changed, otherwise FALSE * + * * + * --------------------------------------------------------------------------- */ + +static FLBoolean isBPBchanged ( FLffVol * pv, FLSByte FAR1 * buf ) +{ + BPB FAR1 * bpb; + SectorNo sectors; + SectorNo firstFATsecNo; + SectorNo lastFATsecNo; + SectorNo rootDirSecNo; + SectorNo rootDirSectors; + SectorNo sectorsPerFAT; + SectorNo firstDataSecNo; + + /* if FAT monitor already inactive on this partition, do nothing and return */ + + if (pv->ffEnabled == FALSE) + return FALSE; + + /* we only handle 512-byte sectors */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + bpb = &( ((DOSBootSector FAR1 *) buf)->bpb ); + + if( UNAL2(bpb->bytesPerSector) != FL_SECTOR_SIZE ) + return TRUE; + + /* check if 'number of sectors in partition' has been changed */ + + sectors = UNAL2( bpb->totalSectorsInVolumeDOS3 ); + + if (sectors == (SectorNo)0) + sectors = (SectorNo) LE4( bpb->totalSectorsInVolume ); +#else + bpb = (BPB FAR1 *) buf; + + if( FL_GET_UNAL2(bpb, FL_BPB_BYTES_PER_SECTOR_OFFSET) != FL_SECTOR_SIZE ) + return TRUE; + + /* check if 'number of sectors in partition' has been changed */ + + sectors = FL_GET_UNAL2(bpb, FL_BPB_TOTAL_SECTORS_IN_VOL_DOS3_OFFSET ); + + if (sectors == (SectorNo)0) + sectors = (SectorNo) FL_GET_LE4(bpb, FL_BPB_TOTAL_SECTORS_IN_VOL_OFFSET ); +#endif + + if (sectors != pv->sectors) + return TRUE; + + /* check if 'FAT's starting sector #' has been changed */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + firstFATsecNo = pv->startSecNo + (SectorNo)( LE2(bpb->reservedSectors) ); +#else + firstFATsecNo = pv->startSecNo + (SectorNo)( FL_GET_LE2(bpb, FL_BPB_RESERVED_SECTORS_OFFSET) ); +#endif + + if (firstFATsecNo != pv->firstFATsecNo) + return TRUE; + + /* check if 'FAT's ending sector #' has been changed */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + sectorsPerFAT = (SectorNo) LE2( bpb->sectorsPerFAT ); +#else + sectorsPerFAT = (SectorNo) FL_GET_LE2(bpb, FL_BPB_SECTORS_PER_FAT_OFFSET ); +#endif + + lastFATsecNo = firstFATsecNo + sectorsPerFAT - (SectorNo)1; + + if (lastFATsecNo != pv->lastFATsecNo) + return TRUE; + + /* check if 'first data sector #' has been changed */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + rootDirSecNo = firstFATsecNo + (sectorsPerFAT * bpb->noOfFATS); + + rootDirSectors = (SectorNo)1 + (SectorNo) + (((UNAL2(bpb->rootDirectoryEntries) * DIRECTORY_ENTRY_SIZE) - 1) / FL_SECTOR_SIZE); +#else + rootDirSecNo = firstFATsecNo + (sectorsPerFAT * FL_REF_1(bpb, FL_BPB_NO_OF_FATS_OFFSET)); + + rootDirSectors = (SectorNo)1 + (SectorNo) + (((FL_GET_UNAL2(bpb, FL_BPB_ROOT_DIR_ENTRIES_OFFSET) * DIRECTORY_ENTRY_SIZE) - 1) / FL_SECTOR_SIZE); +#endif + + firstDataSecNo = rootDirSecNo + rootDirSectors; + + if (firstDataSecNo != pv->firstDataSecNo) + return TRUE; + + /* check if cluster size has been changed */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (pv->clusterSize != bpb->sectorsPerCluster) +#else + if (pv->clusterSize != FL_REF_1(bpb, FL_BPB_SECTORS_PER_CLUSTER_OFFSET)) +#endif + return TRUE; + + return FALSE; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * r e s e t * + * * + * Resets this software module to it's initial state upon boot. * + * * + * Parameters: * + * none * + * * + * Returns: * + * flOK in case of success, otherwise respective error code * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus reset (void) +{ + int iSoc, iDisk; + + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) { + + /* discard existing disk structures for that socket */ + + for (iDisk = 0; iDisk < FL_MAX_TL_PARTITIONS; iDisk++) + (void) discardDisk( SD2H(iSoc, iDisk) ); + + /* pre-allocate disk structure for first disk of every socket */ + + checkStatus( newDisk(SD2H(iSoc, 0)) ); + } + + resetDone = TRUE; + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * p a r s e D i s k * + * * + * Read partition table(s), install and enable FAT filters on all FAT12/16 * + * partitions. * + * * + * Parameters: * + * handle : TFFS handle * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * NOTE: This routine uses disk's scratch buffer. * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus parseDisk ( int handle ) +{ + int socNo, diskNo; + SectorNo extPartStartSec, sec; + int i, depth; + int type; + FLffDisk * pd; + FLffVol * pv; + Partition * pp; + IOreq ioreq; + +#ifdef FL_MALLOC + FLSByte * buf; +#else + FLSByte buf[FL_SECTOR_SIZE]; +#endif + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* if disk structure hasn't been allocated yet, do it now */ + + if (ffDisk[socNo][diskNo] == NULL) + checkStatus( newDisk(handle) ); + + pd = ffDisk[socNo][diskNo]; + +#ifdef FL_MALLOC + + /* make sure scratch buffer is available */ + + if (pd->buf == NULL) + return flBufferingError; + + buf = pd->buf; + +#endif /* FL_MALLOC */ + + /* discard obsolete disk's partition info */ + + (void) discardDiskParts (pd); + + /* read Master Boot Record */ + + ioreq.irHandle = handle; + ioreq.irSectorNo = (SectorNo) 0; + ioreq.irSectorCount = (SectorNo) 1; + ioreq.irData = (void FAR1 *) buf; + checkStatus( flAbsRead(&ioreq) ); + + /* is it MBR indeed ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE) +#else + if (FL_GET_LE2(buf, FL_PARTITION_TABLE_SIGNATURE_OFFSET) != PARTITION_SIGNATURE) +#endif + return flPartitionNotFound; + + /* do primary partitions only (we will do extended partitions later) */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pp = &( ((PartitionTable *) buf)->ptEntry[0] ); +#else + pp = (Partition *) &FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET ); +#endif + + for (i = 0; i < FL_PART_TBL_ENTRIES; i++, pp++) { +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + FLByte ppType = pp->type; +#else + FLByte ppType = FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET); +#endif + + if( ppType == ((FLSByte)0) ) /* skip empty slot */ + continue; + + if( ppType == ((FLSByte)EX_PARTIT) ) /* skip extended partition */ + continue; + + /* primary partition found (not necessarily FAT12/16) */ + + if( addNewDiskPart(pd) != flOK ) + break; + + pv = pd->part[pd->parts - 1]; + + /* remember partition's type, and where it starts */ + + pv->type = (int) ppType; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pv->startSecNo = (SectorNo) UNAL4( pp->startingSectorOfPartition ); +#else + pv->startSecNo = (SectorNo) FL_GET_UNAL4(pp, FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET ); +#endif + } + + /* do extended partitions in depth */ + + for (i = 0; i < FL_PART_TBL_ENTRIES; i++) { + + /* re-read Master Boot Record */ + + ioreq.irHandle = handle; + ioreq.irSectorNo = (SectorNo) 0; + ioreq.irSectorCount = (SectorNo) 1; + ioreq.irData = (void FAR1 *) buf; + checkStatus( flAbsRead(&ioreq) ); + + /* is it MBR indeed ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE) +#else + if (FL_GET_LE2(buf, FL_PARTITION_TABLE_SIGNATURE_OFFSET) != PARTITION_SIGNATURE) +#endif + return flOK; + + /* pick up next extended partition in MBR */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pp = &( ((PartitionTable *) buf)->ptEntry[i] ); + + if( pp->type == ((FLSByte)EX_PARTIT) ) { + + /* remember where extended partition starts */ + + extPartStartSec = (SectorNo) UNAL4( pp->startingSectorOfPartition ); +#else + pp = (Partition *)&FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET + FL_PARTITION_SIZE*i); + + if( FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET) == ((FLSByte)EX_PARTIT) ) { + + /* remember where extended partition starts */ + + extPartStartSec = (SectorNo) FL_GET_UNAL4(pp, FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET ); +#endif + + /* follow the list of partition tables */ + + sec = extPartStartSec; + + for (depth = 0; depth < FL_MAX_PARTITION_DEPTH; depth++) { + + /* read next partition table in the list */ + + ioreq.irHandle = handle; + ioreq.irSectorNo = sec; + ioreq.irSectorCount = (SectorNo) 1; + ioreq.irData = (void FAR1 *) buf; + checkStatus( flAbsRead(&ioreq) ); + + /* is it valid partition table ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (LE2(((PartitionTable *) buf)->signature) != PARTITION_SIGNATURE) +#else + if (FL_GET_LE2(buf, FL_PARTITION_TABLE_SIGNATURE_OFFSET) != PARTITION_SIGNATURE) +#endif + break; + + /* if 1st entry is zero, it's the end of part. table list */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pp = &( ((PartitionTable *) buf)->ptEntry[0] ); + if( pp->type == ((FLSByte)0) ) +#else + pp = (Partition *) &FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET ); + if( FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET) == ((FLSByte)0) ) +#endif + break; + + /* Take this partition. Remember it's type, and where it starts */ + + if( addNewDiskPart(pd) != flOK ) + break; + + pv = pd->part[pd->parts - 1]; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pv->type = (int) pp->type; + pv->startSecNo = + (SectorNo) UNAL4( pp->startingSectorOfPartition) + sec; +#else + pv->type = (int) FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET); + pv->startSecNo = + (SectorNo) FL_GET_UNAL4(pp, FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET) + sec; +#endif + + /* 2nd entry must be extended partition */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pp = &( ((PartitionTable *) buf)->ptEntry[1] ); + if( pp->type != ((FLSByte)EX_PARTIT) ) +#else + pp = (Partition *) &FL_REF_1(buf, FL_PARTITION_TABLE_PT_ENTRY_OFFSET + FL_PARTITION_SIZE ); + if( FL_REF_1(pp, FL_PARTITION_TYPE_OFFSET) != ((FLSByte)EX_PARTIT) ) +#endif + break; + + /* sector where next part. table in the list resides */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + sec = extPartStartSec + + (SectorNo) UNAL4( pp->startingSectorOfPartition ); +#else + sec = extPartStartSec + + (SectorNo) FL_GET_UNAL4(pp, FL_PARTITION_STARTING_SECTOR_OF_PARTITION_OFFSET ); +#endif + + } /* for(depth) */ + } + } /* for(i) */ + +#ifdef FL_INCLUDE_FAT_MONITOR + + /* turn on FAT filters on FAT12/16 partition(s) */ + + if (pd->parts > 0) { + + for (i = 0; i < pd->parts; i++) { + + pv = pd->part[i]; + type = pv->type; + + /* + * WARNING : Routine partEnableFF() uses disk's scratch buffer ! + */ + + if((type == FAT12_PARTIT) || (type == FAT16_PARTIT) || (type == DOS4_PARTIT)) + partEnableFF (pv); + } + } + +#endif /* FL_INCLUDE_FAT_MONITOR */ + + /* watch for MBR (sector #0) update */ + + pd->secToWatch = (SectorNo) 0; + + pd->ffstate = flStateInitialized; + + return flOK; +} + + + + +#ifdef FL_INCLUDE_FAT_MONITOR + +/* --------------------------------------------------------------------------- * + * * + * p a r t E n a b l e F F * + * * + * Installs and enables FAT filter on partition. * + * * + * Parameters: * + * pv : disk partition (filesystem volume) * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * NOTE: This routine uses disk's scratch buffer. * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus partEnableFF ( FLffVol * pv ) +{ + int socNo, diskNo; + FLffDisk * pd; + BPB * bpb; + SectorNo sectors; + SectorNo reservedSectors; + SectorNo rootDirSecNo; + SectorNo rootDirSectors; + SectorNo sectorsPerFAT; + SectorNo rootDirEntries; + unsigned maxCluster; + int partNo; + IOreq ioreq; + +#ifdef FL_MALLOC + FLSByte * buf; +#else + FLSByte buf[FL_SECTOR_SIZE]; +#endif + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) checking FAT type.\r\n"); + + /* arg. sanity check */ + + if (pv == NULL) + return flBadDriveHandle; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(pv->handle); + diskNo = H2D(pv->handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* check if 'pv' belongs to this disk */ + + pd = ffDisk[socNo][diskNo]; + + if (pd == NULL) + return flBadDriveHandle; + + for (partNo = 0; partNo < pd->parts; partNo++) { + + if (pd->part[partNo] == pv) + break; + } + + if (partNo >= pd->parts) + return flBadDriveHandle; + +#ifdef FL_MALLOC + + /* make sure scratch buffer is available */ + + if (pd->buf == NULL) + return flBufferingError; + + buf = pd->buf; + +#endif /* FL_MALLOC */ + + /* make sure FAT filter is off on this partition */ + + pv->ffEnabled = FALSE; + + pv->firstFATsecNo = (SectorNo) -1; + pv->lastFATsecNo = pv->firstFATsecNo; + pv->clusterSize = (unsigned) 0; + + /* read BPB */ + + ioreq.irHandle = pv->handle; + ioreq.irSectorNo = pv->startSecNo; + ioreq.irSectorCount = (SectorNo) 1; + ioreq.irData = (void FAR1 *) buf; + checkStatus( flAbsRead(&ioreq) ); + + /* Does it look like DOS bootsector ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + + bpb = &( ((DOSBootSector *) buf)->bpb ); + + if( !((bpb->jumpInstruction[0] == 0xe9) + || + ((bpb->jumpInstruction[0] == 0xeb) && (bpb->jumpInstruction[2] == 0x90)))) { +#else + + bpb = (BPB *) buf; + + if( !((FL_REF_1(bpb, FL_BPB_JUMP_INSTRUCTION_OFFSET) == 0xe9) + || + ((FL_REF_1(bpb, FL_BPB_JUMP_INSTRUCTION_OFFSET) == 0xeb) && (FL_REF_1(bpb, FL_BPB_JUMP_INSTRUCTION_OFFSET + 2) == 0x90)))) { +#endif + return flNonFATformat; + } + + /* Do we handle this sector size ? */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + if (UNAL2(bpb->bytesPerSector) != FL_SECTOR_SIZE) +#else + if (FL_GET_UNAL2(bpb, FL_BPB_BYTES_PER_SECTOR_OFFSET) != FL_SECTOR_SIZE) +#endif + return flFormatNotSupported; + + /* + * Is it a bogus BPB (leftover from previous disk partitioning) ? + * Check that there is no overlap with next partition (if one exists). + */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + sectors = UNAL2(bpb->totalSectorsInVolumeDOS3); + + if (sectors == (SectorNo)0) + sectors = (SectorNo) LE4(bpb->totalSectorsInVolume); +#else + sectors = FL_GET_UNAL2(bpb, FL_BPB_TOTAL_SECTORS_IN_VOL_DOS3_OFFSET); + + if (sectors == (SectorNo)0) + sectors = (SectorNo) FL_GET_LE4(bpb, FL_BPB_TOTAL_SECTORS_IN_VOL_OFFSET); +#endif + + if ((partNo+1 < pd->parts) && (pd->part[partNo+1] != NULL)) { + + if( sectors > (pd->part[partNo+1])->startSecNo - pv->startSecNo ) + return flNonFATformat; + } + + /* number of sectors in partition as reported by BPB */ + + pv->sectors = sectors; + + /* get number of reserved sectors from BPB, and check it's sanity */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + reservedSectors = (SectorNo) LE2(bpb->reservedSectors); +#else + reservedSectors = (SectorNo) FL_GET_LE2(bpb, FL_BPB_RESERVED_SECTORS_OFFSET); +#endif + + switch( (int)reservedSectors ) { + + case 32: /* always the case with FAT 32 */ + +#ifndef FL_INCLUDE_FAT32 + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT32 detected.\r\n"); + return flFormatNotSupported; +#endif + + case 1: /* must always be the case for FAT 12 and FAT16 */ + default: + + break; + } + + /* get location and size of the first FAT copy */ + + pv->firstFATsecNo = pv->startSecNo + reservedSectors; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + sectorsPerFAT = (SectorNo) LE2(bpb->sectorsPerFAT); +#else + sectorsPerFAT = (SectorNo) FL_GET_LE2(bpb, FL_BPB_SECTORS_PER_FAT_OFFSET); +#endif + +#ifndef FL_INCLUDE_FAT32 + + if (sectorsPerFAT == 0) { /* always the case with FAT32 */ + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT32 detected.\r\n"); + return flFormatNotSupported; + } + +#endif + + pv->lastFATsecNo = pv->firstFATsecNo + sectorsPerFAT - (SectorNo)1; + + /* get location and size of root directory */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + rootDirSecNo = pv->firstFATsecNo + (sectorsPerFAT * bpb->noOfFATS); + + rootDirEntries = (SectorNo) UNAL2(bpb->rootDirectoryEntries); +#else + rootDirSecNo = pv->firstFATsecNo + (sectorsPerFAT * (FL_REF_1(bpb, FL_BPB_NO_OF_FATS_OFFSET))); + + rootDirEntries = (SectorNo) FL_GET_UNAL2(bpb, FL_BPB_ROOT_DIR_ENTRIES_OFFSET); +#endif + + switch (rootDirEntries) { + +#ifndef FL_INCLUDE_FAT32 + + case 0: /* always the case with FAT32 */ + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT32 detected.\r\n"); + return flFormatNotSupported; +#endif + + default: + + if( ((rootDirEntries * DIRECTORY_ENTRY_SIZE) % FL_SECTOR_SIZE) != 0 ) + return flNonFATformat; + break; + } + + rootDirSectors = (SectorNo)(((rootDirEntries * DIRECTORY_ENTRY_SIZE) - 1) / FL_SECTOR_SIZE) + + (SectorNo)1; + + /* get location of data area */ + + pv->firstDataSecNo = rootDirSecNo + rootDirSectors; + + /* get size of FAT cluster in sectors, and check it's sanity */ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED + pv->clusterSize = bpb->sectorsPerCluster; +#else + pv->clusterSize = FL_REF_1(bpb, FL_BPB_SECTORS_PER_CLUSTER_OFFSET); +#endif + + switch( (int)pv->clusterSize ) { + + case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: + break; + + default: + return flNonFATformat; + } + + if ((pv->clusterSize << FL_SECTOR_SIZE_BITS) > (32768 /*(32 * 1024)*/)) + return flFormatNotSupported; + + /* sanity check */ + + if( (pv->lastFATsecNo < pv->firstFATsecNo) || + (pv->firstDataSecNo <= pv->lastFATsecNo) || + (pv->sectors < pv->firstDataSecNo) ) + return flNonFATformat; + + + /* decide which type of FAT is it */ + + maxCluster = (unsigned)1 + (unsigned) + ((pv->sectors - (pv->firstDataSecNo - pv->startSecNo)) / pv->clusterSize); + + if (maxCluster < 4085) { + + pv->flags |= VOLUME_12BIT_FAT; /* 12-bit FAT */ + +#ifndef FS_FAT_12BIT + + DBG_PRINT_ERR(FLZONE_FS,"ERROR - FS_FAT_12BIT must be defined.\r\n"); + return flFormatNotSupported; + +#else + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT12 detected.\r\n"); + +#endif /* FS_FAT_12BIT */ + } + else { + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (partEnableFF) FAT16 detected.\r\n"); + } + + /* turn on FAT filter on this partition */ + + pv->ffEnabled = TRUE; + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * p a r t F r e e D e l C l u s t e r s * + * * + * Compare the new contents of the specified FAT sector against the old * + * one on the disk. If any freed clusters are found, issue 'sector delete' * + * calls for all sectors that are occupied by these freed clusters. * + * * + * Parameters: * + * pv : disk partition (filesystem volume) * + * secNo : abs. sector # of the FAT sector * + * newFAT : new contents of this FAT sector * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * NOTE: This routine uses disk's scratch buffer. * + * * + * --------------------------------------------------------------------------- */ + +static FLStatus partFreeDelClusters ( FLffVol * pv, + SectorNo secNo, + FLSByte FAR1 * newFAT, + IOreq * ioreq_delete ) +{ + FLffDisk * pd; + int socNo, diskNo; + FLWord oldFATentry, newFATentry; + SectorNo iSec; + unsigned firstCluster; + IOreq ioreq; + int offset; + int iPart; + +#ifdef FS_FAT_12BIT + int halfBytes; +#endif + +#ifdef FL_MALLOC + FLSByte * oldFAT; +#else + FLSByte oldFAT[FL_SECTOR_SIZE]; +#endif + + /* arg. sanity check */ + + if (pv == NULL) + return flBadDriveHandle; + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(pv->handle); + diskNo = H2D(pv->handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* check if 'pv' belongs to this disk */ + + pd = ffDisk[socNo][diskNo]; + + if (pd == NULL) + return flBadDriveHandle; + + for (iPart = 0; iPart < pd->parts; iPart++) { + + if (pd->part[iPart] == pv) + break; + } + + if (iPart >= pd->parts) + return flBadDriveHandle; + +#ifdef FL_MALLOC + + /* make sure scratch buffer is available */ + + if (pd->buf == NULL) + return flBufferingError; + + oldFAT = pd->buf; + +#endif /* FL_MALLOC */ + + /* read in the FAT sector from the disk */ + + ioreq.irHandle = pv->handle; + ioreq.irSectorNo = secNo; + ioreq.irSectorCount = 1; + ioreq.irData = (void FAR1 *) oldFAT; + checkStatus( flAbsRead(&ioreq) ); + +#ifdef FS_FAT_12BIT + + /* size of FAT entry in half-bytes */ + + halfBytes = ((pv->flags & VOLUME_12BIT_FAT) ? 3 : 4); + + /* starting cluster */ + + if (halfBytes == 3) { + + firstCluster = + ((((unsigned)(secNo - pv->firstFATsecNo)) * (2 * FL_SECTOR_SIZE)) + 2) / 3; + } + else { + + firstCluster = ((unsigned)(secNo - pv->firstFATsecNo)) * (FL_SECTOR_SIZE / 2); + } + + /* starting data sector */ + + iSec = (((SectorNo)firstCluster - 2) * pv->clusterSize) + pv->firstDataSecNo; + + offset = (firstCluster * ((unsigned) halfBytes)) & ((2 * FL_SECTOR_SIZE) - 1); + + /* + * Find if any clusters were logically deleted, and if so, delete them. + * + * NOTE: We are skipping over 12-bit FAT entries which span more than + * one sector. + */ + + for (; offset < ((2 * FL_SECTOR_SIZE) - 2); + offset += halfBytes, iSec += pv->clusterSize) { + + oldFATentry = UNAL2( *(Unaligned FAR0 *)(oldFAT + (offset / 2)) ); + newFATentry = UNAL2( *(Unaligned FAR1 *)(newFAT + (offset / 2)) ); + + if (offset & 1) { + oldFATentry >>= 4; + newFATentry >>= 4; + } + else { + if (halfBytes == 3) { + oldFATentry &= 0xfff; + newFATentry &= 0xfff; + } + } + +#else /* !FS_FAT_12BIT */ + + firstCluster = ((unsigned) (secNo - pv->firstFATsecNo) * (FL_SECTOR_SIZE / 2)); + iSec = pv->firstDataSecNo + + (((SectorNo)(firstCluster - (unsigned)2)) * pv->clusterSize); + + /* Find if any clusters were logically deleted, and if so, delete them */ + + for (offset = 0; offset < FL_SECTOR_SIZE; offset += 2, iSec += pv->clusterSize) { + + oldFATentry = LE2( *(LEushort FAR0 *)(oldFAT + offset) ); + newFATentry = LE2( *(LEushort FAR1 *)(newFAT + offset) ); + +#endif /* FS_FAT_12BIT */ + + if ((oldFATentry != FAT_FREE) && (newFATentry == FAT_FREE)) { + +#ifdef FL_DEL_SECTOR_SETS + + if (del_sect_sets == TRUE) { + + /* Rather then deleting this cluster's sectors immediately, we try to + * accumulate as many consecutive clusters as only possible before + * calling flAbsDelete(). The hope here is that the underlaying + * TL will be able to handle deletion of larger sets of + * consecutive sectors more efficiently. + */ + + if ((SectorNo)(ioreq_delete->irSectorNo + ioreq_delete->irSectorCount) == iSec) { + + ioreq_delete->irSectorCount += pv->clusterSize; + } + else { + + if (ioreq_delete->irSectorNo != (SectorNo)(-1)) { + +#ifdef FL_DEL_SECTOR_STATS + { register int x = -1, S = (int)(ioreq_delete->irSectorCount); + while (S != 0) { x++; S >>= 1; } + if ((x >= 0) && (x < (sizeof(del_sect_stats)/sizeof(del_sect_stats[0])))) { del_sect_stats[x]++; } + } +#endif + flAbsDelete (ioreq_delete); + } + + ioreq_delete->irSectorNo = iSec; + ioreq_delete->irSectorCount = pv->clusterSize; + } + } + else + +#endif /* FL_DEL_SECTOR_SETS */ + + { /* delete one FAT cluster at a time */ + + ioreq_delete->irHandle = pv->handle; + ioreq_delete->irSectorNo = iSec; + ioreq_delete->irSectorCount = pv->clusterSize; + flAbsDelete (ioreq_delete); + } + } + } + + return flOK; +} + +#endif /* FL_INCLUDE_FAT_MONITOR */ + + + + +/* --------------------------------------------------------------------------- * + * * + * f f C h e c k B e f o r e W r i t e * + * * + * Catch all the FAT updates. Detect disk partitioning operation, track it * + * to completion, re-read partition tables, and re-install FAT filters on * + * all FAT12/16 partitions. * + * * + * Parameters: * + * ioreq : standard I/O request to be checked * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * --------------------------------------------------------------------------- */ + +FLStatus ffCheckBeforeWrite ( IOreq FAR2 * ioreq ) +{ + int socNo, diskNo; + FLffDisk * pd; + FLffVol * pv; + FLSDword iSec; + int iPart; + IOreq ioreq2; + FLSByte FAR1 * usrBuf; + + /* if module hasn't been reset yet, do it now */ + + if (resetDone == FALSE) + (void) reset(); + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(ioreq->irHandle); + diskNo = H2D(ioreq->irHandle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* if disk structure hasn't been allocated yet, do it now */ + + if (ffDisk[socNo][diskNo] == NULL) + checkStatus( newDisk((int)ioreq->irHandle) ); + + pd = ffDisk[socNo][diskNo]; + + /* read partition table(s) and install FAT filters is needed */ + + if (pd->ffstate == flStateNotInitialized) + checkStatus( parseDisk((int)ioreq->irHandle) ); + + /* catch writes to MBR, and track the whole disk partitioning operations */ + + while( isPartTableWrite(pd, ioreq) == TRUE ) { + + /* disk re-partitioning is in progress */ + + if( pd->secToWatch == (SectorNo)0 ) { + + /* it's write to MBR, so trash BPBs in all disk's partitions */ + + if (pd->parts > 0) { + + for (iPart = 0; iPart < pd->parts; iPart++) { + + ioreq2.irHandle = ioreq->irHandle; + ioreq2.irSectorNo = (pd->part[iPart])->startSecNo; + ioreq2.irSectorCount = (SectorNo) 1; + ioreq2.irData = (void FAR1 *) zeroes; + (void) flAbsWrite(&ioreq2); + } + } + } + + /* keep FAT filters disabled while disk partitioning is in progress */ + + pd->ffstate = flStateInitInProgress; + + /* partition table which is about to be written to disk */ + + usrBuf = FLBUF( ioreq, (pd->secToWatch - ioreq->irSectorNo) ); + + switch( isExtPartPresent(usrBuf, &(pd->secToWatch)) ) { + + case flOK: + + /* + * Found valid partition table with extended partition. + * The pd->secToWatch has been updated to point to the + * sector where next partition table will be written to. + */ + continue; + + case flFileNotFound: + + /* + * Valid partition table, but no extended partition in it. + * Partitioning has been completed. Set pd->ffstate to + * 'flStateNotInitialized' to initiate parsing of partition + * table(s) and FAT filter installation next time this routine + * is called. + */ + + pd->ffstate = flStateNotInitialized; + break; + + case flBadFormat: + default: + + /* No valid partition table. */ + + break; + } + + return flOK; + } + +#ifdef FL_INCLUDE_FAT_MONITOR + + /* check for FAT update */ + + if (pd->ffstate == flStateInitialized) { + +#ifdef FL_DEL_SECTOR_SETS + + if (del_sect_sets == TRUE) { + + ioreq2.irHandle = ioreq->irHandle; + ioreq2.irSectorNo = (FLSDword)(-1); + ioreq2.irSectorCount = 0; + } +#endif + + /* NOTE: We can handle 'write' request that spans disk partition boundaries */ + + for (iSec = ioreq->irSectorNo; + iSec < (ioreq->irSectorNo + ioreq->irSectorCount); iSec++) { + + for (iPart = 0; iPart < pd->parts; iPart++) { + + pv = pd->part[iPart]; + + /* we monitor only FAT12/16 partitions */ + + if ((pv->type != FAT12_PARTIT) && (pv->type != FAT16_PARTIT) && + (pv->type != DOS4_PARTIT)) + continue; + + /* FAT filters can be disabled on individual partitions */ + + if (pv->ffEnabled != TRUE) + continue; + + if (iSec == (FLSDword)pv->startSecNo) { + + /* partition's boot sector is being updated */ + + usrBuf = FLBUF( ioreq, (iSec - ioreq->irSectorNo) ); + + if( isBPBchanged(pv, usrBuf) == TRUE ) { + + /* + * Critical fields in partition's boot sector have been changed. + * Turn off FAT monitor on this partition. + */ + + pv->ffEnabled = FALSE; + + DBG_PRINT_FLOW(FLZONE_FS,"Debug: (ffCheckBeforeWrite) BPB update detected.\r\n"); + continue; + } + } + + if ((iSec >= (FLSDword)pv->firstFATsecNo) && (iSec <= (FLSDword)pv->lastFATsecNo)) { + + /* + * Compare new and old contents of FAT sectors(s). If freed + * sectors are detected, add then to ioreq2. + */ + + usrBuf = FLBUF( ioreq, (iSec - ioreq->irSectorNo) ); + + checkStatus( partFreeDelClusters(pv, iSec, usrBuf, &ioreq2) ); + } + } /* for(iPart) */ + } /* for(iSec) */ + +#ifdef FL_DEL_SECTOR_SETS + + if ((del_sect_sets == TRUE) && (ioreq2.irSectorNo != (SectorNo)(-1))) { + +#ifdef FL_DEL_SECTOR_STATS + { register int x = -1, S = (int)(ioreq2.irSectorCount); + while (S != 0) { x++; S >>= 1; } + if ((x >= 0) && (x < (sizeof(del_sect_stats)/sizeof(del_sect_stats[0])))) { del_sect_stats[x]++; } + } +#endif + flAbsDelete (&ioreq2); + } + +#endif /* FL_DEL_SECTOR_SETS */ + } + +#endif /* FL_INCLUDE_FAT_MONITOR */ + + return flOK; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * f l f f C o n t r o l * + * * + * Enable/disable/install FAT filters. See comments inside the routine for * + * the list of supported operations. * + * * + * Parameters: * + * handle : TFFS handle * + * partNo : partition # (0 .. FL_MAX_PARTS_PER_DISK) * + * state : see list of supported operations below * + * * + * Returns: * + * flOK on success, otherwise error code * + * * + * --------------------------------------------------------------------------- * + * * + * The following FAT monitor control requests are supported: * + * * + * state : flStateNotInitialized * + * partNo : [0 ... pd->parts-1] * + * action : turn off FAT monitor on specified partition * + * * + * state : flStateNotInitialized * + * partNo : < 0 * + * action : turn off FAT monitor on all partitions * + * * + * state : flStateInitialized * + * partNo : [0 ... pd->parts-1] * + * action : if FAT monitor has been installed on specified partition, * + * turn it on * + * * + * state : flStateInitInProgress * + * partNo : ignored * + * action : re-read partition table(s), and install FAT filters on all * + * partitions * + * * + * --------------------------------------------------------------------------- */ + +FLStatus flffControl ( int handle, + int partNo, + FLState state ) +{ + int socNo, diskNo; + FLffDisk * pd; + int i; + FLStatus status; + + /* if module hasn't been reset yet, do it now */ + + if (resetDone == FALSE) + (void) reset(); + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return flBadDriveHandle; + + /* if disk structure hasn't been allocated yet, do it now */ + + if (ffDisk[socNo][diskNo] == NULL) + checkStatus( newDisk(handle) ); + + pd = ffDisk[socNo][diskNo]; + + /* abort if disk re-partitioning is in progress */ + + if (pd->ffstate == flStateInitInProgress) + return flDriveNotReady; + + /* read partition table(s) and install FAT filters is needed */ + + if (pd->ffstate == flStateNotInitialized) { + + if (state == flStateNotInitialized) + return flOK; + + checkStatus( parseDisk(handle) ); + } + + /* check 'partNo' arguement for sanity */ + + if ((partNo >= pd->parts) || (partNo >= FL_MAX_PARTS_PER_DISK)) + return flBadDriveHandle; + + /* do requested operation */ + + status = flBadParameter; + + switch (state) { + + case flStateInitInProgress: + + /* read partition table(s), install FAT filters on all partitions */ + + pd->ffstate = flStateNotInitialized; + status = parseDisk(handle); + break; + + case flStateNotInitialized: + + /* turn off FAT monitor */ + + if (partNo < 0) { /* all partitions */ + + for (i = 0; i < FL_MAX_PARTS_PER_DISK; i++) { + + if (pd->part[i] != NULL) + (pd->part[i])->ffEnabled = FALSE; + } + } + else { /* specified partition */ + + if (pd->part[partNo] != NULL) + (pd->part[partNo])->ffEnabled = FALSE; + } + status = flOK; + break; + +#ifdef FL_INCLUDE_FAT_MONITOR + + case flStateInitialized: + + /* turn on FAT monitor */ + + if ((pd->ffstate == flStateInitialized) && (partNo >= 0)) { + + if (pd->part[partNo] != NULL) { + + switch( (pd->part[partNo])->type ) { + + case FAT12_PARTIT: + case FAT16_PARTIT: + case DOS4_PARTIT: + (pd->part[partNo])->ffEnabled = TRUE; + status = flOK; + break; + + case FL_RAW_PART: + DBG_PRINT_ERR(FLZONE_FS,"ERROR - can't ctrl non-existent partition.\r\n"); + break; + + default: + DBG_PRINT_ERR(FLZONE_FS,"ERROR - can't ctrl non-FAT12/16 partition.\r\n"); + break; + } + } + } + break; + +#endif /* FL_INCLUDE_FAT_MONITOR */ + + } /* switch(state) */ + + return status; +} + + + + +/* --------------------------------------------------------------------------- * + * * + * f l f f I n f o * + * * + * Obtain complete partition info for specified disk. * + * * + * Parameters: * + * handle : TFFS handle * + * * + * Returns: * + * NULL if error, otherwise pointer to partitioning info * + * * + * --------------------------------------------------------------------------- */ + +FLffDisk * flffInfo ( int handle ) +{ + int socNo, diskNo; + FLffDisk * pd; + + /* if module hasn't been reset yet, do it now */ + + if (resetDone == FALSE) + (void) reset(); + + /* break TFFS handle into socket# and disk#, and do sanity check */ + + socNo = H2S(handle); + diskNo = H2D(handle); + + if ((socNo >= ((int) noOfSockets)) || (diskNo >= FL_MAX_TL_PARTITIONS)) + return NULL; + + /* if disk structure hasn't been allocated yet, do it now */ + + if (ffDisk[socNo][diskNo] == NULL) { + + if( newDisk(handle) != flOK ) + return NULL; + } + + pd = ffDisk[socNo][diskNo]; + + /* read partition table(s) and install FAT filters is needed */ + + if (pd->ffstate == flStateNotInitialized) { + + if( parseDisk(handle) != flOK ) + return NULL; + } + + return pd; +} + + + +#endif /* FL_ABS_READ_WRITE && FL_READ_ONLY */ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fatfilt.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fatfilt.h new file mode 100755 index 00000000..a5713934 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fatfilt.h @@ -0,0 +1,185 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/fatfilt.h-arc $ + * + * Rev 1.5 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.4 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.3 Aug 09 2006 16:52:48 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +/******************************************************************************* + * * + * Module: FATFILT * + * * + * This module implements installable FAT12/16 filters. It supports up to * + * SOCKETS sockets, with up to FL_MAX_DISKS_PER_SOCKET disks per socket. * + * Each disk can contain up to FL_MAX_PARTS_PER_DISK partitions on it, with * + * maximum depth of partition nesting in extended partitions equal to * + * MAX_PARTITION_DEPTH. * + * * + * In order for this module to work, disks must be abs.mounted rather then * + * mounted. In latter case, this module won't detect any of disk's * + * partitions, and won't install FAT filters. * + * * + * This module uses more then 512 bytes of stack space in case if MALLOC is * + * not enabled. * + * * + *******************************************************************************/ + + +#ifndef FLFF_H +#define FLFF_H + + + +#include "dosformt.h" + + + +/* number of entries in disk's partition table */ + +#define FL_PART_TBL_ENTRIES 4 + +/* max number of partitions (filesystem volumes) per disk */ + +#define FL_MAX_PARTS_PER_DISK (FL_PART_TBL_ENTRIES + FL_MAX_PARTITION_DEPTH) + + + + +/* + * Generic 'initialization status' type + */ + +typedef enum { + + flStateNotInitialized = 0, + flStateInitInProgress = 1, + flStateInitialized = 2 + + } FLState; + + +/* + * Disk partition (filesystem volume). Multiple partitions are allowed + * on the disk. + */ + +typedef struct { + + int handle; /* disk's TFFS handle */ + int type; /* FAT16_PARTIT */ + int flags; /* VOLUME_12BIT_FAT etc. */ + FLBoolean ffEnabled; /* FAT filter is enabled on that part. */ + SectorNo startSecNo; /* sectorNo where partition starts */ + SectorNo sectors; /* (info) total sectors in partition */ + SectorNo firstFATsecNo; /* sectorNo of 1st sector of 1st FAT */ + SectorNo lastFATsecNo; /* sectorNo of last sector of 1st FAT */ + SectorNo firstDataSecNo; + unsigned clusterSize; /* Cluster size in sectors */ + +} FLffVol; + + +/* + * Disk with multiple partitions. Multiple disks are allowed on socket. + */ + +typedef struct { + + int handle; /* disk's TFFS handle */ + FLState ffstate; /* FAT filter init. state */ + int parts; /* total FAT12/16 partitions found */ + FLffVol * part[FL_MAX_PARTS_PER_DISK]; + SectorNo secToWatch; /* used to track disk partitioning */ + FLSByte * buf; /* scratch buffer */ + +} FLffDisk; + + +/* + * Master Boot Record/Extended Boot Record of the disk + */ + +typedef struct { + + FLSByte reserved[0x1be]; + + struct { + FLByte activeFlag; /* 80h = bootable */ + FLByte startingHead; + LEushort startingCylinderSector; + FLSByte type; + FLByte endingHead; + LEushort endingCylinderSector; + Unaligned4 startingSectorOfPartition; + Unaligned4 sectorsInPartition; + } parts [FL_PART_TBL_ENTRIES]; + + LEushort signature; /* = PARTITION_SIGNATURE */ + +} flMBR; + + + + +/* + * FAT Filter API + */ + +#if defined(FL_ABS_READ_WRITE) && !defined(FL_READ_ONLY) + + extern FLStatus ffCheckBeforeWrite (IOreq FAR2 *ioreq); + extern FLStatus flffControl (int devNo, int partNo, FLState state); + extern FLffDisk* flffInfo (int devNo); + +#endif + +#endif /* FLFF_H */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbase.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbase.c new file mode 100755 index 00000000..d7d4e9fd --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbase.c @@ -0,0 +1,89 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flbase.c-arc $ + * + * Rev 1.4 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.3 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.2 Aug 09 2006 16:52:48 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#include "flbase.h" + + +void toUNAL(FLByte FAR0 *unal, FLWord n) +{ + unal[0] = FL2BYTE(n); + unal[1] = FL2BYTE(n >> 8); +} + + +FLWord fromUNAL(FLByte const FAR0 *unal) +{ + return ((FLWord)unal[1] << 8) + unal[0]; +} + + +/* calling another routines looks nice, but it is slower */ + +void toUNALLONG(FLByte FAR0 *le, FLDword n) +{ + le[0] = FL2BYTE(n); + le[1] = FL2BYTE(n >> 8); + le[2] = FL2BYTE(n >> 16); + le[3] = FL2BYTE(n >> 24); +} + +FLDword fromUNALLONG(FLByte const FAR0 *le) +{ + return ((FLDword)le[3] << 24) + + ((FLDword)le[2] << 16) + + ((FLDword)le[1] << 8) + + le[0]; +} + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbase.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbase.h new file mode 100755 index 00000000..3f7a7695 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbase.h @@ -0,0 +1,267 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flbase.h-arc $ + * + * Rev 1.21 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + */ + +#ifndef FLBASE_H +#define FLBASE_H + +#include "flcustom.h" +#include "flsystem.h" +#include "flsystyp.h" +#include "flchkdef.h" +#include "flcommon.h" + +#ifndef MTD_STANDALONE +#include "flsysfun.h" +#endif /* MTD_STANDALONE */ + + /* Number of floors supported by the S/W + * + * Define Maximum Number of floors in a physical device + * + * The actual number of floors depends on the physical device placed + * on the socket. + */ + +#define FL_MAX_NO_OF_FLOORS 4 + + + +/* General purpose macros */ + +#define BYTE_ADD_FAR(x,y) ((FLByte FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define WORD_ADD_FAR(x,y) ((FLWord FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define DWORD_ADD_FAR(x,y) ((FLDword FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define SBYTE_ADD_FAR(x,y) ((FLSByte FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define SWORD_ADD_FAR(x,y) ((FLSWord FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) +#define SDWORD_ADD_FAR(x,y) ((FLSDword FAR1 *)addToFarPointer((FLByte FAR1 *)x,y)) + +/* Drive handle masks */ + +#define FL_GET_LOGICAL_PARTITION_FROM_HANDLE(ioreq) (FLByte)(((ioreq)->irHandle & 0xf00) >> 8) +#define FL_GET_DISK_HANDLE_FROM_S_P_LP(s,p, lp) ((s) | ((p) << 4) | ((FLHandle)(lp) << 8)) + +#define FL_SOCKET_AND_FLASH_PARTITION_BITS 0xFF + +#define FL_DO_NOT_UPDATE_MBR (1 << 14) /* used by formatFS only */ + +#define INVALID_VOLUME_NUMBER 0xff +#define TL_SIGNATURE 6 + +#define FL_SECTOR_MASK (FL_SECTOR_SIZE - 1) +#define BITS_PER_BITE 8 + + +/* General purpose macros adjusted according to the above customization files. */ + + +/* Call a procedure returning status and fail if it fails. This works only in */ +/* routines that return Status: */ +#define checkStatus(exp) { FLStatus fl__status = (exp);if (fl__status != flOK) return fl__status; } +#define updateStatus(cur__stat, exp) { FLStatus fl__status = (exp);if (cur__stat == flOK) cur__stat = fl__status; } + +#define TFFSMIN(a,b) (((a)>(b)) ? (b):(a)) +#define TFFSMAX(a,b) (((a)<(b)) ? (b):(a)) + +/***************************************************************************/ +/* Big \ Little endien architecture conversion macros. */ +/***************************************************************************/ + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED +#define COPY2(to,arg) *((FLWord *)(&to)) = *((FLWord *)(&arg)) +#define COPY4(to,arg) *((FLDword *)(&to)) = *((FLDword *)(&arg)) +#else +#define COPY2(to, offs, arg) FL_REF_2(to, offs) = FL_REF_2(arg, offs) +#define COPY4(to, offs, arg) FL_REF_4(to, offs) = FL_REF_4(arg, offs) +#endif /* FL_NO_PACKED_STRUCTS_SUPPORTED */ + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#define UNAL2(arg) fromUNAL(arg) +#define toUNAL2(to,arg) toUNAL(to,arg) + +#define UNAL4(arg) fromUNALLONG((FLByte const FAR0 *)(arg)) +#define toUNAL4(to,arg) toUNALLONG((FLByte FAR0 *)to,arg) + +/* for both LE and BE */ + +#define FL_GET_UNAL2(arg, offs) fromUNAL(((FLByte *)(arg)) + (offs)) +#define FL_SET_UNAL2(to, offs, arg) toUNAL(((FLByte *)(to)) + (offs), (arg)) +#define FL_GET_UNAL4(arg, offs) fromUNALLONG(((FLByte *)(arg)) + (offs)) +#define FL_SET_UNAL4(to, offs, arg) toUNALLONG(((FLByte *)(to)) + (offs), (arg)) + + +typedef LEulong LEmin; + +/*************************************************/ +/* Use routines instead of 'c' standard librarys */ +/*************************************************/ + +/**********************************************/ +/* Declare the TrueFFS environment variables */ +/**********************************************/ + +#ifdef FL_NO_USE_FUNC +/* The code bellow allows you to customize your own routine for multi bytes */ +/* transfers. Once FL_NO_USE_FUNC is defined, you can define the multi byte */ +/* macros to these routines, and code them yourself in flsystem.c */ +extern void FAR1 fl16bitDocReadNoShift (volatile FLByte FAR0 * win, FLWord offset, FLByte FAR1 * dest, FLWord count ); +extern void FAR1 fl16bitDocWriteNoShift ( volatile FLByte FAR0 * win , FLWord offset , FLByte FAR1 * src, FLWord count ); +#endif /* FL_NO_USE_FUNC */ + +#ifdef FL_ENVIRONMENT_VARS + +extern void flSetEnvVar(void); + +/**********************************************/ +/* Declare the TrueFFS environment variables */ +/**********************************************/ + +extern FLByte flDimageCfg; + +#ifndef MTD_STANDALONE + +extern FLByte flUseMultiDoc; +extern FLByte flMTLdefragMode; +extern FLByte flMaxUnitChain; +#ifdef FL_TFFS_OLD_ENV_VARS +extern FLByte flMarkDeleteOnFlash; +extern FLByte flPolicy[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +#endif /* FL_TFFS_OLD_ENV_VARS */ +extern FLWord flCacheSize[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +extern FLByte flSkipStaticFilesWearLeveling[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +extern FLByte flSuspendMode[FL_SOCKETS]; +extern FLDword flTFFSBDDebugMode[FL_SOCKETS][FL_MAX_TL_PARTITIONS]; +#ifdef FL_BD_AUTO_DPD_MODE +extern FLDword flBDAutoDPDMode[FL_SOCKETS]; +#endif /* FL_BD_AUTO_DPD_MODE */ + +#endif /* MTD_STANDALONE */ + +/* Policies definitions (FL_SET_POLICY) */ +#define FL_DEFAULT_POLICY 0 +#define FL_COMPLETE_ASAP 1 +#define FL_SECURED_DELETE 2 +/* Mtl policies definitions (FL_MTL_POLICY) */ +#define FL_MTL_DEFRAGMENT_ALL_DEVICES 0 +#define FL_MTL_DEFRAGMENT_SEQUANTIAL 1 +/* Suspend mode other then FL_OFF */ +#define FL_SUSPEND_WRITE 1 +#define FL_SUSPEND_IO 3 +#define FL_IGNORE_WRITE 4 +#define FL_IGNORE_ERASE 8 +#define FL_PREVENT_IO (FL_IGNORE_ERASE | FL_IGNORE_WRITE | FL_SUSPEND_IO | FL_SUSPEND_WRITE) +/* Runtime replacement for compilation flags */ +#define FL_DIMAGE 0x01 +#define FL_PUTIMAGE 0x02 +#define FL_PUTIMAGE_PARALLEL 0x04 +#define FL_DIMAGE_ALL (FL_DIMAGE | FL_PUTIMAGE | FL_PUTIMAGE_PARALLEL) +/* Cache full media */ +#define FL_MAX_ALLOWED_TL_CACHE_SIZE 0xFFF + + +#ifndef FL_DEFAULT_POLICY_MODE +#define FL_DEFAULT_POLICY_MODE(socket,partition) FL_OFF +#endif /* FL_DEFAULT_POLICY_MODE */ +#ifndef FL_DEFAULT_BD_DPD_MODE +#define FL_DEFAULT_BD_DPD_MODE(socket) FL_OFF +#endif /* FL_DEFAULT_BD_DPD_MODE */ +#ifndef FL_DEFAULT_BD_SUSPEND_MODE +#define FL_DEFAULT_BD_SUSPEND_MODE(socket) FL_OFF +#endif /* FL_DEFAULT_BD_SUSPEND_MODE */ +#ifndef FL_DEFAULT_BD_DEBUG_MODE +#define FL_DEFAULT_BD_DEBUG_MODE(socket,partition) FL_OFF +#endif /* FL_DEFAULT_BD_DEBUG_MODE */ +/* Either per partition or for all (backward compatible) */ +#ifndef FL_DEFAULT_CACHE_SIZE_FOR_MINIMAL_CACHE +#define FL_DEFAULT_CACHE_SIZE_FOR_MINIMAL_CACHE 0x40 +#endif /* FL_DEFAULT_CACHE_SIZE_FOR_MINIMAL_CACHE */ +#ifndef FL_DEFAULT_TL_CACHE_SIZE +#define FL_DEFAULT_TL_CACHE_SIZE(socket,partition) FL_DEFAULT_CACHE_SIZE_FOR_MINIMAL_CACHE +#endif /* FL_DEFAULT_TL_CACHE_SIZE */ +#ifndef FL_DEFAULT_WEARLEVELING_MODE +#define FL_DEFAULT_WEARLEVELING_MODE(socket,partition) FL_OFF +#endif /* FL_DEFAULT_WEARLEVELING_MODE */ +#ifndef FL_DEFAULT_VERIFY_WRITE_MODE +#define FL_DEFAULT_VERIFY_WRITE_MODE(socket,partition) FL_OFF +#endif /* FL_DEFAULT_VERIFY_WRITE_MODE */ +#ifndef FL_DEFAULT_TOOLS_MODE +#define FL_DEFAULT_TOOLS_MODE FL_OFF +#endif /* FL_DEFAULT_TOOLS_MODE */ + +#endif /* FL_ENVIRONMENT_VARS */ + +/* Set default to bus configuration (unless specified differently in flsystem.h */ +#ifndef FL_DEFAULT_BUS_CONFIGURATION +#if (!defined(CHARSIZE) || (CHARSIZE != 16)) +#define FL_DEFAULT_BUS_CONFIGURATION (FL_NO_ADDR_SHIFT | FL_BUS_HAS_8BIT_ACCESS | \ + FL_BUS_HAS_16BIT_ACCESS | FL_BUS_HAS_32BIT_ACCESS) +#else +#define FL_DEFAULT_BUS_CONFIGURATION (FL_NO_ADDR_SHIFT | FL_BUS_HAS_16BIT_ACCESS) +#endif /* CHARSIZE */ +#endif /* FL_DEFAULT_BUS_CONFIGURATION */ + +#ifndef FL_DEFAULT_BUS_MODE +#define FL_DEFAULT_BUS_MODE(socket) FL_DEFAULT_BUS_CONFIGURATION +#endif /* FL_DEFAULT_BUS_MODE */ + + +#endif /* FLBASE_H */ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbuffer.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbuffer.h new file mode 100755 index 00000000..a34afb5f --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flbuffer.h @@ -0,0 +1,76 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flbuffer.h-arc $ + * + * Rev 1.7 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.6 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.5 Sep 05 2006 17:21:34 rafib + * Fix slow mount problem in H1 512 hynix + * + * Rev 1.4 Aug 09 2006 16:52:50 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLBUFFER_H +#define FLBUFFER_H + +#include "flbase.h" + +#define READ_BACK_BUFFER_SIZE 1024 /* Size of read back buffer + Must be multiplication of 512 */ +typedef struct { + FLByte flData[FL_SECTOR_SIZE]; /* sector buffer */ + FLByte flData2[FL_SECTOR_SIZE]; /* sector buffer */ + SectorNo sectorNo; /* current sector in buffer */ + void *owner; /* owner of buffer */ + FLBoolean dirty; /* sector in buffer was changed */ + FLBoolean checkPoint; /* sector in buffer must be flushed */ +} FLBuffer; + +#endif diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flchkdef.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flchkdef.h new file mode 100755 index 00000000..0a48c02c --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flchkdef.h @@ -0,0 +1,1512 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flchkdef.h-arc $ + * + * Rev 1.99 Dec 26 2007 11:58:02 einat.avidan + * update version + * + * Rev 1.98 Dec 04 2007 17:38:06 einat.avidan + * Define delay for accessing same register twice + * Inc version + * + * Rev 1.97 Dec 03 2007 18:04:02 einat.avidan + * update EQA number + * + * Rev 1.96 Nov 07 2007 19:20:42 einat.avidan + * add defenition for FLTXT_VAR + * update EQA number + * + * Rev 1.95 Nov 05 2007 17:53:14 einat.avidan + * EQA5 + * + * Rev 1.94 Oct 30 2007 17:06:30 einat.avidan + * update version number + * Exported DMA flags receive the values of internal flags + * + * Rev 1.93 Oct 23 2007 12:27:54 einat.avidan + * optimization: delay after setting head register only + * when switching floors + * + * Rev 1.92 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.91 Oct 21 2007 16:59:48 einat.avidan + * fix compilation warnings + * + * Rev 1.90 Oct 21 2007 10:44:06 Einat.Avidan + * add definition for delay after each trial of reading chip ID from SLAVE + * add definition for number of trials of reading chip ID + * default definition of DOCH_SET_WINDOW_OFFSET should return value + * update version number + * + * Rev 1.89 Oct 11 2007 19:04:00 Einat.Avidan + * update version number + * add definition for delay after device switch + * + * + * Rev 1.88 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.87 Jun 20 2007 12:23:36 einat.avidan + * update verion DD 1.1 EQA1 (internal R&D) + * + * Rev 1.86 Mar 22 2007 16:57:54 einat.avidan + * set version 1.1 EQA0 + * + * Rev 1.85 Mar 11 2007 16:39:46 einat.avidan + * bug fix: working on x86 requires read buffer not to be paged out + * replace the former solution (access to the begining and the end of the buffer under NO_INIT_MMU_PAGES compilation flag) + * with full solution: usage of a buffer that is locked on RAM + * + * Rev 1.84 Feb 28 2007 10:50:46 einat.avidan + * bug fix: scr 2831 removed unnecessary definitions: FL_MTDS, FL_TLS, MTD_READ_BBT. + * + * Rev 1.83 Feb 28 2007 10:33:20 einat.avidan + * inc EQA version + * bug fix: “;” at the end of macros definition in flcheckdef may cause compilation errors + * + * Rev 1.82 Feb 15 2007 17:52:18 Einat.Avidan + * New compilation flags: + * DOCH_READ_STATUS_ASYNC_IN_BURST + * DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + * + * Rev 1.81 Jan 01 2007 15:35:12 einat.avidan + * updated to EQA21 + * bug fix: scr2811, boot shceme failed when only one device exists and the reset/warm reset pins of the MDOC are NOT connected to the CPU reset. + * the fix - changed default number of ATA_MAX_NUM_OF_DEVICES to 1. + * + * Rev 1.78.2.16.1.3 Dec 10 2006 17:02:56 Yaniv.Iarovici + * Update EQA 20 + * + * Rev 1.78.2.16.1.2 Dec 05 2006 14:59:14 Yaniv.Iarovici + * Change EQA to 19. + * + * Rev 1.78.2.16.1.1 Dec 04 2006 12:44:48 Yaniv.Iarovici + * Change EQA to 18. + * + * Rev 1.78.2.16.1.0 Dec 03 2006 13:43:14 Yaniv.Iarovici + * Header update + * + * Rev 1.78.2.17 Dec 03 2006 13:32:26 Yaniv.Iarovici + * 1. Change EQA to 17. + * 2. Removed DOCH_FLOORS. + * Encapsulate auto wipe-sector operation for Dev1 under '#ifndef DOCH_NO_AUTO_WIPE_SECTORS_DEV1' + * + * Rev 1.78.2.16 Nov 30 2006 10:24:02 Yaniv.Iarovici + * 1. Change EQA to 16. + * 2. Add default customization for DOCH_WAIT_B4_DEV1_ID. + * + * Rev 1.78.2.15 Nov 21 2006 14:27:06 Yaniv.Iarovici + * Update EQA to 15. + * + * Rev 1.78.2.14 Nov 13 2006 15:14:04 Yaniv.Iarovici + * Change EQA to 14. + * + * Rev 1.78.2.13 Nov 12 2006 09:47:42 Yaniv.Iarovici + * 1. Changed version to EQA12 RC2. + * 2. Added default values for + * - FL_IPL_DELAY_CELL_CONFIG_READ + * - FL_IPL_DELAY_CELL_CONFIG_WRITE + * + * Rev 1.78.2.12 Nov 01 2006 08:56:04 Yaniv.Iarovici + * Change version to EQA12. + * + * Rev 1.78.2.11 Oct 31 2006 12:23:52 yaniv.iarovici + * Change version to EQA11. + * + * Rev 1.78.2.10 Oct 30 2006 15:50:32 yaniv.iarovici + * Change version to EQA10. + * + * Rev 1.78.2.9 Oct 29 2006 14:24:12 Yaniv.Iarovici + * Change version to EQA9. + * + * Rev 1.78.2.8 Oct 29 2006 10:59:50 Yaniv.Iarovici + * Change version to EQA8. + * + * Rev 1.78.2.7 Oct 25 2006 09:10:34 Yaniv.Iarovici + * Change version to EQA7 + * + * Rev 1.78.2.6 Oct 23 2006 11:29:20 yaniv.iarovici + * Change EQA to 6 + * + * Rev 1.78.2.5 Oct 09 2006 14:05:24 yaniv.iarovici + * Removed legacy devices related code and definitions + * + * Rev 1.78.2.4 Oct 05 2006 11:48:12 yaniv.iarovici + * Change version to 'DOC Driver 1.0, EQA4, RC1' + * + * Rev 1.78.2.3 Sep 13 2006 10:44:22 yaniv.iarovici + * Update version to EQA3 Alpha2 + * + * Rev 1.78.1.6 Sep 11 2006 13:45:20 yaniv.iarovici + * Legal header added + * + * Rev 1.78.1.5 Sep 10 2006 10:04:00 Yaniv.Iarovici + * Update version number - DOC Driver 1.0 EQA1 Alpha2. + * + * Rev 1.78.1.4 Sep 03 2006 14:44:50 Yaniv.Iarovici + * 1. Define flReadEvenNumberOfBytes() instead of flRead512Bytes() to support DRQ>1 + * 2. Define flWriteEvenNumberOfBytes() instead of flWrite512Bytes() to support DRQ>1 + * + * Rev 1.78.1.3 Aug 22 2006 13:24:40 Yaniv.Iarovici + * Change FL_MAX_TL_PARTITIONS default to '14' + * + * Rev 1.78.1.2 Aug 16 2006 08:46:36 Yaniv.Iarovici + * 1) Change 7.0.0.0 to 1.0.0.0 + * 2) Change TrueFFSVersion value to "1020" + * 3) If FL_DOC_ADDRESS is NOT defined and FL_LOW_DOC_ADDRESS defined, set '#define FL_DOC_ADDRESS FL_LOW_DOC_ADDRESS'. + * + * Rev 1.78.1.0 Aug 08 2006 15:55:30 Polina.Marimont + * DOC Driver 1.0 initial + */ + +/************************/ +/* TrueFFS source files */ +/* -------------------- */ +/************************/ + +/***************************************************************************** +* File Header * +* ----------- * +* Name : flchkdef.h * +* * +* Description : Sanity check for flcustom.h files. * +* * +*****************************************************************************/ + +#ifndef _FL_CHK_DEFS_H_ +#define _FL_CHK_DEFS_H_ + +#include "flcustom.h" +#include "flsystem.h" + +#define FL_MIGRATION_VERSION + +#define FL_NEW_MAPSECTOR + +#ifndef MTD_STANDALONE + +/* TrueFFS version + * + * Number written on the flash by INFTL format specifying the TrueFFS version + * The media was formated with. the number bellow specifies version + * 1.1.0.0 + */ + +#define TrueFFSVersion "1100" + +/* Tracking number for TrueFFS configuration managment + * + * Number for configuration management of special purpose versions + */ + +#define TrueFFS_EQA_Version 9 +#define TrueFFS_RC_Version 0 +#define TrueFFS_PATCH_Version 0 +#define TrueFFS_Alpha_Version 0 +#define TrueFFS_Beta_Version 1 + + +/* Programmer type version + * + * This string is placed in the media header indicating the programmer + * Name and version used to format the media + */ + +#ifndef FL_PROGRAMMER_NAME +#define FL_PROGRAMMER_NAME "CORE" +#endif /* FL_PROGRAMMER_NAME */ + +#ifndef FL_PROGRAMMER_VERSION +#define FL_PROGRAMMER_VERSION "0000" +#endif /* FL_PROGRAMMER_VERSION */ + +/********************************************************************/ +/* Device base address (Use previous versions definition if exits */ +/* and FL_DOC_ADDRESS does not exist. */ +/********************************************************************/ +#if !defined(FL_DOC_ADDRESS) && defined(FL_LOW_DOC_ADDRESS) +#define FL_DOC_ADDRESS FL_LOW_DOC_ADDRESS +#endif + +/*******************************************/ +/* Validity check and overlapping defines */ +/*******************************************/ + +#if !defined(FL_READ_ONLY) && !defined(FS_READ_ONLY) && defined(READ_ONLY) +#define FL_READ_ONLY +#define FS_READ_ONLY +#endif + +/* The format option needs some internal defintions */ +#if !defined(FL_FORMAT_VOLUME) && defined(FORMAT_VOLUME) +#define FL_FORMAT_VOLUME +#endif + +#if (defined(FL_FORMAT_VOLUME) && defined(FL_READ_ONLY)) +#error "You can not define FL_READ_ONLY and FL_FORMAT_VOLUME at the same time" +#endif /* (defined(FL_FORMAT_VOLUME) && defined(FL_READ_ONLY)) */ + +#if (defined(FS_FORMAT_VOLUME) && defined(FS_READ_ONLY)) +#error "You can not define FS_READ_ONLY and FS_FORMAT_VOLUME at the same time" +#endif /* (defined(FS_FORMAT_VOLUME) && defined(FS_READ_ONLY)) */ + +#if (defined(FS_CREATE_LOGICAL_PARTITIONS) && defined(FS_READ_ONLY)) +#error "You can not define FS_READ_ONLY and FS_CREATE_LOGICAL_PARTITIONS" +#endif + +/* In case FL_READ_ONLY is defined FS_READ_ONLY needs to be defined as well */ +#ifdef FL_READ_ONLY +#ifndef FS_READ_ONLY +#define FS_RED_ONLY +#endif /* FS_READ_ONLY */ +#endif /* FL_READ_ONLY */ + +/* Validity check for system files MACROES */ +#ifndef FL_FOPEN +#define FL_FOPEN +#endif /* FL_FOPEN */ +#ifndef FL_FCLOSE +#define FL_FCLOSE +#endif /* FL_FCLOSE */ +#ifndef FL_FPRINTF +#define FL_FPRINTF +#endif /* FL_FPRINTF */ + + +/* Number of file system - logical partitions + * + * Defines Maximum Number of logical partitons on a BDTL partition + * + * The actual number of partitions depends on the format placed on each device. + */ + +#ifndef FS_MAX_LOGICAL_PARTITIONS +#define FS_MAX_LOGICAL_PARTITIONS 4 /* per TL partition. There is no hard limit */ +#endif /* FS_MAX_LOGICAL_PARTITIONS */ + + +/* Validity check of FL_VOLUMES and FL_SOCKETS parameters. */ + +#if !defined(FL_VOLUMES) && defined(VOLUMES) +#define FL_VOLUMES VOLUMES +#endif + +#if !defined(FS_VOLUMES) && defined(FL_VOLUMES) +#define FS_VOLUMES FL_VOLUMES +#endif + +#if !defined(FL_SOCKETS) && defined(SOCKETS) +#define FL_SOCKETS SOCKETS +#endif + +#if !defined(FS_SOCKETS) && defined(FL_SOCKETS) +#define FS_SOCKETS FL_SOCKETS +#endif + + +#if !defined(FL_VOLUMES) && defined(FL_SOCKETS) +#define FL_VOLUMES FL_SOCKETS +#endif /* SOCKETS && ! VOLUMES */ + +#if !defined(FS_VOLUMES) && defined(FS_SOCKETS) +#define FS_VOLUMES FS_SOCKETS +#endif /* SOCKETS && ! VOLUMES */ + +#if !defined(FL_SOCKETS) && defined(FL_VOLUMES) +#define FL_SOCKETS FL_VOLUMES +#endif /* ! SOCKETS && VOLUMES */ + +#if !defined(FS_SOCKETS) && defined(FS_VOLUMES) +#define FS_SOCKETS FS_VOLUMES +#endif /* ! SOCKETS && VOLUMES */ + +#if (FL_SOCKETS > FL_VOLUMES) || (FS_SOCKETS > FS_VOLUMES) +#error "SOCKETS should not be bigger then VOLUMES" +#endif /* SOCKETS > VOLUMES */ + +/* The POLLING_INTERVAL definition is not really relevant to DiskOnChip + * Starting from TrueFFS 6.1 it was removed from flcustom.h, but TrueFFS + * still support this functionality. + */ +#ifndef POLLING_INTERVAL +#define POLLING_INTERVAL 0 +#endif /* POLLING_INTERVAL */ + +/* TrueFFS 5.2 used the FL_QUICK_MOUNT_INFO_EXIST defintion. TrueFFS 6.1 + * uses simple FL_ON and FL_OFF instead. + */ + +#define FL_QUICK_MOUNT_INFO_EXIST FL_ON + +/* Starting from TrueFFS 6.1 this flag does not reduce code and therfore was + * added as a default. + * + */ + +#define FL_LOW_LEVEL + +/* Some S/W modules like boot SDK do not need the read bad blocks tables routine. + * However for TrueFFS these defintion is vital + */ + +/* 12-bit FAT support + * + * Comment the following line if you do not need support for DOS media with + * 12-bit FAT (typically media of 8 MBytes or less). + */ + +#define FS_FAT_12BIT + + + +#ifndef FL_SOCKETS +#define FL_SOCKETS 1 /* The only available number */ +#endif +#define FIXED_MEDIA +#define DO_NOT_YIELD_CPU + +#endif /* MTD_STANDALONE */ + + +/* Number of translation layer partitions + * + * Defines Maximum Number of Translation layer partitions on a physical device + * + * The actual number of partitions depends on the format placed on each device. + */ + +#ifndef FL_MAX_TL_PARTITIONS +#define FL_MAX_TL_PARTITIONS 14 +#endif /* FL_MAX_TL_PARTITIONS */ + +/* The Maximum number of partitions is limited to 8 due to SAFTL buffers */ + +#if (FL_MAX_TL_PARTITIONS > 14) +#error "Can not define more then 14 partitions\r\n" +#endif /* (FL_MAX_TL_PARTITIONS > 8) */ + + +/* Max Number of binary partitions */ +#ifndef MAX_BINARY_PARTITIONS_PER_DRIVE +#define MAX_BINARY_PARTITIONS_PER_DRIVE 3 +#endif /* MAX_BINARY_PARTITIONS_PER_DRIVE */ + +/* There can not be more binary partition, then total supported partitions */ +#if (MAX_BINARY_PARTITIONS_PER_DRIVE >= FL_MAX_TL_PARTITIONS) +#error "MAX_BINARY_PARTITIONS_PER_DRIVE must be smaller then FL_MAX_TL_PARTITIONS\r\n" +#endif /* (MAX_BINARY_PARTITIONS_PER_DRIVE >= FL_MAX_TL_PARTITIONS) */ + +/* Default file system TL partitions */ +#if !defined(FS_MAX_TL_PARTITIONS) && defined(FL_MAX_TL_PARTITIONS) +#define FS_MAX_TL_PARTITIONS FL_MAX_TL_PARTITIONS +#endif + + +/* Make sure that the CHARSIZE is well defined */ +#ifndef CHARSIZE +#define CHARSIZE 8 /*The default char size is 8*/ +#endif + +/* Make sure flPack and flspread are well defined */ +#if (CHARSIZE == 8) +#ifndef flspread +#define flspread(source,length) +#endif /* flspread */ + +#ifndef flpack +#define flpack(source,length) +#endif /* flpack */ +#endif /* (CHARSIZE == 8) */ + +/* Make sure FL2BYTE is well defined */ +#ifndef FL2BYTE +#if (CHARSIZE == 8) +#define FL2BYTE(var) ((FLByte)(var)) +#else +#define FL2BYTE(var) ((FLByte)((var) & 0x00FF)) +#endif /* (CHARSIZE == 8) */ +#endif /* FL2BYTE */ + + +#ifndef FL_PACKED_STRUCTURES_BEFORE +#define FL_PACKED_STRUCTURES_BEFORE +#endif /* FL_PACKED_STRUCTURES_BEFORE */ + +#ifndef FL_PACKED_STRUCTURES_AFTER +#ifdef FL_PACKED_STRUCTURES +#define FL_PACKED_STRUCTURES_AFTER FL_PACKED_STRUCTURES +#else +#define FL_PACKED_STRUCTURES_AFTER +#endif /* FL_PACKED_STRUCTURES */ +#endif /* FL_PACKED_STRUCTURES_AFTER */ + +/* Starting from TrueFFS version 6.x the ASSUMED_NFTL_UNIT_SIZE was changed to + * FL_ASSUMED_MIN_UNIT_SIZE. + */ + +#ifndef FL_ASSUMED_MIN_UNIT_SIZE +#define FL_ASSUMED_MIN_UNIT_SIZE ASSUMED_NFTL_UNIT_SIZE +#endif /* FL_ASSUMED_MIN_UNIT_SIZE */ + +/* Starting from TrueFFS version 6.x the MAX_VOLUME_MBYTES was changed to + * FL_ASSUMED_MAX_VOLUME_MBYTES. + */ + +#ifndef FL_ASSUMED_MAX_VOLUME_MBYTES +#ifdef MAX_VOLUME_MBYTES +#define FL_ASSUMED_MAX_VOLUME_MBYTES MAX_VOLUME_MBYTES +#else + +/* TrueFFS sets the sector size according to this definitions. As a result customers + that do not customize this definition will be limited to a very small media (32MB) + without even knowing it. + */ + +#define FL_ASSUMED_MAX_VOLUME_MBYTES 64 +#endif /* MAX_VOLUME_MBYTES */ +#endif /* FL_ASSUMED_MAX_VOLUME_MBYTES */ + +/* When using static allocation , SAFTL may requires the number of sectors + * in a logical unit. This value can normally be deduced from the unit size. + * However if you need to support several DiskOnChip devices with different + * unit sizes, you may need to define the smallest unit size, while defining + * the largest number of logical sectors in a logical unit + */ + +#ifndef FL_ASSUMED_MAX_SECTORS_PER_UNIT +#define FL_ASSUMED_MAX_SECTORS_PER_UNIT (FL_ASSUMED_MIN_UNIT_SIZE>>FL_SECTOR_SIZE_BITS) +#endif /* FL_ASSUMED_MAX_SECTORS_PER_UNIT */ + +/* Validity check for FL_LOW_LEVEL compilation flag. + * + * Starting from TrueFFS 5.1 the LOW_LEVEL was changed to FL_LOW_LEVEL + * The reason was that it clashed with Windows NT LOW_LEVEL macro. + */ + +#ifndef FL_LOW_LEVEL +#ifdef LOW_LEVEL +#define FL_LOW_LEVEL +#endif /* LOW_LEVEL */ +#endif /* FL_LOW_LEVEL */ + + +#if !defined(FL_ABS_READ_WRITE) && !defined(FS_ABS_READ_WRITE) && defined(ABS_READ_WRITE) +#define FL_ABS_READ_WRITE +#define FS_ABS_READ_WRITE +#endif + +/* Validity check for FL_SYS_FUNC_RELEASE + * + * Starting from TrueFFS 6.0 the flExit routine calls this macro in + * order to inform the OS/FS that it is about to leave. + */ + +#ifndef FL_SYS_FUNC_RELEASE +#define FL_SYS_FUNC_RELEASE +#endif /* FL_SYS_FUNC_RELEASE */ + +#if !defined(FL_EXIT) && !defined(FS_EXIT) && defined(EXIT) +#define FL_EXIT +#define FS_EXIT +#endif + +/* Validity check for FL_LOWER_PRIORITY_THREAD and FL_RAISE_PRIORITY_THREAD + * + * Starting from TrueFFS 6.0-6.2.2 the MTD waitForReady routine calls the + * FL_LowerPriorityThread and FL_RaisePriorityThread macros allowing the OS + * to lower the driver's priority during the long wait. + * + * After 6.2.2 the name of the macros was changed to all upper case. + */ + +#ifndef FL_LOWER_PRIORITY_THREAD +#ifdef FL_LowerPriorityThread +/*** Add support for older flsystem that use FL_Raise/LowerPriorityThread macros ***/ +#define FL_LOWER_PRIORITY_THREAD FL_LowerPriorityThread +#else +#define FL_LOWER_PRIORITY_THREAD(myFlash) +#endif /* FL_LowerPriorityThread */ +#endif /* FL_LOWER_PRIORITY_THREAD */ + +#ifndef FL_RAISE_PRIORITY_THREAD +#ifdef FL_RaisePriorityThread +/*** Add support for older flsystem that use FL_Raise/LowerPriorityThread macros ***/ +#define FL_RAISE_PRIORITY_THREAD FL_RaisePriorityThread +#else +#define FL_RAISE_PRIORITY_THREAD(myFlash) +#endif /* FL_RaisePriorityThread */ +#endif /* FL_RAISE_PRIORITY_THREAD */ + +#ifndef FL_LowerPriorityThread +#define FL_LowerPriorityThread(myFlash) +#endif /* FL_LowerPriorityThread */ + +#ifndef FL_RaisePriorityThread +#define FL_RaisePriorityThread(myFlash) +#endif /* FL_RaisePriorityThread */ + + +/* Validity check for FL_TFFS_SLEEP + * + * Note that this routine used to be called flsleep, but it's name was + * greater resolution was required. + */ + +#ifndef FL_TFFS_SLEEP +#define FL_TFFS_SLEEP(flash,microseconds) +#endif /* FL_TFFS_SLEEP */ + + +/* Validity check for FL_READ_ONLY + * + * When Block device does not support write operations, also file system + * cannot write. Therefore, if BD read only is set - also FS read only must be set. + */ +#ifdef FL_READ_ONLY +#define FS_READ_ONLY +#endif /*FS_READ_ONLY*/ + +/* Validity check for FL_MALLOC and FL_FREE macros + * + * Starting from TrueFFS 5.0 the FREE and MALLOC macroes were + * changed to FL_MALLOC and FL_FREE in order to avoid name clashes. + * In order to keep backwards compatibility with previous flsystem.h + * files the following new defintions checks were added. + * if your system uses the FREE and MALLOC defintion simply comment + * them out and customized the FL_MALLOC and FL_FREE macroes in your + * flsystem.h file. + */ + +#if (defined(MALLOC) && !defined(FL_MALLOC)) +#define FL_MALLOC MALLOC +#endif /* MALLOC && ! FL_MALLOC */ +#if (defined(FREE) && !defined(FL_FREE)) +#define FL_FREE FREE +#endif /* FREE && ! FL_FREE */ + + +/* Validity check for "subFromFarPointer" and "distanceBetweenFarPointers" + * + * Starting from TrueFFS 6.3.0 2 new memory manipulation macro's were + * introduced for none flat memory architecture. They should be used when + * memory pointers are being subtracted or a difference between 2 pointers + * is needed + */ + +#ifndef subFromFarPointer +#define subFromFarPointer(base,increment) \ + addToFarPointer(base,(-(FLSDword)(increment))) +#endif /* subFromFarPointer */ + +#ifndef distanceBetweenFarPointers +#define distanceBetweenFarPointers(ptr1, ptr2) \ + (((FLDword)(ptr1)) - ((FLDword)(ptr2))) +#endif /* distanceBetweenFarPointers */ + + +/* Validity check for FL_FAR_MALLOC and FL_FAR_FREE + * + * Due to the BIOS driver memory limitations a dedicated routine + * is used for allocating the large ram arrays. + */ + +#if (defined(FL_MALLOC) && !defined(FL_FAR_MALLOC)) +#define FL_FAR_MALLOC FL_MALLOC +#endif /* FL_MALLOC && ! FL_FAR_MALLOC */ + +#if (defined(FL_FREE) && !defined(FL_FAR_FREE)) +#define FL_FAR_FREE FL_FREE +#endif /* FL_MALLOC && ! FL_FAR_MALLOC */ + + +#ifndef FL_MALLOC_DMA_BUFFER +#define FL_MALLOC_DMA_BUFFER FL_FAR_MALLOC +#endif + +#ifndef FL_FREE_DMA_BUFFER +#define FL_FREE_DMA_BUFFER FL_FAR_FREE +#endif + + +/* Validity check for debug printing + * + * Starting from TrueFFS 6.0 there are 6 types of debug print + * In case they were not customized in flsystem.h they are defined here + * as NULL. + */ + +#ifndef DBG_PRINT_FLOW +#define DBG_PRINT_FLOW(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf (str) */ +#endif +#ifndef DBG_PRINT_ERR +#define DBG_PRINT_ERR(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf (str) */ +#endif +#ifndef DBG_PRINT_WRN +#define DBG_PRINT_WRN(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf (str) */ +#endif +#ifndef DBG_PRINT_FLOW_PRM +#define DBG_PRINT_FLOW_PRM(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf str */ +#endif +#ifndef DBG_PRINT_ERR_PRM +#define DBG_PRINT_ERR_PRM(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf str */ +#endif +#ifndef DBG_PRINT_WRN_PRM +#define DBG_PRINT_WRN_PRM(zone,str) /* if (zone & (ACTIVE_DEBUG_ZONE)) printf str */ +#endif + +#ifndef DBG_PRINT_ATA + #define DBG_PRINT_ATA DBG_PRINT_ERR_PRM +#endif /*DBG_PRINT_ATA*/ + + +#ifndef DFORMAT_PRINT +#define DFORMAT_PRINT(a) DBG_PRINT_WRN_PRM(FLZONE_FORMAT,a) +#endif +#ifndef DEBUG_PRINT +#define DEBUG_PRINT(a) DBG_PRINT_WRN(FLZONE_FULL,a) +#endif + + + +/* For backwards compatibility we make sure tffsxxx is defined as flxxx + * + * Versions prior to 6.1 (when ENVIRONMENT_VARS was defined) the user was + * required to customize 2 sets of DiskOnChip memory access routines. + * (flxxx and flmemxxx). One set was for fast memory access and one + * implemented a simple for loop for maximum platform portability. Newer + * versions automatically implement the simple for loop allowing easier + * customization. The new customization model allows the user to customize + * only the tffsxxx routines regardless of the compilation flag + */ + +#if !defined(FL_ENVIRONMENT_VARS) && defined(ENVIRONMENT_VARS) +#define FL_ENVIRONMENT_VARS +#endif + +#ifdef FL_ENVIRONMENT_VARS +#ifndef tffscpy +#define tffscpy flcpy +#endif /* tffscpy */ +#ifndef tffscmp +#define tffscmp flcmp +#endif /* tffscmp */ +#ifndef tffsset +#define tffsset flset +#endif /* tffsset */ +#endif /* FL_ENVIRONMENT_VARS */ + +/* Macro for converting text to string */ +#ifndef FLTXT +#define FLTXT +#endif /* FLTXT */ + +#ifndef FLTXT_VAR +#define FLTXT_VAR +#endif /* FLTXT */ + +/*****************************/ +/* M-Systems forced defaults */ +/*****************************/ + +/* define IO memory access macros - must be defined in flsystem.h */ +#ifndef FLWRITE_IO_BYTE +#define FLWRITE_IO_BYTE(val,address) *((volatile FLByte FAR0*)(address))=(FLByte)(val) +#endif +#ifndef FLWRITE_IO_WORD +#define FLWRITE_IO_WORD(val,address) *((volatile FLWord FAR0*)(address))=(FLWord)(val) +#endif +#ifndef FLWRITE_IO_DWORD +#define FLWRITE_IO_DWORD(val,address) *((volatile FLDword FAR0*)(address))=(FLDword)(val) +#endif +#ifndef TFFSCPY_FROM_IO_8_BITS +#ifdef TFFSCPY_FROM_IO +#define TFFSCPY_FROM_IO_8_BITS TFFSCPY_FROM_IO +#else +#define TFFSCPY_FROM_IO_8_BITS(dest,src,count) tffscpy(dest,(void FAR0*)(src),count) +#endif +#endif /* TFFSCPY_FROM_IO_8_BITS */ + +#ifndef TFFSCPY_FROM_IO_16_BITS +#ifdef TFFSCPY_FROM_IO +#define TFFSCPY_FROM_IO_16_BITS TFFSCPY_FROM_IO +#else +#define TFFSCPY_FROM_IO_16_BITS(dest,src,count) tffscpy(dest,(void FAR0*)(src),count) +#endif +#endif /* TFFSCPY_FROM_IO_16_BITS */ + +#ifndef FLREAD_IO_BYTE +#define FLREAD_IO_BYTE(address) (*((volatile FLByte FAR0*)(address))) +#endif +#ifndef FLREAD_IO_WORD +#define FLREAD_IO_WORD(address) (*((volatile FLWord FAR0*)(address))) +#endif +#ifndef FLREAD_IO_DWORD +#define FLREAD_IO_DWORD(address) (*((volatile FLDword FAR0*)(address))) +#endif + +#ifndef TFFSCPY_TO_IO_8_BITS +#ifdef TFFSCPY_TO_IO +#define TFFSCPY_TO_IO_8_BITS TFFSCPY_TO_IO +#else +#define TFFSCPY_TO_IO_8_BITS(dest,src,count) tffscpy((void FAR0*)(dest),src,count) +#endif +#endif /* TFFSCPY_TO_IO_8_BITS */ + +#ifndef TFFSCPY_TO_IO_16_BITS +#ifdef TFFSCPY_TO_IO +#define TFFSCPY_TO_IO_16_BITS TFFSCPY_TO_IO +#else +#define TFFSCPY_TO_IO_16_BITS(dest,src,count) tffscpy((void FAR0*)(dest),src,count) +#endif +#endif /* TFFSCPY_TO_IO_16_BITS */ + +#ifndef TFFSSET_IO_8_BITS +#ifdef TFFSSET_IO +#define TFFSSET_IO_8_BITS TFFSSET_IO +#else +#define TFFSSET_IO_8_BITS(dest,val,count) tffsset((void FAR0*)(dest),val,count) +#endif +#endif /* TFFSSET_IO_8_BITS */ + +#ifndef TFFSSET_IO_16_BITS +#ifdef TFFSSET_IO +#define TFFSSET_IO_16_BITS TFFSSET_IO +#else +#define TFFSSET_IO_16_BITS(dest,val,count) tffsset((void FAR0*)(dest),val,count) +#endif +#endif /* TFFSSET_IO_16_BITS */ + +/* The FAT-LITE/SURE-FS API definitions were added the FL_ prefix. + * + * Starting from TrueFFS 6.2 + */ + + +#ifndef FS_FILES +#ifdef FILES +#define FS_FILES FILES +#endif /* FILES */ +#ifdef FL_FILES +#define FS_FILES FL_FILES +#endif /* FL_FILES */ +#endif /* FS_FILES */ + +#if defined(FS_FILES) && (FS_FILES <= 0) +#undef FS_FILES +#endif + +#if defined(FS_MAX_FSOS) && ((FS_MAX_FSOS <= 0) || !defined(FS_FILES)) +#undef FS_MAX_FSOS +#endif + +#if defined(FS_SUPPORT_FILE_CACHE) && !defined(FS_MAX_FSOS) +#undef FS_SUPPORT_FILE_CACHE +/* you need FSOs to define the cache size per file type */ +#endif + +#if defined(FS_SUPPORT_FILE_CACHE) && !defined(FL_EXTENDED_SECTOR_CACHE) +#define FL_EXTENDED_SECTOR_CACHE +#endif + +#if defined(FS_MAX_FSOS) && !defined(FS_MM_PERFORMANCE_TUNEUPS) +#define FS_MM_PERFORMANCE_TUNEUPS +#endif + +#if defined(FS_MAX_FSOS) && !defined(STATIC_FS_DB) +#if FS_MAX_FSOS >= 2 +#define STATIC_FS_DB = { DEFAULT_FILE(0, 0), DEFINE_FSO(NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) } +#else +#define STATIC_FS_DB = { DEFAULT_FILE(0, 0) } +#endif +#endif + +#if defined(SUB_DIRECTORY) && !defined(FS_SUB_DIRECTORY) +#define FS_SUB_DIRECTORY +#endif + +#if defined(RENAME_FILE) && !defined(FS_RENAME_FILE) +#define FS_RENAME_FILE +#endif + +#ifndef FILE_IS_ROOT_DIR +#define FILE_IS_ROOT_DIR FL_FILE_IS_ROOT_DIR +#endif + +#ifndef FILE_MODIFIED +#define FILE_MODIFIED FL_FILE_MODIFIED +#endif + +#ifndef FILE_IS_OPEN +#define FILE_IS_OPEN FL_FILE_IS_OPEN +#endif + +#ifndef FILE_IS_DIRECTORY +#define FILE_IS_DIRECTORY FL_FILE_IS_DIRECTORY +#endif + +#ifndef FILE_READ_ONLY +#define FILE_READ_ONLY FL_FILE_READ_ONLY +#endif + +#ifndef FILE_MUST_OPEN +#define FILE_MUST_OPEN FL_FILE_MUST_OPEN +#endif + + +#if defined(FL_TRANSLATE_FROM_UNICODE) && defined(FL_TRANSLATE_TO_UNICODE) +#define FILENAMES_INTERNAL_UNICODE_CONVERSION /* user-defined functions */ + +#elif defined(FL_LONG_FILENAMES_ASCII_SUPPORT) +#define FL_TRANSLATE_FROM_UNICODE unicodeToAscii +#define FL_TRANSLATE_TO_UNICODE asciiToUnicode + +#define FILENAMES_INTERNAL_UNICODE_CONVERSION + +#elif defined(FL_LONG_FILENAMES_UTF8_SUPPORT) +#define FL_TRANSLATE_FROM_UNICODE unicodeToUTF8 +#define FL_TRANSLATE_TO_UNICODE UTF8ToUnicode + +#define FILENAMES_INTERNAL_UNICODE_CONVERSION + +#endif + +#if defined(FL_EXTENDED_SECTOR_CACHE) && (!defined(FS_FILES) || (FS_FILES == 0)) +#undef FL_EXTENDED_SECTOR_CACHE +#endif + +#if defined(FL_EXTENDED_SECTOR_CACHE) && !defined(FS_DATA_CACHE_SIZE) +#define FS_DATA_CACHE_SIZE(socket, partition, logPartition) 200 +#endif + +#if defined(FAT_12BIT) && !defined(FS_FAT_12BIT) +#define FS_FAT_12BIT +#endif + +/******************************** MTD Macros ********************************************/ + +#ifndef FL_CHANGE_READ_ACCESS_TIME +#define FL_CHANGE_READ_ACCESS_TIME(wTimeNanoSec,socket) +#endif /* FL_CHANGE_READ_ACCESS_TIME */ + +/****************************************************************************************/ +/******************************* M I G R A T I O N M A C R O S ***********************/ +/****************************************************************************************/ + +/* Maximum number of supported DOCHs */ +/*===================================*/ +#ifndef DOCH_MAX_SOCKETS + #ifdef FL_SOCKETS + #define DOCH_MAX_SOCKETS FL_SOCKETS + #else /*FL_SOCKETS*/ + #define DOCH_MAX_SOCKETS 1 + #endif /*FL_SOCKETS*/ +#endif /*DOCH_MAX_SOCKETS*/ + +/* + * Length of DOCH register 'read' cycle in nanoseconds (default value should + * do for most systems). + */ +#ifndef DOCH_ACCESS_NANOSEC + #define DOCH_ACCESS_NANOSEC 15 +#endif /*DOCH_ACCESS_NANOSEC*/ + +#ifndef DOCH_SPI_ACCESS_NANOSEC + #define DOCH_SPI_ACCESS_NANOSEC 150000 +#endif /*DOCH_SPI_ACCESS_NANOSEC*/ + +/* Host CPU ENDIANESS */ +/*====================*/ +#ifndef DOCH_BIG_ENDIAN + #ifdef FL_BIG_ENDIAN + #define DOCH_BIG_ENDIAN + #endif /*FL_BIG_ENDIAN*/ +#endif /*DOCH_BIG_ENDIAN*/ + + +/*DOCH specific power mode defaults */ +/*================================= */ +/* by default DPD configured to: + active mode is NORMAL, + after command execution, device passes immediatly to + IDLE mode and after timeout (100msec) to DPD mode*/ +#ifndef DOCH_DPD_DEFAULT_ACTIVE_MODE + #define DOCH_DPD_DEFAULT_ACTIVE_MODE DOCH_WM_NORMAL_AND_AUTO_STBY /*DOCH_WorkMode*/ +#endif /*DOCH_DPD_DEFAULT_ACTIVE_MODE*/ + +#ifndef DOCH_DPD_DEFAULT_INACTIVE_MODE + #define DOCH_DPD_DEFAULT_INACTIVE_MODE DOCH_IM_IDLE_2_DPD /*DOCH_InactiveMode*/ +#endif /*DOCH_DPD_DEFAULT_INACTIVE_MODE*/ + +#ifndef DOCH_DPD_DEFAULT_DPD_TIMEOUT + #define DOCH_DPD_DEFAULT_DPD_TIMEOUT 1 +#endif /*DOCH_DPD_DEFAULT_DPD_TIMEOUT*/ +/*================================= */ +/* end of DOCH power mode settings */ + + +/* Memory allocation */ +/*===================*/ +#ifndef DOCH_MALLOC + #ifdef FL_MALLOC + #define DOCH_MALLOC FL_MALLOC + #endif /*FL_MALLOC*/ +#endif /*DOCH_MALLOC*/ + +#ifndef DOCH_FREE + #ifdef FL_FREE + #define DOCH_FREE FL_FREE + #endif /*FL_FREE*/ +#endif /*DOCH_FREE*/ + +/* System init/release functions */ +/*===============================*/ +#ifndef DOCH_SYS_FUNC_INIT +#define DOCH_SYS_FUNC_INIT +#endif /* DOCH_SYS_FUNC_INIT */ + +#ifndef DOCH_SYS_FUNC_RELEASE + #ifdef FL_SYS_FUNC_RELEASE + #define DOCH_SYS_FUNC_RELEASE FL_SYS_FUNC_RELEASE + #else /*FL_SYS_FUNC_RELEASE*/ + #define DOCH_SYS_FUNC_RELEASE() + #endif /*FL_SYS_FUNC_RELEASE*/ +#endif /*DOCH_SYS_FUNC_RELEASE*/ + +/* DMA transfer */ +/*==============*/ +#ifndef DOCH_DMA_CONFIG + #ifdef FL_DMA_CONFIG + #define DOCH_DMA_CONFIG FL_DMA_CONFIG + #endif /*FL_DMA_CONFIG*/ +#endif + + +/* DMA type flags - FL_DMA_CONFIG */ +/*===================================*/ +/* Note: DMA_Params_S is defined in flsystyp.h */ +#define DOCH_DMA_OPEN_CHANNEL 0 +#define DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST 1 +#define DOCH_DMA_FREE_CHANNEL 2 +#define DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END 3 +#define DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END 4 +#define DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE 5 + +#define DMA_OPEN_CHANNEL DOCH_DMA_OPEN_CHANNEL +#define DMA_CONFIG_TRANSACTION DOCH_DMA_CONFIG_TRANSACTION_DEVICE_TO_HOST +#define DMA_FREE_CHANNEL DOCH_DMA_FREE_CHANNEL +#define DMA_WAIT_FOR_TRANSACTION_END DOCH_DMA_WAIT_FOR_READ_TRANSACTION_END +#define DMA_CONFIG_WRITE_TRANSACTION DOCH_DMA_CONFIG_TRANSACTION_HOST_TO_DEVICE +#define DMA_WAIT_FOR_WRITE_TRANSACTION_END DOCH_DMA_WAIT_FOR_WRITE_TRANSACTION_END + +#ifndef DOCH_DMA_PULSE_WIDTH + #define DOCH_DMA_PULSE_WIDTH 0x001F +#endif /*DOCH_DMA_PULSE_WIDTH*/ + +/* DOCH_DMA_CHECK_BUFFER checks if buffer is suitable for DMA transfer*/ +#ifndef DOCH_DMA_CHECK_BUFFER + #define DOCH_DMA_CHECK_BUFFER(bufAddress, sectors) (((FLDword)bufAddress & 0x3) == 0) +#endif /*DOCH_DMA_CHECK_BUFFER*/ + +/* Burst Mode */ +/*============*/ + +#ifndef DOCH_USE_BURST_MODE_READ + #ifdef FL_USE_BURST_MODE_READ + #define DOCH_USE_BURST_MODE_READ + #endif /*FL_USE_BURST_MODE_READ*/ +#endif /*DOCH_USE_BURST_MODE_READ*/ + +#ifdef DOCH_USE_BURST_MODE_READ + + #ifndef DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + #ifdef FL_USE_BURST_MODE_READ_ONLY_IN_DMA + #define DOCH_USE_BURST_MODE_READ_ONLY_IN_DMA + #endif /*FL_USE_BURST_MODE_READ*/ + #endif /*DOCH_USE_BURST_MODE_READ*/ + + #ifndef DOCH_HOST_ENTER_READ_BURST_MODE + #ifdef FL_HOST_ENTER_BURST_MODE + #define DOCH_HOST_ENTER_READ_BURST_MODE FL_HOST_ENTER_BURST_MODE + #else /*FL_HOST_ENTER_BURST_MODE*/ + #define DOCH_HOST_ENTER_READ_BURST_MODE + #endif /*FL_HOST_ENTER_BURST_MODE*/ + #endif /*DOCH_HOST_ENTER_READ_BURST_MODE*/ + + #ifndef DOCH_HOST_EXIT_READ_BURST_MODE + #ifdef FL_HOST_EXIT_BURST_MODE + #define DOCH_HOST_EXIT_READ_BURST_MODE FL_HOST_EXIT_BURST_MODE + #else /*FL_HOST_EXIT_BURST_MODE*/ + #define DOCH_HOST_EXIT_READ_BURST_MODE + #endif /*FL_HOST_EXIT_BURST_MODE*/ + #endif /*DOCH_HOST_EXIT_READ_BURST_MODE*/ + + #ifndef DOCH_READ_STATUS_ASYNC_IN_BURST + #ifdef FL_READ_STATUS_ASYNC_IN_BURST + #define DOCH_READ_STATUS_ASYNC_IN_BURST + #endif /*FL_READ_STATUS_ASYNC_IN_BURST*/ + #endif /*DOCH_READ_STATUS_ASYNC_IN_BURST*/ + +#endif /*DOCH_USE_BURST_MODE_READ*/ + +#ifdef DOCH_USE_BURST_MODE_WRITE + + #ifndef DOCH_HOST_ENTER_WRITE_BURST_MODE + #define DOCH_HOST_ENTER_WRITE_BURST_MODE + #endif /*DOCH_HOST_ENTER_WRITE_BURST_MODE*/ + + #ifndef DOCH_HOST_EXIT_WRITE_BURST_MODE + #define DOCH_HOST_EXIT_WRITE_BURST_MODE + #endif /*DOCH_HOST_EXIT_WRITE_BURST_MODE*/ + +#endif /*DOCH_USE_BURST_MODE_WRITE*/ + +#ifndef DOCH_BURST_LENGTH + #ifdef BURST_LENGTH + #define DOCH_BURST_LENGTH ( (((BURST_LENGTH)-2)& 0x03 ) <<11) + #else + #ifdef FL_USE_BURST_MODE_READ + #ifdef FL_MIGRATION_VERSION + #error BURST_LENGTH must be defined, when FL_USE_BURST_MODE_READ defined + #else + #error DOCH_BURST_LENGTH must be defined, when DOCH_USE_BURST_MODE_READ defined + #endif /* migration*/ + #endif /*FL_USE_BURST_MODE_READ*/ + #endif /* BURST_LENGTH */ +#endif /*DOCH_BURST_LENGTH*/ + +#ifndef DOCH_BURST_LATENCY + #ifdef BURST_LATENCY + #define DOCH_BURST_LATENCY ( ((BURST_LATENCY)& 0x07 )<<8) + #else + #ifdef FL_USE_BURST_MODE_READ + #ifdef FL_MIGRATION_VERSION + #error BURST_LATENCY must be defined, when FL_USE_BURST_MODE_READ defined + #else + #error DOCH_BURST_LATENCY must be defined, when DOCH_USE_BURST_MODE_READ defined + #endif /* migration*/ + #endif /*FL_USE_BURST_MODE_READ*/ + #endif /* BURST_LENGTH */ +#endif /*DOCH_BURST_LATENCY*/ + +#ifndef DOCH_BURST_HOLD + #ifdef BURST_HOLD + #define DOCH_BURST_HOLD ((BURST_HOLD)<<13) + #else + #ifdef FL_USE_BURST_MODE_READ + #ifdef FL_MIGRATION_VERSION + #error BURST_HOLD must be defined, when FL_USE_BURST_MODE_READ defined + #else + #error DOCH_BURST_HOLD must be defined, when DOCH_USE_BURST_MODE_READ defined + #endif /* migration*/ + #endif /*FL_USE_BURST_MODE_READ*/ + #endif /* BURST_HOLD */ +#endif /*DOCH_BURST_HOLD*/ + +#ifndef DOCH_BURST_WAIT_STATE + #ifdef BURST_WAIT_STATE + #define DOCH_BURST_WAIT_STATE ( ((BURST_WAIT_STATE)&0x03 )<<4) + #else + #ifdef FL_USE_BURST_MODE_READ + #ifdef FL_MIGRATION_VERSION + #error BURST_WAIT_STATE must be defined, when FL_USE_BURST_MODE_READ defined + #else + #error DOCH_BURST_WAIT_STATE must be defined, when DOCH_USE_BURST_MODE_READ defined + #endif /* migration*/ + #endif /*FL_USE_BURST_MODE_READ*/ + #endif +#endif /*DOCH_BURST_WAIT_STATE*/ + +/* end of BURST definitions for H3 */ +/*=================================*/ + + + +/* Interrupt enabling */ +/*====================*/ + +#define DOCH_INT_RB_DISABLED 0x00 +#define DOCH_INT_RB_ENABLED 0x01 + +#ifndef DOCH_IRQ_RB_INIT + #ifdef FL_IRQ_RB_INIT + #define DOCH_IRQ_RB_INIT(wSockeNo) FL_IRQ_RB_INIT((wSockeNo)) + #else /*FL_IRQ_RB_INIT*/ + #define DOCH_IRQ_RB_INIT(wSockeNo) gDochIrqEnabled[(wSockeNo)] + #endif /*FL_IRQ_RB_INIT*/ +#endif /*DOCH_IRQ_RB_INIT*/ + +/* MACRO for "Wait on Interrupt" */ +/*===============================*/ +#ifndef DOCH_SLEEP + #ifdef FL_TFFS_SLEEP + #define DOCH_SLEEP(socket, device, microseconds) FL_TFFS_SLEEP(socket, microseconds) + #else + #define DOCH_SLEEP(socket, device, microseconds) + #endif /*FL_TFFS_SLEEP*/ +#endif /*DOCH_SLEEP*/ + +/* MACRO for notifying application that an interrupt had occurred + and was NOT yet serviced */ +/*==========================*/ +#ifndef DOCH_UNSERVICED_INTERRUPT + #define DOCH_UNSERVICED_INTERRUPT(socket, device) DOCH_SLEEP(socket, device, 0) +#endif /*DOCH_UNSERVICED_INTERRUPT*/ + + +/* DOCH HW Configuration defaults */ +/*================================*/ + +#ifndef DOCH_BURST_WRITE_MODE_DEFAULT + #define DOCH_BURST_WRITE_MODE_DEFAULT (DOCH_BURST_DISABLE | DOCH_BURST_HOLD_1_CLK | DOCH_BURST_LEN_4_CYC) +#endif /*DOCH_BURST_WRITE_MODE_DEFAULT*/ + +#ifndef DOCH_BURST_READ_MODE_DEFAULT + #define DOCH_BURST_READ_MODE_DEFAULT (DOCH_BURST_DISABLE | DOCH_BURST_HOLD_1_CLK | DOCH_BURST_LEN_4_CYC) +#endif /*DOCH_BURST_READ_MODE_DEFAULT*/ + +#ifndef DOCH_IPL_CTRL_DEFAULT + #define DOCH_IPL_CTRL_DEFAULT (DOCH_IPL_WRITE_DISABLE | DOCH_IPL_ALL_CS_ENABLED) +#endif /*DOCH_IPL_CTRL_DEFAULT*/ + +#ifndef DOCH_WARM_BOOT_CTRL_DEFAULT + #define DOCH_WARM_BOOT_CTRL_DEFAULT (DOCH_WARM_RST_POLARITY_HIGH | DOCH_WARM_RST_BURST_ON) +#endif /*DOCH_WARM_BOOT_CTRL_DEFAULT*/ + +#ifndef DOCH_POWER_DOWN_DEFAULT + #define DOCH_POWER_DOWN_DEFAULT (DOCH_DPD_PIN_POL_HIGH | DOCH_DPD_PIN_ENABLED | DOCH_DPD_WAKEUP_HOST_CE) +#endif /*DOCH_POWER_DOWN_DEFAULT*/ + +#ifndef DOCH_DMA_CTRL_DEFAULT + #define DOCH_DMA_CTRL_DEFAULT (DOCH_DMA_REQ_POL_LOW | DOCH_DMA_REQ_EDGE | ((DOCH_DMA_PULSE_WIDTH)<<4)) +#endif /*DOCH_DMA_CTRL_DEFAULT*/ + +#ifndef DOCH_DMA_NEGATION_CTRL_DEFAULT + #define DOCH_DMA_NEGATION_CTRL_DEFAULT 1 +#endif /*DOCH_DMA_NEGATION_CTRL_DEFAULT*/ + +#ifndef DOCH_SLOCK_DEFAULT + #define DOCH_SLOCK_DEFAULT DOCH_SLOCK_OFF +#endif /*DOCH_SLOCK_DEFAULT*/ + +#ifndef DOCH_ENDIAN_CTRL_DEFAULT + #ifdef FL_SWAP_BYTES + #define DOCH_ENDIAN_CTRL_DEFAULT (HIB_END_SWAP_ON) + #else /*FL_SWAP_BYTES*/ + #define DOCH_ENDIAN_CTRL_DEFAULT (HIB_END_SWAP_OFF) + #endif /*FL_SWAP_BYTES*/ +#endif /*DOCH_ENDIAN_CTRL_DEFAULT*/ + +#ifndef DOCH_OPERATION_MODE_CTRL_DEFAULT + #define DOCH_OPERATION_MODE_CTRL_DEFAULT (HIB_ADDR_SHIFT | HIB_NON_PIPE_ACCESS) +#endif /*DOCH_OPERATION_MODE_CTRL_DEFAULT*/ + + +/*Max number of devices per ATA socket (defined by ATA standard)*/ +#ifndef ATA_MAX_NUM_OF_DEVICES /* for mDOC H3 devices only */ + #define ATA_MAX_NUM_OF_DEVICES 1 /* should be 1 or 2 */ +#endif /* ATA_MAX_NUM_OF_DEVICES */ + +/*If a wait is needed between identifying Dev0 and Dev1, customize DOCH_WAIT_B4_DEV1_ID*/ +#ifndef DOCH_WAIT_B4_DEV1_ID + #define DOCH_WAIT_B4_DEV1_ID +#endif /*DOCH_WAIT_B4_DEV1_ID*/ + +/*If a wait is needed after switching between Dev0 and Dev1, customize DOCH_DELAY_USEC*/ +#ifndef DOCH_DELAY_USEC +#ifdef FL_DELAY_USEC + #define DOCH_DELAY_USEC(usec) FL_DELAY_USEC(usec) +#else + #define DOCH_DELAY_USEC(usec) def_dochDelayUsec(usec,gDochAccessNanosec) +#endif /*FL_DELAY_USEC*/ +#endif /*DOCH_DELAY_USEC*/ + +#ifndef DOCH_DELAY_MSEC +#ifdef FL_DELAY_MSEC + #define DOCH_DELAY_MSEC(msec) FL_DELAY_MSEC(msec) +#else + #define DOCH_DELAY_MSEC(msec) def_dochDelayUsec(1000*msec,gDochAccessNanosec) +#endif /*FL_DELAY_MSEC*/ +#endif /*DOCH_DELAY_MSEC*/ + +/*Accessing same register twice requires delay*/ +#ifndef FL_DELAY_BEFORE_ACCESSING_SAME_REGISTER + #define DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER \ + def_dochDelayUsec(4,25) +#else + #define DOCH_DELAY_BEFORE_ACCESSING_SAME_REGISTER \ + FL_DELAY_BEFORE_ACCESSING_SAME_REGISTER +#endif /*FL_DELAY_BEFORE_ACCESSING_SAME_REGISTER*/ + +#if (ATA_MAX_NUM_OF_DEVICES == 2) + + #ifndef FL_SUPPORT_PARALLEL_SDK_INSTANCES + #define DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + #endif /*FL_SUPPORT_PARALLEL_SDK_INSTANCES*/ + + /*cascaded configuration requires delay after switching between Dev0 and Dev1*/ + #ifndef DOCH_DELAY_AFTER_DEVICE_SWITCH + #ifdef DOCH_NO_SUPPORT_PARALLEL_SDK_INSTANCES + /* delay only when switching floors */ + #define DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,floorNo)\ + if ((pdev)->bLastDevNum ^ (floorNo))\ + { \ + DOCH_DELAY_USEC(4); \ + (pdev)->bLastDevNum = (floorNo);\ + } + #else /*DOCH_SUPPORT_PARALLEL_SDK_INSTANCES*/ + /* always delay after setting device head register */ + #define DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,floorNo)\ + DOCH_DELAY_USEC(4) /* 4 uSec delay */ + #endif /*DOCH_SUPPORT_PARALLEL_SDK_INSTANCES*/ + #endif /*DOCH_DELAY_AFTER_DEVICE_SWITCH*/ + + /*cascaded configuration requires delay after each trial of reading chip ID from SLAVE*/ + #ifndef DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE + #define DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE DOCH_DELAY_MSEC(1) /* 1 mSec delay*/ + #endif /*DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE*/ + + /*cascaded configuration requires several trials of reading chip ID*/ + /* 2 seconds timeout for finding SLAVE ~ 2000 trials * 1mSec delay */ + #ifndef DOCH_CHIP_ID_TRIALS_FOR_SLAVE + #define DOCH_CHIP_ID_TRIALS_FOR_SLAVE 2000 + #endif /*DOCH_CHIP_ID_TRIALS_FOR_SLAVE*/ + +#else /*if (ATA_MAX_NUM_OF_DEVICES == 2)*/ + /* single floor does not require any delays*/ + + #ifndef DOCH_DELAY_AFTER_DEVICE_SWITCH + #define DOCH_DELAY_AFTER_DEVICE_SWITCH(pdev,floorNo) /*no delay is needed*/ + #endif /*DOCH_DELAY_AFTER_DEVICE_SWITCH*/ + + #ifndef DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE + #define DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE /*no delay is needed*/ + #endif /*DOCH_DELAY_BETWEEN_CHIP_ID_TRIALS_FOR_SLAVE*/ + + #ifndef DOCH_CHIP_ID_TRIALS_FOR_SLAVE + #define DOCH_CHIP_ID_TRIALS_FOR_SLAVE 0 /* no trials for reading second floor*/ + #endif /*DOCH_CHIP_ID_TRIALS_FOR_SLAVE*/ + +#endif /*if (ATA_MAX_NUM_OF_DEVICES == 2)*/ + +/* Delay cell configuration*/ +/* +0000: No Delay +0001: 1x delay. +0011: 2x delay. +0111: 3x delay. +*/ + +#ifndef FL_IPL_DELAY_CELL_CONFIG_READ + #define FL_IPL_DELAY_CELL_CONFIG_READ 0 +#endif /*FL_IPL_DELAY_CELL_CONFIG_READ*/ + +#ifndef FL_IPL_DELAY_CELL_CONFIG_WRITE + #define FL_IPL_DELAY_CELL_CONFIG_WRITE 0 +#endif /*FL_IPL_DELAY_CELL_CONFIG_READ*/ + + +/*===========================*/ +/* Access Layer Customization*/ +/* --------------------------*/ +/* 2 Sections: */ +/* - Run-Time */ +/* - Compile Time */ +/*===========================*/ +#ifdef DOCH_BIG_ENDIAN +#define C_16_8(a) ((FLByte)((a)>>8)) +#define C_8_16(a) (((FLWord)(a))<<8) +#define C_16_16(a) ((FLWord)((a)<<8) | ((a)>>8)) +#else +#define C_16_8(a) ((FLByte)(a)) +#define C_8_16(a) ((FLWord)(a)) +#define C_16_16(a) ((FLWord)(a)) +#endif /* DOCH_BIG_ENDIAN */ + +#ifdef DOCH_USE_FUNC /*Run-time*/ + +/* DOCH Access Layer macros */ +/*==========================*/ +#ifndef DOCHREAD_ATA_REG +#define DOCHREAD_ATA_REG(base, regNum) C_16_8(pdev->halRoutines.hal_get_ata_reg(base, regNum)) +#endif /*DOCHREAD_ATA_REG*/ +#ifndef DOCHWRITE_ATA_REG +#define DOCHWRITE_ATA_REG(base, regNum, val) (pdev->halRoutines.hal_set_ata_reg(base, regNum, C_8_16(val))) +#endif /*DOCHWRITE_ATA_REG*/ +#ifndef DOCHREAD_CTRL_REG +#define DOCHREAD_CTRL_REG(base, regNum) C_16_16(pdev->halRoutines.hal_get_ctrl_reg(base, regNum)) +#endif /*DOCHREAD_CTRL_REG*/ +#ifndef DOCHWRITE_CTRL_REG +#define DOCHWRITE_CTRL_REG(base, regNum, val) (pdev->halRoutines.hal_set_ctrl_reg(base, regNum, C_16_16(val))) +#endif /*DOCHWRITE_CTRL_REG*/ +#ifndef DOCHBLK_READ +#define DOCHBLK_READ(address, buf, sectors) (pdev->halRoutines.hal_blk_read(address, buf, sectors)) +#endif /*DOCHBLK_READ*/ +#ifndef DOCHBLK_WRITE +#define DOCHBLK_WRITE(address, buf, sectors) (pdev->halRoutines.hal_blk_write(address, buf, sectors)) +#endif /*DOCHBLK_WRITE*/ + +#ifndef DOCHREAD_BURST + #define DOCHREAD_BURST(base, offset, dest, sectors) +#endif /*DOCHREAD_BURST*/ + +#ifndef DOCHWRITE_BURST + #define DOCHWRITE_BURST(base, offset, dest, sectors) +#endif /*DOCHWRITE_BURST*/ + + /* DOCH IO Access macros */ + /*=======================*/ + #ifndef DOCHREAD_IO_WORD + #define DOCHREAD_IO_WORD(address) (FLREAD_IO_WORD(address)) + #endif /*DOCHREAD_IO_WORD*/ + + #ifndef DOCHWRITE_IO_WORD + #define DOCHWRITE_IO_WORD(val, address) (FLWRITE_IO_WORD(val, address)) + #endif /*DOCHWRITE_IO_WORD*/ + + #ifndef DOCHCPY_TO_IO_16_BITS + #define DOCHCPY_TO_IO_16_BITS(win,buf,sectors) (blk_write_using_data_reg(win, buf, sectors)) + #endif /*DOCHCPY_TO_IO_16_BITS*/ + + #ifndef DOCHCPY_FROM_IO_16_BITS + #define DOCHCPY_FROM_IO_16_BITS(win,buf,sectors) (blk_read_using_data_reg(win, buf, sectors)) + #endif /*DOCHCPY_FROM_IO_16_BITS*/ + +#else /*DOCH_USE_FUNC*/ /*Compile-Time*/ +#ifdef FL_MIGRATION_VERSION +/* DOCH Access Layer macros */ +/*==========================*/ +#ifndef DOCHREAD_ATA_REG +#define DOCHREAD_ATA_REG(base, regNum) C_16_8(flDirectRead16BitReg((DOCHFlash),(FLWord)(((regNum)<<1) + DOCH_CONT_REG_AREA))) +#endif /*DOCHREAD_ATA_REG*/ +#ifndef DOCHWRITE_ATA_REG +#define DOCHWRITE_ATA_REG(base, regNum, val) flDirectWrite16BitReg((DOCHFlash),(FLWord)(((regNum)<<1) + DOCH_CONT_REG_AREA),(FLWord)(C_8_16(val))) +#endif /*DOCHWRITE_ATA_REG*/ +#ifndef DOCHREAD_CTRL_REG +#define DOCHREAD_CTRL_REG(base, regNum) C_16_16(flDirectRead16BitReg((DOCHFlash),(FLWord)(regNum))) +#endif /*DOCHREAD_CTRL_REG*/ +#ifndef DOCHWRITE_CTRL_REG +#define DOCHWRITE_CTRL_REG(base, regNum, val) flDirectWrite16BitReg((DOCHFlash),(FLWord)(regNum),(FLWord)(C_16_16(val))) +#endif /*DOCHWRITE_CTRL_REG*/ +#ifndef DOCHBLK_READ +#define DOCHBLK_READ(address, buf, sectors) (flReadEvenNumberOfBytes((DOCHFlash),(FLWord)DOCH_DATA_PORT_AREA,(buf),((FLWord)(512*sectors))),0) +#endif /*DOCHBLK_READ*/ +#ifndef DOCHBLK_WRITE +#define DOCHBLK_WRITE(address, buf, sectors) (flWriteEvenNumberOfBytes((DOCHFlash),(FLWord)DOCH_DATA_PORT_AREA,(buf),((FLWord)(512*sectors))),0) +#endif /*DOCHBLK_WRITE*/ + +#ifndef DOCHREAD_BURST +#define DOCHREAD_BURST(base, offset, dest, sectors) DOCHBLK_READ( (base)+(offset), dest, sectors) +#endif /*DOCHREAD_BURST*/ + +#ifndef DOCHWRITE_BURST +#define DOCHWRITE_BURST(base, offset, dest, sectors) DOCHBLK_WRITE( (base)+(offset), dest, sectors) +#endif /*DOCHWRITE_BURST*/ + + +/* DOCH IO Access macros */ +/*=======================*/ +/* Not defined as we use legacy code */ + +#else /* FL_MIGRATION_VERSION */ + + #ifndef DOCHREAD_ATA_REG + #define DOCHREAD_ATA_REG(base, regNum) \ + (FLByte)(DOCHREAD_IO_WORD((((volatile FLWord FAR0 *)base)+regNum + (DOCH_CONT_REG_AREA/2)))) + #endif /*DOCHREAD_ATA_REG*/ + + #ifndef DOCHWRITE_ATA_REG + #define DOCHWRITE_ATA_REG(base, regNum, val) \ + DOCHWRITE_IO_WORD((FLWord)val,(((volatile FLWord FAR0 *)base)+regNum + (DOCH_CONT_REG_AREA/2))) + #endif /*DOCHWRITE_ATA_REG*/ + + #ifndef DOCHREAD_CTRL_REG + #define DOCHREAD_CTRL_REG(base, regNum) \ + DOCHREAD_IO_WORD(base + regNum) + #endif /*DOCHREAD_CTRL_REG*/ + + #ifndef DOCHWRITE_CTRL_REG + #define DOCHWRITE_CTRL_REG(base, regNum, val) \ + DOCHWRITE_IO_WORD((FLWord)val, (base + regNum)) + + #endif /*DOCHWRITE_CTRL_REG*/ + + #ifndef DOCHBLK_READ + #define DOCHBLK_READ(address, buf, sectors) \ + DOCHCPY_FROM_IO_16_BITS(address, buf, sectors) + #endif /*DOCHBLK_READ*/ + + #ifndef DOCHBLK_WRITE + #define DOCHBLK_WRITE(address, buf, sectors) \ + DOCHCPY_TO_IO_16_BITS(address, buf, sectors) + #endif /*DOCHBLK_WRITE*/ + + /* DOCH IO Access macros */ + /*=======================*/ + #ifndef DOCHREAD_IO_WORD + #define DOCHREAD_IO_WORD(address) (FLREAD_IO_WORD(address)) + #endif /*DOCHREAD_IO_WORD*/ + + #ifndef DOCHWRITE_IO_WORD + #define DOCHWRITE_IO_WORD(val, address) (FLWRITE_IO_WORD(val, address)) + #endif /*DOCHWRITE_IO_WORD*/ + + #ifndef DOCHCPY_TO_IO_16_BITS + #define DOCHCPY_TO_IO_16_BITS(win,buf,sectors) TFFSCPY_TO_IO_16_BITS(win,buf,(sectors<dwVirtAddr) != flOK ) + { + PrintkDebug ("mDOC not found"); + return flAdapterNotFound; + } + + PrintkInfo ("mDOC found"); + psoc->fFound = 1; + + return flOK; +} + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flcustom.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flcustom.h new file mode 100755 index 00000000..f0635ab6 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flcustom.h @@ -0,0 +1,386 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + + +#ifndef FLCUSTOM_H +#define FLCUSTOM_H + + +/* Driver & TrueFFS Version numbers (Previously named OSAK) + * + * The string must not be greater than 10 characters. + * + * Note: Other then being returned by the the flVolumeInfo() routine this + * value has no actual affect on the TrueFFS software. + */ +#define driverVersion "1.1.0" +#define OSAKVersion "1.1.0" + + +#define TFFS_SUPPORTED_DEVICE "H3" + + +/* + * debug/diagnostic messages + */ +#define TFFS_DEBUG_DRIVER + +#ifdef TFFS_DEBUG_DRIVER + +/* EXT filter debug messages */ +# define TFFS_DEBUG_EXTFILTER + +/* enable TFFS debug messages and fl_debug insmod argument */ +# define TFFS_MESSAGES_ENABLED + +/* default for fl_debug parameter: 0 - no messages, 1 - errors, 2 - warnings, 4 - flow */ +# define FL_DEBUG_DEF 2 + +/* #define TFFS_COUNT_REQ_SECTORS */ + +#endif /* TFFS_DEBUG_DRIVER */ + + +/* + * Collect various driver statistics + */ +#define TFFS_STATISTIC + + +/* + * comment out this macro if you want to get "MTD-style" + */ +#define TFFS_PARTITIONABLE + + +/* + * Scatter/gather of read/write requests in tffsdrv.c + */ +#define TFFS_REQ_CACHE_SIZE (4096 * 16) + + +#define DEV2PART_SHIFT 4 /* at most 15 file system partitions per disk */ +#define TFFS_DEVICE_NAME "tffs" +#define TFFS_MAXHW_SECTOR_SIZE_BITS 0 + + +/* + * allow using of unformatted DiskOnChip devices + */ +#define TFFS_ALLOW_UNFORMATTED + + +/* + * allow yielding CPU during flash write/erase operations + */ +#define TFFS_USE_SLEEP + + +/* Number of sockets + * + * Defines the maximum number of supported physical DiskOnChip devices. + * + * The actual number of sockets depends on which socket controllers are + * actually registered and the number of physical devices in the system. + */ +#define FL_SOCKETS 1 + + +/* Number of volumes + * + * Defines the maximum number of supported Disk (BDTL) partitions. + * + * The actual number of drives depends on which socket controllers are + * actually registered, the amount of devices in the system and the + * flash format placed on each device. + */ +#define FL_VOLUMES (14 * FL_SOCKETS) + + +/* Environment Variables + * + * Enable environment variables control of the TrueFFS features. + * + */ +#define FL_ENVIRONMENT_VARS + + +/* #define DOCH_ACCESS_LAYER_NOR */ +/* #define DOCH_ACCESS_LAYER_SPI */ + + +/* If you are using two cascaded DiskOnChip H3 devices, uncomment + * line below; otherwise keep it commented out. + */ +/* #define ATA_MAX_NUM_OF_DEVICES 2 */ /* only when using casacded devices */ + + +/* Forces the device into the deep power down mode after every driver operation */ +/* Compile the auto DPD code + * + * TrueFFS supports a mode, where TrueFFS automatically enters and exit DPD + * after every operation. + * + * The compilation bellow compiles that code. Note that it's operation is + * also under the affect of the dedicated environment variable. + */ +#define FL_BD_AUTO_DPD_MODE +#define FL_DEFAULT_BD_DPD_MODE(socket) tffs_auto_dpd +extern int tffs_auto_dpd; + + +/* Upon completion of every read/write access, DiskOnChip H3 devices + * immediately switch from the normal mode into the idle mode, and stay + * in the idle mode for 'DOCH_DPD_DEFAULT_DPD_TIMEOUT' milliseconds before + * switching into deep-power-down mode. + */ +#define DOCH_DPD_DEFAULT_DPD_TIMEOUT tffs_dpd_timeout +extern int tffs_dpd_timeout; + + +/* + * Remove all flash write functionalities from the code. + * + * When this option is selected, only API functions that do not involve write + * operations to the media can be called. + * + * This option can be used to create read-only applications with low RAM/ROM + * requirements. + */ +/* #define TFFS_RO */ +#ifdef TFFS_RO +# define FL_READ_ONLY +#endif + +/* IO Controll Interface + * + * Support standard IOCTL interface. + * + */ +#define FL_IOCTL_INTERFACE + + +#ifdef FL_IOCTL_INTERFACE + +/* Low level operations + * + * Uncomment the following line if you want to do low level operations + * (i.e. read from a physical address, write to a physical address, + * erase a unit according to its physical unit number, OTP and unique ID + * operations. + */ +# define FL_LOW_LEVEL + +/* Flash Formatting (Block device format) + * + * Uncomment the following line if you need to prepare a virgin DiskOnChip + * for work or in case you want to re-partition your existing device. + * + * This routine compiles the following 3 API routines: + * flFlashFormat(), flEraseBD() and flUnformat() + */ + +# ifndef TFFS_RO +# define FL_FORMAT_VOLUME +# endif + +/* H/W OTP + * + * Enable H/W One Time Programing capability including unique ID + * + */ +# define HW_OTP + +#endif /* FL_IOCTL_INTERFACE */ + + +/* Application exit + * + * If the FLite application ever exits, it needs to call flEXit before + * exiting. Uncomment the following line to enable this. + */ +#define FL_EXIT + + +/* H/W Protection + * + * Enable H/W protection of the device. + * + */ +#define HW_PROTECTION + + +/* Compile the code for reading after write + * + * Compiles the code and buffers for reading after every write operation + * This mode is used for debugging when you are still debugging the platform's + * H/W. + */ +#define FL_VERIFY_WRITE + + +/* Verify entire volume + * + * Compile the flVerifyVolume() routine - this routine scans the entire disk + * partition for power failures symptoms and correct them while initializing + * the TL cache. + * + */ +/* #define VERIFY_VOLUME */ + + +#ifdef FL_IOCTL_INTERFACE + +/* Binary Partition + * + * Enables access to the Binary partition. + * + */ +# define BDK_ACCESS + +#endif + + +#ifdef BDK_ACCESS + +/* Number of Binary partitions on the DiskOnChip. + * + * Defines Maximum Number of Binary partitions on the DiskOnChip. + * The actual number of partitions depends on the format placed + * on each device. + */ +# define FL_BINARY_PARTITIONS (3 * FL_SOCKETS) + +#endif /* BDK_ACCESS */ + + +/* Remove runtime controll over memory access routines + * + * If defined memory access routines will be set at compile time using + * dedicated defintions in flsystem.h + * Note : when compile time customization is chosen, you must sepcify + * the bus width even when working with DiskOnChip Millennium Plus. + * Refer to Trueffs manual for more infromation. + */ +/* #define FL_NO_USE_FUNC */ + + +/* + * Removes the code used for writing and reading the IPL code. + * + */ +#ifndef FL_IOCTL_INTERFACE +# define NO_IPL_CODE +#endif + + +/* Little-endian/big-endian + * + * FAT and translation layer structures use the little-endian (Intel) + * format for integers. + * If your machine uses the big-endian (Motorola) format, uncomment the + * following line. + * Note that even on big-endian machines you may omit the BIG_ENDIAN + * definition for smaller code size and better performance, but your media + * will not be compatible with standard FAT and FTL. + */ +/* #define FL_BIG_ENDIAN */ + + +/* #define FL_NO_INIT_MMU_PAGES */ + + +/* Compile the extended Disk information routine + * + * TrueFFS 6.0 and up provide an extended information routine for internal + * M-Systems utilities named flGetExtendedDiskInfo(). + * To compile its code define + */ +#define FL_EXTENDED_DISK_INFO + + +/* #define FL_NO_QUICK_MOUNT_FEATURE */ + + +/* Disable the automatic argument check + * + * You can remove code and even slightly improve the overall performance by + * allowing TrueFFS to skip its internal argument check by defining + * + */ +/* #define FL_SKIP_ARGS_CHECK */ + + +/* Absolute read & write + * + * Uncomment the following line if you want to be able to read & write + * sectors by absolute sector number (i.e. without regard to files and + * directories). + */ +#define FL_ABS_READ_WRITE + + +/* + * Include code related to DiskOnChip H3 burst mode + */ +#define DOCH_USE_BURST_MODE_READ +/* #define DOCH_USE_BURST_MODE_WRITE */ + +# if defined(DOCH_USE_BURST_MODE_READ) || defined(DOCH_USE_BURST_MODE_WRITE) + +# define BURST_LENGTH tffs_burst_length +# define BURST_LATENCY tffs_burst_latency +# define BURST_HOLD tffs_burst_hold +# define BURST_WAIT_STATE tffs_burst_ws + +# ifdef DOCH_USE_BURST_MODE_READ +# define FL_USE_BURST_MODE_READ +# endif + +# ifdef DOCH_USE_BURST_MODE_WRITE +# define FL_USE_BURST_MODE_WRITE +# endif + + extern int tffs_burst_length, tffs_burst_latency, tffs_burst_hold, tffs_burst_ws; + extern int tffs_burst_enabled; + +# endif /* DOCH_USE_BURST_MODE_READ || DOCH_USE_BURST_MODE_WRITE */ + + +extern unsigned int profiling[]; + + +#endif /* FLCUSTOM_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flioctl.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flioctl.c new file mode 100755 index 00000000..f7e61d2e --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flioctl.c @@ -0,0 +1,612 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/bddoc/src/flioctl.c-arc $ + * + * Rev 1.12 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.11 Feb 28 2007 09:58:42 einat.avidan + * No change + * + * Rev 1.10.1.1 Oct 29 2006 14:23:46 Yaniv.Iarovici + * Update 'FL_IOCTL_PASS_THROUGH' structures. + * + * Rev 1.10.1.0 Oct 22 2006 14:53:52 yaniv.iarovici + * Changed protectionType from FLByte to FLWord in flProtectionOutput stucture. + * + * Rev 1.10 Oct 09 2006 14:05:34 yaniv.iarovici + * Removed #ifndef FL_DO_NOT_SUPPORT_H3 + * + * Rev 1.9 Oct 05 2006 11:00:56 yaniv.iarovici + * Fixed support for FL_IOCTL_PASS_THROUGH. + * + * Rev 1.8 Sep 11 2006 13:45:22 yaniv.iarovici + * Legal header added + * + * Rev 1.7 Aug 15 2006 09:32:32 Polina.Marimont + * IPL protection inside + * + * Rev 1.6 Aug 09 2006 16:52:50 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#include "flbase.h" +#include "blockdev.h" +#include "flioctl.h" +#ifdef BDK_ACCESS +#endif + +#ifdef FL_IOCTL_INTERFACE + +/*----------------------------------------------------------------------*/ +/* f l I O c t l */ +/* */ +/* The entry point for all TrueFFS extended functions. */ +/* */ +/* Note: This interface is common to all TrueFFS based drivers. However */ +/* since you can access TrueFFS diretly (without the driver) you */ +/* can also call the extended routines explicitly. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to flIOctlRecord record see flioclt.h */ +/* irFlags : Opcode of the specific extended function. */ +/* See flioctl.h for the complete opcode list. */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ + +TFFS_DLL_API FLStatus NAMING_CONVENTION bdIOctl(IOreq FAR2 *ioreq1) +{ + IOreq ioreq2; + void FAR1 *inputRecord; + void FAR1 *outputRecord; + + inputRecord = ((flIOctlRecord FAR1 *)(ioreq1->irData))->inputRecord; + outputRecord = ((flIOctlRecord FAR1 *)(ioreq1->irData))->outputRecord; + ioreq2.irHandle = ioreq1->irHandle; + + switch (ioreq1->irFlags) { + case FL_IOCTL_GET_INFO: + { + flDiskInfoOutput FAR1 *outputRec = (flDiskInfoOutput FAR1 *)outputRecord; + + ioreq2.irData = &(outputRec->info); + outputRec->status = flVolumeInfo(&ioreq2); + return outputRec->status; + } +#ifndef FL_READ_ONLY + + case FL_IOCTL_DEFRAGMENT: + { + flDefragInput FAR1 *inputRec = (flDefragInput FAR1 *)inputRecord; + flDefragOutput FAR1 *outputRec = (flDefragOutput FAR1 *)outputRecord; + + ioreq2.irLength = inputRec->requiredNoOfSectors; + outputRec->status = flDefragmentVolume(&ioreq2); + outputRec->actualNoOfSectors = ioreq2.irLength; + return outputRec->status; + } + +#ifdef FL_FORMAT_VOLUME + + case FL_IOCTL_FLASH_FORMAT: + { + flFlashFormatInput FAR1 *inputRec = (flFlashFormatInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irLength = inputRec->sdwNoOfKeeps; + ioreq2.irFlags = inputRec->dwFormatFlags; + ioreq2.irData = (void FAR1 *)inputRec->fpPtr; + outputRec->status = flFlashFormat(&ioreq2); + return outputRec->status; + } + case FL_IOCTL_ERASE_BD: + { + flEraseBDInput FAR1 *inputRec = (flEraseBDInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irPath = NULL; /* Progress callback */ + ioreq2.irFlags = inputRec->dwFlags; + outputRec->status = flEraseBD(&ioreq2); + return outputRec->status; + } + case FL_IOCTL_FLASH_UNFORMAT: + { + flFlashUnformatInput FAR1 *inputRec = (flFlashUnformatInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irPath = NULL; /* Progress callback */ + ioreq2.irFlags = inputRec->dwFlags; + outputRec->status = flUnformat(&ioreq2); + return outputRec->status; + } + +#endif /* FL_FORMAT_VOLUME */ +#endif /* FL_READ_ONLY */ + + case FL_IOCTL_MOUNT_VOLUME: + { + flMountInput FAR1 *inputRec = (flMountInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + if (inputRec->type == FL_DISMOUNT) + outputRec->status = flDismountVolume(&ioreq2); + else + outputRec->status = flAbsMountVolume(&ioreq2); + return outputRec->status; + } +#ifdef BDK_ACCESS + case FL_IOCTL_BDK_OPERATION: + { + flBDKOperationInput FAR1 *inputRec = (flBDKOperationInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irData = &(inputRec->bdkStruct); + switch(inputRec->type) { + case BDK_INIT_READ: + outputRec->status = bdkReadInit(&ioreq2); + break; + case BDK_READ: + outputRec->status = bdkReadBlock(&ioreq2); + break; + case BDK_GET_INFO: + outputRec->status = bdkPartitionInfo(&ioreq2); + break; +#ifndef FL_READ_ONLY + case BDK_INIT_WRITE: + outputRec->status = bdkWriteInit(&ioreq2); + break; + case BDK_WRITE: + outputRec->status = bdkWriteBlock(&ioreq2); + break; + case BDK_ERASE: + outputRec->status = bdkErase(&ioreq2); + break; + case BDK_CREATE: + outputRec->status = bdkCreate(&ioreq2); + break; +#endif /* FL_READ_ONLY */ + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } +#endif /* BDK_ACCESS */ +#ifdef HW_PROTECTION +#ifdef BDK_ACCESS + case FL_IOCTL_BINARY_HW_PROTECTION: + { + flProtectionInput FAR1 *inputRec = (flProtectionInput FAR1 *)inputRecord; + flProtectionOutput FAR1 *outputRec = (flProtectionOutput FAR1 *)outputRecord; + + switch(inputRec->type) + { + case PROTECTION_INSERT_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = bdkInsertProtectionKey(&ioreq2); + break; + case PROTECTION_REMOVE_KEY: + outputRec->status = bdkRemoveProtectionKey(&ioreq2); + break; + case PROTECTION_GET_TYPE: + outputRec->status = bdkIdentifyProtection(&ioreq2); + outputRec->protectionType = (FLWord)ioreq2.irFlags; + break; + case PROTECTION_DISABLE_LOCK: + ioreq2.irFlags = 0; + outputRec->status = bdkHardwareProtectionLock(&ioreq2); + break; + case PROTECTION_ENABLE_LOCK: + ioreq2.irFlags = LOCK_ENABLED; + outputRec->status = bdkHardwareProtectionLock(&ioreq2); + break; + case PROTECTION_CHANGE_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = bdkChangeProtectionKey(&ioreq2); + break; + case PROTECTION_CHANGE_TYPE: + ioreq2.irFlags = inputRec->protectionType; + outputRec->status = bdkChangeProtectionType(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } +#endif /* BDK_ACCESS */ + case FL_IOCTL_BDTL_HW_PROTECTION: + { + flProtectionInput FAR1 *inputRec = (flProtectionInput FAR1 *)inputRecord; + flProtectionOutput FAR1 *outputRec = (flProtectionOutput FAR1 *)outputRecord; + + switch(inputRec->type) + { + case PROTECTION_INSERT_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = flInsertProtectionKey(&ioreq2); + break; + case PROTECTION_REMOVE_KEY: + outputRec->status = flRemoveProtectionKey(&ioreq2); + break; + case PROTECTION_GET_TYPE: + outputRec->status = flIdentifyProtection(&ioreq2); + outputRec->protectionType = (FLWord)ioreq2.irFlags; + break; + case PROTECTION_DISABLE_LOCK: + ioreq2.irFlags = 0; + outputRec->status = flHardwareProtectionLock(&ioreq2); + break; + case PROTECTION_ENABLE_LOCK: + ioreq2.irFlags = LOCK_ENABLED; + outputRec->status = flHardwareProtectionLock(&ioreq2); + break; + case PROTECTION_CHANGE_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = flChangeProtectionKey(&ioreq2); + break; + case PROTECTION_CHANGE_TYPE: + ioreq2.irFlags = inputRec->protectionType; + outputRec->status = flChangeProtectionType(&ioreq2); + break; + case PROTECTION_APPLY_STICKY: + outputRec->status = flApplyStickyLock(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } + case FL_IOCTL_IPL_HW_PROTECTION: + { + flProtectionInput FAR1 *inputRec = (flProtectionInput FAR1 *)inputRecord; + flProtectionOutput FAR1 *outputRec = (flProtectionOutput FAR1 *)outputRecord; + + switch(inputRec->type) + { + case PROTECTION_INSERT_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = flIplInsertProtectionKey(&ioreq2); + break; + case PROTECTION_REMOVE_KEY: + outputRec->status = flIplRemoveProtectionKey(&ioreq2); + break; + case PROTECTION_GET_TYPE: + outputRec->status = flIplIdentifyProtection(&ioreq2); + outputRec->protectionType = (FLWord)ioreq2.irFlags; + break; + case PROTECTION_CHANGE_KEY: + ioreq2.irData = inputRec->key; + outputRec->status = flIplChangeProtectionKey(&ioreq2); + break; + case PROTECTION_CHANGE_TYPE: + ioreq2.irFlags = inputRec->protectionType; + outputRec->status = flIplChangeProtectionType(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } +#endif /* HW_PROTECTION */ +#ifdef HW_OTP + case FL_IOCTL_OTP: + { + flOtpInput FAR1 *inputRec = (flOtpInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + switch(inputRec->type) + { + case OTP_SIZE: + outputRec->status = flOTPSize(&ioreq2); + inputRec->lockedFlag = (FLByte)ioreq2.irFlags; + inputRec->length = ioreq2.irCount ; + inputRec->usedSize = ioreq2.irLength ; + break; + case OTP_READ: + ioreq2.irData = inputRec->buffer; /* user buffer */ + ioreq2.irCount = inputRec->usedSize; /* offset */ + ioreq2.irLength = inputRec->length; /* size to read */ + outputRec->status = flOTPRead(&ioreq2); + break; + case OTP_WRITE_LOCK: + ioreq2.irData = inputRec->buffer; /* user buffer */ + ioreq2.irLength = inputRec->length; /* size to read */ + outputRec->status = flOTPWriteAndLock(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } + + case FL_IOCTL_MCOTP: + { + flMCOtpInput FAR1 *inputRec = (flMCOtpInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + switch(inputRec->type) + { + case MCOTP_SIZE: + outputRec->status = flMCOTPSize(&ioreq2); + inputRec->lockedFlag = (FLByte)ioreq2.irFlags; + inputRec->length = ioreq2.irCount ; + inputRec->usedSize = ioreq2.irLength ; + break; + case MCOTP_READ: + ioreq2.irData = inputRec->buffer; /* user buffer */ + ioreq2.irCount = inputRec->wPageNo; /* offset */ + outputRec->status = flMCOTPRead(&ioreq2); + break; + case MCOTP_WRITE_LOCK: + ioreq2.irData = inputRec->buffer; /* user buffer */ + ioreq2.irCount = inputRec->wPageNo; /* offset */ + outputRec->status = flMCOTPWriteAndLock(&ioreq2); + break; + default: + outputRec->status = flBadParameter; + break; + } + return outputRec->status; + } + + case FL_IOCTL_CUSTOMER_ID: + { + flCustomerIdOutput FAR1 *outputRec = (flCustomerIdOutput FAR1 *)outputRecord; + + ioreq2.irData = outputRec->id; + outputRec->status = flGetCustomerID(&ioreq2); + return outputRec->status; + } + + case FL_IOCTL_UNIQUE_ID: + { + flUniqueIdOutput FAR1 *outputRec = (flUniqueIdOutput FAR1 *)outputRecord; + + ioreq2.irData = outputRec->id; + outputRec->status = flGetUniqueID(&ioreq2); + return outputRec->status; + } +#endif /* HW_OTP */ + + case FL_IOCTL_NUMBER_OF_PARTITIONS: + { + flCountPartitionsOutput FAR1 *outputRec = (flCountPartitionsOutput FAR1 *)outputRecord; + + outputRec->status = flCountVolumes(&ioreq2); + outputRec->noOfPartitions = (FLByte) ioreq2.irFlags; + return outputRec->status; + } + +#ifdef FL_LOW_LEVEL + + case FL_IOCTL_DEEP_POWER_DOWN_MODE: + { + flPowerDownInput FAR1 *inputRec = (flPowerDownInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + ioreq2.irFlags = inputRec->state; + outputRec->status = flDeepPowerDownMode(&ioreq2); + return outputRec->status; + } + +#endif /* FL_LOW_LEVEL */ +#ifdef FL_ABS_READ_WRITE +#ifndef FL_READ_ONLY + case FL_IOCTL_DELETE_SECTORS: + { + flDeleteSectorsInput FAR1 *inputRec = (flDeleteSectorsInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + ioreq2.irSectorNo = inputRec->firstSector; + ioreq2.irSectorCount = inputRec->numberOfSectors; + outputRec->status = flAbsDelete(&ioreq2); + return outputRec->status; + } +#endif /* FL_READ_ONLY */ + + case FL_IOCTL_READ_SECTORS: + { + flReadWriteInput FAR1 *inputRec = (flReadWriteInput FAR1 *)inputRecord; + flReadWriteOutput FAR1 *outputRec = (flReadWriteOutput FAR1 *)outputRecord; + + ioreq2.irSectorNo = inputRec->firstSector; + ioreq2.irSectorCount = inputRec->numberOfSectors; + ioreq2.irData = inputRec->buf; + outputRec->status = flAbsRead(&ioreq2); + outputRec->numberOfSectors = ioreq2.irSectorCount; + return outputRec->status; + } +#ifndef FL_READ_ONLY + + case FL_IOCTL_WRITE_SECTORS: + { + flReadWriteInput FAR1 *inputRec = (flReadWriteInput FAR1 *)inputRecord; + flReadWriteOutput FAR1 *outputRec = (flReadWriteOutput FAR1 *)outputRecord; + + ioreq2.irSectorNo = inputRec->firstSector; + ioreq2.irSectorCount = inputRec->numberOfSectors; + ioreq2.irData = inputRec->buf; + outputRec->status = flAbsWrite(&ioreq2); + outputRec->numberOfSectors = ioreq2.irSectorCount; + return outputRec->status; + } +#endif /* FL_READ_ONLY */ +#endif /* FL_ABS_READ_WRITE */ + +#ifdef FL_ENVIRONMENT_VARS + case FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES: + { + flExtendedEnvVarsInput FAR1 *inputRec = (flExtendedEnvVarsInput FAR1 *)inputRecord; + flExtendedEnvVarsOutput FAR1 *outputRec = (flExtendedEnvVarsOutput FAR1 *)outputRecord; + + switch(inputRec->flags) + { + case FL_APPLY_TO_ALL: + outputRec->status = flSetEnvAll(inputRec->varName, + inputRec->varValue,&(outputRec->prevValue)); + break; + case FL_APPLY_TO_SOCKET: + outputRec->status = flSetEnvSocket(inputRec->varName, + FL_GET_SOCKET_FROM_HANDLE((&ioreq2)), + inputRec->varValue,&(outputRec->prevValue)); + break; + case FL_APPLY_TO_VOLUME: + outputRec->status = flSetEnvVolume(inputRec->varName, + FL_GET_SOCKET_FROM_HANDLE((&ioreq2)), + FL_GET_FLASH_PARTITION_FROM_HANDLE((&ioreq2)), + inputRec->varValue,&(outputRec->prevValue)); + break; + default: + DBG_PRINT_ERR(FLZONE_IOCTL,"ERROR - Unrecognized environment variable function flag.\r\n"); + outputRec->status = flFeatureNotSupported; + } + return outputRec->status; + } +#endif /* FL_ENVIRONMENT_VARS */ + +#ifndef FL_NO_USE_FUNC + case FL_IOCTL_SET_ACCESS_ROUTINE: + { + flSetMemoryAccessInput FAR1 *inputRec = (flSetMemoryAccessInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + + outputRec->status = flSetDocBusRoutine(FL_GET_SOCKET_FROM_HANDLE((&ioreq2)), + inputRec->structPtr); + return outputRec->status; + } + case FL_IOCTL_GET_ACCESS_ROUTINE: + { + flGetMemoryAccessOutput FAR1 *outputRec = (flGetMemoryAccessOutput FAR1 *)outputRecord; + + outputRec->status = flGetDocBusRoutine(FL_GET_SOCKET_FROM_HANDLE((&ioreq2)), + outputRec->structPtr); + return outputRec->status; + } +#endif /* FL_NO_USE_FUNC */ + +#ifdef VERIFY_VOLUME + case FL_IOCTL_VERIFY_VOLUME: + { + flVerifyVolumeInput FAR1 *inputRec = (flVerifyVolumeInput FAR1 *)inputRecord; + flVerifyVolumeOutput FAR1 *outputRec = (flVerifyVolumeOutput FAR1 *)outputRecord; + + ioreq2.irLength = (FLSDword)inputRec->flags; + ioreq2.irData = outputRec->callBack; + outputRec->status = flVerifyVolume(&ioreq2); + return outputRec->status; + } +#endif /* VERIFY_VOLUME */ + +#ifndef NO_IPL_CODE + case FL_IOCTL_WRITE_IPL: + { + flIPLInput FAR1 *inputRec = (flIPLInput FAR1 *)inputRecord; + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + ioreq2.irData = inputRec->bBufPtr; + ioreq2.irLength = inputRec->sdwLength; + ioreq2.irCount = inputRec->sdwOffset; + ioreq2.irFlags = inputRec->dwFlags; + outputRec->status = flWriteIPL(&ioreq2); + return outputRec->status; + } +#endif /* NO_IPL_CODE */ + +#ifndef FL_NO_QUICK_MOUNT_FEATURE + case FL_IOCTL_IS_QUICK_MOUNT_VALID: + { + flGetQuickMountOutput FAR1 *outputRec = (flGetQuickMountOutput FAR1 *)outputRecord; + outputRec->status = flGetQuickMountStatus(&ioreq2); + outputRec->mode = (FLByte)ioreq2.irFlags; + return outputRec->status; + } +#ifndef FL_READ_ONLY + case FL_IOCTL_WRITE_QUICK_MOUNT_INFO: + { + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + outputRec->status = flWriteQuickMountInfo(&ioreq2); + return outputRec->status; + } + + case FL_IOCTL_CLEAR_QUICK_MOUNT_INFO: + { + flOutputStatusRecord FAR1 *outputRec = (flOutputStatusRecord FAR1 *)outputRecord; + outputRec->status = flClearQuickMountInfo(&ioreq2); + return outputRec->status; + } +#endif /* FL_READ_ONLY */ +#endif /* FL_NO_QUICK_MOUNT_FEATURE */ + + case FL_IOCTL_PASS_THROUGH: + { + flAtaPassthroughInput* ptIN = (flAtaPassthroughInput*)inputRecord; + flAtaPassthroughOutput* ptOUT = (flAtaPassthroughOutput*)outputRecord; + + ioreq2.irData = ptIN->userBuff; + ioreq2.irLength = ptIN->secNum; + ioreq2.irCount = ( + (ptIN->passThruOP) | + (ptIN->useInterrupt<<2) | + (ptIN->multSectorFrame<<4) ); + ioreq2.irPath = ptIN->in_regs; + + ptOUT->status = flDochPassThrough(&ioreq2); + + tffscpy(ptOUT->out_regs, ptIN->in_regs, sizeof(DOCH_Registers)); + return ptOUT->status; + } + + default: + return flBadParameter; + } +} + +#endif /* FL_IOCTL_INTERFACE */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flioctl.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flioctl.h new file mode 100755 index 00000000..6dbbbb33 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flioctl.h @@ -0,0 +1,490 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flioctl.h-arc $ + * + * Rev 1.17 Oct 22 2007 11:34:52 einat.avidan + * update copyrights header + * + * Rev 1.16 Jul 02 2007 11:43:46 einat.avidan + * bug fix: SCR2966 : removed flags which are not in use + * FL_IPL_DOWNLOAD + * FL_IPL_ALERNATE_MAP + * FL_USING_BUFFERS + * FL_IPL_NO_ADDRESS_SHIFT_MODE + * + * Rev 1.15 Feb 28 2007 09:53:48 einat.avidan + * No change + * + * Rev 1.14.1.1 Oct 29 2006 14:23:46 Yaniv.Iarovici + * Update 'FL_IOCTL_PASS_THROUGH' structures. + * + * Rev 1.14.1.0 Oct 22 2006 14:53:58 yaniv.iarovici + * Changed protectionType from FLByte to FLWord in flProtectionOutput stucture. + * + * Rev 1.14 Oct 09 2006 14:05:38 yaniv.iarovici + * Removed #ifndef FL_DO_NOT_SUPPORT_H3 + * + * Rev 1.13 Oct 05 2006 11:01:06 yaniv.iarovici + * Fixed support for FL_IOCTL_PASS_THROUGH. + * + * Rev 1.12 Sep 11 2006 13:45:22 yaniv.iarovici + * Legal header added + * + * Rev 1.11 Aug 16 2006 08:47:20 Yaniv.Iarovici + * Encapsulate BDK related defines under '#ifdef BDK_ACCESS'. + * + * Rev 1.9 Aug 09 2006 16:52:50 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLIOCTL_H +#define FLIOCTL_H + +#include "flsystem.h" +#include "flstruct.h" +#include "_dochapi.h" + + +/* In every call to flIOctl function, the irFlags field in the structure +IOreq should hold one of the following: */ +typedef enum{FL_IOCTL_GET_INFO = FL_IOCTL_START, + FL_IOCTL_DEFRAGMENT, + FL_IOCTL_NO_LONGER_SUPPORTED_0, /* FL_IOCTL_WRITE_PROTECT */ + FL_IOCTL_MOUNT_VOLUME, + FL_IOCTL_NO_LONGER_SUPPORTED_1, /* FL_IOCTL_FORMAT_VOLUME */ +#ifdef BDK_ACCESS + FL_IOCTL_BDK_OPERATION, +#else /*BDK_ACCESS*/ + FL_IOCTL_RESERVED1, +#endif /*BDK_ACCESS*/ + FL_IOCTL_DELETE_SECTORS, + FL_IOCTL_READ_SECTORS, + FL_IOCTL_WRITE_SECTORS, + FL_IOCTL_NO_LONGER_SUPPORTED_2, /* FL_IOCTL_FORMAT_PHYSICAL_DRIVE */ + FL_IOCTL_NO_LONGER_SUPPORTED_3, /* FL_IOCTL_FORMAT_LOGICAL_DRIVE */ + FL_IOCTL_BDTL_HW_PROTECTION, +#ifdef BDK_ACCESS + FL_IOCTL_BINARY_HW_PROTECTION, +#else /*BDK_ACCESS*/ + FL_IOCTL_RESERVED2, +#endif /*BDK_ACCESS*/ + FL_IOCTL_OTP, + FL_IOCTL_CUSTOMER_ID, + FL_IOCTL_UNIQUE_ID, + FL_IOCTL_NUMBER_OF_PARTITIONS, + FL_IOCTL_NO_LONGER_SUPPORTED_4, /* FL_IOCTL_INQUIRE_CAPABILITIES */ + FL_IOCTL_NO_LONGER_SUPPORTED_5, /* FL_IOCTL_SET_ENVIRONMENT_VARIABLES */ + FL_IOCTL_NO_LONGER_SUPPORTED_6, /* FL_IOCTL_PLACE_EXB_BY_BUFFER */ + FL_IOCTL_NO_LONGER_SUPPORTED_7, /* FL_IOCTL_WRITE_IPL */ + FL_IOCTL_DEEP_POWER_DOWN_MODE, + FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES, + FL_IOCTL_VERIFY_VOLUME, + FL_IOCTL_SET_ACCESS_ROUTINE, + FL_IOCTL_GET_ACCESS_ROUTINE, + FL_IOCTL_NO_LONGER_SUPPORTED_8, /* FL_IOCTL_EXTENDED_WRITE_IPL */ + FL_IOCTL_NO_LONGER_SUPPORTED_9, /* FL_IOCTL_OPEN_TRANSACTION */ + FL_IOCTL_NO_LONGER_SUPPORTED_10, /* FL_IOCTL_COMMIT_TRANSACTION */ + FL_IOCTL_NO_LONGER_SUPPORTED_11, /* FL_IOCTL_IS_VOLUME_RUGGEDIZED */ + FL_IOCTL_IS_QUICK_MOUNT_VALID, + FL_IOCTL_WRITE_QUICK_MOUNT_INFO, + FL_IOCTL_CLEAR_QUICK_MOUNT_INFO, + FL_IOCTL_NO_LONGER_SUPPORTED_12, /* FL_IOCTL_COMPLETE_OPERATION */ + FL_IOCTL_FLASH_FORMAT, /* Replacing FL_IOCTL_FORMAT_PHYSICAL_DRIVE */ + FL_IOCTL_ERASE_BD, /* Added in TrueFFS 6.3.0 */ + FL_IOCTL_FLASH_UNFORMAT, /* Added in TrueFFS 6.3.0 */ + FL_IOCTL_WRITE_IPL, /* Changed in TrueFFS 6.3.0 */ + FL_IOCTL_MCOTP, + FL_IOCTL_PASS_THROUGH, + FL_IOCTL_IPL_HW_PROTECTION +} flIOctlFunctionNo; + + +/* In every call to flIOctl function, the irData field in the structure +IOreq should point to the structure defined below. The fields +inputRecord and outputRecord should point to structures which are +specific to each IOctl function as defined in this file. */ +typedef struct { + void FAR1 *inputRecord; + void FAR1 *outputRecord; +} flIOctlRecord; + + +/* General output record that returns only status. */ +typedef struct { + FLStatus status; +} flOutputStatusRecord; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +TFFS_DLL_API FLStatus NAMING_CONVENTION bdIOctl(IOreq FAR2 *); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#ifndef flIOctl +#define flIOctl bdIOctl +#endif + + +/* Input and output records for the different IOCTL functions: */ +/* =========================================================== */ + + +/*************************************************************************/ +/* Get disk information (FL_IOCTL_GET_INFO) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct +{ + VolumeInfoRecord info; + FLStatus status; +} flDiskInfoOutput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Defragment volume (FL_IOCTL_DEFRAGMENT) */ +/* Input record: */ +typedef struct { + FLSDword requiredNoOfSectors; /* Minimum number of sectors to make */ + /* available. */ +} flDefragInput; +/* Outout record: */ +typedef struct { + FLSDword actualNoOfSectors; /* Actual number of sectors available */ + FLStatus status; +} flDefragOutput; + +/*************************************************************************/ +/* Mount volume (FL_IOCTL_MOUNT_VOLUME) */ +/* Input record: */ +typedef struct { + FLByte type; /* type of operation: FL_MOUNT\FL_DISMOUNT */ +} flMountInput; +#define FL_MOUNT 0 +#define FL_DISMOUNT 1 +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Delete logical sectors (FL_IOCTL_DELETE_SECTORS) */ +/* Input record: */ +typedef struct { + FLSDword firstSector; /* First logical sector to delete */ + FLSDword numberOfSectors; /* Number of sectors to delete */ +} flDeleteSectorsInput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Format flash device (FL_IOCTL_FLASH_FORMAT) */ +/* Input record: */ +typedef struct { + FLDword dwFormatFlags; /* type of format as defined in blockdev.h */ + FLSDword sdwNoOfKeeps; + FormatParams3 * fpPtr; /* Format parameters structure (defined in flformat.h) */ +} flFlashFormatInput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Erase existing disk partition (FL_IOCTL_ERASE_BD) */ +/* Input record: */ +typedef struct { + FLDword dwFlags; /* Reserved - Must be set to 0 */ +} flEraseBDInput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Format flash device (FL_IOCTL_FLASH_UNFORMAT) */ +/* Input record: */ +typedef struct { + FLDword dwFlags; /* Reserved - Must be set to 0 */ +} flFlashUnformatInput; +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* BDK and BDTL protection operations: (FL_IOCTL_BINARY_HW_PROTECTION) */ +/* (FL_IOCTL_BDTL_HW_PROTECTION) */ +/* insert key \ remove key \ identify \ change key \ */ +/* change protection type \ change lock status */ +/* Input record: */ +typedef struct { + FLByte protectionType; /* Protection attributes. The following */ + /*attributes can be ored: PROTECTABLE, */ + /*READ_PROTECTED, WRITE_PROTECTED, LOCK_ENABLED*/ + /*CHANGEABLE_PROTECTION, OTW_PROTECTED, */ + FLByte key[8]; /* The new key to the change Key call */ + FLByte type; /* Operation type. available values are: */ + /*PROTECTION_INSERT_KEY, PROTECTION_REMOVE_KEY,*/ + /*PROTECTION_GET_TYPE, PROTECTION_DISABLE_LOCK,*/ + /*PROTECTION_ENABLE_LOCK, PROTECTION_CHANGE_KEY,*/ + /*PROTECTION_CHANGE_TYPE */ +} flProtectionInput; +#define PROTECTION_INSERT_KEY 0 +#define PROTECTION_REMOVE_KEY 1 +#define PROTECTION_GET_TYPE 2 +#define PROTECTION_DISABLE_LOCK 3 +#define PROTECTION_ENABLE_LOCK 4 +#define PROTECTION_CHANGE_KEY 5 +#define PROTECTION_CHANGE_TYPE 6 +#define PROTECTION_APPLY_STICKY 7 +/* Output record: */ +typedef struct { + FLWord protectionType; /* Protection attributes. The following */ + /*attributes can be ored: PROTECTABLE, */ + /*READ_PROTECTED, WRITE_PROTECTED, LOCK_ENABLED*/ + /*LOCK_ASSERTED, KEY_INSERTED, */ + /*CHANGEABLE_PROTECTION, OTW_PROTECTED, */ + /*STICKY_LOCK_ASSERTED */ + + FLStatus status; +} flProtectionOutput; + +/*************************************************************************/ +/* One Time Programing operations: (FL_IOCTL_OTP */ +/* OTP size \ OTP read \ OTP write and lock */ +/* Input record: */ +typedef struct { + FLDword length; /* Length to read\write\size */ + FLDword usedSize; /* The written size of the area \ Area offset */ + FLByte lockedFlag; /* The area condition LOCKED_OTP (flflash.h) */ + FLByte FAR1* buffer; /* pointer to user buffer */ + FLWord type; /* defined bellow */ +} flOtpInput; +#define OTP_SIZE 1 +#define OTP_READ 2 +#define OTP_WRITE_LOCK 3 +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* One Time Programing operations: (FL_IOCTL_MCOTP */ +/* OTP size \ OTP read \ OTP write and lock */ +/* Input record: */ +typedef struct { + FLWord wPageNo ; /* Page to write */ + FLDword length; /* Length to read\write\size */ + FLDword usedSize; /* The written size of the area \ Area offset */ + FLByte lockedFlag; /* The area condition LOCKED_OTP (flflash.h) */ + FLByte FAR1* buffer; /* pointer to user buffer */ + FLWord type; /* defined bellow */ +} flMCOtpInput; + +#define MCOTP_SIZE 1 +#define MCOTP_READ 2 +#define MCOTP_WRITE_LOCK 3 +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* Read customer ID (FL_IOCTL_CUSTOMER_ID) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLByte id[4]; + FLStatus status; +} flCustomerIdOutput; + +/*************************************************************************/ +/* Read unique ID (FL_IOCTL_UNIQUE_ID) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLByte id[16]; + FLStatus status; +} flUniqueIdOutput; + +/*************************************************************************/ +/* Read unique ID (FL_IOCTL_NUMBER_OF_PARTITIONS) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLByte noOfPartitions; + FLStatus status; +} flCountPartitionsOutput; + +/*************************************************************************/ +/* Place the device into and out of the power down mode (FL_IOCTL_DEEP_POWER_DOWN_MODE) */ + +/* Input record: */ +typedef struct { + FLByte state; /* DEEP_POWER_DOWN - low power consumption */ + /* EXIT_DEEP_POWER_DOWN - regular power consumption */ +} flPowerDownInput; +/* Output record: flOutputStatusRecord */ + +#ifdef BDK_ACCESS +/*************************************************************************/ +/* BDK operations read\write\erase\create (FL_IOCTL_BDK_OPERATION) */ +/* Input record: */ +typedef struct { + FLByte type; /* type of operation. Available are: */ + /*BDK_INIT_READ, BDK_READ, BDK_INIT_WRITE, */ + /*BDK_WRITE, BDK_ERASE, BDK_CREATE, */ + /* BDK_GET_INFO */ + BDKStruct bdkStruct; /* parameters for BDK operations */ +} flBDKOperationInput; +#define BDK_INIT_READ 0 +#define BDK_READ 1 +#define BDK_INIT_WRITE 2 +#define BDK_WRITE 3 +#define BDK_ERASE 4 +#define BDK_CREATE 5 +#define BDK_GET_INFO 6 +/* Output record: flOutputStatusRecord */ +#endif /*BDK_ACCESS*/ + +/******************************************************************************/ +/* Set environment variables values (FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES) */ +/* Input record: */ +typedef struct { + FLEnvVars varName; /* Enum describing the variable */ + FLDword varValue; /* New variable value */ + FLDword flags; /* FL_APPLY_TO_ALL - All socket and partitions */ + /* FL_APPLY_TO_SOCKET - All socket and partitions */ + /* FL_APPLY_TO_VOLUME - All socket and partitions */ +} flExtendedEnvVarsInput; +#define FL_APPLY_TO_ALL 1 +#define FL_APPLY_TO_SOCKET 2 +#define FL_APPLY_TO_VOLUME 3 +/* Output record: */ +typedef struct { + FLDword prevValue; /* The previous value of the variable */ + FLStatus status; +} flExtendedEnvVarsOutput; + +/******************************************************************************/ +/* Write IPL area for docPlus family (FL_IOCTL_WRITE_IPL) */ +/* Input record: */ +typedef struct { + FLByte FAR1* bBufPtr; /* IPL data buffer */ + FLDword dwFlags; /* IPL flags. Available are: FL_IPL_MODE_NORMAL, */ + /* FL_DOC_IPL_PAGED_RAM_MODE,FL_IPL_VIRTUAL_RAM_MODE*/ + /* FL_IPL_128K_WINDOW_MODE, FL_IPL_SWAP_BYTES_MODE*/ + FLSDword sdwLength; /* IPL length */ + FLSDword sdwOffset; /* IPL offset */ +} flIPLInput; +/* Output record: flOutputStatusRecord */ + +/******************************************************************************/ +/* Check quick mount validity (FL_IOCTL_IS_QUICK_MOUNT_VALID) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLByte mode; /* Either FL_ON for valid and FL_OFF for not */ + FLStatus status; +} flGetQuickMountOutput; + +/******************************************************************************/ +/* Write quick mount data (FL_IOCTL_WRITE_QUICK_MOUNT_INFO) */ +/* Input record: NULL */ +/* Output record: flOutputStatusRecord */ + +/******************************************************************************/ +/* Clear quick mount data (FL_IOCTL_CLEAR_QUICK_MOUNT_INFO) */ +/* Input record: NULL */ +/* Output record: flOutputStatusRecord */ + +/*************************************************************************/ +/* read & write logical sectors (FL_IOCTL_READ_SECTORS & FL_IOCTL_WRITE_SECTORS) */ +/* Input record: */ +typedef struct { + FLSDword firstSector; /* first logical sector */ + FLSDword numberOfSectors; /* Number of sectors to read\write */ + FLByte FAR1 *buf; /* Data to read\write */ +} flReadWriteInput; +/* Output record: */ +typedef struct { + FLSDword numberOfSectors; /* Actual Number of sectors read\written */ + FLStatus status; +} flReadWriteOutput; + +/******************************************************************************/ +/* Check partition for power failures symptoms (FL_IOCTL_VERIFY_VOLUME) */ +/* Input record: NULL */ +typedef struct { + FLDword flags; /* Must be set to 0 */ +} flVerifyVolumeInput; +/* Output record: */ +typedef struct { + void FAR1* callBack; /* Must be set to null */ + FLStatus status; +} flVerifyVolumeOutput; + +/******************************************************************************/ +/* Plant user defined memory access routines (FL_IOCTL_SET_ACCESS_ROUTINE) */ +/* Input record: */ +typedef struct { + FLAccessStruct FAR1 * structPtr; /* Pointer memory access routine struct */ +} flSetMemoryAccessInput; +/* Output record: flOutputStatusRecord */ + +/******************************************************************************/ +/* Plant user defined memory access routines (FL_IOCTL_GET_ACCESS_ROUTINE) */ +/* Input record: NULL */ +/* Output record: */ +typedef struct { + FLAccessStruct FAR1 * structPtr; /* Pointer memory access routine struct */ + FLStatus status; +} flGetMemoryAccessOutput; + +/******************************************************************************/ +/* Perform ATA command using the pass-through mechanism (FL_IOCTL_PASS_THROUGH) */ +/* Input record: */ +typedef struct { + DOCH_PassThru_Op passThruOP; /*0 - No Data(CTRL), 1 - Data IN, 2 - Data OUT*/ + DOCH_PassThru_Int useInterrupt; /*0 - Do NOT use interrupt, 1- USE interrupt*/ + FLSDword multSectorFrame;/*DRQ size exponent (power of 2)*/ + DOCH_Registers* in_regs; /*ATA input registers*/ + FLSDword secNum; /*Number of sectors in user buffer*/ + void* userBuff; /* User buffer (for read\write) */ +} flAtaPassthroughInput; +/* Output record: */ +typedef struct { + DOCH_Registers* out_regs; /*ATA input registers*/ + FLStatus status; +} flAtaPassthroughOutput; + + +#endif /* FLIOCTL_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flstdcmp.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flstdcmp.h new file mode 100755 index 00000000..85e3a405 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flstdcmp.h @@ -0,0 +1,95 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 6.3-up/TrueFFS/src/flstdcmp.h-arc $ + * + * Rev 1.25 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.24 Feb 28 2007 09:53:48 einat.avidan + * No change + * + * Rev 1.23.1.0 Oct 22 2006 14:54:06 yaniv.iarovici + * Changed flRegisterDOCH3SOC()return type to FLStatus. + * + * Rev 1.23 Oct 09 2006 14:05:48 yaniv.iarovici + * 1. Removed #ifndef FL_DO_NOT_SUPPORT_H3 + * 2. Removed legacy devices related code and definitions + * + * Rev 1.22 Sep 13 2006 10:30:46 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.21 Sep 11 2006 13:45:22 yaniv.iarovici + * Legal header added + * + * Rev 1.20 Aug 09 2006 16:52:50 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLSTDCOMP_H +#define FLSTDCOMP_H + +#include "doch_api.h" + +/************************************************************************/ +/* Registration routines for socket I/F supplied with TrueFFS */ +/************************************************************************/ + +FLStatus flRegisterDOCH3SOC(FLDword dwAddress); /* see TFFS_API.C */ + +/* DiskOnChip H3 Register Routine */ +FLStatus flRegisterDochParams(void); + +/* DiskOnChip H3 Access layer routine - not used in 7.x version */ +#ifdef DOCH_USE_FUNC +#define flRegisterDOCH_Hal_SPI() ((hal_init_spi(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#define flRegisterDOCH_Hal_SIM() ((hal_init_sim(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#define flRegisterDOCH_Hal_NOR() ((hal_init_nor(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#else /*DOCH_USE_FUNC*/ +#define flRegisterDOCH_Hal_SPI() ((hal_init_spi_noFunc(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#define flRegisterDOCH_Hal_SIM() ((hal_init_sim_noFunc(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#define flRegisterDOCH_Hal_NOR() ((hal_init_nor_noFunc(0) == 0) ? DOCH_OK : DOCH_GeneralFailure) +#endif /*DOCH_USE_FUNC*/ + +#endif /* FLSTDCOMP_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flstruct.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flstruct.h new file mode 100755 index 00000000..a5b976d6 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flstruct.h @@ -0,0 +1,847 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/common/flstruct.h-arc $ + * + * Rev 1.13 Oct 30 2007 17:08:54 einat.avidan + * new fast area type - FL_LENGTH_ALL + * + * Rev 1.12 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.11 Oct 11 2007 18:50:24 Einat.Avidan + * add compilation flags for SOTP and SLPP + * + * Rev 1.10 Mar 13 2007 13:47:18 einat.avidan + * add support for SLPP + * + * Rev 1.9 Feb 28 2007 09:53:48 einat.avidan + * No change + * + * Rev 1.7.1.3 Sep 11 2006 13:45:24 yaniv.iarovici + * Legal header added + * + * Rev 1.7.1.2 Sep 03 2006 14:45:12 Yaniv.Iarovici + * 1. Added '#define FL_EXT_INFO_NO_SPEC_PART 0xFF'. + * (Indicates SDK not to retrieve specific partition info in certain APIs) + * 2. Encapsulate '#define TL_LEAVE_BINARY_AREA' and '#define TL_LEAVE_SOME_BINARY_AREA' + * under '#ifdef BDK_ACCESS'. + * 3. Define 'TL_LEAVE_SOME_PARTITIONS' with value of 0x9. + * + * Rev 1.7.1.1 Aug 16 2006 08:47:42 Yaniv.Iarovici + * 1) Add '#define TL_LEAVE_SOME_PARTITIONS TL_LEAVE_SOME_BINARY_AREA' + * 2) Encapsulate BDK related defines under '#ifdef BDK_ACCESS'. + * + * Rev 1.7.1.0 Aug 08 2006 15:55:30 Polina.Marimont + * DOC Driver 1.0 initial + */ + +#ifndef FLSTRUCT_H +#define FLSTRUCT_H + +#include "flcommon.h" + + +/**************************************************************************/ +/* Function opcode definitions: */ +/* All TrueFFS functions has a uniques opcodes. The following enum */ +/* defines all the function calls used by the TrueFFS SDK API. */ +/* Note: */ +/* The order of the enum bellow should be strictly kept since the bdcall */ +/* function utilizes the index values to simplify the function search */ +/**************************************************************************/ +typedef enum { +/* The following routines are files related routines */ + + /*********/ + /* FILES */ + /*********/ + + FL_READ_FILE = 0, + FL_WRITE_FILE, + FL_SPLIT_FILE, + FL_JOIN_FILE, + FL_SEEK_FILE, + FL_FIND_NEXT_FILE, + FL_FIND_FILE, + FL_TRUNCATE_FILE, + INDEX_WRITE_FILE_START = 100, + FL_CLOSE_FILE, + FL_FLUSH_FILE, + INDEX_OPENFILES_END = 200, + FL_OPEN_FILE, + FL_DELETE_FILE, + FL_FIND_FIRST_FILE, + FL_GET_DISK_INFO, + FL_RENAME_FILE, + FL_MAKE_DIR, + FL_REMOVE_DIR, + FL_FLUSH_BUFFER, + FL_CLOSE_ALL_FILES, + FL_FLUSH_ALL_FILES, + FL_OPEN_DIRECTORY, + FL_OPEN_MM_FILE, + FL_LAST_FAT_FUNCTION = 300, + + /* The following routines will not perform valid partition check */ + /**********/ + /* BINARY */ + /**********/ + INDEX_BINARY_START = 400, + FL_BINARY_WRITE_INIT, + FL_BINARY_WRITE_BLOCK, + FL_BINARY_CREATE, + FL_BINARY_ERASE, + FL_BINARY_PROTECTION_CHANGE_KEY, + FL_BINARY_PROTECTION_CHANGE_LOCK, + FL_BINARY_PROTECTION_SET_TYPE, + INDEX_BINARY_WRITE_END = 500, + FL_BINARY_READ_INIT, + FL_BINARY_READ_BLOCK, + FL_BINARY_PARTITION_INFO, + FL_BINARY_PROTECTION_GET_TYPE, + FL_BINARY_PROTECTION_INSERT_KEY, + FL_BINARY_PROTECTION_REMOVE_KEY, + INDEX_BINARY_END = 600, + +/* The following routines must be called with partition number 0 */ + INDEX_NEED_PARTITION_0_START = 700, + /* OTP */ + FL_OTP_SIZE, + FL_OTP_READ, + FL_OTP_WRITE, + FL_WRITE_IPL, + FL_READ_IPL, + /* PHYSICAL */ + FL_DEEP_POWER_DOWN_MODE, + FL_GET_PHYSICAL_INFO, + FL_PHYSICAL_READ, + FL_PHYSICAL_WRITE, + FL_PHYSICAL_ERASE, + FL_UPDATE_SOCKET_PARAMS, + FL_UNIQUE_ID, + FL_CUSTOMER_ID, + BD_FORMAT_VOLUME, + BD_FORMAT_PHYSICAL_DRIVE, + FL_PLACE_EXB, + FL_READ_BBT, + FL_WRITE_BBT, + FL_GET_EXTENDED_DISK_INFO, + FL_PROTECTION_STICKY_LOCK, + BD_FLASH_FORMAT, + BD_UNFORMAT, + FL_HW_CONFIG, + FL_RECOVER_FROM_POWER_LOSS, + FL_IPL_PROTECTION_GET_TYPE, + FL_IPL_PROTECTION_REMOVE_KEY, + FL_IPL_PROTECTION_INSERT_KEY, + FL_IPL_PROTECTION_CHANGE_KEY, + FL_IPL_PROTECTION_CHANGE_TYPE, + + INDEX_NEED_PARTITION_0_END = 800, +/* The following routines will go through the volume validity check */ + /* PROTECTION */ + FL_PROTECTION_GET_TYPE, + FL_PROTECTION_REMOVE_KEY, + FL_PROTECTION_INSERT_KEY, + FL_PROTECTION_SET_LOCK, + FL_PROTECTION_CHANGE_KEY, + FL_PROTECTION_CHANGE_TYPE, + FL_COUNT_VOLUMES, + FL_INQUIRE_CAPABILITIES, + /* BDTL */ + FL_MOUNT_VOLUME, + FL_ABS_MOUNT, + BD_FORMAT_LOGICAL_DRIVE, + FL_WRITE_PROTECTION, + FL_DISMOUNT_VOLUME, + FL_CHECK_VOLUME, + FL_DEFRAGMENT_VOLUME, + FL_ABS_WRITE, + FL_ABS_DELETE, + FL_ABS_READ, + FL_ABS_ADDRESS, + FL_GET_BPB, + FL_SECTORS_IN_VOLUME, + FL_VOLUME_INFO, + FL_VERIFY_VOLUME, + FL_CLEAR_QUICK_MOUNT_INFO, + FL_RUGGEDIZE_OPERATION, /* not used */ + FL_ABS_WRITE_UNCOMMITED, /* not used */ + FL_ABS_DELETE_UNCOMMITED, /* not used */ + FL_ABS_READ_RUGGEDIZED, /* not used */ + FL_GET_QUICK_MOUNT_STATUS, + FL_WRITE_QUICK_MOUNT_INFO, + FL_LOAD_VOLUMES_CACHE, + FL_COMPLETE_OPERATION, + FL_FIND_LOGICAL_PARTITION, + FL_CREATE_LOGICAL_PARTITIONS, + FL_FORMAT_FS, + FL_GET_BD_VERSION, + FL_GET_FS_VERSION, + BD_ERASE_BD, + FL_ABS_SECURE_DELETE, + FL_MCOTP_SIZE,/* not used - must gone */ + FL_MCOTP_READ,/* not used - must gone */ + FL_MCOTP_WRITE,/* not used - must gone */ +#ifdef FL_SLPP + FL_SLPP_UNLOCK_RANGE, + FL_SLPP_LOCK_RANGE, + FL_SLPP_UNLOCK_ENTIRE_PARTITION, + FL_SLPP_STICKY_LOCK_RANGE, + FL_SLPP_REPORT_LOCKED_RANGES, +#endif /*FL_SLPP*/ + FL_DOCH_PASS_THROUGH /* DOCH only */ +} FLFunctionNo; + + + +/**************************************************************************/ +/* Structures and defines for GetInfo routines: */ +/* GetInfo routines are used by several TrueFFS packages. */ +/* The output structures and values are defined below */ +/**************************************************************************/ + +/*---------------------------------------------------------*/ +/* V o l u m e I n f o R e c o r d */ +/* */ +/* A structure that holds general information about the */ +/* media. The information includes Physical Info (see */ +/* flGetPhysicalInfo), Logical partition (number of sectors*/ +/* and CHS), boot area size, S/W versions Media life-time */ +/* etc. */ +/* A pointer to this structure is passed to the function */ +/* flVolumeInfo where it receives the relevant data. */ +/*---------------------------------------------------------*/ + +typedef struct { + FLDword logicalSectors; /* number of logical sectors */ + FLDword bootAreaSize; /* boot area size */ + FLDword baseAddress; /* physical base address */ + FLWord flashType; /* JEDEC id of the flash */ + FLDword dwPhysicalSize; /* physical size of the media */ + FLDword dwPhysicalUnitSize;/* Erasable block size */ + FLByte DOCType; /* DiskOnChip type (MDoc/Doc2000) */ + FLSByte lifeTime; /* Life time indicator for the media (1-10) */ + /* 1 - the media is fresh, */ + /* 10 - the media is close to its end of life */ + FLSByte driverVer[10]; /* driver version (NULL terminated string) */ + FLSByte OSAKVer[10]; /* TrueFFS version that driver is based on */ + /* (NULL terminated string) */ + FLDword cylinders; /* Media..... */ + FLDword heads; /* geometry...... */ + FLDword sectors; /* parameters. */ +} VolumeInfoRecord; + + +/*---------------------------------------------------------*/ +/* P h y s i c a l I n f o */ +/* */ +/* A structure that holds physical information about the */ +/* media. The information includes JEDEC ID, unit size and */ +/* media size. Pointer to this structure is passed to the */ +/* function flGetPhysicalInfo where it receives the */ +/* relevant data. */ +/*---------------------------------------------------------*/ + +typedef struct { + FLWord type; /* Flash device type (JEDEC id) */ + FLByte mediaType; /* type of media see below */ + FLDword dwUnitSize; /* Smallest physically erasable size in sectors */ + FLDword dwMediaSize; /* media size in sectors */ + FLDword dwChipSize; /* individual chip size in sectors */ + FLDword interleaving; /* device interleaving */ +} PhysicalInfo; + + + +/*---------------------------------------------------------*/ +/* f l E x t e n d e d D i s k I n f o */ +/* */ +/* This structure supplies very low-level information on */ +/* the device */ +/* */ +/* Note: This structure is used for M-Systems low level */ +/* utilities. It is subject to chages from one TrueFFS*/ +/* version to the other. */ +/* */ +/*---------------------------------------------------------*/ + +typedef struct { + + /******************************************/ + /* Fields that belong to the entire media */ + /******************************************/ + FLDword dwStructSize; /* INPUT - Size of the given structure */ + FLDword dwTLType; /* See definitions in flflash.h */ + FLDword dwFormatFlags; /* Format attributes for the entire media */ + FLDword dwTrueFFSVersion; /* Version of OSAK used to format the media */ + FLDword dwFlashTechnology; /* Flash technology supported properties */ + + FLDword dwType; /* Flash type */ + FLDword dwSubType; /* Sub Flash type */ + FLByte bMediaType; /* Controller family */ + FLByte bNoOfFloors; /* Number of floors in the device */ + FLByte bNoOfPlanes; /* Number of flash planes */ + FLByte bNoOfBanks; /* Number of flash banks */ + FLByte bDataBusWidth; /* Value of the IF_CFG (either 8 or 16 bits)*/ + FLByte bSectorsPerPage; /* Number of sectors in a flash page */ + FLByte bSharedSectors; /* The minimal number of logical sectors */ + /* that might be affected by one another */ + /* write operation. */ + FLByte bFastAreaSharedSectors; /* Minimal number of sectors that can affect */ + /* one another when written in fast mode. */ + FLByte bMaxRelatedSectors; /* Max number of sectors that might share */ + /* the same write operation or might be */ + /* affected by each other write operation. */ + FLDword dwIPLSize; /* Number of bytes of SRAM in the device */ + FLByte bChangeableProtectedAreas; /* Number of protection areas capable */ + /* of changing. */ + FLByte btotalProtectedAreas; /* Total number of protection areas */ + FLDword dwUnitsInFirstFloor; /* Number of units in the first floor */ + FLDword dwUnitSize; /* Size of logical erasable unit */ + FLDword dwMaxBadPercentage; /* Flash guaranteed worst bad blocks percentage */ + FLByte bNoOfBinaryPartitions; /* Number of binary partition on the media */ + FLByte bNoOfDiskPartitions; /* Number of disk partition on the media */ + FLByte bBlockMultiplierBits; /* no of bits used to represent the time a */ + /* flash logical unit fits inside in a TL */ + /* erasable unit. */ + FLByte dwPercentUsed; /* Percent of the media to be exported */ + FLByte bHeaderUnits; /* Number of units reserved in the begining */ + /* of each floor for the media header */ + FLWord wHeaderLocation; /* Unit number where the header of the */ + /* current floor resides. In case all floors*/ + /* are requested, the value should indicate */ + /* the location of the header in the first */ + /* floor. */ + + FLByte bProgrammerNamePtr[4]; /* Programmer name */ + FLByte bProgrammerVersionPtr[4]; /* Programmer version */ + + /************************************************/ + /* Fields that belong to the specific partition */ + /************************************************/ + + FLDword dwVirtualUnits; /* Virtual size exported by the translation layer */ + /* Note some units are smaller then others */ + FLDword dwFastUnits; /* Number of virtual units that are fast units */ + FLDword dwFirstQuickMountUnit; /* First unit used for the quick mount data */ + FLDword dwFirstUnit; /* First unit of the partition */ + FLDword dwLastUnit; /* Last unit of the partition */ + FLDword dwSpareUnits; /* Number of spare units requested by the user */ + FLDword dwTransferUnits; /* Number of transfer units used for chaining */ + FLDword dwPartitionFlags;/* See list above "Partition flags" */ + FLDword dwNormalAreaUnitSize; /* Logical size of a TL normal unit */ + FLDword dwFastAreaLogicalUnitSize; /* Logical size of a TL fast unit */ + FLDword dwFastAreaVirtualFactor; /* Virtual unit factor between fast */ + /* and normal area (power of 2) */ + + FLByte bMinSectorsForFolding; /* Number of sectors to be copied */ + /* together in a folding operation */ + FLByte bMinSectorsForNextWrite; /* For performance reasons the TL */ + /* decide to reduce the above value */ + FLByte bfastAreaMinSectorsForNextWrite; /* For performance reasons the TL */ + /* decide to reduce the above value */ + + /******************************************/ + /* Fields that are valid only after mount */ + /******************************************/ + + FLDword dwUsedUnits; /* Number of used virtual chains */ + FLDword dwFreeUnits; /* Number of currently free units */ + FLByte bNeededFreeUnits; /* Minimal number of free units */ + /* before folding */ + FLDword dwUMDBBTSector; /* Location of latest UMDBBT sector */ +} FLExtendedDiskInfo; + +/* media types */ +#define FL_NOT_DOC 0 +#define FL_DOC 1 +#define FL_MDOC 2 +#define FL_DOC2000TSOP 3 +#define FL_MDOCP_16 4 +#define FL_MDOCP 5 +#define FL_DOC_H1 6 +#define FL_MDOC512_G3 7 +#define FL_MDOC256_P3 8 +#define FL_MDOC256_G3 9 +#define FL_MDOC128_P3 10 +#define FL_AMD_NOR 11 +#define FL_SEIJA 12 +#define FL_MDOC_G4 13 +#define FL_MDOC_P4 14 +#define FL_H3 15 + +/*Defines for flExtendedDiskInfo*/ +#define SAFTL_ADVANCED_MATCHING 0x00100000L +#define SAFTL_QUICK_MOUNT 0x10000000L + +#define FL_BDK_PARTITION 1 +#define FL_DISK_PARTITION 0 +#define FL_ALL_FLOORS 0xff +#define BINARY_SPARE_BLOCKS_SIGN "S4BB" /* Must be the same as BINARY_SPARE_BLOCKS_SIGN (FLFORMAT.H) */ + +#define FL_EXT_INFO_NO_SPEC_PART 0xFF /*Indicates SDK not to retrieve specific partition info*/ + + +/**************************************************************************/ +/* Structures and defines for Format routines: */ +/**************************************************************************/ + +typedef FLStatus (*FLProgressCallback)(FLWord totalUnitsToFormat, FLWord totalUnitsFormattedSoFar); + +/*----------------------------------------------*/ +/* User BDTL Partition Format Parameters record */ +/*----------------------------------------------*/ + +typedef struct { +FLDword length; + /* The size in bytes of the usable storage space. The size + rounded upwards to a multiplication of a block size. + The size of the last partition will calculated automatically, + but if the requested size is greater then the remaining space + an error code will be returned,. Requesting zero size for any + partition but the last will generate an flBadParameters status. */ +FLDword fastAreaLength; +FLWord lengthType; +FLWord fastAreaLengthType; +FLWord fastAreaVirtualFactor; /* Should be set to FL_NORMAL_SPACING */ +FLWord noOfSpareUnits; + /* BDTL needs at least one spare erase unit in order to function + as a read/write media. It is possible to specify more than one + spare unit, which takes more media space. The advantage of + specifying more than one spare unit is that if one of the flash + erase units becomes bad and un-erasable in the future, then one + of the spare units can replace it. In that case, a second spare + unit enables TrueFFS to continue its read/write functionality, + whereas if no second spare unit is available the media goes into + read-only mode. The standard value used is 3 */ + +FLDword BDTLFP_0_RFU_0; /* Reserved 0 */ +FLDword BDTLFP_1_RFU_0; /* Reserved 0 */ +FLDword BDTLFP_2_RFU_0; /* Reserved 0 */ +FLDword BDTLFP_3_RFU_0; /* Reserved 0 */ + +FLByte protectionKey[8]; /* The key for the protection*/ +FLByte protectionType; + /* PROTECTABLE - Can receive protection */ + /* READ_PROTECTED - Protect against read operations */ + /* WRITE_PROTECTED - Protect against write operations */ + /* LOCK_ENABLED - Enables the hardware lock signal */ + /* PROTECTABLE - This partition can be protected */ + /* CHANGEABLE_PROTECTION - protection type can be changed */ + /* The ratio between the real media size and the virtual size + reported to the file system when compression is active. */ +} BDTLPartitionFormatParams3; + +/*------------------------------------------------*/ +/* User binary Partition Format Parameters record */ +/*------------------------------------------------*/ + +typedef struct { +FLDword length; /* Required number of usable bytes (rounded to units) */ + /* in the partition. */ + +FLWord lengthType; /* Must be FL_LENGTH_IN_BYTES */ + +FLByte sign[4]; /* signature of the binary partition to format. + The signature 0xFFFF FFFF is not a valid signature */ + +FLDword flags; /* TL_NORMAL_FORMAT / TL_SPL_FORMAT */ + +FLWord spareBlocks; /* Spare blocks for DBB support */ + +FLDword BDKFP_0_RFU_0; /* Reserved 0 */ +FLDword BDKFP_1_RFU_0; /* Reserved 0 */ +FLDword BDKFP_2_RFU_0; /* Reserved 0 */ +FLDword BDKFP_3_RFU_0; /* Reserved 0 */ + +/* TL_NORMAL_FORMAT / TL_SPL_FORMAT */ + +FLByte protectionKey[8]; /* The key for the protection*/ +FLByte protectionType; + /* PROTECTABLE - Can receive protection */ + /* READ_PROTECTED - Protect against read operations */ + /* WRITE_PROTECTED - Protect against write operations */ + /* LOCK_ENABLED - Enables the hardware lock signal */ + /* PROTECTABLE - This partition can be protected */ + /* CHANGEABLE_PROTECTION - protection type can be changed */ +} BinaryPartitionFormatParams3; + + +/*---------------------------------------------------------*/ +/* User Format Parameters record for flFlashFormat routine */ +/*---------------------------------------------------------*/ + + +typedef struct { + +/*****************************/ +/* Device formatting section */ +/*****************************/ + +FLByte percentUse; + /* NAND flash inherently contains some bad blocks. TrueFFS handles + * those blocks by managing a pool of spare blocks also called transfer + * units. This format parameter specifies the percentage of the media + * to use. + * + * Starting from TrueFFS 6.3.0 alpha 4 this field is no longer a + * configurable formatting argument. You must set this field to + * TL_DEFAULT_PERCENTAGE, letting TrueFFS to choose this value for you. + */ + +FLByte noOfBDTLPartitions; + /* Indicates the number of Disk partition (1 to 4). */ + +FLByte noOfBinaryPartitions; + /* Indicates the number of binary partitions (up to 3). 0 will + * cause formatting with no binary partition. This value is ignored + * if TL_LEAVE_BINARY_AREA flag is set in the irFlags field the ioreq + */ + +BDTLPartitionFormatParams3 FAR2* BDTLPartitionInfo; + /* BDTL partition information array */ + +BinaryPartitionFormatParams3 FAR2* binaryPartitionInfo; + /* Binary partition information array*/ + +/***********************************/ +/* Special format features section */ +/***********************************/ + +FLByte cascadedDeviceNo; /* Not used */ + +FLByte noOfCascadedDevices; /* Not used */ + +FLProgressCallback progressCallback; + /* Progress callback routine, will be called if not NULL. + The callback routine is called after erasing each unit, + and its parameters are the total number of erase units + to format and the number erased so far. + The callback routine returns a Status value. A value of + OK (0) allows formatting to continue. Any other value + will abort the formatting with the returned status code. */ + /* In case the FL_REPORT_MOUNT_PROGRESS compilation flag is set the + routine will also report the mount progress of the mount routine + for each of the Disk partitions. A 0,0 return values will report + the end of a format status and of a mount operation */ + +FLDword FP_0_RFU_0; /* Reserved 0 */ + +FLDword FP_1_RFU_0; /* Reserved 0 */ + +/* Note the following section is not used by for DiskOnChips */ +/*************************************************************/ + +FLSDword bootImageLen; /* Reserved 0 */ + +FLDword vmAddressingLimit; /* Reserved 0 */ + +FLWord embeddedCISlength; /* Reserved 0 */ + +FLByte FAR1 * embeddedCIS; /* Reserved NULL */ +} FormatParams3; + +/*--------------------------------------------------*/ +/* Flags for format routine (non partition related) */ +/*--------------------------------------------------*/ +#ifdef BDK_ACCESS +#define TL_LEAVE_BINARY_AREA 0x8 /* Is assumed to be a single bit */ +#define TL_LEAVE_SOME_BINARY_AREA 0x9 /* Must include TL_LEAVE_BINARY_AREA bits */ +#endif /*BDK_ACCESS*/ + +#define TL_SINGLE_FLOOR 0x10 /* Format only a selection of the floors */ +#define TL_DO_NOT_PERFORM_DOWNLOAD 0x20 /* Do not issue a download operation at */ + /* end of the format routine. */ +#define TL_FAIL_ON_UNMARKED_BB 0x80 /* Fail in case an unmarked bad block is */ + /* Found. */ + +#define TL_LEAVE_SOME_PARTITIONS 0x9 + +/*--------------------------------------------------*/ +/* Formatting parameter structure definition */ +/*--------------------------------------------------*/ +#define FL_LENGTH_IN_BYTES 0 +#define FL_LENGTH_IN_SECTORS 1 +#define FL_LENGTH_IN_UNITS 2 +#define FL_LENGTH_IN_PERCENTS 3 +#define FL_LENGTH_IN_CYLINDERS 10 +#define FL_LENGTH_ALL 20 + +/*--------------------------------------------------*/ +/* Internal Partition flags - N O T F O R U S E */ +/*--------------------------------------------------*/ +#define TL_SIMPLE_MATCHING 0x10 /* Use simple matching for partition */ +#define TL_FORCE_REL 0x20 /* Use RELIABLE mode */ +#define TL_FAST_MODE 0x40 /* Use FAST mode */ +#define TL_NO_PLANES 0x80 /* Do not match blocks for planes */ + +/*--------------------------------------------------*/ +/* External Disk Partition Flags (TL_NORMAL_FORMAT):*/ +/*--------------------------------------------------*/ +#define TL_NORMAL_FORMAT 0 + +#ifdef BDK_ACCESS +/*--------------------------------------------------*/ +/* External Binary Partition Flags */ +/* (TL_NORMAL_FORMAT / TL_SPL_FORMAT) */ +/*--------------------------------------------------*/ +#define TL_SPL_FORMAT (TL_SIMPLE_MATCHING | TL_NO_PLANES | TL_FORCE_REL) /* SPL partition */ +#endif /*BDK_ACCESS*/ + +/*--------------------------------------------------*/ +/* External spacing factors - only 1 value */ +/*--------------------------------------------------*/ +#define FL_NORMAL_SPACING 1 + +/*--------------------------------------------------*/ +/* Standard initializer for */ +/* BDTLPartitionFormatParams3 structure */ +/*--------------------------------------------------*/ + +#define TL_DEFAULT_PERCENTAGE 0 /* Use default percentage of the media */ +#define TL_NO_BOOST 0 /* Do not use any performance boost */ +#define TL_BASIC_BOOST 1 /* Use basic 1% performance boost */ +#define TL_ENHANCED_PERFORMANCE 100 /* Define as enhanced performance partition */ + +#define TL_BDTL_STD_SPACE_FACTOR FL_NORMAL_SPACING +#define TL_BDTL_STD_SPARE_UNITS_NO 3 +#define STD_BDTL_PARAMS3 {0, /* Total Length */ \ + 0, /* Fast Length */ \ + FL_LENGTH_IN_BYTES, /* Total Length type */ \ + FL_LENGTH_IN_SECTORS, /* Fast Length type */ \ + TL_BDTL_STD_SPACE_FACTOR,/* Spaced Factor */ \ + TL_BDTL_STD_SPARE_UNITS_NO,/* No of spare units */ \ + 0,0,0,0, /* Reserved 0 */ \ + {0,0,0,0,0,0,0,0},0} /* No H/W protection */ + +/*--------------------------------------------------*/ +/* Standard initializer for */ +/* BinaryPartitionFormatParams3 structure */ +/*--------------------------------------------------*/ +#define TL_BDK_STD_SPARE_BLOCKS_NO 1 +#define STD_BINARY_PARAMS3 {0, /* Partition length */ \ + FL_LENGTH_IN_BYTES, /* Partition length type */ \ + {'B','I','P','O'}, /* Signature */ \ + 0, /* 0 -normal partition , TL_SPL_FORMAT for SPL Partition */ \ + TL_BDK_STD_SPARE_BLOCKS_NO,/* Number of spare blocks */ \ + 0,0,0,0, /* Reserved 0 */ \ + {0,0,0,0,0,0,0,0}, /* Protection key */ \ + 0} /* Protection type */ \ + +/*--------------------------------------------------*/ +/* Standard initializer for FormatParams3 structure */ +/*--------------------------------------------------*/ +#define STD_FORMAT_PARAMS3 {TL_DEFAULT_PERCENTAGE, /* Percent used */ \ + 1, /* No of Disk Partitions */ \ + 0, /* No of Binary Partitions */ \ + NULL, /* Disk partition structure */ \ + NULL, /* Binary partition structure */ \ + 0, /* This cascaded device */ \ + 0, /* Total cascaded devices */ \ + NULL, /* Progress call back */ \ + 0, 0, /* Reserved 0 */ \ + 0, 0, 0, NULL} /* Reserved 0 */ + + + +#ifdef BDK_ACCESS +/**************************************************************************/ +/* Structures and defines for BDK routines: */ +/**************************************************************************/ +#define BDK_SIGNATURE_NAME 4 + +typedef struct { + FLByte oldSign[BDK_SIGNATURE_NAME]; + FLByte newSign[BDK_SIGNATURE_NAME]; + FLByte signOffset; + FLDword startingBlock; + FLDword length; + FLByte flags; + FLByte FAR1 *bdkBuffer; +} BDKStruct; + +#define ERASE_BEFORE_WRITE 8 + +#endif /*BDK_ACCESS*/ + + +/**************************************************************************/ +/* Defines for Defrag routines: */ +/**************************************************************************/ +#define FL_MINIMAL_DEFRAGMENTATION -1 +#define FL_MAXIMUM_DEFRAGMENTATION -20 +#define FL_STATIC_WEAR_LEVELING_DELAYED -2 +#define FL_STATIC_WEAR_LEVELING_NOW -3 +#define FL_STATIC_WEAR_LEVELING_ON -4 +#define FL_STATIC_WEAR_LEVELING_OFF -5 + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED +typedef struct { + FLByte jumpInstruction[3]; + FLSByte OEMname[8]; + Unaligned bytesPerSector; + FLByte sectorsPerCluster; + LEushort reservedSectors; + FLByte noOfFATS; + Unaligned rootDirectoryEntries; + Unaligned totalSectorsInVolumeDOS3; + FLByte mediaDescriptor; + LEushort sectorsPerFAT; + LEushort sectorsPerTrack; + LEushort noOfHeads; + LEulong noOfHiddenSectors; + LEulong totalSectorsInVolume; +} BPB; +#else /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +#define FL_BPB_JUMP_INSTRUCTION_OFFSET 0 /* size 3, array */ +#define FL_BPB_OEM_NAME_OFFSET 3 /* size 8, array */ +#define FL_BPB_BYTES_PER_SECTOR_OFFSET 11 /* size 2, unaligned */ +#define FL_BPB_SECTORS_PER_CLUSTER_OFFSET 13 /* size 1 */ +#define FL_BPB_RESERVED_SECTORS_OFFSET 14 /* size 2 */ +#define FL_BPB_NO_OF_FATS_OFFSET 16 /* size 1 */ +#define FL_BPB_ROOT_DIR_ENTRIES_OFFSET 17 /* size 2, unaligned */ +#define FL_BPB_TOTAL_SECTORS_IN_VOL_DOS3_OFFSET 19 /* size 2, unaligned */ +#define FL_BPB_MEDIA_DESCRIPTOR_OFFSET 21 /* size 1 */ +#define FL_BPB_SECTORS_PER_FAT_OFFSET 22 /* size 2 */ +#define FL_BPB_SECTORS_PER_TRACK_OFFSET 24 /* size 2 */ +#define FL_BPB_NO_OF_HEADS_OFFSET 26 /* size 2 */ +#define FL_BPB_NO_OF_HIDDEN_SECTORS_OFFSET 28 /* size 4 */ +#define FL_BPB_TOTAL_SECTORS_IN_VOL_OFFSET 32 /* size 4 */ +#define FL_BPB_SIZE 36 +typedef FLByte BPB[FL_BPB_SIZE]; +#endif /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +typedef struct { +FLDword length; +FLWord lengthType; +FLByte pType; +FLByte flags; +}LogicalPartitionParams; + +#define STD_LOG_PARTITION_PARAMS {0, /* Partition length */ \ + FL_LENGTH_IN_BYTES, /* Bytes, Sectors ... */ \ + DOS4_PARTIT, /* Partition type */ \ + FL_MARK_PARTITION_BOOTABLE}/* Either bootable or not */ \ + +typedef struct { +SectorNo bootSectorNo; +SectorNo sectorsInVolume; +SectorNo MBR; +int MBRslot; +} LogPartitionInfo; + +#ifndef FL_NO_PACKED_STRUCTS_SUPPORTED +typedef struct { + FLSByte name[11]; + FLByte attributes; /* mapped below */ + FLByte lowerCaseFlags; + FLByte createTimeMilisec; + LEushort createTimeHourMin; + LEushort createDate; + LEushort lastAccessedDate; + LEushort reserved1; + LEushort updateTime; + /* The date field is encoded as follows: */ + /* bit 0-4: Day of month (1-31) */ + /* bit 5-8: Month (1-12) */ + /* bit 9-15: Year relative to 1980 */ + LEushort updateDate; + /* The DOS time field is encoded as follows: */ + /* bit 0-4: seconds divided by 2 (0-29) */ + /* bit 5-10: minutes (0-59) */ + /* bit 11-15: hours (0-23) */ + LEushort startingCluster; + LEulong fileSize; +} DirectoryEntry; +#else /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +#define FL_DIRECTORY_ENTRY_NAME_OFFSET 0 /* size 11, array */ +#define FL_DIRECTORY_ENTRY_ATTRIBUTES_OFFSET 11 /* size 1 */ +#define FL_DIRECTORY_ENTRY_LOWERCASE_FLAGS_OFFSET 12 /* size 1 */ +#define FL_DIRECTORY_ENTRY_CREATE_TIME_MILLISEC_OFFSET 13 /* size 1 */ +#define FL_DIRECTORY_ENTRY_CREATE_TIME_HOURMIN_OFFSET 14 /* size 2 */ +#define FL_DIRECTORY_ENTRY_CREATE_DATE_OFFSET 16 /* size 2 */ +#define FL_DIRECTORY_ENTRY_LAST_ACCESS_DATE_OFFSET 18 /* size 2 */ +#define FL_DIRECTORY_ENTRY_RESERVED1_OFFSET 20 /* size 2 */ +#define FL_DIRECTORY_ENTRY_UPDATE_TIME_OFFSET 22 /* size 2 */ +#define FL_DIRECTORY_ENTRY_UPDATE_DATE_OFFSET 24 /* size 2 */ +#define FL_DIRECTORY_ENTRY_STARTING_CLUSTER_OFFSET 26 /* size 2 */ +#define FL_DIRECTORY_ENTRY_FILESIZE_OFFSET 28 /* size 4 */ +#define FL_DIRECTORY_ENTRY_SIZE 32 +typedef FLByte DirectoryEntry[FL_DIRECTORY_ENTRY_SIZE]; +#endif /*FL_NO_PACKED_STRUCTS_SUPPORTED*/ +/* FAT Format Parameters record - given to flFormatFS */ + +typedef struct { +FLWord noOfRootEntries; +FLWord noOfSectorsPerCluster; +FLByte noOfFATs; +FLByte pType; +FLByte reserved1; +FLByte flags; +FLByte volumeId[4]; /* FAT partition identification number */ +FLByte* volumeLabel; /* FAT partition label string. If NULL, no label */ +} FATFormatParams; + + +#define FAT12_PARTIT 0x01 +#define FAT16_PARTIT 0x04 +#define EX_PARTIT 0x05 +#define DOS4_PARTIT 0x06 +#define FAT32_PARTIT 0x0b + +#define FL_TFAT_MODE 0x1 + +#define FS_USE_DEFAULT_CLUSTER_SIZE 0 + +#define STD_FAT_FORMAT_PARAMS {512, /* No of entries in the rood directory */ \ + FS_USE_DEFAULT_CLUSTER_SIZE, /* No of sectors per cluster */ \ + 1, /* No of FAT copies */ \ + 0, /* Partition type */ \ + 0, 0, /* Reseved 0 */ \ + {0, 0, 0, 0}, /* FAT Volume ID */ \ + NULL} /* FAT Lable */ + + +#endif /* FLSTRUCT_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsysfun.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsysfun.h new file mode 100755 index 00000000..905eace1 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsysfun.h @@ -0,0 +1,239 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/flsysfun.h-arc $ + * + * Rev 1.8 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.7 Sep 11 2006 13:45:24 yaniv.iarovici + * Legal header added + * + * Rev 1.6 Aug 09 2006 16:52:52 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLSYSFUN_H +#define FLSYSFUN_H + + +/*----------------------------------------------------------------------*/ +/* f l S y s f u n I n i t */ +/* */ +/* Do any necessary initialization for routines in this module. */ +/* */ +/* Called from fatlite.c (flInit) */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/*----------------------------------------------------------------------*/ + +extern void flSysfunInit(void); + + +/*----------------------------------------------------------------------*/ +/* f l R a n d B y t e */ +/* */ +/* Returns a random number between 0 and 255 */ +/* */ +/* Called from FTLLITE.C */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* A random number between 0 and 255 */ +/*----------------------------------------------------------------------*/ + +extern unsigned flRandByte(void); + + +/*----------------------------------------------------------------------*/ +/* f l I n s t a l l T i m e r */ +/* */ +/* Installs an interval timer. */ +/* The implementation of this routine usually means hooking a clock */ +/* interrupt. The polling interval is specified as a parameter. If the */ +/* clock frequency is faster, the interval timer should count several */ +/* clock ticks before calling the interval routine. */ +/* */ +/* This routine is necessary if POLLING_INTERVAL (custom.h) is greater */ +/* than 0. In this case this routine will be called from socket.c */ +/* (init). It will be called to install 'socketIntervalRoutine' with a */ +/* period specified by POLLING_INTERVAL. */ +/* */ +/* Parameters: */ +/* routine : Routine to call at each interval */ +/* interval : Milliseconds per polling interval */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failure */ +/*----------------------------------------------------------------------*/ + +extern FLStatus flInstallTimer(void (*routine)(void), unsigned interval); + + +#ifdef FL_EXIT + +/*----------------------------------------------------------------------*/ +/* f l R e m o v e T i m e r */ +/* */ +/* Removes the active interval timer. */ +/* This routine removes the active interval timer set by 'removeTimer'. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/*----------------------------------------------------------------------*/ + +extern void flRemoveTimer(void); + +#endif + + +/*----------------------------------------------------------------------*/ +/* f l C u r r e n t D a t e */ +/* */ +/* Returns the current DOS-format date */ +/* */ +/* The DOS date format is documented in dosformt.h. */ +/* */ +/* If a TOD clock is not available, return the value of 1/1/80. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* Current date */ +/*----------------------------------------------------------------------*/ + +extern unsigned flCurrentDate(void); + + +/*----------------------------------------------------------------------*/ +/* f l C u r r e n t T i m e */ +/* */ +/* Returns the current DOS-format time */ +/* */ +/* The DOS time format is documented in dosformt.h. */ +/* */ +/* If a TOD clock is not available, return the value of 0:00 AM. */ +/* */ +/* Parameters: */ +/* None */ +/* */ +/* Returns: */ +/* Current time */ +/*----------------------------------------------------------------------*/ + +extern unsigned flCurrentTime(void); + + +/*----------------------------------------------------------------------*/ +/* f l C r e a t e M u t e x */ +/* */ +/* Creates and initializes a mutex object */ +/* */ +/* The mutex is initializes as not owned by anyone. */ +/* */ +/* Parameters: */ +/* mutex : Pointer to mutex object */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failure */ +/*----------------------------------------------------------------------*/ + +extern FLStatus flCreateMutex(FLMutex *mutex); + + +/*----------------------------------------------------------------------*/ +/* f l D e l e t e M u t e x */ +/* */ +/* Destroys a mutex object */ +/* */ +/* This function frees any resources taken by flCreateMutex. */ +/* */ +/* Parameters: */ +/* mutex : Pointer to mutex object */ +/* */ +/* Returns: */ +/* None */ +/*----------------------------------------------------------------------*/ + +extern void flDeleteMutex(FLMutex *mutex); + + +/*----------------------------------------------------------------------*/ +/* f l T a k e M u t e x */ +/* */ +/* Attempts to take ownership of a mutex. If the mutex is currently not */ +/* owned, TRUE is returned and the mutex becomes owned. If the mutex is */ +/* currently owned, FALSE is returned and ownership is not taken. */ +/* */ +/* Parameters: */ +/* mutex : Pointer to mutex object */ +/* */ +/* Returns: */ +/* FLBoolean : TRUE if ownership taken, FALSE otherwise */ +/*----------------------------------------------------------------------*/ + +extern FLBoolean flTakeMutex(FLMutex *mutex); + + +/*----------------------------------------------------------------------*/ +/* f l F r e e M u t e x */ +/* */ +/* Frees ownership of a mutex */ +/* */ +/* Parameters: */ +/* mutex : Pointer to mutex object */ +/* */ +/* Returns: */ +/* None */ +/*----------------------------------------------------------------------*/ + +extern void flFreeMutex(FLMutex *mutex); + + +#endif /* FLSYSFUN_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystem.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystem.c new file mode 100755 index 00000000..bf4621e8 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystem.c @@ -0,0 +1,720 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + + +/* + * includes + */ + +#include "tffsdrv.h" +#include "flbase.h" +#include "doch_sys.h" +#include "hib.h" + + +#ifdef TFFS_MESSAGES_ENABLED +int fl_debug = FL_DEBUG_DEF; +module_param(fl_debug, int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(fl_debug,"Print TrueFFS debug messages [0-7]."); +#endif + +/* For portability reasons, Linux drivers should use macros readXXX/writeXXX + * when reading/writing hardware registers and transferring data from + * devices. Command line parameter "tffs_memcpy=<1|2|3>" allows DiskOnChip + * driver to use memcpy() library routine instead, which often greatly + * improves driver's 'read' performance. + * + * insmod tffs.o tffs_memcpy=1 + */ +int tffs_memcpy = 0; +module_param(tffs_memcpy, int, S_IRUGO); +MODULE_PARM_DESC(tffs_memcpy, "Use memcpy() for DiskOnChip data transfers."); + + +/* Command line parameter "tffs_addr=" allows user to tell + * DiskOnChip driver where to look for DiskOnChip. For example, to instruct + * driver to probe for DiskOnChip at physical address 0x14000000: + * + * insmod tffs.o tffs_addr=0x14000000 + */ +ulong tffs_addr[FL_SOCKETS] = { TFFS_PHYS_ADDR }; +static int __fl_sockets = FL_SOCKETS; /* just for module_param_array() below */ +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,9)) + module_param_array(tffs_addr, ulong, __fl_sockets, S_IRUGO); +#else + module_param_array(tffs_addr, ulong, &__fl_sockets, S_IRUGO); +#endif +MODULE_PARM_DESC(tffs_addr,"Physical address of DiskOnChip."); + +/* Command line parameter "tffs_skip_sleeps=" instructs DiskOnChip driver + * how often it should yield CPU during DiskOnChip 'write' operations. The + * higher the , the less frequently driver yield CPU, thus increasing + * it's 'write' performance, but also increasing it's load on CPU. + * + * insmod tffs.o tffs_skip_sleep=3 + */ +int tffs_skip_sleeps = 5; +module_param(tffs_skip_sleeps, int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(tffs_skip_sleeps,"How often to yield CPU during write operations."); + + +unsigned int profiling[10] = {0}; + + + +/* + * static routines + */ +static void TffsMapMem (SocketInfo *psoc, unsigned long phys_addr, unsigned long length); +static void TffsUnmapMem (SocketInfo *psoc); +static void irq_wait_timed_out (unsigned long arg); + + + +/* + * static vars + */ + +/* semaphore used by TrueFFS: one per socket, plus one for dochVol.mutex */ +static struct semaphore sems [FL_SOCKETS + 1]; + +/* next TrueFFS semaphore to allocate (0..FL_SOCKETS-1) */ +static int total_sems = 0; + + + + +/*-----------------------------------------------------------------------* + * * + * T f f s M a p M e m * + * * + * Allocate physical memory region, and map it into kernel's address * + * space. * + * * + * Parameters: * + * psoc socket pointer * + * phys_addr starting address of physical memory region * + * length length (in bytes) of this physical memory region * + * * + *-----------------------------------------------------------------------*/ +static +void TffsMapMem ( SocketInfo * psoc, + unsigned long phys_addr, + unsigned long length ) +{ + struct resource * rs; + + /* no memory region has been obtained yet */ + psoc->fMemRequested = 0; + psoc->dwPhysAddr = 0; + psoc->dwMappedLen = 0; + psoc->dwVirtAddr = 0; + + /* request physical memory region that DiskOnChip resides in */ + if ((rs = request_mem_region(phys_addr, length, "tffs")) != NULL) + { + /* map this physical memory region to kernel's virtual addr. space */ + if ((psoc->dwVirtAddr = (ulong)ioremap_nocache(phys_addr, length)) != 0) + { + psoc->fMemRequested = 1; + psoc->dwPhysAddr = phys_addr; + psoc->dwMappedLen = length; + } + else + { + PrintkDebug("ioremap_nocache(0x%lx,0x%lx) failed", phys_addr, length); + release_mem_region (phys_addr, length); + } + } + else + { PrintkDebug("request_mem_region(0x%lx,0x%lx) failed", phys_addr, length); } +} + + + + +/*-----------------------------------------------------------------------* + * * + * T f f s U n m a p M e m * + * * + * Unmap and free memory region previously allocated by TffsMapMem(). * + * * + * Parameters: * + * psoc socket pointer * + * * + *-----------------------------------------------------------------------*/ +static +void TffsUnmapMem ( SocketInfo * psoc ) +{ + if (psoc->dwVirtAddr != 0) + iounmap ((void *)psoc->dwVirtAddr); + + if (psoc->fMemRequested == 1) + release_mem_region (psoc->dwPhysAddr, psoc->dwMappedLen); + + psoc->fMemRequested = 0; + psoc->dwPhysAddr = 0; + psoc->dwMappedLen = 0; + psoc->dwVirtAddr = 0; +} + + + + +void * TffsMalloc (unsigned long size) +{ + return vmalloc (size + 4); +} + + + + +void TffsFree (void * vptr) +{ + vfree (vptr); +} + + + + +int LnxTffsPrint(const char *fmt, ...) +{ + va_list args; + char buf[1024]; /* hopefully enough, kernel/printk.c thinks so */ + int i; + + va_start(args, fmt); + i = vsprintf(buf, fmt, args); + va_end(args); + buf[i] = '\0'; + + while(i>0) + { + if(buf[i-1]==0xd || buf[i-1]==0xa) + { + buf[--i]=0; + } + else + break; + } + printk(KERN_ERR TFFS_DEVICE_NAME": %s\n",buf); + return i; +} + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ r e a d w * + * * + * This routine transfers data from RAM to DiskOnChip device in cases * + * when DMA is not used. * + * * + * Parameters: * + * io_vaddr virtual address of DiskOnChip's data port * + * vbuf buffer to transfer data from * + * words number of 16-bit short words to transfer * + * * + *-----------------------------------------------------------------------*/ + +void tffs_readw ( unsigned long io_vaddr, short * vbuf, int words ) +{ + if (tffs_memcpy & 1) /* use memcpy() to transfer data; might not work ! */ + { + register char * p = (char *) vbuf; + register int n; + + for (words <<= 1; words > 0; words -= n, p += n) + { + /* DiskOnChip's I/O register is aliased across 1024-bytes region */ + n = ((words <= 1024) ? words : 1024); + memcpy (p, (void *)io_vaddr, n); + } + } + else /* standard Linux case: use __raw_readw for portability */ + { + while (words--) + *vbuf++ = __raw_readw (io_vaddr); + } +} + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ w r i t e w * + * * + * This routine transfers data from DiskOnChip device to RAM in cases * + * when DMA is not used. * + * * + * Parameters: * + * io_vaddr virtual address of DiskOnChip's data port * + * vbuf buffer to transfer data to * + * words number of 16-bit short words to transfer * + * * + *-----------------------------------------------------------------------*/ + +void tffs_writew ( unsigned long io_vaddr, short * vbuf, int words ) +{ + if (tffs_memcpy & 2) /* use memcpy() to transfer data; might not work ! */ + { + register char * p = (char *) vbuf; + register int n; + + for (words <<= 1; words > 0; words -= n, p += n) + { + /* DiskOnChip's I/O register is aliased across 1024-bytes region */ + n = ((words <= 1024) ? words : 1024); + memcpy ((void *)io_vaddr, p, n); + } + } + else /* standard Linux case: use __raw_writew for portability */ + { + while (words--) + { + __raw_writew (*vbuf, io_vaddr); + vbuf++; + } + } +} + + + +/*-----------------------------------------------------------------------* + * * + * d o c h b l k _ r e a d * + * * + * This routine transfers data from DiskOnChip H3 device to RAM. * + * * + * Parameters: * + * vbuf buffer to transfer data to * + * sectors number of 512-byte sectors to transfer * + * * + *-----------------------------------------------------------------------*/ + +int dochblk_read (void * vbuf, unsigned int sectors) +{ + flReadEvenNumberOfBytes ((DOCHFlash), DOCH_DATA_PORT_AREA, vbuf, ((sectors) << 9)); + return 0; +} + + + +/*-----------------------------------------------------------------------* + * * + * d o c h b l k _ w r i t e * + * * + * This routine transfers data from RAM to DiskOnChip H3 device. * + * * + * Parameters: * + * vbuf buffer to transfer data from * + * sectors number of 512-byte sectors to transfer * + * * + *-----------------------------------------------------------------------*/ + +int dochblk_write (void * vbuf, unsigned int sectors) +{ + flWriteEvenNumberOfBytes ((DOCHFlash), DOCH_DATA_PORT_AREA, vbuf, ((sectors) << 9)); + return 0; +} + + + + +void flSysfunInit ( void ) +{ + register int iSoc; + unsigned long win_size; /* size of DiskOnChip window in bytes */ + + total_sems = 0; + + /* DiskOnChip H3 devices can be configured to use 8-, 32- or 128-KByte + * window; we assume the worst case here (128-KB). + */ + win_size = DOCH_MEM_WIN_SIZE_128KB /* or DOCH_MEM_WIN_SIZE_8KB */; + + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + TffsMapMem (&tffsInfo.sockets[iSoc], tffs_addr[iSoc], win_size); + + /* We are not doing 'resume' after previous power 'suspend', but rather + * a full scale board initialization, hence FALSE flag below. + */ + if( tffsarch_init(FALSE) == 0 ) + PrintkWarning("tffsarch_init error"); +} + + + +void LnxSysfunRelease ( void ) +{ + int i; + + for (i = 0; i < FL_SOCKETS; i++) + TffsUnmapMem (&tffsInfo.sockets[i]); + + total_sems = 0; + + TffsHWRelease (); +} + + + +/*-----------------------------------------------------------------------* + * * + * f l C r e a t e M u t e x * + * * + * Create mutex. . * + * * + * Parameters: * + * mutex ID of newly created sempahore will be stored here * + * * + * Returns: * + * flOK if successful otherwise respective error code * + * * + *-----------------------------------------------------------------------*/ + +FLStatus flCreateMutex (FLMutex * mutex) +{ + if (total_sems >= (sizeof(sems) / sizeof(sems[0]))) + { + PrintkError("flCreateMutex: error creating mutex"); + return flNotEnoughMemory; + } + + /* initialize next available semaphore to 'available' state */ + sema_init (&sems[total_sems], 1); + + *mutex = (FLMutex) total_sems++; + + return flOK; +} + + + +/*-----------------------------------------------------------------------* + * * + * f l T a k e M u t e x * + * * + * Called to aquire the mutex. * + * * + * Parameters: * + * mutex identifies mutex to release * + * * + * Returns: * + * always TRUE * + * * + *-----------------------------------------------------------------------*/ + +FLBoolean flTakeMutex (FLMutex * mutex) +{ + register struct semaphore * psem = &sems[ (int)(*mutex) ]; + + /* put caller to sleep until semaphore is available */ + if( down_interruptible(psem) != 0 ) + { + /* Semaphore still isn't available - down_interruptible() returned + * because caller was waken up by signal. We must abort TrueFFS call. + */ + return FALSE; + } + + /* semaphore has been taken; TrueFFS call can proceed now */ + return TRUE; +} + + + +/*-----------------------------------------------------------------------* + * * + * f l F r e e M u t e x * + * * + * Called to release the mutex. * + * * + * Parameters: * + * mutex identifies mutex to release * + * * + *-----------------------------------------------------------------------*/ + +void flFreeMutex (FLMutex * mutex) +{ + register struct semaphore * psem = &sems[ (int)(*mutex) ]; + + /* release semaphore */ + up (psem); +} + + + +/*-----------------------------------------------------------------------* + * * + * f l D e l e t e M u t e x * + * * + * Called to destroy the mutex and free all associated resources. * + * * + * Parameters: * + * mutex identifies mutex to destroy * + * * + *-----------------------------------------------------------------------*/ + +void flDeleteMutex (FLMutex * mutex) +{ + /* just in case some thread(s) are still sleeping on this semaphore */ + flFreeMutex (mutex); +} + + + + +/*-----------------------------------------------------------------------* + * * + * f l B u i l d G e o m e t r y * + * * + * This routine calculates cylinder/head/sector geometry based on the * + * number of sectors on the disk. * + * * + * Parameters: * + * sectors total sectors on disk * + * cyl pointer to number of cylinders * + * heads pointer to number of heads * + * sec_per_track pointer to number of sectors per track * + * oldFormat ignored * + * wirHandle ignored * + * * + *-----------------------------------------------------------------------*/ + +void flBuildGeometry ( unsigned long sectors, + unsigned long * cyl, + unsigned long * heads, + unsigned long * sec_per_track, + unsigned char oldFormat, + unsigned short wIrHandle ) +{ + DeviceInfo * pdisk; + register int i; + + for (i = 0; i < (sizeof(tffsInfo.ppDevices) / sizeof(tffsInfo.ppDevices[0])); i++) + { + if ((pdisk = tffsInfo.ppDevices[i]) == NULL) + return; + + /* The 'wIrHandle' argument is the internal TrueFFS handle which is + * different from TrueFFS handle stored in DeviceInfo.bHandle, and + * passed to TrueFFS API routines. + */ + if (pdisk->dwSize == sectors) /* was (pdisk->bHandle == wIrHandle) */ + { + if (cyl != NULL) *cyl = pdisk->wCyl; + if (heads != NULL) *heads = pdisk->bHead; + if (sec_per_track != NULL) *sec_per_track = pdisk->bSect; + + return; + } + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * i r q _ w a i t _ t i m e d _ o u t * + * * + * This routine is called when DiskOnChip interrupt gets lost, and * + * watchdog timer gets activated. It prevents driver from hanging up in * + * such cases by posting a semaphore that socket's I/O thread is waiting * + * for. * + * * + * Parameters: * + * arg pointer to semaphore * + * * + *-----------------------------------------------------------------------*/ + +static +void irq_wait_timed_out ( unsigned long arg ) +{ + profiling[5]++; + + /* Since this routine is running, it means that DiskOnChip interrupt + * got lost (or delayed for too long). To prevent socket's I/O thread + * from hanging up, we wake up I/O thread here. + */ + complete ((struct completion *)arg); /* up ((struct semaphore *)arg); */ +} + + + + +/*-----------------------------------------------------------------------* + * * + * f l _ t f f s _ s l e e p * + * * + * This routine is called right after starting flash 'write' or 'erase' * + * operation on DiskOnChip. These operations usually take around 700 * + * ('write') or 3000 ('erase') microseconds to complete. This routine * + * might yield the CPU and cause task switch. * + * * + * Parameters: * + * handle TrueFFS handle (only lower 4 bits are used) * + * microseconds expected average duration of flash operation * + * * + *-----------------------------------------------------------------------*/ + +void fl_tffs_sleep ( unsigned int handle, + unsigned long microseconds ) +{ +#ifdef TFFS_USE_SLEEP + + int socNo = (int)(handle & 0xf); /* extract socket # from TrueFFS handle */ + + static int _counter = 0; + + if (tffsInfo.sockets[socNo].io_thread_state != 1) + { + /* DiskOnChip driver is being uninstalled, or power-suspended, or is + * power-resuming. In either of these cases, we want to process all + * outstanding I/O requests as quickly as possible; therefore we + * will not sleep. + */ + return; + } + + if (tffs_irq < 0) /* DiskOnChip R/B interrupts are not used */ + { + if (++_counter > tffs_skip_sleeps) + { + /* Once in a while (once in 'tffs_skip_sleeps' calls to this routine) + * we yield CPU and put DiskOnChip driver to sleep, to give chance + * to other tasks to run. Note that this negatively impacts + * DiskOnChip's 'write' performance. + */ + unsigned long jiffies_to_sleep = (HZ * microseconds) / 1000000; +#if 0 + if (jiffies_to_sleep == 0) + jiffies_to_sleep = 1; +#endif + /* yield CPU and sleep */ + set_current_state (TASK_INTERRUPTIBLE); + schedule_timeout (jiffies_to_sleep); + + _counter = 0; + } + else + { + /* TrueFFS will busy-poll DiskOnChip's status register to + * detect completion of flash 'write' and 'erase' operations. This + * improves DiskOnChip's 'write' performance, but also ties up CPU + * for extensive periods of time. + */ + return; + } + } + else /* yield CPU and sleep until waken up by DiskOnChip interrupt */ + { + struct timer_list watchdog_timer; + + profiling[0]++; + + /* To guard ourselves against stray DiskOnChip interrupts, + * we clear tffsInfo.sockets[socNo].wait_for_irq + * before enabling IRQ that DiskOnChip is nonnected to + */ + init_completion (&tffsInfo.sockets[socNo].wait_for_irq); /* sema_init (&tffsInfo.sockets[socNo].sleep_sem, 0); */ + + tffs_irq_enable (TRUE); + + /* To guard ourselves against the case when DiskOnChip interrupt + * will not be generated for some reason, or will get lost, we + * set watchdog timer to wake us up after 30 milliseconds. + */ + init_timer (&watchdog_timer); + watchdog_timer.function = irq_wait_timed_out; + watchdog_timer.data = (unsigned long) &tffsInfo.sockets[socNo].wait_for_irq /* &tffsInfo.sockets[socNo].sleep_sem */ ; + watchdog_timer.expires = jiffies + ((30 * HZ) / 1000); + add_timer (&watchdog_timer); + + /* sleep until DiskOnChip interrupt or watchdog timer wakes us up */ + wait_for_completion (&tffsInfo.sockets[socNo].wait_for_irq); /* down_interruptible (&tffsInfo.sockets[socNo].sleep_sem); */ + + tffs_irq_disable (TRUE); + + /* no longer need watchdog timer */ + del_timer_sync (&watchdog_timer); + } +#endif /* TFFS_USE_SLEEP */ +} + + + + +/*-----------------------------------------------------------------------* + * * + * d o c h _ s l e e p * + * * + * This routine is called numerous times during DiskOnChip H3 'write' * + * operations. * + * * + * Parameters: * + * sock socket # (zero-based) * + * microseconds expected average duration of flash operation * + * * + *-----------------------------------------------------------------------*/ + +void doch_sleep ( unsigned int soc, + unsigned long microseconds ) +{ + extern int write_requests; + static int __write_requests = 0; + + /* If DiskOnChip IRQ is enabled, or if 'tffs_skip_sleeps' set to yeild + * CPU often, we yield CPU. + */ + if (tffs_irq >= 0) + { + fl_tffs_sleep (soc, microseconds); + } + else + { + /* DiskOnChip IRQ is disabled. We yield CPU according to + * 'tffs_skip_sleep' setting, making sure that we do yield CPU + * at least once per I/O 'write' request. + */ + if ((tffs_skip_sleeps >= 100) || (write_requests != __write_requests)) + { + fl_tffs_sleep (soc, microseconds); + } + __write_requests = write_requests; + } +} diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystem.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystem.h new file mode 100755 index 00000000..e03bd289 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystem.h @@ -0,0 +1,173 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef FLSYSTEM_H +#define FLSYSTEM_H + +#include "flcustom.h" +#include "tffsarch.h" + +#include +#include +#include +#ifdef __KERNEL__ +# include +#endif + +#define NAMING_CONVENTION /* don't change me */ +#define TFFS_DLL_API +#define FL_PACKED_STRUCTURES __attribute__ ((packed)) +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif + +#define FAR_LEVEL 0 +#define FLMutex int + +#ifndef FL_IOCTL_START +# define FL_IOCTL_LNX 0 /* don't change */ +# define FL_IOCTL_START 1 /* don't change */ +#endif + + +/* + * "yield CPU and sleep" implementation for G4/G3/H1 DiskOnChip devices + */ +#define FL_TFFS_SLEEP(handle,microseconds) fl_tffs_sleep((unsigned int)(handle),(microseconds)) +extern void fl_tffs_sleep (unsigned int handle, unsigned long microseconds); + + +/* + * "yield CPU and sleep" implementation for H3 DiskOnChip devices + */ +#define DOCH_SLEEP(soc,dev,microseconds) doch_sleep((soc),(microseconds)) +extern void doch_sleep (unsigned int soc, unsigned long microseconds); + + +/* + * macros for printing debug messages + */ + +#define DBG_PRINT_FLOW(zone,str) do { {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_FLOW_PRM(zone,str) do { {LnxTffsPrint str; } } while(0) +#define DBG_PRINT_WRN(zone,str) do { {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_WRN_PRM(zone,str) do { {LnxTffsPrint str; } } while(0) +#define DBG_PRINT_ERR(zone,str) do { {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_ERR_PRM(zone,str) do { {LnxTffsPrint str; } } while(0) +/* +#define DBG_PRINT_FLOW(zone,str) do { if(fl_debug & 4) {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_FLOW_PRM(zone,str) do { if(fl_debug & 4) {LnxTffsPrint str; } } while(0) +#define DBG_PRINT_WRN(zone,str) do { if(fl_debug & 2) {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_WRN_PRM(zone,str) do { if(fl_debug & 2) {LnxTffsPrint str; } } while(0) +#define DBG_PRINT_ERR(zone,str) do { if(fl_debug & 1) {LnxTffsPrint(str);} } while(0) +#define DBG_PRINT_ERR_PRM(zone,str) do { if(fl_debug & 1) {LnxTffsPrint str; } } while(0) +*/ +extern int LnxTffsPrint (const char *fmt, ...); +extern int fl_debug; + +/* + * dynamic memory allocation/freeing + */ +#define FL_MALLOC TffsMalloc +#define FL_FREE TffsFree +extern void * TffsMalloc (unsigned long size); +extern void TffsFree (void *vptr); + +/* + * Macro DOCH_SYS_FUNC_RELEASE is invoked when rmmod is called + */ +#define DOCH_SYS_FUNC_RELEASE LnxSysfunRelease() +extern void LnxSysfunRelease (void); + +/* + * pointer manupulation macros + */ +#define physicalToPointer(paddr,size,drive) ((void *) (paddr)) +#define addToFarPointer(ptr,val) ((void *) ((unsigned char *) (ptr) + (val))) +#define freePointer(ptr,size) /* do nothing */ + +/* + * macros tffscpy/tffscmp/tffsset are used with RAM buffers only + */ +#define tffscpy memcpy +#define tffscmp memcmp +#define tffsset memset + +/* + * macros for writing byte/short word/long word to I/O memory + */ +#define FLWRITE_IO_BYTE(val,addr) writeb((unsigned char) (val),(volatile unsigned char *)(addr)) +#define FLWRITE_IO_WORD(val,addr) __raw_writew((unsigned short)(val),(addr)) +#define FLWRITE_IO_DWORD(val,addr) __raw_writel((unsigned long) (val),(addr)) + +/* + * macros for reading byte/short word/long word from I/O memory + */ +#define FLREAD_IO_BYTE(addr) readb((volatile unsigned char*) (addr)) +#define FLREAD_IO_WORD(addr) __raw_readw(addr) +#define FLREAD_IO_DWORD(addr) __raw_readl(addr) + +/* + * macros for transferring data blocks to I/O memory + */ +#define TFFSCPY_FROM_IO(dest,src,cnt) memcpy_fromio((dest),(void*)(src),(cnt)) +#define TFFSCPY_FROM_IO_8_BITS TFFSCPY_FROM_IO +#define TFFSCPY_FROM_IO_16_BITS TFFSCPY_FROM_IO + +/* + * macros for transferring data blocks from I/O memory + */ +#define TFFSCPY_TO_IO(dest,src,cnt) memcpy_toio((void*)(dest),(src),(cnt)) +#define TFFSCPY_TO_IO_8_BITS TFFSCPY_TO_IO +#define TFFSCPY_TO_IO_16_BITS TFFSCPY_TO_IO + +/* + * macros for memset-like operations on I/O memory + */ +#define TFFSSET_IO(dest,val,cnt) memset_io((void*)(dest),(val),(cnt)) +#define TFFSSET_IO_8_BITS TFFSSET_IO +#define TFFSSET_IO_16_BITS TFFSSET_IO + + +extern int tffs_irq; +extern void tffs_irq_enable (int lock); +extern void tffs_irq_disable (int lock); + + +#endif /* FLSYSTEM_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystyp.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystyp.h new file mode 100755 index 00000000..67385c8c --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/flsystyp.h @@ -0,0 +1,96 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/version 6.3-up/BDK/src/flsystyp.h-arc $ + * + * Rev 1.14 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + */ + +/***************************************************************************** +* File Header * +* ----------- * +* Name : flsystyp.h * +* * +* Description : System defintions and types required for the implementation * +* of the system customization routines. * +* * +*****************************************************************************/ + +#ifndef FLSYSTYPE_H +#define FLSYSTYPE_H + + +#include "_common.h" +#include "flsystem.h" + +/* Boolean constants */ +#ifndef FALSE +#define FALSE 0 +#endif /* FALSE */ +#ifndef TRUE +#define TRUE 1 +#endif /* TRUE */ + + +/* Zones for debug printing */ + +#define FLZONE_NONE 0 +#define FLZONE_MTD 0x0001 +#define FLZONE_BDK 0x0002 +#define FLZONE_TL 0x0004 +#define FLZONE_BLKDEV 0x0008 +#define FLZONE_FORMAT 0x0010 +#define FLZONE_FS 0x0020 +#define FLZONE_SOCKET 0x0040 +#define FLZONE_IOCTL 0x0080 +#define FLZONE_PROD 0x0100 +#define FLZONE_STATISTICS 0x0200 +#define FLZONE_UTIL 0x0400 +#define FLZONE_PARA 0x0800 +#define FLZONE_ABS 0x1000 +#define FLZONE_ATA 0x2000 +#define FLZONE_API 0x4000 +#define FLZONE_FULL 0xffff + +#endif /* FLSYSTYPE_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fltl.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fltl.h new file mode 100755 index 00000000..9e38c292 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/fltl.h @@ -0,0 +1,122 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/fltl.h-arc $ + * + * Rev 1.9 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.8 Sep 11 2006 13:45:24 yaniv.iarovici + * Legal header added + * + * Rev 1.7 Aug 09 2006 16:52:52 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#ifndef FLTL_H +#define FLTL_H + +#include "flbase.h" +#include "flstruct.h" + + +typedef struct tTL TL; + +/*----------------------------------------------------------*/ +/* Format Parameters record passed to the translation layer */ +/*----------------------------------------------------------*/ + +typedef struct { + + /* Global device info */ + + FLByte percentUse; + + FLByte noOfBDTLPartitions; + + FLByte noOfBinaryPartitions; + + BDTLPartitionFormatParams3 FAR2* BDTLPartitionInfo; + + BinaryPartitionFormatParams3 FAR2* binaryPartitionInfo; + + FLDword flags; + + /* First volume info */ + + FLByte protectionKey[8]; + + FLByte protectionType; + + FLByte noOfSpareUnits; + + /* Special features */ + + FLByte cascadedDeviceNo; + + FLByte noOfCascadedDevices; + + FLProgressCallback progressCallback; + + FLDword osakVersion; + + /* None DiskOnChip parameters */ + + FLSDword bootImageLen; + + FLSDword dataPartitionLen; + + FLDword vmAddressingLimit; + + FLWord embeddedCISlength; + + FLByte FAR1 * embeddedCIS; + +} TLFormatParams; + +#include "_fltl.h" + +#endif /* FLTL_H */ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/geometry.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/geometry.c new file mode 100755 index 00000000..b9ab3b3f --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/geometry.c @@ -0,0 +1,132 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Testing/TrueFFS 6.3/Drop 2.5/3/common/geometry.c-arc $ + * + * Rev 1.6 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.5 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.4 Aug 09 2006 16:52:52 Polina.Marimont + * initial for DOC Driver 1.0 + */ + +#include "flbase.h" + +/*----------------------------------------------------------------------*/ +/* f l B u i l d G e o m e t r y */ +/* */ +/* Get C/H/S information of the disk according to number of sectors. */ +/* */ +/* Parameters: */ +/* capacity : Number of Sectors in Volume */ +/* cylinders : Pointer to Number of Cylinders */ +/* heads : Pointer to Number of Heads */ +/* sectors : Pointer to Number of Sectors per Track */ +/* oldFormat : True for one sector per culoster */ +/* wIrHandle : Handle of the disk partition to check */ +/* */ +/*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +#endif /* __cplusplus */ + +TFFS_DLL_API void NAMING_CONVENTION flBuildGeometry(FLDword capacity, FLDword FAR2 *cylinders, + FLDword FAR2 *heads, FLDword FAR2 *sectors, FLBoolean oldFormat, FLWord wIrHandle) +{ + FLDword temp; + FLDword orgCapacity = capacity; + +START_BUILD_GEOMETRY_ROUTINE: + + *cylinders = 1024; /* Set number of cylinders to max value */ + + if (oldFormat == TRUE) + { + *sectors = 62L; /* Max out number of sectors per track */ + temp = (*cylinders) * (*sectors); /* Compute divisor for heads */ + (*heads) = capacity / temp; /* Compute value for number of heads */ + if (capacity % temp) { /* If no remainder, done! */ + (*heads)++; /* Else, increment number of heads */ + temp = (*cylinders) * (*heads); /* Compute divisor for sectors */ + (*sectors) = capacity / temp; /* Compute value for sectors per track */ + if (capacity % temp) { /* If no remainder, done! */ + (*sectors)++; /* Else, increment number of sectors */ + temp = (*heads) * (*sectors); /* Compute divisor for cylinders */ + (*cylinders) = capacity / temp; /* Compute number of cylinders */ + } + } + } + else + { + *heads = 16L; /* Max out number of heads */ + temp = (*cylinders) * (*heads); /* Compute divisor for heads */ + *sectors = capacity / temp; /* Compute value for sectors per track */ + while (*sectors > 0x3f ){ /* While number of sectors too big */ + *heads *= 2; /* use one more head */ + temp = (*cylinders) * (*heads); /* Recompute divisor for heads */ + *sectors = capacity / temp; /* Recompute sectors per track */ + } + if (capacity % temp) { /* If no remainder, done! */ + (*sectors)++; /* Else, increment number of sectors */ + temp = (*cylinders) * (*sectors); /* Compute divisor for heads */ + *heads = capacity / temp; /* Compute value for heads */ + if (capacity % temp) { /* If no remainder, done! */ + (*heads)++; /* Else, increment number of heads */ + temp = (*heads) * (*sectors); /* Compute divisor for cylinders */ + *cylinders = (FLDword)(capacity / temp); /* Compute number of cylinders */ + } + } + } + /* Make sure some free sectors are left between C*H*S and TL sectors */ + if(orgCapacity == (*sectors) * (*heads) * (*cylinders)) + { + capacity--; + goto START_BUILD_GEOMETRY_ROUTINE; + } +} + +/*----------------------------------------------------------------------*/ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hal_nor.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hal_nor.c new file mode 100755 index 00000000..6a05e59f --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hal_nor.c @@ -0,0 +1,464 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/hal_nor.c-arc $ + * + * Rev 1.25 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.24 Mar 11 2007 16:41:20 einat.avidan + * bug fix: working on x86 requires read buffer not to be paged out + * replace the former solution (access to the begining and the end of the buffer under NO_INIT_MMU_PAGES compilation flag) + * with full solution: usage of a buffer that is locked on RAM + * + * Rev 1.23 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.22 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +/* + * includes + */ +#include "flbase.h" +#include "hal_nor.h" +#include "doch_sys.h" +#include "doch_ata.h" + +#ifdef FL_MIGRATION_VERSION +#include "docsys.h" +#endif /*FL_MIGRATION_VERSION*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Externals + */ +extern FLDword gAccessLayerType; + +#ifdef __cplusplus +} +#endif + + +#ifdef DOCH_USE_FUNC + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Externals + */ +extern FLDword gAccessLayerType; + +/* + * global vars + */ + +/****************************************************************************** + * * + * d o c h _ s y s _ i n i t * + * * + * Initialize BSP specific part of DOCH driver. * + * * + * Parameters : * + * socketNo : Socket # (0...DOCH_MAX_SOCKETS-1) * + * * + * Returns : * + * 0 if success, otherwise respective error code. * + * * + ******************************************************************************/ + +DOCH_Error hal_init_nor ( FLSNative socketNo) +{ + DOCH_Socket* pdev; + DOCH_get_socket(pdev, socketNo); + + /*If socket is not registered, return error*/ + if(pdev == NULL) + return DOCH_DiskNotFound; + + /*Register access layer routines*/ + pdev->halRoutines.hal_get_ata_reg = hal_get_ata_reg_nor; + pdev->halRoutines.hal_set_ata_reg = hal_set_ata_reg_nor; + pdev->halRoutines.hal_get_ctrl_reg = hal_get_ctrl_reg_nor; + pdev->halRoutines.hal_set_ctrl_reg = hal_set_ctrl_reg_nor; + pdev->halRoutines.hal_blk_read = hal_blk_read_nor; + pdev->halRoutines.hal_blk_write = hal_blk_write_nor; + pdev->halRoutines.hal_doch_release = doch_sys_release_nor; + + gAccessLayerType = DOCH_AL_NOR; + + return DOCH_OK; +} + +/*********************************************************/ +/* Function name : doch_sys_release_nor*/ +/* Description : */ +/* Return type : */ +/* Argument : int socketNo*/ +/*********************************************************/ +FLSNative doch_sys_release_nor(int socketNo) +{ + return flOK; +} + +/****************************************************************************** + * * + * d o c h_ s y s _ g e t _ r e g X * + * * + * Reads DOCH register. * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * reg : ATA register number * + * * + * Returns : * + * value of specified register * + * * + ******************************************************************************/ +FLByte hal_get_ata_reg_nor(volatile FLByte *base, FLSNative reg) +{ + volatile FLWord* vPtr = (volatile FLWord*)addToFarPointer(base, (reg<<1) + DOCH_CONT_REG_AREA); + FLWord val = DOCHREAD_IO_WORD(vPtr); + +#ifdef DOCH_BIG_ENDIAN + return (FLByte)(val>>8); /*Value is returned in the higher byte*/ +#else /*DOCH_BIG_ENDIAN*/ + return (FLByte)(val); +#endif /*DOCH_BIG_ENDIAN*/ +} + +FLWord hal_get_ctrl_reg_nor ( volatile FLByte * base, + FLSNative reg ) +{ + volatile FLWord* vPtr = (volatile FLWord*)addToFarPointer(base, reg); + FLWord regVal = DOCHREAD_IO_WORD(vPtr); + +#ifdef DOCH_BIG_ENDIAN + return ((regVal<<8) | (regVal>>8)); /*Swap high/low bytes*/ +#else /*DOCH_BIG_ENDIAN*/ + return regVal; +#endif /*DOCH_BIG_ENDIAN*/ +} + +/****************************************************************************** + * * + * d o c h _ s y s _ s e t _ r e g X * + * * + * Writes DOCH register. * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * reg : ATA register number * + * val : value to write to register * + * * + * Returns : * + * value of specified register * + * * + ******************************************************************************/ + +void hal_set_ata_reg_nor( volatile FLByte * base, + FLSNative reg, + FLNative val ) +{ + volatile FLWord* vPtr = (volatile FLWord*)addToFarPointer(base, (reg<<1) + DOCH_CONT_REG_AREA); + +#ifdef DOCH_BIG_ENDIAN + val = ((val>>8) | (val<<8)); +#endif /*DOCH_BIG_ENDIAN*/ + + DOCHWRITE_IO_WORD((FLWord)val, vPtr); +} + +void hal_set_ctrl_reg_nor ( volatile FLByte * base, + FLSNative reg, + FLNative val ) +{ +#ifdef DOCH_BIG_ENDIAN + val = ((val>>8) | (val<<8)); +#endif /*DOCH_BIG_ENDIAN*/ + + DOCHWRITE_IO_WORD((FLWord)val, (base + reg)); +} + +/****************************************************************************** + * * + * b l k _ r e a d_ u s i n g _ d a t a _ r e g * + * * + * Read specified # of bytes through the ATA data register * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * buf : buffer to write from * + * bytes : number of bytes to write * + * * + * Returns : * + * NONE * + * * + ******************************************************************************/ +void blk_read_using_data_reg ( volatile FLByte * base, + FLByte * buf, + FLSNative bytes ) +{ + register FLWord * buf16 ; + register FLSNative max; + + buf16 = (FLWord *) buf; + max = (FLSNative)buf + bytes; + + /* retrieve data */ + for (; (FLSNative)buf16 < max; buf16+=8) + { + buf16[0] = DOCHREAD_IO_WORD(base); + buf16[1] = DOCHREAD_IO_WORD(base); + buf16[2] = DOCHREAD_IO_WORD(base); + buf16[3] = DOCHREAD_IO_WORD(base); + buf16[4] = DOCHREAD_IO_WORD(base); + buf16[5] = DOCHREAD_IO_WORD(base); + buf16[6] = DOCHREAD_IO_WORD(base); + buf16[7] = DOCHREAD_IO_WORD(base); + } +} + +/****************************************************************************** + * * + * h a l _ b l k _ r e a d _ n o r * + * * + * Read 'sectors' sectors from DOCH * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * dest : buffer to read to * + * sectors : number of sectors to read * + * * + * Returns : * + * always zero (success) * + * * + ******************************************************************************/ + +FLSNative hal_blk_read_nor ( volatile FLByte * base, + FLByte * dest, + FLSNative sectors ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)(addToFarPointer(base, DOCH_DATA_PORT_AREA)); + FLSNative count = sectors<>8); + dest[i++] = (FLByte)tmp; +#else + dest[i++] = (FLByte)tmp; + dest[i++] = (FLByte)(tmp>>8); +#endif /* DOCH_BIG_ENDIAN */ + } + } + else + { /* mainstream case */ + /* Some memcpy implementations from none 4 bytes aligned destination + * buffer may use a for loop of single byte calls to the first 2 + * bytes. This implementation may be good for RAM, but will be + * problematic to 16bit DiskOnChip that does not have a BHE signal. + * so if the buffer is not dword aligned we would not perform memcpy */ + + if (((FLDword)dest&0x3)==0) + { + DOCHCPY_FROM_IO_16_BITS( (volatile byte *)swin, dest, count ); + } + else + { /* read in short words */ + for (i = 0, count = count >> 1; i < (int)count; i++) + ((FLWord FAR1 *)dest)[i] = DOCHREAD_IO_WORD(swin); + } + } +#ifndef FL_NO_PF_PROTECTED_READ_MEM + tffscpy(OrigDest,protectedBuffer,count); +#endif /* FL_NO_PF_PROTECTED_READ_MEM */ + + return 0; +} + +/****************************************************************************** + * * + * b l k _ w r i t e _ u s i n g _ d a t a _ r e g * + * * + * Write specified # of bytes through the ATA data register * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * buf : buffer to write from * + * bytes : number of bytes to write * + * * + * Returns : * + * NONE * + * * + ******************************************************************************/ +void blk_write_using_data_reg ( volatile FLByte * base, + FLByte * buf, + FLSNative bytes ) +{ + volatile FLWord * reg16 = (FLWord*)base; + register FLWord * buf16 ; + register FLSNative max; + + buf16 = (FLWord *) buf; + max = (FLSNative)buf + bytes; + + /* write data */ + for (; (FLSNative)buf16 < max; buf16+=8) + { + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[0],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[1],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[2],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[3],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[4],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[5],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[6],reg16); + DOCHWRITE_IO_WORD(((FLWord FAR1 *)buf16)[7],reg16); + } +} + +/****************************************************************************** + * * + * h a l _ b l k _ w r i t e _ n o r * + * * + * write 'sectors' sectors to DOCH * + * * + * Parameters : * + * base : pointer to the base of DOCH register set * + * src : buffer to write from * + * sectors : number of sectors to write * + * * + * Returns : * + * always zero (success) * + * * + ******************************************************************************/ + +FLSNative hal_blk_write_nor ( volatile FLByte * base, + FLByte * src, + FLSNative sectors ) +{ + volatile FLWord FAR0 * swin = (volatile FLWord FAR0 *)addToFarPointer(base, DOCH_DATA_PORT_AREA); + FLSNative count = sectors<> 1; i < (int)count; i++) + /* while incrementing buffer offset */ + /* but do not increament DiskOnChip offset */ + DOCHWRITE_IO_WORD(((FLWord FAR1 *)src)[i],swin); + } + } + return 0; +} + + +#ifdef __cplusplus +} +#endif + +#else /*DOCH_USE_FUNC*/ + +DOCH_Error hal_init_nor_noFunc ( FLSNative socketNo) +{ + gAccessLayerType = DOCH_AL_NOR; + + return DOCH_OK; +} + +#endif /*DOCH_USE_FUNC*/ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hal_nor.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hal_nor.h new file mode 100755 index 00000000..c427a041 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hal_nor.h @@ -0,0 +1,91 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/hal_nor.h-arc $ + * + * Rev 1.17 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.16 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.15 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef DOCH_SYS_NOR_H +#define DOCH_SYS_NOR_H + +#include "flsystyp.h" +#include "doch_api.h" +#include "hib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +DOCH_Error hal_init_nor (FLSNative socketNo); +DOCH_Error hal_init_nor_noFunc (FLSNative socketNo); +FLByte hal_get_ata_reg_nor (volatile FLByte *base, FLSNative reg); +void hal_set_ata_reg_nor (volatile FLByte *base, FLSNative reg, FLNative val); +FLWord hal_get_ctrl_reg_nor (volatile FLByte *base, FLSNative reg); +void hal_set_ctrl_reg_nor (volatile FLByte *base, FLSNative reg, FLNative val); +FLSNative hal_blk_read_nor (volatile FLByte *base, FLByte *buf, FLSNative sectors); +FLSNative hal_blk_write_nor (volatile FLByte *base, FLByte *buf, FLSNative sectors); +FLSNative doch_sys_release_nor (int socketNo); + +/*Default read.write routines, using the ATA data register*/ +void blk_read_using_data_reg ( volatile FLByte * base, + FLByte * buf, + FLSNative bytes ); + +void blk_write_using_data_reg ( volatile FLByte * base, + FLByte * buf, + FLSNative bytes ); + +#ifdef __cplusplus +} +#endif + +#endif /*DOCH_SYS_NOR_H*/ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hib.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hib.h new file mode 100755 index 00000000..cf74bede --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/hib.h @@ -0,0 +1,272 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/general storage/TrueFFS (7.x)/src/H3/Include/hib.h-arc $ + * + * Rev 1.24 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.23 Oct 21 2007 10:46:04 Einat.Avidan + * optimization: save address of each Hib area instead of + * saving offset and core address (spare repetitive add commands) + * + * Rev 1.22 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.21 Aug 09 2006 17:26:56 Polina.Marimont + * initial for DOC Driver 1.0 + * + */ + +#ifndef HIB_H +#define HIB_H + +/* HIB registers */ +/* ============= */ + +extern FLWord gMemWindowType; +extern FLDword gDochMemWinSize; + +extern FLWord gHibContRegAreaAddress; +extern FLWord gHibDataPortAreaAddress; +extern FLWord gHibConfigRegAreaAddress; + +/*Memory window type and size*/ +/*---------------------------*/ +/*Type*/ +#define MEM_WIN_8KB 0 +#define MEM_WIN_128KB 1 + +/*Size*/ +#define DOCH_MEM_WIN_SIZE (gDochMemWinSize) +#ifdef DOCH_32K_SLIDING_WINDOW + #define DOCH_MEM_WIN_SIZE_8KB 0x8000 /*32KB*/ + #define DOCH_MEM_WIN_SIZE_128KB 0x8000 /*32KB*/ +#else /*DOCH_32K_SLIDING_WINDOW*/ + #define DOCH_MEM_WIN_SIZE_8KB 0x2000 /*8KB*/ + #define DOCH_MEM_WIN_SIZE_128KB 0x20000 /*128KB*/ +#endif /*DOCH_32K_SLIDING_WINDOW*/ + +/*Register Areas*/ +/*--------------*/ + + +#define HIB_CORE_ADDRESS_8KB 0x0000 +#ifdef DOCH_32K_SLIDING_WINDOW + #define HIB_CORE_ADDRESS_128KB 0x0000 +#else /*DOCH_32K_SLIDING_WINDOW*/ + #define HIB_CORE_ADDRESS_128KB 0x8000 +#endif /*DOCH_32K_SLIDING_WINDOW*/ + +/*Area Address*/ +#ifndef DOCH_CONT_REG_AREA_ADDRESS + #define DOCH_CONT_REG_AREA_ADDRESS (gHibContRegAreaAddress) +#endif /*DOCH_CONT_REG_AREA_ADDRESS*/ + +#ifndef DOCH_DATA_PORT_AREA_ADDRESS + #define DOCH_DATA_PORT_AREA_ADDRESS (gHibDataPortAreaAddress) +#endif /*DOCH_DATA_PORT_AREA_ADDRESS*/ + +#ifndef DOCH_CONFIG_REG_AREA_ADDRESS + #define DOCH_CONFIG_REG_AREA_ADDRESS (gHibConfigRegAreaAddress) +#endif /*DOCH_CONFIG_REG_AREA_ADDRESS*/ + +/*8KB Offsets*/ +#define DOCH_CONT_REG_AREA_8KB_OFFSET 0x0800 +#define DOCH_DATA_PORT_AREA_8KB_OFFSET 0x1000 +#define DOCH_CONFIG_REG_AREA_8KB_OFFSET 0x1400 + +/*128KB Offsets*/ +#define DOCH_CONT_REG_AREA_128KB_OFFSET 0 +#define DOCH_DATA_PORT_AREA_128KB_OFFSET 0x0800 +#define DOCH_CONFIG_REG_AREA_128KB_OFFSET 0x1400 +#define DOCH_PRIMARY_SECONDARY_AREA_128KB_OFFSET 0x1800 + + +#define DOCH_CONT_REG_AREA DOCH_CONT_REG_AREA_ADDRESS +#define DOCH_DATA_PORT_AREA DOCH_DATA_PORT_AREA_ADDRESS +#define DOCH_CONFIG_REG_AREA DOCH_CONFIG_REG_AREA_ADDRESS + + +/* Control registers - offset is from DOCH_CONT_REG_AREA*/ +/*------------------------------------------------------*/ +#define DOCH_VERSION_REG (DOCH_CONT_REG_AREA + 0xC1A) +#define DOCH_LAST_ACCESS_ADDR_REG (DOCH_CONT_REG_AREA + 0xC1E) +#define DOCH_PAGED_RAM_CMD_REG (0x30) +#define DOCH_PAGED_RAM_SELECT_REG (0x70) +#define DOCH_PAGED_RAM_COTP_STAT_DL_REG (0x78) +#define DOCH_PAGED_RAM_COTP_SELECT_REG (0x7C) +#define DOCH_PAGED_RAM_UNIQUE_ID_DL (0x80) + +/* Host Configuration registers - offset is from DOCH_CONFIG_REG_AREA*/ +/*-------------------------------------------------------------------*/ +#define HIB_CHIPID1_REG (DOCH_CONFIG_REG_AREA) +#define HIB_BURST_WRITE_MODE_CTRL_REG (DOCH_CONFIG_REG_AREA + 0x02) +#define HIB_BURST_WRITE_MODE_EXIT_REG (DOCH_CONFIG_REG_AREA + 0x04) +#define HIB_DOWNLOAD_CONTROL_REG (DOCH_CONFIG_REG_AREA + 0x06) +#define HIB_IPL_CONTROL_REG (DOCH_CONFIG_REG_AREA + 0x08) +#define HIB_WARM_BOOT_REG (DOCH_CONFIG_REG_AREA + 0x0A) +#define HIB_POWER_DOWN_REG (DOCH_CONFIG_REG_AREA + 0x0C) +#define HIB_DMA_CTRL_REG (DOCH_CONFIG_REG_AREA + 0x0E) +#define HIB_SW_LOCK_REG (DOCH_CONFIG_REG_AREA + 0x10) +#define HIB_ENDIAN_CTRL_REG (DOCH_CONFIG_REG_AREA + 0x12) +#define HIB_OPERATION_MODE_REG (DOCH_CONFIG_REG_AREA + 0x14) +#define HIB_POWER_MODE_REG (DOCH_CONFIG_REG_AREA + 0x16) +#define HIB_DMA_NEGATION_REG (DOCH_CONFIG_REG_AREA + 0x18) +#define HIB_CHIPID2_REG (DOCH_CONFIG_REG_AREA + 0x22) +#define HIB_BURST_READ_MODE_CTRL_REG (DOCH_CONFIG_REG_AREA + 0x24) + + + + +/*Specific per-register values*/ +/*============================*/ +/*Burst Read/Write Mode Control Register*/ +#define HIB_BURST_HOLD_1_CLK 0x0000 +#define HIB_BURST_HOLD_2_CLK 0x2000 + +#define HIB_BURST_LEN_4_CYC 0x0000 +#define HIB_BURST_LEN_8_CYC 0x0800 +#define HIB_BURST_LEN_16_CYC 0x1000 +#define HIB_BURST_LEN_32_CYC 0x1800 + +#define HIB_BURST_DISABLE 0x0000 +#define HIB_BURST_ENABLE 0x0001 + +/*Download Control Register*/ +#define HIB_DOWNLOAD_COMPLETED 0x0000 +#define HIB_DOWNLOAD_IN_PROCESS 0x0001 + +/*IPL Control Register*/ +#define HIB_IPL_WRITE_DISABLE 0x0000 +#define HIB_IPL_WRITE_ENABLE 0x0001 + +#define HIB_IPL_NOT_READY_FOR_WRITE 0x0000 +#define HIB_IPL_READY_FOR_WRITE 0x0002 + +/*Warm Boot Register*/ +#define HIB_WARM_RST_POLARITY_LOW 0x0000 +#define HIB_WARM_RST_POLARITY_HIGH 0x0001 + +#define HIB_WARM_RST_BURST_ON 0x0000 +#define HIB_WARM_RST_BURST_NO_CHNG 0x0002 + +/*Power Down Register*/ +#define HIB_DPD_PIN_POLARITY_LOW 0x0000 +#define HIB_DPD_PIN_POLARITY_LOW 0x0000 + +#define HIB_DPD_PIN_DISABLE 0x0000 +#define HIB_DPD_PIN_ENABLE 0x0002 + +/*DMA Control Register*/ +#define HIB_DMA_REQ_DISABLE 0x0000 +#define HIB_DMA_REQ_ENABLE 0x0001 + +#define HIB_DMA_REQ_POL_HIGH 0x0000 +#define HIB_DMA_REQ_POL_LOW 0x0002 + +#define HIB_DMA_REQ_LEVEL 0x0000 +#define HIB_DMA_REQ_EDGE 0x0004 + +/*S/W Lock Register*/ +#define HIB_SW_LOCK_ON 0x0001 + +/*Endian Control Register*/ +#define HIB_END_SWAP_OFF 0x0000 +#define HIB_END_SWAP_ON 0x0101 + +/*Operation Mode Register*/ +#define HIB_NON_PIPE_ACCESS 0x00 +#define HIB_PIPE_ACCESS 0x01 + +#define HIB_NO_ADDR_SHIFT 0x00 +#define HIB_ADDR_SHIFT 0x02 + +/*Power Mode Register*/ +#define HIB_POWER_DOWN 0x0001 + +/*Paged RAM Command Register*/ +#define HIB_PAGED_RAM_ENABLE_SELECT 0x71 + +/*Paged RAM Select Register*/ +#define HIB_PAGED_RAM_SEQ 0x0080 + + +/*Folloing array is used to conserve every write to a configuration register. +The purpose is to enable reseting the device registers in case of power loss*/ +typedef struct { + FLWord wBurstWriteModeCtrl; + FLWord wIPLCtrl; + FLWord wPowerDown; + FLWord wDMACtrl; + FLWord wSWLock; + FLWord wEndianCtrl; + FLWord wEndianNegation; + FLWord wOperationMode; + FLWord wBurstReadModeCtrl; +} DOCH_ConfigRegsValue; + +typedef struct { + FLWord wBurstWriteModeCtrlSet; + FLWord wIPLCtrlSet; + FLWord wPowerDownSet; + FLWord wDMACtrlSet; + FLWord wSWLockSet; + FLWord wEndianCtrlSet; + FLWord wEndianNegationSet; + FLWord wOperationModeSet; + FLWord wBurstReadModeCtrlSet; +} DOCH_ConfigRegsSet; + +/* Changing device memory window size (8/128 KB)*/ +#define DOCH_PAGED_RAM_TIMEOUT 300000L +#define DOCH_READ_PAGED_RAM_DELAY 20 + +typedef enum { + DOCH_MEM_WIN_SIZE_8K = 0, + DOCH_MEM_WIN_SIZE_128K = 1, /*Regular, with no pull-downs on high address bits*/ + DOCH_MEM_WIN_SIZE_128K_SPECIAL = 2 /*Special, with pull-downs on high address bits*/ +} DOCH_MemWinSize; + +#endif /*HIB_H*/ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/ioctl_example/Makefile b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/ioctl_example/Makefile new file mode 100755 index 00000000..62a80263 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/ioctl_example/Makefile @@ -0,0 +1,72 @@ +#=============================================================================== +# +# Makefile for IOCTL demo application for DOC driver. +# +#=============================================================================== +# +# Copyright (C) 2006 msystems Ltd. 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 msystems nor the names of its contributors may be +# used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +#=============================================================================== + + +# +# Specify root directory of Linux kernel's source tree as appropriate +# for your installation. +# +KERNEL_DIR = /opt/ti/omap2420/kernel/269 + +# +# Specify which compiler to use (default is ARM/GCC compiler) +# +CC = arm-unknown-linux-gnu-gcc + +# +# Specify compiler flags in the same fashion as 'make modules' does. +# Flags below are appropriate for XScale compilation. +# +CFLAGS += -I$(KERNEL_DIR)/include +CFLAGS += -I.. +CFLAGS += -Wall +# CFLAGS += -g + +# +# 'make all' rule +# +all : ioctl-example + +# +# make 'ioctl-example' demo application +# +ioctl-example : ioctl-example.c + $(CC) $(CFLAGS) -o $@ $< + +# +# 'make clean' rule +# +clean : + rm -f *.o ioctl-example + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/ioctl_example/ioctl-example.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/ioctl_example/ioctl-example.c new file mode 100755 index 00000000..bc9c4844 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/ioctl_example/ioctl-example.c @@ -0,0 +1,791 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2006, msystems Ltd. 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 msystems nor the names of its contributors may be */ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 +#include +#include +#include +#include +#include +#include +#include "tffsioct.h" + + + + +#define ALLOW_FORMATTING +#undef ALLOW_BDK +#define ALLOW_HW_PROTECTION + + +/* make TrueFFS ahndle out of socket and disk ## */ +#define mk_tffs_handle(socNo,diskNo) (((unsigned short)(socNo) & 0xf) | \ + (((unsigned int)(diskNo) << 4) & 0xf0)) + + +/* + * static routines + */ + +static int fl_ioctl_get_info (int fd); +static int fl_ioctl_defragment (int fd); +static int fl_ioctl_customer_id (int fd); + +#ifdef ALLOW_BDK + static int fl_ioctl_bdk_operation (int fd); +#endif + +static int hdio_getgeo (int fd); + +#ifdef ALLOW_FORMATTING + static int fl_ioctl_erase_bd (int fd); + static int fl_ioctl_flash_format (int fd); + static int fl_ioctl_flash_unformat (int fd); + static int fl_ioctl_mount_volume (int fd); +#endif + +#ifdef ALLOW_HW_PROTECTION + static int fl_ioctl_hw_protection (int fd, int ioctl_opcode); +#endif + + + + +int main ( int argc, char * argv[] ) +{ + int ioctl_opcode; + int flags; + int fd; + int rc = -1; + + /* check if devce name and IOCTL opcode are specified, and get IOCTL opcode */ + if ((argc < 3) || (sscanf(argv[2], "%d", &ioctl_opcode) != 1)) + { + fprintf (stderr, "Usage: ioctl-example \n"); + fprintf (stderr, "Example: ioctl-example /dev/tffsa 14\n"); + fprintf (stderr, "Accepted values for :\n"); + fprintf (stderr, " %d for FL_IOCTL_CUSTOMER_ID\n", FL_IOCTL_CUSTOMER_ID); + fprintf (stderr, " %d for FL_IOCTL_DEFRAGMENT\n", FL_IOCTL_DEFRAGMENT); + fprintf (stderr, " %d for FL_IOCTL_GET_INFO\n", FL_IOCTL_GET_INFO); +#ifdef ALLOW_BDK + fprintf (stderr, " %d for FL_IOCTL_BDK_OPERATION\n", FL_IOCTL_BDK_OPERATION); +#endif +#ifdef ALLOW_FORMATTING + fprintf (stderr, " %d for FL_IOCTL_MOUNT_VOLUME\n", FL_IOCTL_MOUNT_VOLUME); + fprintf (stderr, " %d for FL_IOCTL_ERASE_BD\n", FL_IOCTL_ERASE_BD); + fprintf (stderr, " %d for FL_IOCTL_FLASH_FORMAT\n", FL_IOCTL_FLASH_FORMAT); + fprintf (stderr, " %d for FL_IOCTL_FLASH_UNFORMAT\n", FL_IOCTL_FLASH_UNFORMAT); +#endif +#ifdef ALLOW_HW_PROTECTION + fprintf (stderr, " %d for FL_IOCTL_BDTL_HW_PROTECTION\n", FL_IOCTL_BDTL_HW_PROTECTION); +#endif + fprintf (stderr, " %d for HDIO_GETGEO\n", 0x0301 /* HDIO_GETGEO */); + exit (-1); + } + + /* open device */ + flags = ((ioctl_opcode == FL_IOCTL_GET_INFO) ? O_RDONLY : O_RDWR); + if((fd = open(argv[1], flags)) == -1) + { + perror ("Can't open device"); + exit (-1); + } + + /* issue IOCTL to device */ + switch (ioctl_opcode) + { + case FL_IOCTL_CUSTOMER_ID: + rc = fl_ioctl_customer_id (fd); + break; + + case FL_IOCTL_DEFRAGMENT: + rc = fl_ioctl_defragment (fd); + break; + + case FL_IOCTL_MOUNT_VOLUME: + rc = fl_ioctl_mount_volume (fd); + break; + + case FL_IOCTL_GET_INFO: + rc = fl_ioctl_get_info (fd); + break; + +#ifdef ALLOW_BDK + case FL_IOCTL_BDK_OPERATION: + rc = fl_ioctl_bdk_operation (fd); + break; +#endif + +#ifdef ALLOW_FORMATTING + case FL_IOCTL_ERASE_BD: + rc = fl_ioctl_erase_bd (fd); + break; + + case FL_IOCTL_FLASH_FORMAT: + rc = fl_ioctl_flash_format (fd); + break; + + case FL_IOCTL_FLASH_UNFORMAT: + rc = fl_ioctl_flash_unformat (fd); + break; +#endif + +#ifdef ALLOW_HW_PROTECTION + case FL_IOCTL_BDTL_HW_PROTECTION: + rc = fl_ioctl_hw_protection (fd, ioctl_opcode); + break; +#endif + + case 0x0301: /* HDIO_GETGEO */ + rc = hdio_getgeo (fd); + break; + + } + + close (fd); + + exit (rc); +} + + + + +static +int fl_ioctl_customer_id (int fd) +{ + flIOctlRecord ioctl_data; + flCustomerIdOutput out; + int rc; + + ioctl_data.inputRecord = NULL; /* no input record for this IOCTL */ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_CUSTOMER_ID, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_CUSTOMER_ID IOCTL failed, error %d\n", out.status); + else + fprintf (stdout, "SUCCESS getting customer ID: 0x%x 0x%x 0x%x 0x%x\n", + out.id[0], out.id[1], out.id[2], out.id[3]); + return rc; +} + + + + +static +int fl_ioctl_defragment (int fd) +{ + flIOctlRecord ioctl_data; + flDefragInput in; + flDefragOutput out; + int rc; + + in.requiredNoOfSectors = -1; + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_DEFRAGMENT, &ioctl_data); + if ((rc == 0) && (out.status == flOK)) + fprintf (stdout, "free sectors after defragmentation: %ld\n", out.actualNoOfSectors); + + return rc; +} + + + + +static +int fl_ioctl_get_info (int fd) +{ + flIOctlRecord ioctl_data; + flDiskInfoOutput out; + int rc; + + ioctl_data.inputRecord = NULL; /* no input record for this IOCTL */ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_GET_INFO, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_GET_INFO failed %d\n", out.status); + else + fprintf (stdout, "FL_IOCTL_GET_INFO reports %ld sectors\n", out.info.logicalSectors); + + return rc; +} + + + + +#ifdef ALLOW_FORMATTING + +static +int fl_ioctl_mount_volume (int fd) +{ + flIOctlRecord ioctl_data; + flMountInput in; + flOutputStatusRecord out; + int rc; + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + +#if 1 + in.type = FL_DISMOUNT; /* unmount disk */ +#else + in.type = FL_MOUNT; /* re-mount disk */ +#endif + + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME failed %d\n", out.status); + + return rc; +} + +#endif /* ALLOW_FORMATTING */ + + + + +#ifdef ALLOW_FORMATTING + +static +int fl_ioctl_erase_bd (int fd) +{ + flIOctlRecord ioctl_data; + int rc; + + /* unmount disk before formatting */ + { flMountInput in; + flOutputStatusRecord out; + + in.type = FL_DISMOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT failed %d\n", out.status); + } + + /* re-format disk */ + { flEraseBDInput in; + flOutputStatusRecord out; + + in.dwFlags = 0; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_ERASE_BD, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_ERASE_BD failed %d\n", out.status); + } + + /* re-mount disk */ + { flMountInput in; + flOutputStatusRecord out; + + in.type = FL_MOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_MOUNT failed %d\n", out.status); + } + + return rc; +} + +#endif /* ALLOW_FORMATTING */ + + + + +#ifdef ALLOW_FORMATTING + +static +int fl_ioctl_flash_format (int fd) +{ + flIOctlRecord ioctl_data; + flOutputStatusRecord out; + int rc; + + /* WARNING: You must send FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT call + * to all DiskOnChip disks (except for '/dev/tffsa') prior + * to calling this routine. You should not do that for + * /dev/tffsa - this routine must do it by itself. + */ + + /* send FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT call to '/dev/tffsa' */ + { flMountInput in; + + in.type = FL_DISMOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT failed %d\n", out.status); + } + + /* format DiskOnChip */ + { flFlashFormatInput in; + FormatParams3 fp3; + BDTLPartitionFormatParams3 disks[16]; /* WARNING: Large data structure 1 */ + BinaryPartitionFormatParams3 bins[4]; + + memset (&in, 0, sizeof(in)); + memset (&fp3, 0, sizeof(FormatParams3)); + memset (disks, 0, sizeof(disks)); + memset (bins, 0, sizeof(bins)); + + in.fpPtr = &fp3; +#if 1 + in.dwFormatFlags = TL_NORMAL_FORMAT; +#else + /* If you intent on keeping some of BDTL partitions, uncomment + * this section, and specify how many partitions you want to keep. + */ + in.dwFormatFlags = TL_LEAVE_SOME_PARTITIONS; + in.sdwNoOfKeeps = 5; /* keep this many partitions */ +#endif + + fp3.progressCallback = NULL; + fp3.percentUse = 95; + fp3.BDTLPartitionInfo = &disks[0]; + fp3.binaryPartitionInfo = &bins[0]; + fp3.noOfBinaryPartitions = 0; + fp3.noOfBDTLPartitions = 0; + + /* specify size of 1-st DiskOnChip disk */ + disks[ fp3.noOfBDTLPartitions ].length = (40 * 0x100000); /* disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; +#if 0 + /* specify sizes of 2-nd .. 13-th DiskOnChip disk (if you need them) */ + disks[ fp3.noOfBDTLPartitions ].length = (20 * 0x100000); /* 2-nd disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (30 * 0x100000); /* 3-rd disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (40 * 0x100000); /* 4-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 5-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (60 * 0x100000); /* 6-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (70 * 0x100000); /* 7-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (80 * 0x100000); /* 8-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (90 * 0x100000); /* 9-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 10-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 11-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 12-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; + + disks[ fp3.noOfBDTLPartitions ].length = (50 * 0x100000); /* 13-th disk size in bytes */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; +#endif + +#if 1 /* specify size of last DiskOnChip disk (if you need it) */ + disks[ fp3.noOfBDTLPartitions ].length = 0; /* take all remaing space on DiskOnChip */ + disks[ fp3.noOfBDTLPartitions++ ].noOfSpareUnits = 3; +#endif + +#if 0 + /* specify size of the first binary partition */ + bins[fp3.noOfBinaryPartitions].length = (1 * 0x100000); /* size in bytes */ + memcpy (bins[fp3.noOfBinaryPartitions].sign, "BIPO", 4); + fp3.noOfBinaryPartitions++; + + /* specify size of the second binary partition */ + bins[fp3.noOfBinaryPartitions].length = (2 * 0x100000); /* size in bytes */ + memcpy (bins[fp3.noOfBinaryPartitions].sign, "BIPO", 4); + fp3.noOfBinaryPartitions++; +#endif + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + + rc = ioctl (fd, FL_IOCTL_FLASH_FORMAT, &ioctl_data); + + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_FLASH_FORMAT failed %d\n", out.status); + } + + /* re-mount disk */ + { flMountInput in; + + in.type = FL_MOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_MOUNT failed %d\n", out.status); + } + + /* WARNING: You must kill DiskOnChip driver and reboot your system now ! */ + return rc; +} + +#endif /* ALLOW_FORMATTING */ + + + + +#ifdef ALLOW_FORMATTING + +static +int fl_ioctl_flash_unformat (int fd) +{ + flIOctlRecord ioctl_data; + flOutputStatusRecord out; + int rc; + + /* unmount disk before formatting */ + { flMountInput in; + + in.type = FL_DISMOUNT; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_MOUNT_VOLUME, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_MOUNT_VOLUME/FL_DISMOUNT failed %d\n", out.status); + } + + { flFlashUnformatInput in; + + in.dwFlags = 0; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_FLASH_UNFORMAT, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "FL_IOCTL_FLASH_UNFORMAT failed %d\n", out.status); + } + + /* WARNING: You must kill DiskOnChip driver and reboot your system now ! */ + return rc; +} + +#endif /* ALLOW_FORMATTING */ + + + + +static +int hdio_getgeo (int fd) +{ + struct hd_geometry + { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + unsigned long start; + }; + + struct hd_geometry geo; + int rc; + + if ((rc = ioctl(fd, 0x0301 /* HDIO_GETGEO */, &geo)) != 0) + perror ("Error in HDIO_GETGEO"); + else + printf ("Disk geometry: %d heads, %d cylinders, %d sectors, start sector %ld\n", + (int)geo.heads, (int)geo.cylinders, (int)geo.sectors, geo.start); + return rc; +} + + + +#ifdef ALLOW_BDK + +static +int fl_ioctl_bdk_operation (int fd) +{ + flIOctlRecord ioctl_data; + int buf_size = (4 * 1024); + char * buf; + char * buf2; + int rc; + register int iBin = 0; + + /* allocate buffers */ + if ((buf = malloc(buf_size)) == NULL) + { + fprintf (stderr, "Can't alloc buffer"); + return -1; + } + if ((buf2 = malloc(buf_size)) == NULL) + { + fprintf (stderr, "Can't alloc buffer"); + free (buf); + return -1; + } + +#if 0 + for (; iBin <= 1; iBin++) +#endif + { + /* set this binary partition as the target of subsequent IOCTLs */ + + { flInputLnxRecord in; + flOutputLnxRecord out; + + in.command = 0; + in.data = mk_tffs_handle (0, 0); + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + + rc = ioctl (fd, FL_IOCTL_LNX, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_LNX failed %d\n", (int)out.status); + rc = -1; + goto quit; + } + } + + /* write, the read back and verify 'buf_size' bytes to this binary partition */ + + { flBDKOperationInput in; + flOutputStatusRecord out; + + fprintf (stdout, "Writing %d bytes to binary partition %d\n", buf_size, iBin); + + in.type = BDK_GET_INFO; + in.bdkStruct.flags = 0; + in.bdkStruct.length = 0; + in.bdkStruct.startingBlock = 0; + in.bdkStruct.bdkBuffer = NULL; + in.bdkStruct.signOffset = 8; + if (iBin == 0) + memcpy (in.bdkStruct.oldSign, "BIPO", 4); + else + memcpy (in.bdkStruct.oldSign, "BIPO", 4); + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_GET_INFO failed %d\n", out.status); + rc = -1; + goto quit; + } + + in.type = BDK_INIT_WRITE; + in.bdkStruct.flags = 0; + in.bdkStruct.length = buf_size; + in.bdkStruct.bdkBuffer = NULL; + in.bdkStruct.signOffset = 8; + if (iBin == 0) + { + in.bdkStruct.startingBlock = 0; + memcpy (in.bdkStruct.oldSign, "BIPO", 4); + } + else + { + in.bdkStruct.startingBlock = 15; + memcpy (in.bdkStruct.oldSign, "BIPO", 4); + } + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_INIT_WRITE failed %d\n", out.status); + rc = -1; + goto quit; + } + + in.type = BDK_WRITE; + in.bdkStruct.flags = ERASE_BEFORE_WRITE; + in.bdkStruct.length = buf_size; + in.bdkStruct.bdkBuffer = buf; + memset (buf, '$', buf_size); + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_WRITE failed %d\n", out.status); + rc = -1; + goto quit; + } + + fprintf (stdout, "SUCCESS writing %d bytes to binary partition %d\n", buf_size, iBin); + + fprintf (stdout, "Reading back and verifying %d bytes from binary partition %d\n", buf_size, iBin); + + in.type = BDK_INIT_READ; + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_INIT_READ failed %d\n", out.status); + rc = -1; + goto quit; + } + + in.type = BDK_READ; + in.bdkStruct.bdkBuffer = buf2; + memset (buf2, 0, buf_size); + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + rc = ioctl (fd, FL_IOCTL_BDK_OPERATION, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_BDK_OPERATION/BDK_READ failed %d\n", out.status); + rc = -1; + goto quit; + } + + if( memcmp(buf, buf2, buf_size) != 0) + { + fprintf (stderr, "Error: mismatching data\n"); + rc = -1; + goto quit; + } + fprintf (stdout, "SUCCESS reading back and verifying data\n"); + } + } /* for(iBin) */ + +quit: + + free (buf); + free (buf2); + + return rc; +} + +#endif /* ALLOW_BDK */ + + + +#ifdef ALLOW_HW_PROTECTION + +/* + * This routine sets TrueFFS handle for subsequent IOCTLs + */ +static +int set_ioctl_handle (int fd, int tffs_handle) +{ + flIOctlRecord ioctl_data; + flInputLnxRecord in; + flOutputLnxRecord out; + int rc; + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + + in.command = 0; + in.data = tffs_handle; + + rc = ioctl (fd, FL_IOCTL_LNX, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + { + fprintf (stderr, "FL_IOCTL_LNX failed %d\n", (int)out.status); + rc = -1; + } + else + fprintf (stdout, "SUCCESS setting handle 0x%x for future IOCTLs\n", tffs_handle); + + return rc; +} + + + +/* + * This routine provides example of using FL_IOCTL_..._HW_PROTECTION + * IOCTLs to insert key into protected partition. + */ +static +int fl_ioctl_hw_protection (int fd, int ioctl_opcode) +{ + flIOctlRecord ioctl_data; + int socket_no = 0; + int partition_no; + int rc; + + partition_no = /* specify your own partition here */ 0; + + /* set TrueFFS handle for subsequent IOCTL */ + + rc = set_ioctl_handle (fd, mk_tffs_handle(socket_no, partition_no)); + if (rc != 0) + return rc; + + /* insert key into partition */ + + { flProtectionInput in; + flProtectionOutput out; + + ioctl_data.inputRecord = ∈ + ioctl_data.outputRecord = &out; + + in.type = PROTECTION_INSERT_KEY; + + /* this is my usual key; replace it with your own */ + + in.key[0] = 'p'; + in.key[1] = 'i'; + in.key[2] = 's'; + in.key[3] = 's'; + in.key[4] = 'w'; + in.key[5] = 'o'; + in.key[6] = 'r'; + in.key[7] = 'd'; + + in.protectionType = 0; /* not actually used by PROTECTION_INSERT_KEY */ + + rc = ioctl (fd, ioctl_opcode, &ioctl_data); + if ((rc != 0) || (out.status != flOK)) + fprintf (stderr, "%d IOCTL failed %d\n", ioctl_opcode, out.status); + else + fprintf (stdout, "SUCCESS inserting protection key\n"); + } + + /* for security, set TrueFFS handle to impossible value (0xffff) */ + + set_ioctl_handle (fd, 0xffff); + + return rc; +} + +#endif /* ALLOW_HW_PROTECTION */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/part_inf.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/part_inf.h new file mode 100755 index 00000000..c817533c --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/part_inf.h @@ -0,0 +1,227 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ + +/***********************************************************************************/ +/* */ +/* This file contains various structure and defines concerning Partition info and */ +/* access */ +/* */ +/***********************************************************************************/ + +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/part_inf.h-arc $ + * + * Rev 1.20 Oct 22 2007 11:34:54 einat.avidan + * update copyrights header + * + * Rev 1.19 Feb 28 2007 09:53:48 einat.avidan + * No change + * + * Rev 1.18.1.0 Nov 30 2006 10:24:10 Yaniv.Iarovici + * Added 'DOCH_SecureDeleteDev1' to SDK Device Attributes. + * + * Rev 1.18 Sep 11 2006 13:45:26 yaniv.iarovici + * Legal header added + * + * Rev 1.17 Aug 09 2006 17:26:58 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.16.1.0 Aug 08 2006 15:55:32 Polina.Marimont + * DOC Driver 1.0 initial + * + * Rev 1.16 May 28 2006 13:02:34 polina.marimont + * 1. IDENTIFY DEVICE interface update + * 2. floors fix for format, where partition ended at the end of floor 0 + * + * Rev 1.15 May 18 2006 14:41:24 polina.marimont + * v1.40Fin1, PVCS log inside + */ + +#ifndef _PARTITION_INFO_H +#define _PARTITION_INFO_H + +#include "doch_api.h" + +/* Extended device info structure*/ +typedef struct { + FLWord wFlashType; + FLWord wPhysicalPageSize; /*In Sectors*/ + FLWord wNumOfPhysicalPagesInPhysicalErasableBlockSize; + FLWord wNumOfErasableBlocksPerPhysicalChip; + FLWord wPhysicalChipBusWidth; /*8/16*/ + FLWord wNumOfChipsOnDataBus; /*1..2*/ + FLWord wFlashChipNumOfPlanes; /*1..4*/ + FLWord wFlashChipNumOfBanks; /*Independently accessible parts of flash array*/ + FLWord wLogicalPageSize; /*In Sectors*/ + FLWord wNumOfLogicalPagesInLogicalErasableBlockSize; + FLWord wTotalNumOfLogicalErasableUnits; + FLWord wMapinfoUnitsUsed; + FLWord wLUNCurrentlyUsed; + FLWord wFreeUnitsOnMedia; + FLByte bReserved1[0x1E4]; +} DOCH_ExtendedDeviceInfo; + +/*Partition user attributes +512Byte overall (1 sector) +First DOCH_PART_INFO_SDK_RESERVED_BYTES bytes are reserved for SDK*/ +#define DOCH_PART_INFO_SDK_RESERVED_BYTES 0x40 +typedef struct { + FLByte bReserved1[DOCH_PART_INFO_SDK_RESERVED_BYTES]; /*For SDK use*/ + FLByte bReserved2[DOCH_SECTOR_SIZE - DOCH_PART_INFO_SDK_RESERVED_BYTES]; /*For application use*/ +} DOCH_PartitionUserAttr; + +/*Device user attributes +512Byte overall (1 sector) +First DOCH_DEVICE_INFO_SDK_RESERVED_BYTES bytes are reserved for SDK*/ +#define DOCH_DEVICE_INFO_SDK_RESERVED_BYTES 0x40 + +typedef struct { + FLByte bLastDev0PartSpanned; + FLByte numOfSpannedPartitionOnDev0; + FLByte secondFloorActive; /*At least 1 user partition resides on Dev1*/ + FLByte bLastPartitionOnDev0; /*Number of last partition that resides on Dev0*/ + FLDword dwSpanSector; /*Which sector in the spanned partition is the last that resides on dev0*/ + FLDword dwSpanSizeOnDev0; /*How many sectors on Dev0*/ + FLByte spare[4]; +} DOCH_PartitionSpanData; + +typedef struct { + FLDword dwSecureDeleteStartSector; + FLDword dwSecureDeleteNumOfSectors; + FLByte bOperationRequired; + FLByte bPart; + FLByte spare[2]; +} DOCH_SecureDeleteDev1; + +typedef struct { + DOCH_PartitionSpanData sSpanInfo; + DOCH_SecureDeleteDev1 sSecureDeleteDev1; + FLByte spare[0x24]; /*Rest of 0x40 bytes that are reserved for SDK use*/ +} DOCH_SDKDeviceAttr; + +typedef struct { + DOCH_SDKDeviceAttr sdkAttributes; + FLByte bReserved2[DOCH_SECTOR_SIZE - DOCH_DEVICE_INFO_SDK_RESERVED_BYTES]; /*For application use*/ +} DOCH_DeviceUserAttr; + + +/******************************************************************************/ +/* + * Configuration Partition structure, sub-structures and ENUMS + */ +/******************************************************************************/ + +/*Configuration Partition Layout*/ + +/*Sector #0*/ +typedef struct { + FLWord wVersion; + FLWord wCompatabilityVersion; + FLDword dwCommandFlagsOrStatuses; + FLDword dwDiskAttributes1; + FLDword dwGateKeeperAttr; /*FLDword dwDiskAttributes2;*/ + FLByte bReserved2[0x10]; + FLByte bUniqueID[0x10]; + FLByte bReserved3[0x10]; + FLByte bSerialNumber[0x14]; + FLByte bModelNumber[0x28]; + FLByte breserved4[2]; + FLWord wDefaultPartitionNumber; + FLDword dwUnformattedCapacity; /*In Sectors*/ + FLDword dwConfigurationPartitionExistsSign; + FLDword dwETFFSVER; + FLDword dwConfigPartitionSize; /*In Bytes*/ + FLByte bProgrammerName[0x10]; + FLByte bProgrammerVersion[0x8]; + FLByte bReserved6[0x58]; + FLByte bGateKeeperKey[0x80]; + FLByte bGateKeeperKeyReservedLargerKey[0x80]; +} DOCH_ConfigPartitionSector0; + +/*Sector #1*/ +typedef enum { + DOCH_MP_AUTH_TYPE_NONE = 0, /*No master password*/ + DOCH_MP_AUTH_TYPE_PWD = 1, /*Password protection (Null terminated)*/ + DOCH_MP_AUTH_TYPE_RSA = 2 /*RSA Protection (All 128Bytes are significant*/ +} DOCH_MasterPwdAuthType; + +typedef enum { + DOCH_MAO_MASTER_PWD_AUTH_TYPE = 0 +} DOCH_MasterAttributes_Offset; + +typedef enum { + DOCH_MAB_MASTER_PWD_AUTH_TYPE = 0x0000003F +} DOCH_MasterAttributes_Bits; + +typedef struct { + FLByte bReserved1[0xC]; + FLDword masterAttributes; + FLByte bReserved2[0xF0]; + FLByte bMasterPasskey[0x80]; + FLByte bReservedLargeMasterPasskey[0x80]; +} DOCH_ConfigPartitionSector1; + +/*Sector #2*/ +typedef struct { + FLByte bDochPublicKey[0x80]; + FLByte bReserved1[0x80]; + FLByte bDochPrivateKey[0x80]; + FLByte bReserved2[0x80]; +} DOCH_ConfigPartitionSector2; + +/*Sector #3*/ +/*Identical to DOCH_DriveParameters structure (ATA IDENTIFY_DEVICE structure)*/ + +/*Sectors #4..#14 are reserved*/ + +/*Sector #15 - OTP sector for tester*/ +typedef struct { + FLByte bUniqueID[0x10]; + FLByte bReserved1[0x10]; + FLByte bSerialNumber[0x14]; + FLByte bModelNumber[0x28]; + FLByte bReserved2[0x1A4]; +} DOCH_ConfigPartitionSector15; + + +#endif /*_PARTITION_INFO_H*/ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs-pm26.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs-pm26.c new file mode 100755 index 00000000..1e3e8908 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs-pm26.c @@ -0,0 +1,184 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + + +#include "tffsdrv.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(CONFIG_PM) + +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + + /****************************************************************************** + * * + * Generic power management implementation for Linux kernels 2.6.15 and up. * + * * + ******************************************************************************/ + + static int suspend_driver (struct platform_device * dev, pm_message_t state) + { + tffs_suspend(); + return 0; + } + + static int resume_driver (struct platform_device * dev) + { + tffs_resume (); + return 0; + } + + static struct platform_driver pm_driver = + { + .suspend = suspend_driver, + .resume = resume_driver, + .driver = + { + .name = TFFS_DEVICE_NAME, + }, + }; + + int tffs_pm_init (void) + { + int rc; + + if( (rc = platform_driver_register(&pm_driver)) != 0) + PrintkError ("platform_driver_register() failed, PM disabled"); + return rc; + } + + int tffs_pm_exit (void) + { + platform_driver_unregister (&pm_driver); + return 0; + } + +# else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) */ + + /****************************************************************************** + * * + * Generic power management implementation for Linux kernels 2.6.0 .. 2.6.14 * + * * + ******************************************************************************/ + +# if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11)) + static int suspend_driver (struct device * dev, pm_message_t state, u32 level) +# else + static int suspend_driver (struct device * dev, u32 state, u32 level) +# endif + { + switch (level) + { + case SUSPEND_POWER_DOWN: + tffs_suspend (); + break; + + case SUSPEND_DISABLE: + case SUSPEND_SAVE_STATE: + default: + break; + } + return 0; + } + + static int resume_driver (struct device * dev, u32 level) + { + switch (level) + { + case RESUME_POWER_ON: + tffs_resume (); + break; + + case RESUME_RESTORE_STATE: + case RESUME_ENABLE: + default: + break; + } + return 0; + } + + static + void pm_release_device (struct device * pdev) + { } + + static struct platform_device pm_device = { + .name = TFFS_DEVICE_NAME, + .id = 0, + .dev.release = pm_release_device, + }; + + static struct device_driver pm_driver = { + .name = TFFS_DEVICE_NAME, + .bus = &platform_bus_type, + .suspend = suspend_driver, + .resume = resume_driver, + }; + + int tffs_pm_init (void) + { + /* register device with Linux Device Manager */ + if( platform_device_register(&pm_device) != 0 ) + { + PrintkError ("can't register device %s with LDM", pm_device.name); + return -ENODEV; + } + + /* register driver with Linux Device Manager */ + if( driver_register(&pm_driver) != 0 ) + { + PrintkError ("can't register driver %s with LDM", pm_driver.name); + + /* unregister device from Linux Device Manager */ + platform_device_unregister (&pm_device); + + return -ENODEV; + } + + return 0; /* success */ + } + + int tffs_pm_exit (void) + { + /* unregister driver from Linux Device Manager */ + driver_unregister (&pm_driver); + + /* unregister device from Linux Device Manager */ + platform_device_unregister (&pm_device); + + return 0; + } + +# endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) */ +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(CONFIG_PM) */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs2lnx.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs2lnx.c new file mode 100755 index 00000000..71adf896 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs2lnx.c @@ -0,0 +1,1756 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + +#include "tffsdrv.h" +#include "tffs2lnx.h" +#include "_tffsioct.h" + +#include "fatfilt.h" +#include "flioctl.h" +#include "blockdev.h" +#include "doch_api.h" +#include "doch_ata.h" +#include "defs.h" + + +#define USE_FAT_FILTER /* allow runtime enabling/disabling of FAT filter */ +#define USE_EXT_FILTER /* allow runtime enabling/disabling of EXT filter */ + +#include "extfiltr.h" + + +/* + * global vars + */ + +TffsInfo tffsInfo; + + + +/* + * static routines + */ + +static int /* __init */ init_socket (SocketInfo *pSocket); +static int /* __init */ init_disk (DeviceInfo *pDisk, SocketInfo *pSocket); +static int release_socket (SocketInfo *pSoc); +static int release_disk (DeviceInfo *pDevice); +static void set_disk_geometry (DeviceInfo *pDevice); +static FLStatus socket_std_format (SocketInfo *psoc); +static FLStatus socket_unformat (SocketInfo *psoc); +static FLStatus print_firmware_string (void); +static int ata_passthrough (DeviceInfo *pdev, flIOctlRecord *ioctl_rec_ptr, + flInputLnxRecord *lnx_inrec_ptr); + +#if defined(DOCH_USE_BURST_MODE_READ) || defined(DOCH_USE_BURST_MODE_WRITE) + +/* Command line parameter "tffs_burst_enabled=1" enables synchronous + * burst in DiskOnChip. In this case user might also want to specify + * other burst-releated command-line parameters: + * + * "tffs_burst_length=" + * "tffs_burst_latency=" + * "tffs_burst_hold=" + * "tffs_burst_ws=" + */ + int tffs_burst_enabled = FALSE; + module_param(tffs_burst_enabled, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_enabled, "enable (1) or disable (0) synchronous burst."); + + int tffs_burst_length = 5; + module_param(tffs_burst_length, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_length, "burst length (2..5)."); + + int tffs_burst_latency = 0; + module_param(tffs_burst_latency, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_latency, "burst latency (0..7)."); + + int tffs_burst_hold = 0; + module_param(tffs_burst_hold, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_hold, "burst hold (0 or 1)."); + + int tffs_burst_ws = 0; + module_param(tffs_burst_ws, int, S_IRUGO); + MODULE_PARM_DESC(tffs_burst_ws, "burst wait states (0..3)."); + +#endif /* DOCH_USE_BURST_MODE_READ || DOCH_USE_BURST_MODE_WRITE */ + +/* Command line parameter "tffs_hardsect=", when specified as non-zero, + * forces DiskOnChip driver to use this hardsector size rather then obtain it + * from the DiskOnChip. The must be either zero (default - obtain + * hardsector from DiskOnChip), or power of 2 in the range [512..4096]. + */ +static int tffs_hardsect = 0; /* zero - obtain hardsector from DiskOnChip */ +module_param(tffs_hardsect, int, S_IRUGO); +MODULE_PARM_DESC(tffs_hardsect, "Size (in bytes) of hardware sector for all devices."); + +/* Command line parameter "tffs_unformat=" allows user to return + * DiskOnChip to it's original factory state. + * For example: + * + * insmod tffs.o tffs_unformat=0 + * + * will unformat DiskOnchip socket #0. + */ +static int tffs_unformat = 0xff; /* 0xff: don't unformat anything */ +module_param(tffs_unformat, int, S_IRUGO); +MODULE_PARM_DESC(tffs_unformat, "Unformat DiskOnChip socket."); + +/* Command line parameter "tffs_format=" allows user to perform + * low-level formatting of specified DiskOnChip socket when driver starts up. + * For example: + * + * insmod tffs.o tffs_format=0 + * + * will re-format DiskOnchip socket #0. + */ +static int tffs_format = 0xff; /* 0xff: don't format anything */ +module_param(tffs_format, int, S_IRUGO); +MODULE_PARM_DESC(tffs_format, "Format DiskOnChip socket."); + +/* Command line parameter "tffs_pio=", when specified as non-zero, + * forces DiskOnChip driver to use multi-sector polled I/O transfers with + * DiskOnChip H3 devices. The must be in range [0..256]; it specifies + * maximum number of sectors that can be written to or read from DiskOnChip + * H3 device in a single transfer. Default value is zero (use single-sector + * polled I/O mode). + */ +static unsigned int tffs_pio = 0; /* zero for single-sector polled I/O */ +module_param(tffs_pio, int, S_IRUGO); +MODULE_PARM_DESC(tffs_pio, "Multi-sector polled I/O mode."); + +#if defined(USE_FAT_FILTER) || defined(USE_EXT_FILTER) + /* Command line parameter "tffs_fs_filter=" allows user to enable/disable + * various file system filters at runtime. Allowed values for are zero + * (default - don't use filters), '1' (use EXT filter), and '2' (use FAT filter). + */ + static int tffs_fs_filter = 0; /* zero - don't use file system filters */ + module_param(tffs_fs_filter, int, S_IRUGO); + MODULE_PARM_DESC(tffs_fs_filter, "Enable FAT (tffs_fs_filter=1) or EXT (tffs_fs_filter=2) file system filters."); +#endif + + + + + + +unsigned char TffsIsWriteProtected (DeviceInfo *pDevice) +{ +#ifdef HW_PROTECTION + IOreq ioreq; + FLStatus stat; + + ioreq.irHandle = pDevice->bHandle; + + if ((stat = flIdentifyProtection(&ioreq)) == flOK) + { + if ((ioreq.irFlags & WRITE_PROTECTED) && !(ioreq.irFlags & KEY_INSERTED)) + return 1; + } + else + { + if ((stat != flFeatureNotSupported) && (stat != flNotProtected)) + { PrintkDebug ("flIdentifyProtection() error %d", stat); } + } +#endif /* HW_PROTECTION */ + + return 0; +} + + + + +/******************************************************************************* + * * + * T f f s I n i t * + * * + * Initialize TrueFFS, and find all disks on all DiskOnChip sockets. * + * * + * Parameters: none * + * * + * Returns: total number of disks found on all DiskOnChip sockets (zero if * + * none found), or -1 if error occurred. * + * * + *******************************************************************************/ + +int /* __init */ TffsInit (void) +{ + register int iSoc; + FLStatus stat; + +#if (ATA_MAX_NUM_OF_DEVICES != 1) + PrintkInfo ("configured for cascaded mDOC devices"); +#endif + + tffsInfo.wDevices = 0; + + memset (tffsInfo.ppDevices, 0, sizeof(tffsInfo.ppDevices)); + + /* initialize TrueFFS, and find all DiskOnChip sockets */ + if ((stat = flInit()) != flOK) + { + PrintkDebug ("flInit() error %d", stat); + return -1; + } + + /* if in verbose mode, print out DiskOnChip firmware info */ + if (fl_debug > FL_DEBUG_DEF) + print_firmware_string (); + + /* find all disks on all DiskOnChip sockets */ + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + init_socket (&tffsInfo.sockets[iSoc]); + + /* return total number of disks on all DiskOnChip sockets */ + return tffsInfo.wDevices; +} + + + + +/******************************************************************************* + * * + * T f f s C l e a n u p * + * * + * Uninitialize TrueFFS, and shut it down. * + * * + * Parameters: none * + * * + * Returns: always zero (success). * + * * + *******************************************************************************/ + +int TffsCleanup (void) +{ + register int iSoc; + + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + release_socket (&tffsInfo.sockets[iSoc]); + + memset (tffsInfo.ppDevices, 0, sizeof(tffsInfo.ppDevices)); + + tffsInfo.wDevices = 0; + +#ifdef FL_EXIT + flExit(); +#endif + + return 0; +} + + + + +static +int /* __init */ init_socket (SocketInfo *pSoc) +{ + IOreq ioreq; + FLStatus stat; + register int iDev; + SocketInfo*pS; + +#ifdef TFFS_USE_RAM + pSoc->fFound=1; +#endif + + /* if socket wasn't found, abort */ + if (pSoc->fFound == 0) + { pSoc->bHandle = 0xff; return 0; } + + for(pS=tffsInfo.sockets;pS!=pSoc;pS++) + { + if(pSoc->bHandle==pS->bHandle) + pSoc->bHandle++; + } + + PrintkInfo("Socket %u in addr 0x%lx",pSoc->bHandle,pSoc->dwPhysAddr); + + /* if requested, unformat socket */ + if (pSoc->bHandle == tffs_unformat) + { + PrintkInfo("unformat socket %d", tffs_unformat); + if( (stat = socket_unformat(pSoc)) != flOK ) + { + PrintkError ("unformat failed on socket %d, error %d", tffs_unformat, stat); + return 0; + } + PrintkInfo("unformatting successful"); + } + + /* if requested, format socket using standard formatting parameters */ + if (pSoc->bHandle == tffs_format) + { + PrintkInfo("format socket %d", tffs_format); + if( (stat = socket_std_format(pSoc)) != flOK ) + { + PrintkError ("format failed on socket %d, error %d", tffs_format, stat); + return 0; + } + PrintkInfo("formatting successful"); + } + + /* find out how many disks are on this DiskOnChip socket */ + ioreq.irHandle = pSoc->bHandle; + + stat = flCountVolumes(&ioreq); + if ((stat != flOK) || (ioreq.irFlags == 0)) + { + PrintkDebug("flCountVolumes error %d irFlags %lu", (int)stat, ioreq.irFlags); + +#ifdef TFFS_ALLOW_UNFORMATTED + pSoc->wDevices = 1; +#else + pSoc->wDevices = 0; +#endif + } + else + pSoc->wDevices = ioreq.irFlags; + + if (pSoc->wDevices == 0) + { + /* There are no any disk on this socket; probably this + * socket has never been formatted. + */ + return 0; + } + + if ((pSoc->pDevices = KMalloc(pSoc->wDevices * sizeof(DeviceInfo))) == NULL) + { + pSoc->wDevices = 0; + return 0; + } + + for (iDev = 0; iDev < pSoc->wDevices; iDev++) + init_disk (&pSoc->pDevices[iDev], pSoc); + + /* If configured, allocate scatter/gather buffer. Align size + * of scatter/gather buffer up to multiple of PAGE_SIZE. + */ + if (tffs_sg_bufsize > 0) + { + tffs_sg_bufsize = (((tffs_sg_bufsize - 1) / PAGE_SIZE) + 1) * PAGE_SIZE; + + if ((pSoc->pCache = KMalloc(tffs_sg_bufsize)) == NULL) + { + PrintkError ("can't allocate scatter/gather buffer"); + tffs_sg_bufsize = 0; + } + } + +#if 0 /* enable h/w DMA in DiskOnChip */ + ioreq.irHandle = pSoc->bHandle; + ioreq.irFlags = FL_DMA_TYPE; + ioreq.irLength = FL_DMA_HW_ENABLED; + + flHwConfig (&ioreq); +#endif + + /* set single- or multi-sector polled I/O mode */ + TffsSetPIO (pSoc); + +#if 0 /* andrayk June 23 2006: added for H3 burst */ + set_burst (pSoc); +#endif + + return (pSoc->wDevices != 0); +} + + + +/* defice still dismounted after init */ +static +int /* __init */ init_disk (DeviceInfo * pDisk, SocketInfo * pSocket) +{ + unsigned char bDevice; + + pDisk->bHandle=pSocket->bHandle+((pDisk-pSocket->pDevices)<<4); + pDisk->pSocket=(SocketInfo*)pSocket; + pDisk->wTffsHWSectorSizeShift=0; + while( (1<wTffsHWSectorSizeShift) != 8 ) + pDisk->wTffsHWSectorSizeShift++; + if(tffs_hardsect > 0) + pDisk->wHWSectorSize=tffs_hardsect; + else + pDisk->wHWSectorSize=512<<(TFFS_MAXHW_SECTOR_SIZE_BITSwTffsHWSectorSizeShift?TFFS_MAXHW_SECTOR_SIZE_BITS:pDisk->wTffsHWSectorSizeShift); + if(pDisk->wHWSectorSize>4096) + pDisk->wHWSectorSize=4096; + + pDisk->dwSize=0; + pDisk->fAbsMounted=0; + + if(TffsOpenDevice(pDisk)) + { + IOreq ioreq; + FLStatus stat; + + ioreq.irHandle=pDisk->bHandle; + + if ((stat = flSectorsInVolume(&ioreq)) == flOK) + pDisk->dwSize=ioreq.irLength; + else + PrintkDebug("flSectorsInVolume error %d",stat); + } + else + PrintkDebug("TffsOpenDevice error"); + +#ifndef TFFS_ALLOW_UNFORMATTED + if(pDisk->dwSize > 0) + { +#endif + for(bDevice=0; (tffsInfo.ppDevices[bDevice] != NULL) && (bDevice < FL_VOLUMES); bDevice++) + ; + if (bDevice >= FL_VOLUMES) + return 0; + tffsInfo.ppDevices[bDevice]=pDisk; + tffsInfo.wDevices++; + pDisk->diskNo=bDevice; +#ifndef TFFS_ALLOW_UNFORMATTED + } + else + return 0; +#endif + +#ifdef USE_EXT_FILTER + /* if we are going to use EXT filter, install it */ + if ((tffs_fs_filter == 1) && (pDisk->dwSize != 0)) + { + ExtFilterInit (pDisk); + } +#endif + + set_disk_geometry (pDisk); + + PrintkInfo ("Device 0x%x: %ld 512-byte sectors, h/w sector %d bytes", + pDisk->diskNo, pDisk->dwSize, pDisk->wHWSectorSize); + PrintkInfo ("C/H/S %u %u %u", pDisk->wCyl, pDisk->bHead, pDisk->bSect); + + return 1; +} + + + + +static +int release_socket (SocketInfo * pSoc) +{ + register int iDev; + + for (iDev = 0; iDev < pSoc->wDevices; iDev++) + release_disk (&pSoc->pDevices[iDev]); + + if (pSoc->pDevices != NULL) + { + kfree (pSoc->pDevices); + pSoc->pDevices = NULL; + } + + pSoc->wDevices = 0; + + /* free scatter/gather cache if was allocated */ + if (pSoc->pCache != NULL) + kfree (pSoc->pCache); + + return 0; +} + + + + +static +int release_disk (DeviceInfo *pDevice) +{ +#ifndef TFFS_ALLOW_UNFORMATTED + if(pDevice->dwSize==0) + return 0; +#endif + +#ifdef USE_EXT_FILTER + /* if we were using EXT filter, uninstall it */ + if ((tffs_fs_filter == 1) && (pDevice->dwSize != 0)) + { + ExtFilterRelease(pDevice); + } +#endif + if(!TffsCloseDevice(pDevice)) + PrintkDebug("TffsCloseDevice() error"); + + pDevice->dwSize=0; + tffsInfo.wDevices--; + return 1; +} + + + + +unsigned char TffsOpenDevice (DeviceInfo * pDisk) +{ + IOreq ioreq; + FLStatus status = flDriveNotAvailable; + + if (pDisk->fAbsMounted == 0) + { + ioreq.irHandle = pDisk->bHandle; + + if ((status = flAbsMountVolume(&ioreq)) == flOK) + pDisk->fAbsMounted = 1; + else + PrintkError("flAbsMountVolume() error %d", status); + } + +#ifdef TFFS_ALLOW_UNFORMATTED + if (pDisk->dwSize == 0) + return 1; +#endif + + return pDisk->fAbsMounted; +} + + + + +unsigned char TffsCloseDevice (DeviceInfo * pDevice) +{ + IOreq ioreq; + FLStatus stat = flDriveNotAvailable; + + if (pDevice->fAbsMounted != 0) + { + ioreq.irHandle = pDevice->bHandle; + + stat = flDismountVolume (&ioreq); + + pDevice->fAbsMounted = 0; + + if (stat != flOK) + { + PrintkDebug("flDismountVolume() error %d", stat); + return 0; + } + } + + return 1; +} + + + +#ifdef TFFS_STATISTIC + +static +void CountAl(DeviceInfo*pDevice,int block,int count,int dir) +{ + int sector=block,sectors=count,noInShared; + + while(sectors) + { + noInShared=(((sector>>pDevice->wTffsHWSectorSizeShift)+1)<wTffsHWSectorSizeShift)-sector; + if(noInShared>sectors) + noInShared=sectors; + if(noInShared==(1<wTffsHWSectorSizeShift)) + { + if(dir==READ) + { + pDevice->stat.dwAlReadShared++; + pDevice->stat.dwAlReadSec+=noInShared; + } + else + { + pDevice->stat.dwAlWriteShared++; + pDevice->stat.dwAlWriteSec+=noInShared; + } + } + else + { + if(dir==READ) + { + pDevice->stat.dwUnalReadShared++; + pDevice->stat.dwUnalReadSec+=noInShared; + } + else + { + pDevice->stat.dwUnalWriteShared++; + pDevice->stat.dwUnalWriteSec+=noInShared; + } + } + sectors-=noInShared; + sector+=noInShared; + } +} + +#endif /* TFFS_STATISTIC */ + + +#ifdef TFFS_COUNT_REQ_SECTORS +extern unsigned long dwRead,dwWritten; +#endif + + + +unsigned char TffsRead(DeviceInfo*pDevice,void*data,int block,int count) +{ + IOreq ioreq; + FLStatus stat = flDriveNotAvailable; + +#ifdef TFFS_COUNT_REQ_SECTORS + dwRead+=count; +#endif + +#ifdef TFFS_STATISTIC + pDevice->stat.dwAbsRead++; + pDevice->stat.dwAbsReadSec+=count; + CountAl(pDevice,block,count,READ); +#endif + + ioreq.irHandle=pDevice->bHandle; + ioreq.irData=data; + ioreq.irLength=block; + ioreq.irCount=count; + + if ((stat = flAbsRead(&ioreq)) == flOK) + return 1; + + PrintkDebug("flAbsRead() error %d",stat); + return 0; +} + +/* Perform read or write of appropriate number of sectors from a DOC volume */ +unsigned char TffsWrite(DeviceInfo*pDevice,void*data,int block,int count) +{ +#ifndef TFFS_RO + IOreq ioreq; + FLStatus stat = flDriveNotAvailable; + +# ifdef TFFS_COUNT_REQ_SECTORS + dwWritten+=count; +# endif + +# ifdef TFFS_STATISTIC + pDevice->stat.dwAbsWrite++; + pDevice->stat.dwAbsWriteSec+=count; + CountAl(pDevice,block,count,WRITE); +# endif + ioreq.irHandle=pDevice->bHandle; + ioreq.irData=data; + ioreq.irLength=block; + ioreq.irCount=count; + +# ifdef USE_EXT_FILTER + if (tffs_fs_filter == 1) /* use EXT filter */ + ExtFilter (pDevice,data,block,count); +# endif + +# ifdef USE_FAT_FILTER + if (tffs_fs_filter == 2) /* use FAT filter */ + ffCheckBeforeWrite (&ioreq); +# endif + if ((stat = flAbsWrite(&ioreq)) == flOK) + return 1; + PrintkError ("flAbsWrite error %d",stat); + +#endif /* TFFS_RO */ + + return 0; +} + + + +/************************************************************************ + * * + * s o c k e t _ s t d _ f o r m a t * + * * + * Formats DiskOnChip socket with standard format parameters. * + * WARNING: all existing data on DiskOnChip is destroyed ! * + * * + * Parameters: * + * psoc : socket to format * + * * + * Returns: * + * flOK on success, otherwise respective error code * + * * + ************************************************************************/ +static +FLStatus socket_std_format (SocketInfo * psoc) +{ + IOreq ioreq; + FLStatus stat = flDriveNotAvailable; + + /* format socket using standard formatting parameters */ + +static FormatParams3 std_fp3 = STD_FORMAT_PARAMS3; +static BDTLPartitionFormatParams3 std_bdtl_fp3 = STD_BDTL_PARAMS3; + + std_fp3.BDTLPartitionInfo = &std_bdtl_fp3; + + ioreq.irHandle = psoc->bHandle; + ioreq.irFlags = TL_NORMAL_FORMAT; + ioreq.irData = &std_fp3; + + if ((stat = flFlashFormat(&ioreq)) != flOK) + PrintkError("flFlashFormat error %d", stat); + + return stat; +} + + + +/************************************************************************ + * * + * s o c k e t _ u n _ f o r m a t * + * * + * Unformats DiskOnChip socket returning it to it's original factory * + * state. * + * WARNING: all existing data on DiskOnChip is destroyed ! * + * * + * Parameters: * + * psoc : socket to unformat * + * * + * Returns: * + * flOK on success, otherwise respective error code * + * * + ************************************************************************/ +static +FLStatus socket_unformat (SocketInfo * psoc) +{ + IOreq ioreq; + FLStatus stat; + + memset (&ioreq, 0, sizeof(ioreq)); + ioreq.irHandle = psoc->bHandle; + + if ((stat = flUnformat(&ioreq)) != flOK) + PrintkError("flUnformat error %d", stat); + + return stat; +} + + + +/************************************************************************ + * * + * p r i n t _ f i r m w a r e _ s t r i n g * + * * + * Print out various firmware informatio. * + * * + * Returns: * + * flOK on success, otherwise respective error code * + * * + ************************************************************************/ +static +FLStatus print_firmware_string (void) +{ + IOreq ioreq; + DOCH_Registers in_regs; + FLByte buf [512]; + FLStatus stat; + + memset (&in_regs, 0 , sizeof(in_regs)); + memset (&buf, 0 , sizeof(buf)); + + ioreq.irPath = &in_regs; + ioreq.irCount = DOCH_PASSTHRU_DATA_IN; + ioreq.irLength = 1; + ioreq.irData = buf; + + in_regs.bCommandStatus = DOCH_VSCMD_EXT_DEVICE_CTRL; + in_regs.bFeaturesError = DOCH_GET_EXTENDED_DEVICE_INFO; + + if( (stat = flDochPassThrough(&ioreq)) == flOK ) + PrintkInfo("%s", buf); + else + PrintkError("Can't get mDOC firmware info"); + + return stat; +} + + + +/************************************************************************ + * * + * a t a _ p a s s t h r o u g h * + * * + * This routine implements ATA pass-through command for DiskOnChip H3 * + * devices. * + * * + * Parameters: * + * pdev : device * + * ioctl_rec_ptr : kernel copy of user's flIOctlRecord * + * lnx_inrec_ptr : kernel copy of user's flInputLnxRecord * + * * + * Returns: * + * zero on success, otherwise -EFAULT or -ENOMEM * + * * + ************************************************************************/ +static +int ata_passthrough ( DeviceInfo * pdev, + flIOctlRecord * ioctl_rec_ptr, + flInputLnxRecord * lnx_inrec_ptr ) +{ + flOutputLnxRecord lnx_outrec; + flAtaPassthrough ata; + char * buf = NULL; + int rc = -EFAULT; + + /* copy struct flAtaPassthrough from user space */ + if( access_ok(VERIFY_WRITE, (void *)(lnx_inrec_ptr->data), sizeof(ata)) == 0 ) + return -EFAULT; + + if( copy_from_user(&ata, (void *)(lnx_inrec_ptr->data), sizeof(ata)) != 0 ) + return -EFAULT; + + if ((ata.passThruOP == DOCH_PASSTHRU_DATA_OUT) || (ata.passThruOP == DOCH_PASSTHRU_DATA_IN)) + { + /* currently we don't allow more then 256 sectors in single transfer */ + if (ata.userBuffSize > (256 * FL_SECTOR_SIZE)) + return -ENOMEM; + + /* check if we can access user buffer */ + if (ata.passThruOP == DOCH_PASSTHRU_DATA_OUT) + { + if( access_ok(VERIFY_READ, ata.userBuff, ata.userBuffSize) == 0 ) + return -EFAULT; + } + else if (ata.passThruOP == DOCH_PASSTHRU_DATA_IN) + { + if( access_ok(VERIFY_WRITE, ata.userBuff, ata.userBuffSize) == 0 ) + return -EFAULT; + } + + /* allocate kernel buffer to hold user data */ + if ((buf = vmalloc(ata.userBuffSize)) == NULL) + return -ENOMEM; + } + + /* For output (host -> DiskOnChip) operations, copy data from + * user buffer 'ata.userBuff' to to kernel buffer 'buf' + */ + if (ata.passThruOP == DOCH_PASSTHRU_DATA_OUT) + { + if( copy_from_user(buf, ata.userBuff, ata.userBuffSize) != 0 ) + goto quit; + +#if 0 /* andrayk May 12 2006: firmware checksum calculation to assist debugging */ + { register unsigned long s; + register int n = (ata.userBuffSize / sizeof(long)) - 1; + unsigned long * p = (unsigned long *)buf; + + for (s = 0; n >= 0; n--) + s ^= p[n]; + + PrintkDebug ("Firmware file checksum is 0x%lx", s); + } +#endif + } + + /* Execute pass-through ATA command, and put it's status into + * both 'flOutputLnxRecord.status' and 'flAtaPassthrough.status'. + */ + ata.status = lnx_outrec.status = + + DOCHAtaPassThrough (pdev->bHandle, /* not 'ata.socketNum', for security reasons */ + ata.passThruOP, + (DOCH_Registers *) &ata.in_regs, + (DOCH_Registers *) &ata.out_regs, + ata.secNum, + buf, + FALSE); /* don't use DiskOnChip interrupt */ + + /* For input (DiskOnChip -> host) operations, copy data from + * kernel buffer 'buf' to user buffer 'ata.userBuff'. + */ + if (ata.passThruOP == DOCH_PASSTHRU_DATA_IN) + { + if( copy_to_user(ata.userBuff, buf, ata.userBuffSize) != 0 ) + goto quit; + } + + /* copy updated struct flAtaPassthrough back to user space */ + if( copy_to_user((void *)(lnx_inrec_ptr->data), &ata, sizeof(ata)) != 0 ) + goto quit; + + /* copy updated struct flOutputLnxRecord back to user space */ + if( copy_to_user(ioctl_rec_ptr->outputRecord, &lnx_outrec, sizeof(lnx_outrec)) != 0 ) + goto quit; + + rc = 0; /* success */ + + quit: + + if (buf != NULL) + { + memset (buf, 0, ata.userBuffSize); + vfree (buf); + } + + return rc; +} + + + + +#define USR2KRN_O_START(typeOut) \ + { \ + typeOut output; \ + void *tmp; \ + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(typeOut))) \ + return -EFAULT; \ + tmp = ioctlRecord.outputRecord; \ + ioctlRecord.outputRecord = &output; + +#define USR2KRN_IO_START(typeIn,typeOut) \ + { \ + typeIn input; \ + typeOut output; \ + void *tmp; \ + if (!access_ok(VERIFY_READ,ioctlRecord.inputRecord,sizeof(typeIn))) \ + return -EFAULT; \ + if (copy_from_user(&input,ioctlRecord.inputRecord,sizeof(typeIn))) \ + return -EFAULT; \ + ioctlRecord.inputRecord = &input; \ + if (!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(typeOut))) \ + return -EFAULT; \ + tmp = ioctlRecord.outputRecord; \ + ioctlRecord.outputRecord = &output; + +#define USR2KRN_END \ + if (copy_to_user(tmp, &output, sizeof(output))) \ + return -EFAULT; \ + return 0; \ + } + +#define USR2KRN01(theHandle,typeOut,pSoc) \ + USR2KRN_O_START(typeOut) \ + ioreq.irHandle = theHandle; \ + flIOctl(&ioreq); \ + USR2KRN_END + +#define USR2KRN11(theHandle,typeIn,typeOut,pSoc) \ + USR2KRN_IO_START(typeIn,typeOut) \ + ioreq.irHandle = theHandle; \ + flIOctl(&ioreq); \ + USR2KRN_END + + +/* returns: 0 - OK, 1 - no TFFS ioctl, <0 - error */ +int TffsIoctl(DeviceInfo*pDevice,int cmd,unsigned long arg) +{ +#ifdef FL_IOCTL_INTERFACE + unsigned char bdtlVolume=pDevice->bHandle; + IOreq ioreq; + flIOctlRecord ioctlRecord; + + static unsigned int handle_for_ioctls = 0xffff; + + if ((cmd < FL_IOCTL_LNX) || (cmd > FL_IOCTL_IPL_HW_PROTECTION)) + { PrintkError ("unknown IOCTL code %d passed to TrueFFS", cmd); return 1; } + + + /* map flIOctlRecord */ + if(!access_ok(VERIFY_WRITE|VERIFY_READ,(void*)arg,sizeof(flIOctlRecord))) + return -EFAULT; + if(copy_from_user(&ioctlRecord,(void*)arg,sizeof(flIOctlRecord))) + return -EFAULT; + ioreq.irData=&ioctlRecord; + ioreq.irFlags=cmd; + + switch(cmd) + { + + + case FL_IOCTL_GET_INFO: + { + struct hd_geometry geometry; + USR2KRN_O_START(flDiskInfoOutput); + + ioreq.irHandle = bdtlVolume; + flIOctl(&ioreq); + + geometry.heads = pDevice->bHead; + geometry.sectors = pDevice->bSect; + geometry.cylinders = pDevice->wCyl; + + ((flDiskInfoOutput*)(ioctlRecord.outputRecord))->info.cylinders=geometry.cylinders; + ((flDiskInfoOutput*)(ioctlRecord.outputRecord))->info.heads=geometry.heads; + ((flDiskInfoOutput*)(ioctlRecord.outputRecord))->info.sectors=geometry.sectors; + USR2KRN_END; + } + + + case FL_IOCTL_DEFRAGMENT: + USR2KRN11(bdtlVolume,flDefragInput,flDefragOutput,pSoc); + + + case FL_IOCTL_MOUNT_VOLUME: + USR2KRN11(bdtlVolume,flMountInput,flOutputStatusRecord,pSoc); + + +#ifdef BDK_ACCESS + case FL_IOCTL_BDK_OPERATION: + { + void*tmp1=NULL,*tmpIn=NULL; + flBDKOperationInput input; + flOutputStatusRecord output; + void*tmp; + + if(!access_ok(VERIFY_READ|VERIFY_WRITE,ioctlRecord.inputRecord,sizeof(flBDKOperationInput))) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:access_ok(inputRecord)"); + return -EFAULT; + } + if(copy_from_user(&input,ioctlRecord.inputRecord,sizeof(flBDKOperationInput))) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:copy_from_user(inputRecord)"); + return -EFAULT; + } + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(flOutputStatusRecord))) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:access_ok(outputRecord)"); + return -EFAULT; + } + tmp=ioctlRecord.outputRecord; + tmpIn=ioctlRecord.inputRecord; + ioctlRecord.inputRecord=&input; + ioctlRecord.outputRecord=&output; + + if(input.bdkStruct.bdkBuffer!=NULL) + { + tmp1=input.bdkStruct.bdkBuffer; + input.bdkStruct.bdkBuffer=VMalloc(input.bdkStruct.length); + if(input.bdkStruct.bdkBuffer==NULL) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:vmalloc"); + return -ENOMEM; + } + if(!access_ok(VERIFY_WRITE|VERIFY_READ,tmp1,input.bdkStruct.length)) + { + vfree(input.bdkStruct.bdkBuffer); + PrintkDebug("FL_IOCTL_BDK_OPERATION:access_ok"); + return -EFAULT; + } + if(copy_from_user(input.bdkStruct.bdkBuffer,tmp1,input.bdkStruct.length)) + { + vfree(input.bdkStruct.bdkBuffer); + PrintkDebug("FL_IOCTL_BDK_OPERATION:copy_from_user"); + return -EFAULT; + } + } + + ioreq.irHandle = handle_for_ioctls; + flIOctl(&ioreq); + + if(input.bdkStruct.bdkBuffer!=NULL) + { + if(copy_to_user(tmp1,input.bdkStruct.bdkBuffer,input.bdkStruct.length)) + { + PrintkDebug("FL_IOCTL_BDK_OPERATION:copy_to_user(bdkBuffer)"); + vfree(input.bdkStruct.bdkBuffer); + return -EFAULT; + } + vfree(input.bdkStruct.bdkBuffer); + } + + /* copy flBDKOperationInput */ + input.bdkStruct.bdkBuffer=tmp1; + if(copy_to_user(tmpIn,&input,sizeof(flBDKOperationInput))) + { + if(input.bdkStruct.bdkBuffer!=NULL) + vfree(input.bdkStruct.bdkBuffer); + PrintkDebug("FL_IOCTL_BDK_OPERATION:copy_to_user(inputRecord)"); + return -EFAULT; + } + + if(copy_to_user(tmp,&output,sizeof(output))) + return -EFAULT; + return 0; + } +#endif /* BDK_ACCESS */ + + + case FL_IOCTL_DELETE_SECTORS: + case FL_IOCTL_READ_SECTORS: + case FL_IOCTL_WRITE_SECTORS: + return -EINVAL; + + + case FL_IOCTL_BDTL_HW_PROTECTION: + case FL_IOCTL_IPL_HW_PROTECTION: +#ifdef BDK_ACCESS + case FL_IOCTL_BINARY_HW_PROTECTION: +#endif + +#ifdef HW_PROTECTION + { flProtectionInput my_prot_in, *usr_prot_in = (flProtectionInput *)ioctlRecord.inputRecord; + flProtectionOutput my_prot_out, *usr_prot_out = (flProtectionOutput *)ioctlRecord.outputRecord; + + if( !access_ok((VERIFY_WRITE | VERIFY_READ), usr_prot_in, sizeof(flProtectionInput)) ) + return -EFAULT; + if( !access_ok(VERIFY_WRITE, usr_prot_out, sizeof(flProtectionOutput))) + return -EFAULT; + + if( copy_from_user(&my_prot_in, usr_prot_in, sizeof(flProtectionInput)) ) + return -EFAULT; + + ioctlRecord.inputRecord = &my_prot_in; + ioctlRecord.outputRecord = &my_prot_out; + +# ifdef BDK_ACCESS + if (cmd == FL_IOCTL_BINARY_HW_PROTECTION) + ioreq.irHandle = handle_for_ioctls; + else +# endif + ioreq.irHandle = ((handle_for_ioctls != 0xffff) ? handle_for_ioctls : bdtlVolume); + + flIOctl (&ioreq); + + if( copy_to_user(usr_prot_in, &my_prot_in, sizeof(flProtectionInput)) ) + return -EFAULT; + if( copy_to_user(usr_prot_out, &my_prot_out,sizeof(flProtectionOutput)) ) + return -EFAULT; + + return 0; + } + +#else /* !HW_PROTECTION */ + return -EINVAL; +#endif + + + case FL_IOCTL_OTP: +#ifdef HW_OTP + { + void*tmp1; + USR2KRN_IO_START(flOtpInput,flOutputStatusRecord); + tmp1=input.buffer; + input.buffer=KMalloc(input.length); + if(input.buffer==NULL) + return -ENOMEM; + if(!access_ok(VERIFY_WRITE|VERIFY_READ,tmp1,input.length)) + { + kfree(input.buffer); + return -EFAULT; + } + if(copy_from_user(input.buffer,tmp1,input.length)) + { + kfree(input.buffer); + return -EFAULT; + } + + ioreq.irHandle = (bdtlVolume & 0x0f); + flIOctl(&ioreq); + + if(copy_to_user(tmp1,input.buffer,input.length)) + { + kfree(input.buffer); + return -EFAULT; + } + kfree(input.buffer); + USR2KRN_END; + } +#else /* HW_OTP */ + return -EINVAL; +#endif /* HW_OTP */ + + + case FL_IOCTL_CUSTOMER_ID: +#ifdef HW_OTP + USR2KRN01(bdtlVolume&0x0f,flCustomerIdOutput,pSoc); +#else /* HW_OTP */ + return -EINVAL; +#endif + + + case FL_IOCTL_UNIQUE_ID: +#ifdef HW_OTP + USR2KRN01(bdtlVolume&0x0f,flUniqueIdOutput,pSoc); +#else /* HW_OTP */ + return -EINVAL; +#endif + + + case FL_IOCTL_NUMBER_OF_PARTITIONS: + USR2KRN01(bdtlVolume&0x0f,flCountPartitionsOutput,pSoc); + + + case FL_IOCTL_WRITE_IPL: +#ifndef NO_IPL_CODE + { + flIPLInput iplInput; + flOutputStatusRecord outputStatusRecord; + void*outputStatusRecordSave,*bBufPtrSave; + if(!access_ok(VERIFY_READ,ioctlRecord.inputRecord,sizeof(flIPLInput))) + return -EFAULT; + if(copy_from_user(&iplInput,ioctlRecord.inputRecord,sizeof(flIPLInput))) + return -EFAULT; + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(flOutputStatusRecord))) + return -EFAULT; + outputStatusRecordSave=ioctlRecord.outputRecord; + ioctlRecord.inputRecord=&iplInput; + ioctlRecord.outputRecord=&outputStatusRecord; + + bBufPtrSave=iplInput.bBufPtr; + iplInput.bBufPtr=KMalloc(iplInput.sdwLength); + if(iplInput.bBufPtr==NULL) + return -ENOMEM; + if(!access_ok(VERIFY_READ,bBufPtrSave,iplInput.sdwLength)) + { + kfree(iplInput.bBufPtr); + return -EFAULT; + } + if(copy_from_user(iplInput.bBufPtr,bBufPtrSave,iplInput.sdwLength)) + { + kfree(iplInput.bBufPtr); + return -EFAULT; + } + ioreq.irHandle=bdtlVolume&0x0f; + flIOctl (&ioreq); + + kfree(iplInput.bBufPtr); + if(copy_to_user(outputStatusRecordSave,&outputStatusRecord,sizeof(flOutputStatusRecord))) + return -EFAULT; + return 0; + } +#else /* NO_IPL_CODE */ + return -EINVAL; +#endif /* NO_IPL_CODE */ + + + case FL_IOCTL_DEEP_POWER_DOWN_MODE: + USR2KRN11(bdtlVolume&0x0f,flPowerDownInput,flOutputStatusRecord,pSoc); + + + case FL_IOCTL_EXTENDED_ENVIRONMENT_VARIABLES: +#ifdef FL_ENVIRONMENT_VARS + USR2KRN11(bdtlVolume,flExtendedEnvVarsInput,flExtendedEnvVarsOutput,pSoc); +#else + return -EINVAL; +#endif /* FL_ENVIRONMENT_VARS */ + + + case FL_IOCTL_VERIFY_VOLUME: +#ifdef VERIFY_VOLUME + USR2KRN11(bdtlVolume,flVerifyVolumeInput,flVerifyVolumeOutput,pSoc); +#endif + + + case FL_IOCTL_SET_ACCESS_ROUTINE: + return -EINVAL; + + + case FL_IOCTL_GET_ACCESS_ROUTINE: + return -EINVAL; + + + case FL_IOCTL_IS_QUICK_MOUNT_VALID: +# ifndef FL_NO_QUICK_MOUNT_FEATURE + USR2KRN01(bdtlVolume,flGetQuickMountOutput,pSoc); +# else + return -EINVAL; +# endif /* FL_NO_QUICK_MOUNT_FEATURE */ + + + case FL_IOCTL_WRITE_QUICK_MOUNT_INFO: +# ifndef FL_NO_QUICK_MOUNT_FEATURE + USR2KRN01(bdtlVolume,flOutputStatusRecord,pSoc); +# else + return -EINVAL; +# endif /* FL_NO_QUICK_MOUNT_FEATURE */ + + + case FL_IOCTL_CLEAR_QUICK_MOUNT_INFO: +# ifndef FL_NO_QUICK_MOUNT_FEATURE + USR2KRN01(bdtlVolume,flOutputStatusRecord,pSoc); +# else + return -EINVAL; +# endif /* FL_NO_QUICK_MOUNT_FEATURE */ + + + case FL_IOCTL_FLASH_FORMAT: + +# ifndef FL_FORMAT_VOLUME + return -EINVAL; +# else + { FormatParams3 formatParams3; + BDTLPartitionFormatParams3 bdtl_fp [FL_VOLUMES]; +# ifdef BDK_ACCESS + BinaryPartitionFormatParams3 bin_fp [FL_BINARY_PARTITIONS]; +# endif + flFlashFormatInput flashFormatInput; + flOutputStatusRecord outputStatusRecord; + void * user_outputStatusRecord; + int bdtls; /* BDTL partitions to create */ + int bins; /* binary partitions to create */ + + PrintkDebug("TffsIoctl:FL_IOCTL_FLASH_FORMAT"); + + if( !access_ok(VERIFY_WRITE, ioctlRecord.outputRecord, sizeof(flOutputStatusRecord)) ) + return -EFAULT; + + user_outputStatusRecord = ioctlRecord.outputRecord; + ioctlRecord.outputRecord = &outputStatusRecord; + + if( !access_ok(VERIFY_READ, ioctlRecord.inputRecord, sizeof(flFlashFormatInput)) ) + return -EFAULT; + + if( copy_from_user(&flashFormatInput, ioctlRecord.inputRecord, sizeof(flFlashFormatInput)) ) + return -EFAULT; + + ioctlRecord.inputRecord = &flashFormatInput; + + if( !access_ok(VERIFY_READ, flashFormatInput.fpPtr, sizeof(FormatParams3)) ) + return -EFAULT; + + if( copy_from_user(&formatParams3, flashFormatInput.fpPtr, sizeof(FormatParams3)) ) + return -EFAULT; + + /* BDTL partitions layout */ + bdtls = flashFormatInput.fpPtr->noOfBDTLPartitions; + if (bdtls > FL_VOLUMES) + return -EINVAL; + + if( !access_ok(VERIFY_READ, flashFormatInput.fpPtr->BDTLPartitionInfo, + (sizeof(BDTLPartitionFormatParams3) * bdtls)) ) + return -EFAULT; + + if( copy_from_user(bdtl_fp, flashFormatInput.fpPtr->BDTLPartitionInfo, + (sizeof(BDTLPartitionFormatParams3) * bdtls)) ) + return -EFAULT; + + flashFormatInput.fpPtr->BDTLPartitionInfo = bdtl_fp; + + /* binary partitions layout */ + bins = flashFormatInput.fpPtr->noOfBinaryPartitions; + if (bins > 0) + { +# ifdef BDK_ACCESS + if( !access_ok(VERIFY_READ, flashFormatInput.fpPtr->binaryPartitionInfo, + (sizeof(BinaryPartitionFormatParams3) * bins)) ) + return -EFAULT; + + if( copy_from_user(bin_fp, flashFormatInput.fpPtr->binaryPartitionInfo, + (sizeof(BinaryPartitionFormatParams3) * bins)) ) + return -EFAULT; + + flashFormatInput.fpPtr->binaryPartitionInfo = bin_fp; +# else + return -EINVAL; +# endif + } + + /* set to NULL not mapped pointers */ + flashFormatInput.fpPtr->progressCallback = NULL; + flashFormatInput.fpPtr->embeddedCIS = NULL; + flashFormatInput.fpPtr->embeddedCISlength = 0; + + ioreq.irHandle = (bdtlVolume & 0x0f); + flIOctl (&ioreq); + + if( copy_to_user(user_outputStatusRecord, &outputStatusRecord, sizeof(outputStatusRecord))) + return -EFAULT; + + return 0; + } +# endif /* FL_FORMAT_VOLUME */ + + + case FL_IOCTL_ERASE_BD: +# ifdef FL_FORMAT_VOLUME + PrintkDebug("TffsIoctl:FL_IOCTL_ERASE_BD"); + USR2KRN11(bdtlVolume,flEraseBDInput,flOutputStatusRecord,pSoc); +# else /* FL_FORMAT_VOLUME */ + return -EINVAL; +# endif /* FL_FORMAT_VOLUME */ + + + case FL_IOCTL_FLASH_UNFORMAT: +# ifdef FL_FORMAT_VOLUME + USR2KRN11(bdtlVolume,flFlashUnformatInput,flOutputStatusRecord,pSoc); +# else /* FL_FORMAT_VOLUME */ + return -EINVAL; +# endif /* FL_FORMAT_VOLUME */ + + +#if defined(TFFS_USE_G4) && defined(HW_OTP) + case FL_IOCTL_MCOTP: + { + flMCOtpInput mcotpInput; + flOutputStatusRecord outputStatusRecord; + void*outputStatusRecordSave,*bufferSave=NULL,*mcotpInputSave; + + if(!access_ok(VERIFY_READ|VERIFY_WRITE,ioctlRecord.inputRecord,sizeof(flMCOtpInput))) + return -EFAULT; + if(copy_from_user(&mcotpInput,ioctlRecord.inputRecord,sizeof(flMCOtpInput))) + return -EFAULT; + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(flOutputStatusRecord))) + return -EFAULT; + outputStatusRecordSave=ioctlRecord.outputRecord; + mcotpInputSave=ioctlRecord.inputRecord; + ioctlRecord.inputRecord=&mcotpInput; + ioctlRecord.outputRecord=&outputStatusRecord; + + if(mcotpInput.length!=0) + { + bufferSave=mcotpInput.buffer; + mcotpInput.buffer=VMalloc(mcotpInput.length); + if(mcotpInput.buffer==NULL) + return -ENOMEM; + if(!access_ok(VERIFY_READ|VERIFY_WRITE,mcotpInput.buffer,mcotpInput.length)) + return -EFAULT; + if(copy_from_user(mcotpInput.buffer,bufferSave,sizeof(mcotpInput.length))) + return -EFAULT; + } + + ioreq.irHandle = bdtlVolume&0x0f; + flIOctl (&ioreq); + + if(mcotpInput.length!=0) + { + if(copy_to_user(bufferSave,mcotpInput.buffer,sizeof(mcotpInput.length))) + return -EFAULT; + vfree(mcotpInput.buffer); + mcotpInput.buffer=bufferSave; + } + if(copy_to_user(mcotpInputSave,&mcotpInput,sizeof(flMCOtpInput))) + return -EFAULT; + if(copy_to_user(outputStatusRecordSave,&outputStatusRecord,sizeof(flMCOtpInput))) + return -EFAULT; + + } +#endif /* defined(TFFS_USE_G4) && defined(HW_OTP) */ + + + case FL_IOCTL_LNX: + { + flInputLnxRecord inRec; + flOutputLnxRecord outRec; + + if(!access_ok(VERIFY_READ,ioctlRecord.inputRecord,sizeof(flInputLnxRecord))) + return -EFAULT; + if(copy_from_user(&inRec,ioctlRecord.inputRecord,sizeof(flInputLnxRecord))) + return -EFAULT; + if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(flOutputLnxRecord))) + return -EFAULT; + + switch(inRec.command) + { + case 0: /* set TrueFFS handle for future IOCTLs */ + { + handle_for_ioctls = inRec.data; + + outRec.status = flOK; + if(copy_to_user(ioctlRecord.outputRecord, &outRec, sizeof(flOutputLnxRecord))) + return -EFAULT; + return 0; + } +#if defined(TFFS_DEBUG_DRIVER) && !defined(TFFS_RO) + case 3: /* print no of used sectors on device */ + { + ioreq.irHandle=pDevice->bHandle; + ioreq.irLength=0; + + outRec.status =flDefragmentVolume (&ioreq); + + outRec.data=ioreq.irLength; + if(copy_to_user(ioctlRecord.outputRecord,&outRec,sizeof(flOutputLnxRecord))) + return -EFAULT; + return 0; + } +#endif /* TFFS_DEBUG_DRIVER */ + + case 5: /* ATA pass-through command */ + return ata_passthrough (pDevice, &ioctlRecord, &inRec); + } + } + + + default: + PrintkDebug("TffsIoctl: no Tffs ioctl"); + return -EINVAL; + } + + /* do not check error code - it sended by outRec->status */ + flIOctl (&ioreq); + + return 0; +#else /* FL_IOCTL_INTERFACE */ + return 1; +#endif /* FL_IOCTL_INTERFACE */ +} + + + + +/******************************************************************************* + * * + * T f f s E n a b l e I R Q * + * * + * This routine enables DiskOnChip interrupt generation upon completion of * + * flash erase/write operation. Works with all types of DiskOnChip devices. * + * * + * Parameters: * + * * + * psoc socket pointer * + * * + * Returns: * + * * + * always zero (success) * + * * + *******************************************************************************/ + +int TffsEnableIRQ (SocketInfo * psoc) +{ + IOreq ioreq; + + ioreq.irHandle = psoc->bHandle; + ioreq.irFlags = FL_IRQ_RB_TYPE; + ioreq.irLength = (FL_INT_RB_ENABLED | /* FL_IRQ_EDGE_TYPE */ FL_IRQ_LEVEL_TYPE); + + flHwConfig (&ioreq); + + return 0; +} + + + + +/******************************************************************************* + * * + * T f f s S e t P I O * + * * + * If requested, this routine sets multi-sector polled I/O mode in DiskOnChip * + * H3 devices. It has no effect on H1/G4/G3 DiskOnChip devices. * + * * + * Parameters: * + * * + * psoc socket pointer * + * * + * Returns: * + * * + * zero if success otherwise respective error code * + * * + *******************************************************************************/ + +int TffsSetPIO (SocketInfo * psoc) +{ + IOreq ioreq; + DOCH_Error rc = DOCH_OK; + + if (tffs_pio > 0) /* multi-sector polled I/O mode requested */ + { + /* If we are going to use intermediate DMA buffer (which is one MMU page + * in size), we must make sure that multi-sector PIO won't overrun it. + */ + if( (tffs_dma_mode > 0) && !(tffs_dma_mode & 0x4) && + ((tffs_pio * FL_SECTOR_SIZE) > PAGE_SIZE) ) + { + PrintkError ("Multi-sector polled I/O overruns DMA buffer, disabled"); + tffs_pio = 0; + return -1; + } + + /* Set multi-sector polled I/O mode to transfer up to + * 'tffs_pio_mode' (but no more then 256) sectors at once. + */ + ioreq.irHandle = psoc->bHandle; + ioreq.irCount = DOCH_DATA_XFER_MODE_MULT; + ioreq.irLength = ((tffs_pio <= 255) ? tffs_pio : 0); + + if ((rc = flDOCHSetDataTransferMode(&ioreq)) != DOCH_OK) + { + PrintkError ("Can't set multi-sector polled I/O, error %d", rc); + tffs_pio = 0; + return -1; + } + PrintkInfo ("use multi-sector I/O (%d sectors)", tffs_pio); + } + else /* single-sector polled I/O mode requested */ + { + /* DiskOnChip H3 devices default to single-sector polled I/O mode + * upon reset, so we don't have to do anything here. + */ + } + + return (int)rc; +} + + + +/******************************************************************************* + * * + * T f f s S u s p e n d * + * * + * Power down DiskOnChip socket. * + * * + * Parameters: * + * * + * psoc socket pointer * + * * + * Returns: * + * * + * always zero (success) * + * * + *******************************************************************************/ + +int TffsSuspend (SocketInfo * psoc) +{ + IOreq ioreq; + + ioreq.irHandle = psoc->bHandle; + ioreq.irFlags = DEEP_POWER_DOWN; + + flDeepPowerDownMode (&ioreq); + + return 0; +} + + + + +/******************************************************************************* + * * + * T f f s R e s u m e * + * * + * Power up (previously powered down) DiskOnChip socket. * + * * + * Parameters: * + * * + * psoc socket pointer * + * * + * Returns: * + * * + * always zero (success) * + * * + *******************************************************************************/ + +int TffsResume (SocketInfo * psoc) +{ + IOreq ioreq; + + ioreq.irHandle = psoc->bHandle; + ioreq.irFlags = EXIT_DEEP_POWER_DOWN; + + flDeepPowerDownMode (&ioreq); + + return 0; +} + + + +static +void set_disk_geometry (DeviceInfo *pDisk) +{ + /* Limitations for old BIOSes: + no. of heads : 8 bits - max 255 + no. of cylinders: 10 bits - max 1023 + no. of sectors per track: 6 bits - max 63 */ + + if (pDisk->dwSize == 0) + { + pDisk->wCyl = 1; + pDisk->bHead = 1; + pDisk->bSect = 1; + return; + } + else if (pDisk->dwSize <= 0x800000) /* up to 4 GByte */ + { + unsigned long sectors, rest, minSec, maxSec, sec, minCyl, cyl; + + rest=sectors = (pDisk->dwSize >> pDisk->wTffsHWSectorSizeShift); /* use shared sector size instead kernel HW sector size - the same geometry for any harsect */ + + minSec=sectors/(1023*255); + if(sectors!=minSec*1023*255) + minSec++; + maxSec=63>>pDisk->wTffsHWSectorSizeShift; + minCyl=sectors/(maxSec*255); + if(sectors!=minCyl*maxSec*255) + minCyl++; + + for(sec=maxSec;sec>=minSec;sec--) + { + unsigned long minHead,maxHead,dwHead; + minHead=sectors/(sec*1023); + if(sectors!=minHead*sec*1023) + minHead++; + /* if(minHead%16) minHead=((minHead>>4)+1)<<4; */ + + maxHead=sectors/(sec*minCyl); + if(maxHead>255) + maxHead=255; + for(dwHead=minHead;dwHead<=maxHead;dwHead++ /*=16*/ ) + { + unsigned long tmp; + cyl=sectors/(sec*dwHead); + tmp=sectors-cyl*sec*dwHead; + if(rest>tmp) + { + pDisk->wCyl=cyl; + pDisk->bHead=dwHead; + pDisk->bSect=sec<wTffsHWSectorSizeShift; + if(tmp==0) + { + PrintkDebug("C/H/S (0) %u %u %u",pDisk->wCyl,pDisk->bHead,pDisk->bSect); + return; + } + rest=tmp; + } + } + } + } + else /* 4 .. 512 GByte */ + { + unsigned long heads = 16L, sectors_per_track = 63L, cylinders; + + /* Our preferences are (from highest to lowest): + * - 63 sectors per track + * - 16 heads + * - less then 65535 cylinders + */ + while ((cylinders = pDisk->dwSize / (heads * sectors_per_track)) > 65535L) + { + if (heads < 255L) heads++; + else if (sectors_per_track < 255L) sectors_per_track++; + else + { + PrintkError ("Error calculating C/H/S"); + break; + } + } + + pDisk->wCyl = (unsigned short) cylinders; + pDisk->bHead = (unsigned char) heads; + pDisk->bSect = (unsigned char) sectors_per_track; + + /* disk should have whole number of cylinders */ + pDisk->dwSize = (unsigned long)pDisk->wCyl * pDisk->bHead * pDisk->bSect; + } +} + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs2lnx.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs2lnx.h new file mode 100755 index 00000000..9975b4db --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs2lnx.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + +#ifndef ___TFFS2LNX__H__ +#define ___TFFS2LNX__H__ + +/* Driver Functions */ +int TffsInit (void); +int TffsCleanup (void); +unsigned char TffsOpenDevice(DeviceInfo*pDevice); +unsigned char TffsCloseDevice(DeviceInfo*pDevice); +unsigned char TffsRead(DeviceInfo*pDevice,void*data,int block,int count); +unsigned char TffsWrite(DeviceInfo*pDevice,void*data,int block,int count); +int TffsIoctl(DeviceInfo*pDevice,int cmd,unsigned long arg); +unsigned char TffsIsWriteProtected(DeviceInfo*pDevice); + +/* enable DiskOnChip interrupt */ +extern int TffsEnableIRQ (SocketInfo *psoc); + +/* set multi-sector polled I/O mode */ +extern int TffsSetPIO (SocketInfo *psoc); + +/* suspend/resume power */ +extern int TffsSuspend (SocketInfo *psoc); +extern int TffsResume (SocketInfo *psoc); + +#endif /* ___TFFS2LNX__H__ */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs_api.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs_api.c new file mode 100755 index 00000000..8a23d0f4 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs_api.c @@ -0,0 +1,5359 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/tffs_api.c-arc $ + * + * Rev 1.100 Dec 25 2007 11:21:16 einat.avidan + * bug fix: unformat should not delete all partitions only if + * identified protected partitions + * + * Rev 1.99 Dec 16 2007 11:43:34 einat.avidan + * Add format start and format complete signatures in disk user attributes + * AbsMount: check format complete signature if format start signature exist + * + * + * Rev 1.98 Dec 04 2007 17:48:08 einat.avidan + * Bug fix: add check for format completeness in flAbsMountVolume + * Round requested fast area size up to unit Size + * Changed parameters passed to flDOCHWipeSectors + * Bug fix: TFFSChangeProtectionType failed setting partition as OTW + * + * Rev 1.97 Nov 04 2007 17:08:24 einat.avidan + * use secure erase command + * fix printout + * + * Rev 1.96 Oct 30 2007 17:12:00 einat.avidan + * new fast area type - FL_LENGTH_ALL + * unformat - delete partitions even if bad format + * implement eraseBD and SecureDelete by writing + * + * Rev 1.95 Oct 23 2007 11:30:36 einat.avidan + * update function documentation + * + * Rev 1.94 Oct 22 2007 11:34:56 einat.avidan + * update copyrights header + * + * Rev 1.93 Oct 11 2007 18:50:44 Einat.Avidan + * Replace global Boolean pattern with pattern in size of + * byte instead of dWord + * add compilation flags for SOTP and SLPP + * remove internal call to flDOCHFreeSectors in TFFSAbsDelete + * bug fix: TFFSWriteIPL did not support FL_IPL_SWAP_BYTES_MODE + * + * Rev 1.92 Sep 04 2007 15:42:24 einat.avidan + * bug fix: SCR 2993: flIdentifyProtection() does not report LOCK_ASSERTED + * + * Rev 1.91 Jul 02 2007 11:44:42 einat.avidan + * bug fix: SCR2966 : removed flags which are not in use + * FL_PREPARE_FOR_RESUME + * FL_IPL_NO_ADDRESS_SHIFT_MODE + * + * Rev 1.90 Jul 01 2007 13:47:28 einat.avidan + * bug fix: SCR 2964 compilation flag FL_VERIFY_WRITE should exclude \ include code for write verification + * + * Rev 1.89 Jun 20 2007 12:08:40 einat.avidan + * when DOCH_AUTO_DPD_BY_HOST is enabeled: wrong macro name was used(TFFS_API_IS_DPD_ON instead of TFFS_API_IS_AUTO_DPD_ON) + * + * Rev 1.88 Mar 22 2007 17:12:12 einat.avidan + * add SOTP + * + * Rev 1.87 Mar 22 2007 16:44:50 einat.avidan + * bug fix: TFFSVolumeInfo will return SLPP protection indication in case of SLPP and 0 otherwise. + * + * Rev 1.86 Mar 13 2007 13:47:18 einat.avidan + * add support for SLPP + * + * Rev 1.85 Mar 11 2007 16:59:06 einat.avidan + * bug fix: scr2886 flHardwareProtectionLock was not supported. + * bug fix: scr2819 maximum number of authentication tries of IPL partition was 1 + * + * Rev 1.84 Feb 28 2007 10:34:08 einat.avidan + * In write IPL – do not write whole partition, in order to reduce the time between reset and busy + * + * Rev 1.83 Feb 15 2007 17:53:14 Einat.Avidan + * Enable burst without DMA + * + * Rev 1.81.1.8 Nov 30 2006 10:24:16 Yaniv.Iarovici + * Fixed compilation warnings. + * + * Rev 1.81.1.7 Nov 21 2006 14:26:32 Yaniv.Iarovici + * Enable removing 'lock enabled' attribute from a partition. + * + * Rev 1.81.1.6 Nov 12 2006 09:48:00 Yaniv.Iarovici + * Write default/customized delay cell configuration values in flWriteIPL(). + * + * Rev 1.81.1.5 Nov 01 2006 08:56:28 Yaniv.Iarovici + * Prevent leaving ALL existing partitions in flFlashFormat(). + * + * Rev 1.81.1.4 Oct 31 2006 14:00:52 yaniv.iarovici + * Prevent setting a NON-CHANGABLE partition to CHANGEABLE. + * + * Rev 1.81.1.3 Oct 30 2006 15:50:40 yaniv.iarovici + * Fixed comment for flFlashFormat(). + * + * Rev 1.81.1.2 Oct 29 2006 11:00:00 Yaniv.Iarovici + * 1. All HW protection related routines enabled in bdCall() + * (Removed '#ifdef HW_PROTECTION') + * 2. Added casting to (void*) on 'DEFAULT_KEY' when calling tffsAPISetIoreq(). + * + * Rev 1.81.1.1 Oct 25 2006 09:10:48 Yaniv.Iarovici + * 1. Declare TFFSIdentifyProtection(). + * 2. Remove '#ifdef FL_EXTENDED_DISK_INFO' from implementation of TFFSGetExtendedDiskInfo(). + * 3. Change comment in description of TFFSFlashFormat(). + * 4. In TFFSUnFormat() - Check that all partitions are authenticated before trying to unformat. + * 5. Remove '#ifdef HW_PROTECTION' from implementation of protection routines. + * 6. Allow setting Normal IPL mode when using 8KB window. + * 7. Allow removing the 'CHANGEABLE_PROTECTION' attribute from a partition. + * + * Rev 1.81.1.0 Oct 22 2006 14:54:14 yaniv.iarovici + * 1. Fixed compilation warnings. + * 2. Changed flRegisterDOCH3SOC()return type to FLStatus. + * + * Rev 1.81 Oct 09 2006 14:06:06 yaniv.iarovici + * 1. Fixed compilation errors when FL_RDA_ONLY is defined + * 2. Fix TrueFFS version in TFFSGetExtendedDiskInfo() + * + * Rev 1.80 Oct 05 2006 11:01:22 yaniv.iarovici + * 1. Modified debug prints. + * 2. Removed unnecessary use of #ifdef HW_OTP + * 3. Fixed wrong protection attribute returned by TFFSIdentifyProtection() + * for READ and WRITE protected partition. + * + * Rev 1.79 Sep 14 2006 09:56:50 yaniv.iarovici + * Set IPL partition as 'protectable' upon its creation. + * + * Rev 1.78 Sep 13 2006 10:30:46 yaniv.iarovici + * Fix compilation warnings + * + * Rev 1.77 Sep 11 2006 13:45:28 yaniv.iarovici + * Legal header added + * + * Rev 1.76 Sep 03 2006 14:45:22 Yaniv.Iarovici + * 1. Allow calling TFFSGetExtendedDiskInfo() without request for specific partition info. + * 2. Bug fix: In TFFSChangeProtectionType() - set dwLockControl correctly. + * + * Rev 1.75 Aug 24 2006 11:40:04 Yaniv.Iarovici + * Bug fix in TFFSGetExtendedDiskInfo() - wrong return code checked. + * + * Rev 1.74 Aug 22 2006 13:26:56 Yaniv.Iarovici + * Fix calculation of 'numOfBinaryParToLeave' when BDK_ACCESS is defined. + * + * Rev 1.73 Aug 17 2006 15:33:28 Yaniv.Iarovici + * Remove Joint Protection + * + * Rev 1.71 Aug 17 2006 15:20:18 Yaniv.Iarovici + * 1) Encapsulate Joint Protection code under '#ifdef FL_JOINT_PROTECTION' (NOT define by default!) + * 2) Fix Joint protection support for Read protected partitions. + * + * Rev 1.69 Aug 16 2006 08:48:26 Yaniv.Iarovici + * 1) Enable READ+Write protection: + * - tffsFormatSetProtectionAttribs() + * - TFFSChangeProtectionType() + * 2) TFFSflashFormat(): + * - Add /LEAVE support for BDTL partitions as well as BDK + * - Rename 'binParToLeave; to 'numOfParToLeave ' + * - Encasulate BDK related code by '#ifdef BDK_ACCESS' + * 3) Fix description for TFFSChangeProtectionType() + * 4) Encapsulate BDK related code under '#ifdef BDK_ACCESS'. + * 5) Change error code returned by 'TFFSChangeProtectionKey()' to flHWProtection. + * + * Rev 1.67 Aug 09 2006 17:27:40 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.66 Aug 09 2006 17:20:28 Polina.Marimont + * initial for DOC Driver 1.0, DPD fixes from branch 1.64... applied + * + * Rev 1.63 Jul 03 2006 22:13:56 polina.marimont + * 1. bug fix - protection with leave failed to format + * 2. bug fix - flags returned by identifyProtection on OTW protected partition + * + * Rev 1.62 Jun 28 2006 11:34:56 Polina.Marimont + * bug fix - TFFSGetUniqueID() shoudl be enabled / disabled by HW_OTP flag and not by FL_EXTENDED_DISK_INFO + * + * Rev 1.61 Jun 28 2006 10:36:00 Polina.Marimont + * bug fix - writeIPL() on non-first data chunk caused to wrong data to be written + * + * Rev 1.60 Jun 27 2006 15:53:26 Polina.Marimont + * bug fix flVolumeInfo() API return base address + * + * Rev 1.59 Jun 26 2006 11:05:22 Polina.Marimont + * added include to hib.h file + * + * Rev 1.58 Jun 22 2006 17:55:38 Polina.Marimont + * compilation warnings fixes + * + * Rev 1.57 Jun 22 2006 13:18:40 Polina.Marimont + * updated comments + * + * Rev 1.56 Jun 22 2006 09:36:46 Polina.Marimont + * error codes compatibility for extendedDiskInfo() + * + * Rev 1.55 Jun 22 2006 09:06:06 Polina.Marimont + * TFFSRemoveProtectionKey() error code compatibily fix + * + * Rev 1.54 Jun 21 2006 18:25:42 Polina.Marimont + * 1. enter/exit DPD function fix + * 2. change protection to OTW updated + * 3. identify prrotection updated + * + * Rev 1.53 Jun 20 2006 12:40:28 Polina.Marimont + * error codes for insert key and authenticate partition fixed to be compatible to non mDOC h3 devices + * + * Rev 1.52 Jun 18 2006 13:09:00 Polina.Marimont + * 1. error codes changed to be compatible to non mDOC H3 devices + * 2. macros definition usage update + * 3. AutoDPD and DPD parameters set changed, storage moved to SA SDK + * + * Rev 1.51 Jun 14 2006 17:59:48 Polina.Marimont + * 1. structure definitions moved to header file + * 2. special function added for set IOreq structure parameters + * 3. printing fixes + * 4. bug fix - flash lifetime indication fix + * 5. bug fix - number of volume on unformatted device (returns 1) + * 6. check BDTL size should not be equal to 0, while formatting + * 7. unformat - remove all, including OTP and IPL partitions from the device + * 8. wipe sectors usage restored + * 9. bdkWriteInit() added check for requested size exceeded subpartition size + * 10. bug fix - used unit on BDK subparition rounded to the low boundary + * 11. When EDGE interrupt configured - print warning and configure to LEVEL interrupt. + * + * Rev 1.50 May 31 2006 15:41:44 polina.marimont + * TrueFFS 7.1.0 EQA16 + * + * Rev 1.49 May 28 2006 14:50:30 polina.marimont + * fix for IDENTIFY DEVICE + * + * Rev 1.48 May 28 2006 13:03:10 polina.marimont + * update for IDENTIFY DEVICE change + * + * Rev 1.47 May 24 2006 14:57:26 polina.marimont + * bugfix - erase BDK subpartition always erases first unit of subpartition 0 + * + * Rev 1.46 May 24 2006 08:17:06 polina.marimont + * dochVol.intermediateBuf - free added to tffsApiExit() function + * + * Rev 1.45 May 24 2006 08:13:30 polina.marimont + * TFFSbdkPartitionInfo() - wrong handle received from ioreq. + * + * Rev 1.44 May 21 2006 18:06:44 polina.marimont + * compilation errors fix, when CHECK_BEFORE_EVERY_COMMAND defined + * + * Rev 1.43 May 18 2006 14:29:56 polina.marimont + * TFFSBdkPartitionInfo() fixed to return flBadDriveHandle, when wrong number of partition specified, using migration variable + * + * Rev 1.42 May 18 2006 09:47:06 polina.marimont + * 1. IOCTL fixed + * 2. used size set back to 0 + * + * Rev 1.41 May 17 2006 15:42:28 polina.marimont + * 1. Error codes are fixed up to Legacy + SA package + * 2. LOCK and CHANGABLE protection support + * 3. Format fixed - common functions used to add IPL and OTP partitions, also to set partition protection attributes + * 4. PassThrough implemented + * 5. bug fixes + * + * Rev 1.40 Apr 11 2006 13:21:34 tal.heller + * enable EraseBD API. + * Bug Fix - Last Partition size wasn't initialized. + * Fix CC compilation + * adapt SecureDelete ioreq implementation to DOCH + * Bug Fix - StickLock API + * Comments syntax errors. + * + * Rev 1.39 Mar 29 2006 16:39:50 DoronC + * Bug fix - compilation warnings ove various compilers. + * + * Rev 1.38 Mar 27 2006 16:21:58 DoronC + * Add DMA support. + * + * Rev 1.37 Mar 22 2006 17:35:46 DoronC + * Bug fix - add signature to disk attributes in order to use only + * format made by TrueFFS 7.1 and not by host SDK. + * Other format will force reformatting of the media. + * + * Rev 1.36 Mar 20 2006 17:21:58 DoronC + * Bug fix - read IPL using buffers failed. + * + * Rev 1.35 Mar 20 2006 10:41:16 DoronC + * Bug fix - protection change was not working. + * + * Rev 1.34 Mar 15 2006 16:17:54 DoronC + * Bug fix - wrong flag was checked when reading IPL. + * + * Rev 1.33 Mar 15 2006 15:58:04 DoronC + * Bug fix - change protection key caused an exception. + * + * Rev 1.32 Mar 15 2006 14:14:46 DoronC + * Bug fix - formating protected partition with no active protection failed. + * Bug fix - IPL flags were not checked. + * + * Rev 1.31 Mar 15 2006 11:28:16 DoronC + * Bug fix - IPL write was not working properly. + * Bug fix - BDK used size was faulty. + * + * Rev 1.30 Mar 14 2006 09:53:52 DoronC + * Bug fix - DOCFlash win field was not initialized by the init routine + * causing exception on some conditions. + * + * Rev 1.29 Mar 06 2006 08:40:52 DoronC + * Bug fix - protection identify was reported wrong. + * + * Rev 1.28 Mar 05 2006 15:52:24 DoronC + * Protection structure of H3 changed to contain dwords instead + * of words. + * + * Rev 1.27 Mar 02 2006 12:02:30 DoronC + * Bug fix - mount was checked for wrong number of partitions. + * + * Rev 1.26 Mar 02 2006 08:30:26 DoronC + * Host SDK API changed from IOreq2 to IOreq. + * + * Rev 1.25 Feb 16 2006 11:32:38 DoronC + * Store binary partition flags in the attributes and return then + * when requested by extendedInfo for computability with legacy + * devices. + * + * Rev 1.24 Feb 16 2006 10:02:40 DoronC + * Bug fix - Compilation warnings removed. + * Bug fix - Combining DPS between BDK and BDTL was not + * working properly during format. + * Bug fix - change protection key&type of combined DPS was not + * working. + * + * Rev 1.23 Feb 14 2006 10:50:02 DoronC + * Remove large variables from stack. use one global buffer for + * all large buffers needs. + */ + + +#include "flsystem.h" +#include "flcustom.h" +#include "defs.h" +#include "flbase.h" +#include "flstdcmp.h" + +#include "flsystyp.h" +#include "flchkdef.h" +#include "blockdev.h" +#include "_docsys.h" + +#include "hib.h" +#include "doch_ata.h" +#include "doch_api.h" +#include "bdkemul.h" +#include "tffs_api.h" +#include "doch_func.h" +#include "dochtl.h" + + +#define MAX_MOUNT_COUNT 100 /*100 Times...*/ +#define DOCH_NUM_OF_PLANES 1 +#define DOCH_NUM_OF_BANKS 1 +#define DOCH_SECTORS_PER_PAGE 4 +#define DOCH_SHARED_SECTORS 32 + +#define DOCH_CAPACITY_128MB 0x40000 /*In Sectors*/ +#define DOCH_CAPACITY_256MB 0x80000 /*In Sectors*/ +#define DOCH_CAPACITY_512MB 0x100000 /*In Sectors*/ +#define DOCH_CAPACITY_1GB 0x200000 /*In Sectors*/ +#define DOCH_CAPACITY_2GB 0x400000 /*In Sectors*/ +#define DOCH_CAPACITY_4GB 0x800000 /*In Sectors*/ +#define DOCH_CAPACITY_8GB 0x1000000 /*In Sectors*/ + +#define DOCH_UNIT_SIZE_256KB 0x40000 /*In Bytes*/ +#define DOCH_UNIT_SIZE_512KB 0x80000 /*In Bytes*/ +#define DOCH_UNIT_SIZE_1MB 0x100000 /*In Bytes*/ +#define DOCH_UNIT_SIZE_2MB 0x200000 /*In Bytes*/ +#define DOCH_UNIT_SIZE_4MB 0x400000 /*In Bytes*/ + +#define createIrHandle(socket, partition) ((socket) + ((partition) << 4)); + +/********************/ +/* Externs */ +/********************/ + +#ifdef __cplusplus +extern "C" { +#endif + +extern FLByte gIsDMAEnabled; /*DMA is Enabled/Disabled*/ +extern DOCH_DpdSettings gDpdSettings; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +extern FLByte gDeviceTurnedOff; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#ifdef __cplusplus +} +#endif + +/********************/ +/* Global Vars */ +/********************/ + +DocHVolume dochVol; +FLBoolean dochBdCallWasCalled = FALSE; +FLBoolean dochDpdInitialized = FALSE; + +#ifdef CHECK_POWER_ON_EVERY_COMMAND +#define TFFS_API_RET(rc)((rc==DOCH_DeviceTurnedOff) ? flSuspendModeDetected : flGeneralFailure) +#else /*CHECK_POWER_ON_EVERY_COMMAND*/ +#define TFFS_API_RET(rc) flGeneralFailure +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + +#define TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, dochStatus, flStatus){\ + DOCH_DeviceInfo * pDevInfo = (DOCH_DeviceInfo*)dochVol.intermediateBuf;\ + dochStatus = flDOCHIdentifyDiskOnChipDevice(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0,dochVol.intermediateBuf, 0,0));\ + if(dochStatus != DOCH_OK){\ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("flDOCHIdentifyDiskOnChipDevice failed with status: 0x%x "),dochStatus));\ + return (dochStatus==DOCH_DiskNotFound)? flUnknownMedia:TFFS_API_RET(dochStatus);}\ + dochVol.dwUnformattedCapacity = pDevInfo->dwUnformattedCapacity;\ + dochVol.dwVirtualUnitSizeInSectors = (pDevInfo->dwUnitSize!=0) ? pDevInfo->dwUnitSize : (dochVol.dwUnformattedCapacity>>9);\ + dochVol.dwVirtualUnitSize = ((dochVol.dwVirtualUnitSizeInSectors)<dwOtpEnabled = ((protectionType & CHANGEABLE_PROTECTION) && \ + (!(protectionType & SECTOR_LEVEL_PROTECTION))) ? TRUE : FALSE;\ + pPartitionFormatInfoAPI->dwPartitionType = DOCH_PRT_TYPE_NORMAL;\ + pPartitionFormatInfoAPI->dwPerformanceControl = DOCH_NORMAL_PERFORMANCE;\ + pPartitionFormatInfoAPI->dwPageSizeExp = DOCH_PAGE_SIZE_512B;\ + pPartitionFormatInfoAPI->dwHashType = DOCH_HASH_TYPE_SHA1;\ + pPartitionFormatInfoAPI->dwEncryptionType = DOCH_ENCRYPT_NONE;\ + pPartitionFormatInfoAPI->dwMasterControl = DOCH_PART_ACCESS_MODE_FULL;\ + pPartitionFormatInfoAPI->dwMaxNumOfAuthAttempts = DOCH_MAX_PWD_ATTEMPTS;\ + pPartitionFormatInfoAPI->bSOTP = FALSE; +#else /*FL_SLPP*/ + /*SOTP is supported and SLPP isn't*/ + #define TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, protectionType)\ + pPartitionFormatInfoAPI->dwOtpEnabled = (protectionType & CHANGEABLE_PROTECTION) ? TRUE : FALSE;\ + pPartitionFormatInfoAPI->dwPartitionType = DOCH_PRT_TYPE_NORMAL;\ + pPartitionFormatInfoAPI->dwPerformanceControl = DOCH_NORMAL_PERFORMANCE;\ + pPartitionFormatInfoAPI->dwPageSizeExp = DOCH_PAGE_SIZE_512B;\ + pPartitionFormatInfoAPI->dwHashType = DOCH_HASH_TYPE_SHA1;\ + pPartitionFormatInfoAPI->dwEncryptionType = DOCH_ENCRYPT_NONE;\ + pPartitionFormatInfoAPI->dwMasterControl = DOCH_PART_ACCESS_MODE_FULL;\ + pPartitionFormatInfoAPI->dwMaxNumOfAuthAttempts = DOCH_MAX_PWD_ATTEMPTS;\ + pPartitionFormatInfoAPI->bSOTP = FALSE; +#endif /*FL_SLPP*/ +#else /*FL_SOTP*/ +#ifdef FL_SLPP + /*SOTP is not supported and SLPP is supported*/ + #define TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, protectionType)\ + pPartitionFormatInfoAPI->dwOtpEnabled = ((protectionType & CHANGEABLE_PROTECTION) && \ + (!(protectionType & SECTOR_LEVEL_PROTECTION))) ? TRUE : FALSE;\ + pPartitionFormatInfoAPI->dwPartitionType = DOCH_PRT_TYPE_NORMAL;\ + pPartitionFormatInfoAPI->dwPerformanceControl = DOCH_NORMAL_PERFORMANCE;\ + pPartitionFormatInfoAPI->dwPageSizeExp = DOCH_PAGE_SIZE_512B;\ + pPartitionFormatInfoAPI->dwHashType = DOCH_HASH_TYPE_SHA1;\ + pPartitionFormatInfoAPI->dwEncryptionType = DOCH_ENCRYPT_NONE;\ + pPartitionFormatInfoAPI->dwMasterControl = DOCH_PART_ACCESS_MODE_FULL;\ + pPartitionFormatInfoAPI->dwMaxNumOfAuthAttempts = DOCH_MAX_PWD_ATTEMPTS; +#else /*FL_SLPP*/ + /*both SOTP and SLPP are not supported*/ + #define TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, protectionType)\ + pPartitionFormatInfoAPI->dwOtpEnabled = (protectionType & CHANGEABLE_PROTECTION) ? TRUE : FALSE;\ + pPartitionFormatInfoAPI->dwPartitionType = DOCH_PRT_TYPE_NORMAL;\ + pPartitionFormatInfoAPI->dwPerformanceControl = DOCH_NORMAL_PERFORMANCE;\ + pPartitionFormatInfoAPI->dwPageSizeExp = DOCH_PAGE_SIZE_512B;\ + pPartitionFormatInfoAPI->dwHashType = DOCH_HASH_TYPE_SHA1;\ + pPartitionFormatInfoAPI->dwEncryptionType = DOCH_ENCRYPT_NONE;\ + pPartitionFormatInfoAPI->dwMasterControl = DOCH_PART_ACCESS_MODE_FULL;\ + pPartitionFormatInfoAPI->dwMaxNumOfAuthAttempts = DOCH_MAX_PWD_ATTEMPTS; +#endif /*FL_SLPP*/ +#endif /*FL_SOTP*/ +/*********************/ +/* Static functions */ +/*********************/ +#ifndef FL_READ_ONLY +static FLStatus tffsApiAddOtpIPL(FLBoolean bIPL, IOreq * myIoreq, IOreq * ioreq); +static FLStatus tffsFormatSetProtectionAttribs(FLByte bProtType, DOCH_PartitionFormatInfoAPI* pPartitionFormatInfoAPI, FLByte * bKey, FLWord wKeyLen); +#endif /*FL_READ_ONLY*/ + +static FLStatus tffsApiAuthPartition(IOreq * myIoreq, IOreq * ioreq, FLByte bPartNo, FLByte * pKey, FLWord wKeyLen); +static IOreq* tffsAPISetIoreq(IOreq * pIoreq, FLHandle irHandle, FLDword irFlags, void* irPath, void * irData, FLSDword irLength, FLSDword irCount); + +static FLStatus TFFSIdentifyProtection(IOreq* ioreq); + +/*----------------------------------------------------------------------*/ +/* Function name : actualPartitionNum*/ +/* Description : */ +/* Return type : FLStatus */ +/* Argument : FLByte* partNum*/ +/* Argument : FLByte partitionType*/ +/*----------------------------------------------------------------------*/ +FLStatus actualPartitionNum(FLByte* partNum, FLByte partitionType, FLSDword sdwSocketNo) +{ + DOCH_Socket* pDev; + + DOCH_get_socket(pDev, sdwSocketNo); + if( pDev==NULL ) + return flBadParameter; + + switch(partitionType) + { + case PARTITION_TYPE_IPL: + break; + + case PARTITION_TYPE_BDTL: + *partNum += (dochVol.numOfBinaryPartitions + (dochVol.iplExists + dochVol.otpExists)); + break; + + case PARTITION_TYPE_BINARY: +#ifdef BDK_ACCESS + *partNum += (dochVol.iplExists + dochVol.otpExists); + break; +#else /*BDK_ACCESS*/ + return flPartitionNotFound; +#endif /*BDK_ACCESS*/ + + case PARTITION_TYPE_OTP: + break; + + default: + break; + } + + if( (*partNum) == 0 ) + return flOK; + + if( ((*partNum) >= DOCH_MAX_PARTITIONS) || ((*partNum) >=pDev->wTotalNumOfPartitions) ) + return flPartitionNotFound; + + return flOK; +}/*actualPartitionNum()*/ + + +/*----------------------------------------------------------------------*/ +/* T F F S E x t e n d e d G e t D i s k I n f o */ +/* */ +/* Returns general information about the Device and a specific partition */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Must be set to 0 */ +/* bits 3-0 - Socket # (zero based) */ +/* irCount : Partition number */ +/* irFlags : Either FL_BDK_PARTITION or FL_DISK_PARTITION */ +/* irData : Address of FLExtendedDiskInfo structure */ +/* irLength : Floor number to access - FL_ALL_FLOORS */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSGetExtendedDiskInfo(IOreq* ioreq) +{ + DOCH_Error rc; + FLStatus flStatus = flOK; + DOCH_Error specificPartRC = DOCH_PartitionNotFound; + DOCH_Error iplRC = DOCH_PartitionNotFound; + IOreq myIoreq; + FLExtendedDiskInfo FAR1 * info = (FLExtendedDiskInfo FAR1 *)ioreq->irData; + FLDword dwIPLSize; + FLByte bNumOfBinaryPartitions, partition; + FLWord wTotalNumOfPartitions; + FLDword dwPartitionFlags = 0; + DOCH_DeviceInfo * pDochDevInfo = (DOCH_DeviceInfo*)dochVol.intermediateBuf; + DOCH_DiskUserAttrWithBinary * pDiskUserAttrWithBinary = (DOCH_DiskUserAttrWithBinary*)dochVol.intermediateBuf; + DOCH_PartitionUserAttrWithBinary* pPartUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + DOCH_Socket * pDev; + + DOCH_get_socket(pDev, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + + + /*Retrieve DOCH extended info structure*/ + /*-------------------------------------*/ + rc = flDOCHIdentifyDiskOnChipDevice(tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetExtendedDiskInfo(): flDOCHIdentifyDiskOnChipDevice failed with status: %d "), rc)); + return (rc==DOCH_DiskNotFound)? flUnknownMedia:TFFS_API_RET(rc); + } + + TFFS_API_GET_UNIT_SIZE(myIoreq,ioreq, rc, flStatus); + + wTotalNumOfPartitions = pDochDevInfo->wTotalNumOfPartitions; + + /* Retrieve Disk User Attributes */ + /*-------------------------------*/ + rc = flDOCHGetDiskUserAttributes(tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetExtendedDiskInfo(): flDOCHGetDiskUserAttributes failed with status: 0x%x "),rc)); + return (rc==DOCH_ProtectionFault)?flHWProtection:flBadFormat; /* if not protected -> like media header not found */ + } + + /* Check if device is not formatted */ + if( (! pDiskUserAttrWithBinary->bIplPresent) && (! pDiskUserAttrWithBinary->bOtpPresent) ) + { + /*Fill only relevant fields*/ + info->dwTLType = 0; + info->dwFormatFlags = 0; + info->dwTrueFFSVersion = 0; + info->dwFlashTechnology = 0; + info->dwType = FL_H3; + info->dwSubType = 0; + info->bMediaType = 0; + info->bNoOfFloors = (FLByte)pDev->wNumOfDevices; + info->bNoOfPlanes = DOCH_NUM_OF_PLANES; + info->bNoOfBanks = DOCH_NUM_OF_BANKS; + info->bDataBusWidth = 16; /*DOCH always uses 16bit*/ + info->bSectorsPerPage = DOCH_SECTORS_PER_PAGE; + info->bSharedSectors = DOCH_SHARED_SECTORS; + info->bFastAreaSharedSectors = 0; + info->bMaxRelatedSectors = 0; + info->dwIPLSize = 0; + info->bChangeableProtectedAreas = 0; + info->btotalProtectedAreas = 0; + info->dwUnitsInFirstFloor = 0; + info->dwUnitSize = dochVol.dwVirtualUnitSize; + info->dwMaxBadPercentage = 0; + + info->bNoOfBinaryPartitions = 0; + info->bNoOfDiskPartitions = 0; + info->bBlockMultiplierBits = 0; + info->dwPercentUsed = 0; + info->bHeaderUnits = 0; + info->wHeaderLocation = 0; + + /* Programmer name and version strings */ + /* Retrieve from disk attributes*/ + tffscpy(info->bProgrammerNamePtr, pDiskUserAttrWithBinary->bProgrammerName, sizeof(FLDword)); + tffscpy(info->bProgrammerVersionPtr, pDiskUserAttrWithBinary->bProgrammerVersion, sizeof(FLDword)); + info->dwTrueFFSVersion = 0; + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): device NOT formatted \r\n"); + return flBadFormat; + } + wTotalNumOfPartitions = wTotalNumOfPartitions - pDiskUserAttrWithBinary->bIplPresent - + pDiskUserAttrWithBinary->bOtpPresent; + bNumOfBinaryPartitions = pDiskUserAttrWithBinary->bNumOfBinaryPartitions; + + /* Programmer name and version strings */ + tffscpy(&info->bProgrammerNamePtr[0], pDiskUserAttrWithBinary->bProgrammerName, + sizeof(pDiskUserAttrWithBinary->bProgrammerName)); + tffscpy(&info->bProgrammerVersionPtr[0], pDiskUserAttrWithBinary->bProgrammerVersion, + sizeof(pDiskUserAttrWithBinary->bProgrammerVersion)); + + info->dwTrueFFSVersion = + (((pDiskUserAttrWithBinary->bTFFSVersion[0] - 0x30)*1000) + + ((pDiskUserAttrWithBinary->bTFFSVersion[1] - 0x30)*100 ) + + ((pDiskUserAttrWithBinary->bTFFSVersion[2] - 0x30)*10 ) + + (pDiskUserAttrWithBinary->bTFFSVersion[3] - 0x30)); + + /*Retrieve IPL partition size*/ + /*---------------------------*/ + iplRC = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq) + (DOCH_IPL_PARTITION_NUM << 4), + 0,0,dochVol.intermediateBuf,0,0)); + if(iplRC != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetExtendedDiskInfo(): flDOCHPartitionInfo of IPL partition failed with status: 0x%x "), rc)); + return (iplRC==DOCH_ProtectionFault)?flHWProtection:flBadFormat; /* if not protected, but fails -> like bad format */ + } + dwIPLSize = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize << DOCH_SECTOR_SIZE_BITS; + + /* Fill FLExtendedDiskInfo structure */ + /*--------------------------------------*/ + + /******************************************/ + /* Fields that belong to the entire media */ + /******************************************/ + info->dwTLType = 0; + info->dwFormatFlags = 0; + + info->dwFlashTechnology = 0; + info->dwType = FL_H3; + info->dwSubType = 0; + info->bMediaType = 0; + info->bNoOfFloors = (FLByte)pDev->wNumOfDevices; + info->bNoOfPlanes = DOCH_NUM_OF_PLANES; + info->bNoOfBanks = DOCH_NUM_OF_BANKS; + info->bDataBusWidth = 16; /*DOCH always uses 16bit*/ + info->bSectorsPerPage = DOCH_SECTORS_PER_PAGE; + info->bSharedSectors = DOCH_SHARED_SECTORS; + info->bFastAreaSharedSectors = 0; + info->bMaxRelatedSectors = 0; + info->dwIPLSize = dwIPLSize; + info->bChangeableProtectedAreas = 2; + info->btotalProtectedAreas = 2; + info->dwUnitsInFirstFloor = 0; + info->dwUnitSize = dochVol.dwVirtualUnitSize; + info->dwMaxBadPercentage = 0; + + info->bNoOfBinaryPartitions = bNumOfBinaryPartitions; + info->bNoOfDiskPartitions = wTotalNumOfPartitions - bNumOfBinaryPartitions; + info->bBlockMultiplierBits = 0; + info->dwPercentUsed = 0; + info->bHeaderUnits = 0; + info->wHeaderLocation = 0; + + + /*Retrieve specific partition info + Note that the specific partition is always a BDTL partition + Hence jumping over IPL/OTP/Binary Partition + -------------------------------------------*/ + partition = (FLByte)ioreq->irCount; + if(partition != FL_EXT_INFO_NO_SPEC_PART) + { + if(ioreq->irFlags == FL_DISK_PARTITION) + flStatus = actualPartitionNum(&partition, PARTITION_TYPE_BDTL, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + else if(ioreq->irFlags == FL_BDK_PARTITION) + { + #ifdef BDK_ACCESS + flStatus = actualPartitionNum(&partition, PARTITION_TYPE_BINARY, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + #else /*BDK_ACCESS*/ + return flPartitionNotFound; + #endif /*BDK_ACCESS*/ + } + if( flStatus!=flOK ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): specific partition NOT FOUND \r\n"); + return flStatus; + } + + specificPartRC = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (partition << 4), + 0,0,dochVol.intermediateBuf,0,0)); + if(specificPartRC != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): specific partition NOT FOUND \r\n"); + return (specificPartRC==DOCH_ProtectionFault)? flHWProtection : flBadDriveHandle; + } + if ((ioreq->irFlags == FL_DISK_PARTITION) && (pPartUserAttrWithBinary->bType != PARTITION_TYPE_BDTL)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): Partition is not BDTL partition. \r\n"); + return flGeneralFailure; + } + + #ifdef BDK_ACCESS + if ((ioreq->irFlags == FL_BDK_PARTITION) && (pPartUserAttrWithBinary->bType != PARTITION_TYPE_BINARY)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): Partition is not BDK partition. \r\n"); + return flGeneralFailure; + } + + if( pPartUserAttrWithBinary->bType == PARTITION_TYPE_BINARY ) + dwPartitionFlags = pPartUserAttrWithBinary->binPartHeader.dwPartitionFlags; + #endif /*BDK_ACCESS*/ + + specificPartRC = flDOCHPartitionInfo(tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (partition << 4), + 0, 0, dochVol.intermediateBuf, 0, 0)); + /* Check if partition exists */ + if(specificPartRC == DOCH_PartitionNotFound) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSGetExtendedDiskInfo(): specific partition NOT FOUND \r\n"); + return flBadDriveHandle; + } + /************************************************/ + /* Fields that belong to the specific partition */ + /************************************************/ + if(specificPartRC == DOCH_OK) + { + DOCH_PartitionInfo* pPartInfo = (DOCH_PartitionInfo*)dochVol.intermediateBuf; + info->wHeaderLocation = 0; + info->dwVirtualUnits = pPartInfo->nPartitionSize/dochVol.dwVirtualUnitSizeInSectors; + info->dwNormalAreaUnitSize = dochVol.dwVirtualUnitSize; + if(ioreq->irFlags == FL_DISK_PARTITION) + { + info->dwFastAreaVirtualFactor = pPartInfo->wFastAreaFactor; + info->dwFastAreaLogicalUnitSize = dochVol.dwVirtualUnitSize / (1<wFastAreaFactor); + info->dwFastUnits = pPartInfo->nFastAreaSize / (info->dwFastAreaLogicalUnitSize>>DOCH_SECTOR_SIZE_BITS); + } + else + {/* binary partition */ + #ifdef BDK_ACCESS + info->dwFastAreaVirtualFactor = 0; + info->dwFastAreaLogicalUnitSize = 0; + info->dwFastUnits = 0; + #else /*BDK_ACCESS*/ + return flPartitionNotFound; + #endif /*BDK_ACCESS*/ + } + info->dwFirstUnit = 0; + info->dwLastUnit = info->dwVirtualUnits; + info->dwPartitionFlags = dwPartitionFlags; + info->dwFirstQuickMountUnit = 0; + info->dwSpareUnits = 0; + info->dwTransferUnits = 0; + + + info->bMinSectorsForFolding = 0; + info->bMinSectorsForNextWrite = 0; + info->bfastAreaMinSectorsForNextWrite = 0; + + /******************************************/ + /* Fields that are valid only after mount */ + /******************************************/ + info->dwUsedUnits = 0; + info->dwFreeUnits = 0; + info->bNeededFreeUnits = 0; + info->dwUMDBBTSector = 0; + } + else + return TFFS_API_RET(specificPartRC); + + }/*end of if(partition != FL_EXT_INFO_NO_SPEC_PART)*/ + + return flOK; +}/*TFFSGetExtendedDiskInfo()*/ + + +/*----------------------------------------------------------------------*/ +/* T F F S V o l u m e I n f o */ +/* */ +/* Get general information about the media. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of user buffer to read general */ +/* information into. */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irFlags : SECTOR_LEVEL_PROTECTION if the partition is */ +/* defined as SLPP */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSVolumeInfo(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + VolumeInfoRecord FAR1 * volumeInfo = (VolumeInfoRecord FAR1 *)ioreq->irData; + FLDword dwPartitionSize; + + /*Retrieve specific partition info*/ + /*--------------------------------*/ + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSVolumeInfo(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flBadDriveHandle : TFFS_API_RET(rc)); + } + dwPartitionSize = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize; + +#ifdef FL_SLPP + /* Is the partition SLPP?*/ + if(((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2 & DOCH_PA2B_PROTECTION_TYPE) >> DOCH_PA2O_PROTECTION_TYPE) + == DOCH_PARTITION_SLPP_PROTECTED) + ioreq->irFlags = SECTOR_LEVEL_PROTECTION; + else + ioreq->irFlags = 0; +#endif /*FL_SLPP*/ + + /*Retrieve DOCH extended info structure and calculate unit number if required */ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /* Fill VolumeInfoRecord structure */ + /*----------------------------------*/ + /*Media Geometry*/ + flBuildGeometry( dwPartitionSize, &volumeInfo->cylinders, + &volumeInfo->heads, &volumeInfo->sectors, + FALSE, (FLWord)ioreq->irHandle); + + volumeInfo->logicalSectors = dwPartitionSize; + volumeInfo->bootAreaSize = 0; + /* Return window base reg */ + /*------------------------*/ + tffsAPISetIoreq( &myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,0,0,0); + rc=flDOCHGetPhysicalAddress(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetPhysicalInfo(): DOCHGetPhysicalAddress failed with status: 0x%x "), rc)); + return (DOCH_DiskNotFound==rc) ? flAdapterNotFound : TFFS_API_RET(rc); + } + volumeInfo->baseAddress = myIoreq.irCount; + +#ifdef FL_LOW_LEVEL + volumeInfo->flashType = FL_H3; + volumeInfo->dwPhysicalUnitSize = dochVol.dwVirtualUnitSizeInSectors; + volumeInfo->dwPhysicalSize = dochVol.dwUnformattedCapacity; + volumeInfo->DOCType = FL_H3; + volumeInfo->lifeTime= 1; /*1 - indicates fresh media*/ +#endif /*FL_LOW_LEVEL*/ + + tffsset(volumeInfo->driverVer,0,sizeof(volumeInfo->driverVer)); + tffscpy(volumeInfo->driverVer,driverVersion, + TFFSMIN(sizeof(volumeInfo->driverVer),sizeof(driverVersion))); + + tffsset(volumeInfo->OSAKVer,0,sizeof(volumeInfo->OSAKVer)); + tffscpy(volumeInfo->OSAKVer, OSAKVersion, + TFFSMIN(sizeof(volumeInfo->OSAKVer),sizeof(OSAKVersion))); + + return flOK; +}/*TFFSVolumeInfo()*/ + +/*----------------------------------------------------------------------*/ +/* T F F S C o u n t V o l u m e s */ +/* */ +/* Counts the number of volumes on the Flash device. */ +/* */ +/* Not all the volumes necessarily need to be mounted. A drive formated */ +/* with a read protection will be registered but can not be accessed. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* : Partition number ( 0,1,2... ) */ +/* */ +/* Returns: */ +/* irFlags : Number of partitions */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSCountVolumes(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_GeneralFailure; + + IOreq myIoreq; + FLByte bNumOfPartition; + DOCH_DiskUserAttrWithBinary * pDiskUserAttrWithBinary = (DOCH_DiskUserAttrWithBinary *)(dochVol.intermediateBuf); + + /*Retrieve DOCH global info structure*/ + /*-------------------------------------*/ + rc = flDOCHIdentifyDiskOnChipDevice(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), + 0,0,dochVol.intermediateBuf, 0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSCountVolumes(): flDOCHIdentifyDiskOnChipDevice failed with status: 0x%x "), rc)); + return (rc==DOCH_DiskNotFound)? flUnknownMedia : TFFS_API_RET(rc); + } + bNumOfPartition = (FLByte)((DOCH_DeviceInfo*)dochVol.intermediateBuf)->wTotalNumOfPartitions; + + /*Retrieve disk attributes*/ + rc = flDOCHGetDiskUserAttributes(tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, + dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSCountVolumes(): flDOCHGetDiskUserAttributes failed with status: 0x%x"), rc)); + return (rc==DOCH_ProtectionFault)?flHWProtection:TFFS_API_RET(rc); + } + bNumOfPartition = bNumOfPartition - pDiskUserAttrWithBinary->bIplPresent - + pDiskUserAttrWithBinary->bOtpPresent - pDiskUserAttrWithBinary->bNumOfBinaryPartitions; + + /*Extract # of partitions from Extended Info*/ + /*------------------------------------------*/ + ioreq->irFlags = bNumOfPartition; + + /* fix number of partitions - unformatted device should return 1*/ + if( (pDiskUserAttrWithBinary->bNumOfBinaryPartitions==0) && + (bNumOfPartition==0) ) + { + ioreq->irFlags = 1; + } + return flOK; +}/* TFFSCountVolumes() */ + + +/*----------------------------------------------------------------------*/ +/* f l S e c t o r s I n V o l u m e */ +/* */ +/* Returns number of virtual sectors in volume. */ +/* */ +/* In case the inserted volume is not mounted, returns current status. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irLength : number of virtual sectors in volume */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSectorsInVolume(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + + + /*Retrieve specific partition info*/ + /*--------------------------------*/ + myIoreq.irHandle = ioreq->irHandle; + myIoreq.irData = dochVol.intermediateBuf; + + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSectorsInVolume(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flBadDriveHandle : TFFS_API_RET(rc)); + } + + ioreq->irLength = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize; + return flOK; +}/* TFFSSectorsInVolume */ + +#ifndef FL_NO_QUICK_MOUNT_FEATURE +/*----------------------------------------------------------------------*/ +/* */ +/* Quick mount routines are Obsoleted for DOCH */ +/* */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSClearQuickMountInfo(IOreq* ioreq) +{ + return flOK; +}/*TFFSClearQuickMountInfo*/ + +static FLStatus TFFSWriteQuickMountInfo(IOreq* ioreq) +{ + return flOK; +}/*TFFSWriteQuickMountInfo*/ + +static FLStatus TFFSGetQuickMountStatus(IOreq* ioreq) +{ + ioreq->irFlags = FL_ON; + return flOK; +}/*TFFSGetQuickMountStatus*/ + +#endif /* FL_NO_QUICK_MOUNT_FEATURE */ + +/********************************************************/ +/* */ +/* Mount related routines are obsolete for DOCH */ +/* Maintained in API only for backward compatibility */ +/* */ +/********************************************************/ +static FLStatus TFFSAbsMountVolume(IOreq* ioreq) +{ + FLByte partition; + FLStatus flStatus; + IOreq myIoreq; + DOCH_Error rc; + DOCH_DiskUserAttrWithBinary* pDiskUserAttr = (DOCH_DiskUserAttrWithBinary*) dochVol.intermediateBuf; + + partition = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = ioreq->irHandle; + myIoreq.irData = dochVol.intermediateBuf; + rc = flDOCHGetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsMountVolume(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + /*Get some data from disk attributes sector*/ + if ((tffscmp(pDiskUserAttr->bMigrationSignature, + TFFS_API_MIGRATION_SIGNATURE, + sizeof(pDiskUserAttr->bMigrationSignature)) != 0) + || (!pDiskUserAttr->bIplPresent) + || (!pDiskUserAttr->bOtpPresent)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSAbsMountVolume(): Device is not formated with TrueFFS. Either reformat the device or run upgrade utility.\n"); + return flBadFormat; + } + + /* check whether format with DD 1.1 beta or upper*/ + if (tffscmp(pDiskUserAttr->bFormatStartSignature, + TFFS_API_FORMAT_START_SIGNATURE, + sizeof(pDiskUserAttr->bFormatStartSignature)) == 0) + { + if (tffscmp(pDiskUserAttr->bFormatCompleteSignature, + TFFS_API_FORMAT_COMPLETE_SIGNATURE, + sizeof(pDiskUserAttr->bFormatCompleteSignature)) != 0) + { + DBG_PRINT_ERR(FLZONE_API,"TFFSAbsMountVolume(): No format completion signature \n"); + return flBadFormat; + } + }else + { /* Format with earlier versions*/ + /* retrieve last partition number*/ + FLByte bLastPartition; + rc = flDOCHIdentifyDiskOnChipDevice(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), + 0,0,dochVol.intermediateBuf, 0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsMountVolume(): flDOCHIdentifyDiskOnChipDevice failed with status: 0x%x \n"), rc)); + return (rc==DOCH_DiskNotFound)? flUnknownMedia : TFFS_API_RET(rc); + } + bLastPartition = (FLByte)((DOCH_DeviceInfo*)dochVol.intermediateBuf)->wTotalNumOfPartitions -1; + + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (bLastPartition << 4), 0,0, dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if((rc != DOCH_OK && rc!=DOCH_ProtectionFault) ||(rc==DOCH_ProtectionFault && bLastPartition==partition)) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsMountVolume(): flDOCHGetParitionUserAttributes failed with status: 0x%x \n"), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + /* no failure if last partition is hidden and we try to mount different partition*/ + } + + if (rc!=DOCH_ProtectionFault) + { /* if last partition is not hidden we can check format completeness*/ + if ((FLByte)((DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf)->bType != PARTITION_TYPE_BDTL) + { + DBG_PRINT_ERR(FLZONE_API,"TFFSAbsMountVolume(): No format completion indication on last partition \n"); + return flBadFormat; + } + } + } + + flStatus = dochMountTL(partition, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + if (flStatus == flOK) + { + if(dochVol.mountCount[partition] < 0x64) + dochVol.mountCount[partition]++; + } + return flStatus; +}/*TFFSAbsMountVolume*/ + +static FLStatus TFFSAbsDismountVolume(IOreq* ioreq) +{ + FLByte partition; + FLStatus rc; + partition = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + if(dochVol.mountCount[partition] == 0) + { + return flNotMounted; + } + + if(dochVol.mountCount[partition] > 0) + { + rc = dochDismountTL(partition); + if (rc == flOK) + { + dochVol.mountCount[partition]--; + } + } + else + rc = flNotMounted; + return rc; +}/*TFFSAbsDismountVolume*/ + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSCheckVolume*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSCheckVolume(IOreq* ioreq) +{ + FLStatus flStatus; + if(dochVol.mountCount[FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq)] > 0) + flStatus = flOK; + else + flStatus = flNotMounted; + return flStatus; +}/*TFFSCheckVolume*/ + +#ifndef FL_READ_ONLY +/*----------------------------------------------------------------------*/ +/* T F F S D e f r a g m e n t V o l u m e */ +/* */ +/* Performs a general defragmentation and recycling of non-writable */ +/* Flash areas, to achieve optimal write speed. */ +/* */ +/* NOTE: The required number of sectors (in irLength) may be changed */ +/* (from another execution thread) while defragmentation is active. In */ +/* particular, the defragmentation may be cut short after it began by */ +/* modifying the irLength field to 0. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irLength : Minimum number of sectors to make available for */ +/* writes. */ +/* */ +/* Returns: */ +/* irLength : Actual number of sectors available for writes */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSDefragmentVolume(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLSDword request = ioreq->irLength; + + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + /*Return values*/ + /*=============*/ + switch(request) + { + case FL_MINIMAL_DEFRAGMENTATION: + case FL_MAXIMUM_DEFRAGMENTATION: + ioreq->irLength = dochVol.dwVirtualUnitSizeInSectors; + return flNotEnoughMemory; + + case FL_STATIC_WEAR_LEVELING_DELAYED: + case FL_STATIC_WEAR_LEVELING_NOW: + case FL_STATIC_WEAR_LEVELING_ON: + case FL_STATIC_WEAR_LEVELING_OFF: + ioreq->irLength = dochVol.dwVirtualUnitSizeInSectors; + break; + + default: + if(request > 0) + ioreq->irLength = dochVol.dwVirtualUnitSizeInSectors; + else + { + if(request == 0) + ioreq->irLength = 0; + else + return flBadParameter; + } + return flNotEnoughMemory; + } + return flOK; +}/*TFFSDefragmentVolume()*/ + + + + + +/*********************************************************/ +/* Function name : tffsFormatSetProtectionAttribs*/ +/* Description : */ +/* Return type : FLStatus */ +/* Argument : FLByte bProtType*/ +/* Argument : DOCH_PartitionFormatInfoAPI* pPartitionFormatInfoAPI*/ +/* Argument : FLByte * bKey*/ +/* Argument : FLWord wKeyLen*/ +/*********************************************************/ +static FLStatus tffsFormatSetProtectionAttribs( FLByte bProtType, DOCH_PartitionFormatInfoAPI* pPartitionFormatInfoAPI, + FLByte * pKey, FLWord wKeyLen) +{ + FLBoolean read_protect, write_protect, change_protect, locked; +#ifdef FL_SLPP + FLBoolean slpp =FALSE; +#endif /*FL_SLPP*/ +#ifdef FL_SOTP + FLBoolean sotp =FALSE; +#endif /*FL_SOTP*/ + + read_protect = write_protect = change_protect = locked = FALSE; + /*Enabled Protections*/ + + if( (bProtType & READ_PROTECTED) == READ_PROTECTED) + read_protect = TRUE; + if( (bProtType & WRITE_PROTECTED) == WRITE_PROTECTED) + write_protect = TRUE; + if( (bProtType & CHANGEABLE_PROTECTION) == CHANGEABLE_PROTECTION) + change_protect = TRUE; + if( (bProtType & LOCK_ENABLED) == LOCK_ENABLED) + locked = TRUE; +#ifdef FL_SLPP + if ((bProtType & SECTOR_LEVEL_PROTECTION) == SECTOR_LEVEL_PROTECTION) + slpp=TRUE; +#endif /*FL_SLPP*/ +#ifdef FL_SOTP + if ((bProtType & FORMAT_SEQUENTIAL_OTP)==FORMAT_SEQUENTIAL_OTP) + sotp=TRUE; + + if (sotp) + { + pPartitionFormatInfoAPI->bSOTP =TRUE; + pPartitionFormatInfoAPI->dwOtpEnabled =TRUE; + change_protect =TRUE; /* lock of SOTP is performed later on and is not allowed if not changeable*/ + } +#endif /*FL_SOTP*/ + + /*Protection requested*/ + if(read_protect || write_protect) + { + pPartitionFormatInfoAPI->dwProtectionType = DOCH_PARTITION_PWD_PROTECTED; + + /*Specific protection*/ + if(read_protect) + { + pPartitionFormatInfoAPI->dwGuestAccessMode = DOCH_PART_ACCESS_MODE_NONE; + } + else /*write_protect*/ + { + pPartitionFormatInfoAPI->dwGuestAccessMode = DOCH_PART_ACCESS_MODE_RO; + } + } + else + { +#ifdef FL_SLPP + /*SLPP partition*/ + if(slpp) + pPartitionFormatInfoAPI->dwProtectionType = DOCH_PARTITION_SLPP_PROTECTED; + /*No protection requested or changeable protection only requested */ + else +#endif /*FL_SLPP*/ + pPartitionFormatInfoAPI->dwProtectionType = (change_protect!=FALSE)?DOCH_PARTITION_PWD_PROTECTED:DOCH_PARTITION_NOT_PROTECTED; + + pPartitionFormatInfoAPI->dwUserAccessMode = DOCH_PART_ACCESS_MODE_FULL; + pPartitionFormatInfoAPI->dwGuestAccessMode = DOCH_PART_ACCESS_MODE_FULL; + } + + /* lock notification */ + pPartitionFormatInfoAPI->dwLockControl = (locked==TRUE) ? DOCH_LOCK_ACTIVE : DOCH_LOCK_NOT_ACTIVE; + + /*Passkey*/ +#ifndef FL_SLPP + if(read_protect || write_protect || change_protect) +#else /*FL_SLPP*/ + if(read_protect || write_protect || change_protect||slpp) +#endif /*FL_SLPP*/ + { + tffscpy(pPartitionFormatInfoAPI->bPasskey, pKey, wKeyLen); + } + + + + return flOK; +}/*tffsFormatSetProtectionAttribs*/ + +#ifdef FL_FORMAT_VOLUME +/*----------------------------------------------------------------------*/ +/* T F F S F l a s h F o r m a t */ +/* */ +/* Performs formatting of the DiskOnChip. */ +/* All existing data is destroyed. */ +/* */ +/* Note : This routine is the format routine for OSAK 5.0 and up. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* Partition number must be 0 */ +/* irFlags : */ +/* TL_NORMAL_FORMAT : Normal format */ +/* TL_LEAVE_SOME_PARTITIONS : Leave some of the previously */ +/* existing partitions */ +/* TL_DO_NOT_PERFORM_DOWNLOAD */ +/* irData : Address of FormatParams3 structure to use */ +/* (defined in format.h) */ +/* irLength : If the TL_LEAVE_SOME_PARTITIONS flag is set, */ +/* this field will indicate the number of partitions */ +/* to leave. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSflashFormat(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + FLStatus myStatus; + IOreq myIoreq; + FLSNative i=0; + FLByte partNum=0, numOfBinaryPartitions; + +#ifdef BDK_ACCESS + FLByte totalNumOfPartitions; +#endif /*BDK_ACCESS*/ + + FormatParams3 FAR1 * FP3 = (FormatParams3 FAR1 *)ioreq->irData; + BDTLPartitionFormatParams3 FAR2 * bdtlUserParams; + +#ifdef BDK_ACCESS + BinaryPartitionFormatParams3 FAR2 * binUserParams; + FLSNative numOfBinaryParToLeave = 0; +#endif /*BDK_ACCESS*/ + + FLSNative total_num_of_partitions = (FP3->noOfBinaryPartitions + FP3->noOfBDTLPartitions); + FLSNative numOfParToLeave = 0; + FLByte bOtpPresent, bIplPresent; + FLWord lastRemainingPartition, wNumOfOriginalPartitions; + + FLByte* intBuf = dochVol.intermediateBuf; + DOCH_DiskUserAttrWithBinary* pDiskUserAttrWithBinary = (DOCH_DiskUserAttrWithBinary*)intBuf; + DOCH_PartitionUserAttrWithBinary* pPartitionUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)intBuf; + DOCH_PartitionFormatInfoAPI* pPartitionFormatInfoAPI = (DOCH_PartitionFormatInfoAPI*)intBuf; + DOCH_Socket* pDev; + +#ifdef BDK_ACCESS + FLDword dwPartitionTotalSize; +#endif /*BDK_ACCESS*/ + + DOCH_get_socket(pDev, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + if( pDev==NULL ) + return flBadParameter; + + /*If binary partitions requested and no BDK support - return error*/ +#ifndef BDK_ACCESS + if(FP3->noOfBinaryPartitions > 0) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): Binary partitions not supported when BDK_ACCESS Not Defined!\r\n"))); + return flBadParameter; + } +#endif /*BDK_ACCESS*/ + + /*Retrieve disk attributes*/ + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + myIoreq.irData = intBuf; + rc = flDOCHGetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + + /* Get some data from disk attributes sector */ + numOfBinaryPartitions = pDiskUserAttrWithBinary->bNumOfBinaryPartitions; + bIplPresent = pDiskUserAttrWithBinary->bIplPresent; + bOtpPresent = pDiskUserAttrWithBinary->bOtpPresent; + +#ifdef BDK_ACCESS + totalNumOfPartitions = (FLByte)pDev->wTotalNumOfPartitions; +#endif /*BDK_ACCESS*/ + + /* check for corruption during format or wrong format */ + /* wrong signature */ + if( (tffscmp(pDiskUserAttrWithBinary->bMigrationSignature, TFFS_API_MIGRATION_SIGNATURE, + sizeof(pDiskUserAttrWithBinary->bMigrationSignature)) != 0) + /* disk attributes not match no. of partitions */ + || (pDev->wTotalNumOfPartitions<2 && bIplPresent && bOtpPresent) + /* there are enough partitions but IPL or/and OTP indication corrupted */ + || (pDev->wTotalNumOfPartitions>2 && (bIplPresent!=1 || bOtpPresent!=1)) ) + { + bIplPresent = 0; + bOtpPresent = 0; + numOfBinaryPartitions = 0; + } + +#ifdef BDK_ACCESS + /*Calculate how many binary partition to LEAVE*/ + if(ioreq->irFlags == TL_LEAVE_BINARY_AREA) + { + numOfParToLeave = numOfBinaryPartitions; + numOfBinaryParToLeave = numOfBinaryPartitions; + } + else + { + if(ioreq->irFlags == TL_LEAVE_SOME_BINARY_AREA) + { + numOfParToLeave = ioreq->irLength; + numOfBinaryParToLeave = TFFSMIN(numOfBinaryPartitions, numOfParToLeave); + } + else + { + numOfParToLeave = 0; + numOfBinaryParToLeave = 0; + } + } + + if(numOfParToLeave > totalNumOfPartitions) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): numOfParToLeave > totalNumOfPartitions \r\n "); + return flBadParameter; + } + + if((numOfBinaryParToLeave + FP3->noOfBinaryPartitions) > MAX_BINARY_PARTITIONS_PER_DRIVE) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Number of binary partitions exceed maximum allowed.\r\n "); + return flBadParameter; + } + + if((numOfParToLeave > numOfBinaryPartitions) && (FP3->noOfBinaryPartitions > 0)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Can`t create Binary after BDTL.\r\n "); + return flBadParameter; + } + +#else /*BDK_ACCESS*/ + if(ioreq->irFlags == TL_LEAVE_SOME_PARTITIONS) + { + numOfParToLeave = ioreq->irLength; + } + else + { + numOfParToLeave = 0; + } +#endif /*BDK_ACCESS*/ + + /* Check that total number of partitions AFTER format does not exceed FL_VOLUMES */ + if((numOfParToLeave + FP3->noOfBinaryPartitions + FP3->noOfBDTLPartitions) > FL_VOLUMES) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Number of partitions exceed maximum allowed.\r\n "); + return flBadParameter; + } + + /* Leaving all existing partitions is not allowed */ + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = ioreq->irHandle; + myStatus = TFFSCountVolumes(&myIoreq); + if(myStatus != flOK) + return myStatus; + if(numOfParToLeave >= (FLSNative)myIoreq.irFlags) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Leaving all existing partitions is not allowed!!!.\r\n "); + return flBadParameter; + } + + + /*Calculate number of remaining partitions*/ + lastRemainingPartition = (numOfParToLeave + bOtpPresent + bIplPresent); + + /*Retrieve DOCH extended info structure*/ + /*-------------------------------------*/ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + wNumOfOriginalPartitions = ((DOCH_DeviceInfo*)intBuf)->wTotalNumOfPartitions; + + /*Clear partition attributes for partitions to be deleted */ + if(lastRemainingPartition > 0) + { + tffsset(intBuf, 0, DOCH_SECTOR_SIZE); + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irData = intBuf; + for(i=lastRemainingPartition; i < wNumOfOriginalPartitions; i++) + { + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq) + (i << 4); + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if( rc!=DOCH_OK ) + { + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + } + } + + /*Set numOfBinaryPartitions*/ +#ifdef BDK_ACCESS + numOfBinaryPartitions = numOfBinaryParToLeave; +#else /*BDK_ACCESS*/ + numOfBinaryPartitions = 0; +#endif /*BDK_ACCESS*/ + + /*Set programmer name, programmer version and TFFS version*/ + tffsset(intBuf, 0, DOCH_SECTOR_SIZE); + pDiskUserAttrWithBinary->bNumOfBinaryPartitions = numOfBinaryPartitions; + pDiskUserAttrWithBinary->bIplPresent = bIplPresent; + pDiskUserAttrWithBinary->bOtpPresent = bOtpPresent; + tffscpy(&pDiskUserAttrWithBinary->bProgrammerName, FL_PROGRAMMER_NAME, 4); + tffscpy(&pDiskUserAttrWithBinary->bProgrammerVersion, FL_PROGRAMMER_VERSION, 4); + tffscpy(&pDiskUserAttrWithBinary->bTFFSVersion, TrueFFSVersion, 4); + tffscpy(pDiskUserAttrWithBinary->bMigrationSignature, TFFS_API_MIGRATION_SIGNATURE, + sizeof(pDiskUserAttrWithBinary->bMigrationSignature)); + /* starting DD 1.1 beta - indication on format start and format complete*/ + tffscpy(pDiskUserAttrWithBinary->bFormatStartSignature, TFFS_API_FORMAT_START_SIGNATURE, + sizeof(pDiskUserAttrWithBinary->bFormatStartSignature)); + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + myIoreq.irData = intBuf; + rc = flDOCHSetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + dochVol.numOfBinaryPartitions = numOfBinaryPartitions; + + if (bOtpPresent == 0) + total_num_of_partitions++; + if (bIplPresent == 0) + total_num_of_partitions++; + + if( (wNumOfOriginalPartitions > 2) ||/* more, than IPL and OTP present */ + (bIplPresent==0 && bOtpPresent == 0 && numOfBinaryPartitions == 0) )/* or not proper format */ + { + /*Delete partitions not marked to "leave" (if such exists)*/ + tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0,0,0xFF, + numOfParToLeave + bIplPresent + bOtpPresent); + rc = flDOCHDeletePartitions(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHDeletePartitions failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection:TFFS_API_RET(rc); + } + } + + /*Set IPL partition*/ + if(bIplPresent == 0) + { + /* add IPL partition, update it's attributes and disk attributes */ + checkStatus( tffsApiAddOtpIPL(TRUE, &myIoreq, ioreq) ); + memset (intBuf, 0xff, DOCH_SECTOR_SIZE); + for (i = 0; i < TFFS_API_8K_NORMAL_IPL_SIZE ; i++) + { + tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), + (DOCH_IPL_MODE_8KB_WINDOW|DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT), + 0, dochVol.intermediateBuf, 1, TFFS_API_8K_NORMAL_IPL_SIZE); + if (i == 0) + myIoreq.irFlags |= DOCH_IPL_WRITE_FIRST_CHUNK; + rc = flDOCHWriteIPL(&myIoreq); + if (rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Failed writing default IPL. status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x \n"), rc)); + TFFS_API_RET_PART_FLSTATUS(rc,flWriteFault); + } + } + dochVol.iplExists = 1; + bIplPresent = 1; + }/* IPL should be added */ + + /*Set OTP partition*/ + if(bOtpPresent == 0) + { + checkStatus( tffsApiAddOtpIPL(FALSE, &myIoreq, ioreq) ); + dochVol.otpExists = 1; + bOtpPresent = 1; + }/*OTP partition should be added */ + + partNum = bOtpPresent + bIplPresent + numOfParToLeave; + +#ifdef BDK_ACCESS + + binUserParams = FP3->binaryPartitionInfo; + + /*Perform for every binary partition*/ + /*----------------------------------*/ + for(i=0; i< FP3->noOfBinaryPartitions; i++) + { + /* Fill DOCH_PartitionFormatInfoAPI structure from FormatParams3 structure */ + /*==========================================================================*/ + tffsset(intBuf, 0, sizeof(DOCH_PartitionFormatInfoAPI)); + + /* standard migration format params */ + TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, binUserParams->protectionType); + + /* protection features */ + checkStatus( tffsFormatSetProtectionAttribs(binUserParams->protectionType, pPartitionFormatInfoAPI, + binUserParams->protectionKey, sizeof(binUserParams->protectionKey)) ); + + + /*Partition size (must be FL_LENGTH_IN_BYTES)*/ + pPartitionFormatInfoAPI->nPartitionSize = (binUserParams->length & 0x1FF) ? + ((binUserParams->length)>>DOCH_SECTOR_SIZE_BITS)+1 : ((binUserParams->length)>>DOCH_SECTOR_SIZE_BITS); + + /*Round partition size to Unit Size*/ + pPartitionFormatInfoAPI->nPartitionSize = + (pPartitionFormatInfoAPI->nPartitionSize+dochVol.dwVirtualUnitSizeInSectors-1) & (~(dochVol.dwVirtualUnitSizeInSectors-1)); + + if( pPartitionFormatInfoAPI->nPartitionSize == 0 ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): cannot add zero length binary partition "); + return flBadParameter; + } + + /*Add partition*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf,0,0); + rc = flDOCHAddPartition(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHAddPartition (Binary) failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } +#ifdef HW_PROTECTION + /*Authenticate partition*/ + if(((binUserParams->protectionType & PROTECTABLE) == PROTECTABLE) && + ((binUserParams->protectionType & (READ_PROTECTED | WRITE_PROTECTED)) != 0)) + { + checkStatus( tffsApiAuthPartition(&myIoreq, ioreq, partNum, binUserParams->protectionKey, + sizeof(binUserParams->protectionKey))); + } +#endif /*HW_PROTECTION*/ + + /*Retrieve partition info*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (partNum << 4), 0,0, intBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + dwPartitionTotalSize = ((DOCH_PartitionInfo*)intBuf)->nPartitionSize; + + /*Retrieve current attributes*/ + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + + /* Update the partition attributes and write them back to device */ + /*-------------*/ + /*Set type to binary*/ + pPartitionUserAttrWithBinary->bType = PARTITION_TYPE_BINARY; + pPartitionUserAttrWithBinary->binPartHeader.dwPartitionFlags = binUserParams->flags; + /*Set signature*/ + tffscpy( pPartitionUserAttrWithBinary->binPartHeader.subPartitions[0].bSignature, + binUserParams->sign, BDK_SIGNATURE_NAME); + /*Set length*/ + pPartitionUserAttrWithBinary->binPartHeader.subPartitions[0].dwSize = dwPartitionTotalSize; + /*Set # of sub-partitions to 1*/ + pPartitionUserAttrWithBinary->binPartHeader.bNumOfSubPartitions = 1; + /*Set DPS attribute*/ + pPartitionUserAttrWithBinary->bDPSFwd = 0; /*Not used*/ + pPartitionUserAttrWithBinary->bDPSBwd = 0; /*Not used*/ + /*Set protection attribute*/ + pPartitionUserAttrWithBinary->bChangableProtection = ((binUserParams->protectionType & CHANGEABLE_PROTECTION) == CHANGEABLE_PROTECTION); + pPartitionUserAttrWithBinary->bProtected = ((binUserParams->protectionType & PROTECTABLE) == PROTECTABLE); + /*Set attributes back to device*/ + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + + /* Update the disk attributes and write them back to device */ + /*-------------*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf,0,0); + rc = flDOCHGetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + pDiskUserAttrWithBinary->bNumOfBinaryPartitions = numOfBinaryPartitions + 1; + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf,0,0); + rc = flDOCHSetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + +#ifdef HW_PROTECTION + /*Authenticate partition*/ + if((((binUserParams->protectionType & PROTECTABLE) == PROTECTABLE) && + (binUserParams->protectionType & (READ_PROTECTED | WRITE_PROTECTED)) != 0) && + (ioreq->irFlags & TL_DO_NOT_PERFORM_DOWNLOAD) == 0) + { + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&myIoreq, partNum); + myIoreq.irFlags = DOCH_ACCESS_USER_PASSWORD; + rc = flDOCHDisablePartAccess(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHDisablePartAccess failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } + } +#endif /*HW_PROTECTION*/ + + numOfBinaryPartitions++; + partNum++; + dochVol.numOfBinaryPartitions = numOfBinaryPartitions; + binUserParams++; + } +#endif /*BDK_ACCESS*/ + + /* fix the partition size to be zero - spend on the reminder of the disk + required for last partition */ + FP3->BDTLPartitionInfo[FP3->noOfBDTLPartitions-1].length = 0; + + /*Perform for every bdtl partition*/ + /*--------------------------------*/ + bdtlUserParams = FP3->BDTLPartitionInfo; + for(i=0; i< FP3->noOfBDTLPartitions; i++) + { + /* Fill DOCH_PartitionFormatInfoAPI structure from FormatParams3 structure */ + /*==========================================================================*/ + tffsset(intBuf, 0, sizeof(DOCH_PartitionFormatInfoAPI)); + + /* standard migration format params */ + TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI, bdtlUserParams->protectionType); + + /* protection features */ + checkStatus( tffsFormatSetProtectionAttribs(bdtlUserParams->protectionType, pPartitionFormatInfoAPI, + bdtlUserParams->protectionKey, sizeof(bdtlUserParams->protectionKey)) ); + + /*Partition size*/ + /*--------------*/ + switch(bdtlUserParams->lengthType) + { + case FL_LENGTH_IN_BYTES: + /*Convert to Sectors*/ + pPartitionFormatInfoAPI->nPartitionSize = + (bdtlUserParams->length & 0x1FF) ? + ((bdtlUserParams->length)>>DOCH_SECTOR_SIZE_BITS)+1 : ((bdtlUserParams->length)>>DOCH_SECTOR_SIZE_BITS); + break; + + case FL_LENGTH_IN_SECTORS: + /*Already in sectors*/ + pPartitionFormatInfoAPI->nPartitionSize = bdtlUserParams->length; + break; + + case FL_LENGTH_IN_UNITS: + pPartitionFormatInfoAPI->nPartitionSize = (bdtlUserParams->length << DOCH_SECTORS_IN_UNIT_BITS); + break; + + case FL_LENGTH_IN_PERCENTS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_PERCENTS Not supported\r\n "); + return flBadParameter; + + case FL_LENGTH_IN_CYLINDERS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_CYLINDERS Not supported\r\n "); + return flBadParameter; + + default: + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Unsupported Normal area length type\r\n "); + return flBadParameter; + } + + /*Round partition size to Unit Size*/ + /*---------------------------------*/ + pPartitionFormatInfoAPI->nPartitionSize = + ((pPartitionFormatInfoAPI->nPartitionSize + + dochVol.dwVirtualUnitSizeInSectors - 1) & (~(dochVol.dwVirtualUnitSizeInSectors-1))); + + /*Fast area size*/ + /*--------------*/ + switch(bdtlUserParams->fastAreaLengthType) + { + case FL_LENGTH_IN_BYTES: + pPartitionFormatInfoAPI->nFastAreaSize = (bdtlUserParams->fastAreaLength >> DOCH_SECTOR_SIZE_BITS); + pPartitionFormatInfoAPI->dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_SECTORS; + break; + + case FL_LENGTH_IN_SECTORS: + pPartitionFormatInfoAPI->nFastAreaSize = bdtlUserParams->fastAreaLength; + pPartitionFormatInfoAPI->dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_SECTORS; + break; + + case FL_LENGTH_IN_UNITS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_UNITS Not supported\r\n "); + return flBadParameter; + /*break;*/ + + case FL_LENGTH_IN_PERCENTS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_PERCENTS Not supported\r\n "); + return flBadParameter; + + + case FL_LENGTH_IN_CYLINDERS: + /*Not supported*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): FL_LENGTH_IN_CYLINDERS Not supported\r\n "); + return flBadParameter; + /*break;*/ + + case FL_LENGTH_ALL: + pPartitionFormatInfoAPI->nFastAreaSize = TL_ENHANCED_PERFORMANCE; + pPartitionFormatInfoAPI->dwFastAreaSizeType = DOCH_FAST_AREA_TYPE_PERCENT; + break; + + default: + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat(): Unsupported Fast area length type\r\n "); + return flBadParameter; + /*break;*/ + } + pPartitionFormatInfoAPI->wFastAreaFactor = bdtlUserParams->fastAreaVirtualFactor; + + /*Round fast area size up to Unit Size*/ + /*------------------------------------*/ + if (pPartitionFormatInfoAPI->dwFastAreaSizeType == DOCH_FAST_AREA_TYPE_SECTORS) + { + pPartitionFormatInfoAPI->nFastAreaSize = + ((pPartitionFormatInfoAPI->nFastAreaSize + + dochVol.dwVirtualUnitSizeInSectors - 1) & (~(dochVol.dwVirtualUnitSizeInSectors-1))); + } + + /*Add partition*/ + /*-------------*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf,0,0); + rc = flDOCHAddPartition(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHAddPartition (Bdtl) failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } + + /*Authenticate partition*/ + if(((bdtlUserParams->protectionType & PROTECTABLE) == PROTECTABLE) && + (bdtlUserParams->protectionType & (READ_PROTECTED | WRITE_PROTECTED)) != 0) + { + checkStatus( tffsApiAuthPartition(&myIoreq, ioreq, partNum, + bdtlUserParams->protectionKey, sizeof(bdtlUserParams->protectionKey)) ); + } + + + /*Retrieve current attributes*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (partNum << 4), 0,0, intBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + + /*Set type to BDTL*/ + pPartitionUserAttrWithBinary->bType = PARTITION_TYPE_BDTL; + /*Set DPS attribute*/ + pPartitionUserAttrWithBinary->bDPSFwd = 0; /*Not used*/ + pPartitionUserAttrWithBinary->bDPSBwd = 0; /*Not used*/ + /*Set protection attribute*/ + pPartitionUserAttrWithBinary->bChangableProtection = ((bdtlUserParams->protectionType & CHANGEABLE_PROTECTION) == CHANGEABLE_PROTECTION); + pPartitionUserAttrWithBinary->bProtected = ((bdtlUserParams->protectionType & PROTECTABLE) == PROTECTABLE); + /*Set attributes back to device*/ + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + +#ifdef FL_SOTP + if (bdtlUserParams->protectionType & FORMAT_SEQUENTIAL_OTP/*pPartitionFormatInfoAPI->bSOTP*/) + { + /*lock SOTP partition*/ + + pPartitionFormatInfoAPI->bSOTP =TRUE; + pPartitionFormatInfoAPI->dwOtpEnabled =TRUE; + + + myIoreq.irHandle = ((FL_GET_SOCKET_FROM_HANDLE(ioreq))|((partNum)<<4)); + rc = flDOCHSetParitionProtection(tffsAPISetIoreq(&myIoreq, myIoreq.irHandle,(DOCH_LOCK_AS_OTP|DOCH_SEQUENTIAL_OTP),0,pPartitionFormatInfoAPI,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSflashFormat()(): flDOCHSetParitionProtection Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc) ; + } + + } +#endif /*FL_SOTP*/ + + /*Authenticate partition*/ + if (((bdtlUserParams->protectionType & PROTECTABLE) == PROTECTABLE) && + ((ioreq->irFlags & TL_DO_NOT_PERFORM_DOWNLOAD) == 0)) + { + tffsset(&myIoreq, 0, sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&myIoreq, partNum); + myIoreq.irFlags = DOCH_ACCESS_USER_PASSWORD; + rc = flDOCHDisablePartAccess(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHDisablePartAccess failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } + } + partNum++; + bdtlUserParams++; + } + + /* starting DD 1.1 beta - add format complete indication*/ + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf, 0,0); + rc = flDOCHGetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + tffscpy(pDiskUserAttrWithBinary->bFormatCompleteSignature, TFFS_API_FORMAT_COMPLETE_SIGNATURE, + sizeof(pDiskUserAttrWithBinary->bFormatCompleteSignature)); + rc = flDOCHSetDiskUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSflashFormat(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + return flOK; +}/* TFFSFlashFormat() */ + + +/*----------------------------------------------------------------------*/ +/* T F F S U n f o r m a t */ +/* */ +/* Erase the entire media returning the DiskOnChip to it's virgin state */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0, 1, ...) */ +/* Partition number must be 0 */ +/* irPath : Pointer to progress call back routine, or NULL */ +/* irFlags : reserved ( 0 ) */ +/* irData : reserved (NULL) */ +/* irLength : reserved ( 0 ) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSUnFormat(IOreq* ioreq) +{ + FLStatus status; + DOCH_Error rc; + IOreq myIoreq; + FLExtendedDiskInfo extInfo; + FLByte i; + + tffsset(&myIoreq, 0, sizeof(myIoreq)); + + /*Retrieve # of partitions*/ + myIoreq.irHandle = (ioreq->irHandle & 0xF); + myIoreq.irCount = FL_EXT_INFO_NO_SPEC_PART; + myIoreq.irFlags = FL_BDK_PARTITION; + myIoreq.irData = &extInfo; + status = TFFSGetExtendedDiskInfo(&myIoreq); + /* if GetExtendedDiskInfo fails (bad format) force deletion of partitions + do not return status*/ + if (status ==flOK) + { + /*Check that all partitions are not actively protected + If so - return flHWProtection*/ + for(i = 0; iirHandle, 0,0, dochVol.intermediateBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSEraseBD(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + numOfSectors = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize; + + /* check protection */ + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0, NULL,0,0); + status = TFFSIdentifyProtection(&myIoreq); + if(status != flOK && status != flNotProtected) + return status; + if((myIoreq.irFlags & (WRITE_PROTECTED)) && ((myIoreq.irFlags & KEY_INSERTED)==0)) + return flHWProtection; + + /*Erase the entire partition*/ + /*--------------------------*/ + + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,NULL,0,numOfSectors); + rc = flDOCHWipeSectors(&myIoreq); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSEraseBD(): flDOCHErasePartition failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, TFFS_API_RET(rc)); + } + return flOK; +}/*TFFSEraseBD()*/ +#endif /*FL_FORMAT_VOLUME*/ +#endif /*FL_READ_ONLY*/ + +#ifdef FL_ABS_READ_WRITE +/*----------------------------------------------------------------------*/ +/* f l A b s R e a d */ +/* */ +/* Reads absolute sectors by sector no. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of user buffer to read into */ +/* irSectorNo : First sector no. to read (sector 0 is the */ +/* DOS boot sector). */ +/* irSectorCount : Number of consecutive sectors to read */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually read */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsRead(IOreq* ioreq, FLSDword * pIrCount) +{ + DOCH_Error rc; + FLSDword dwsOrigIrCount=ioreq->irCount; + + /*Read required sectors*/ + /*---------------------*/ +#ifdef FL_DMA_CONFIG + if( (((FLDword)ioreq->irData & 3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) ) + { + ioreq->irFlags |= DOCH_USE_DMA; + } +#endif /* FL_DMA_CONFIG */ +#ifdef FL_USE_BURST_MODE_READ + if((((FLDword)ioreq->irData & 3) == 0) && (tffs_burst_enabled == TRUE)) /* andrayk Nov 01 2007: enabling burst at runtime */ + { + ioreq->irFlags |= DOCH_USE_BURST; + } +#endif /* FL_USE_BURST_MODE_READ */ + + rc = flDOCHReadPartitionSectors(ioreq); + if(rc != DOCH_OK) + { + (*pIrCount) = dwsOrigIrCount - ioreq->irCount; /*update number of sectors which is read */ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsRead(): flDOCHReadPartitionSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flReadFault); + } + + (*pIrCount) = dwsOrigIrCount; + return flOK; +}/*TFFSAbsRead()*/ + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSAbsAddress*/ +/* Description : dummy function */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsAddress(IOreq* ioreq) +{ + return flFeatureNotSupported; +}/*TFFSAbsAddress()*/ + + +#ifndef FL_READ_ONLY +/*----------------------------------------------------------------------*/ +/* f l A b s W r i t e */ +/* */ +/* Writes absolute sectors by sector no. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of user buffer to write from */ +/* irSectorNo : First sector no. to write */ +/* irSectorCount : Number of consecutive sectors to write */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually written */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsWrite(IOreq* ioreq) +{ + DOCH_Error rc; + FLSDword dwOrigIrCount = ioreq->irCount; + + /*Write required sectors*/ +#ifdef FL_USE_DMA_ON_WRITE /* should be changed to FL_DMA_CONFIG */ + if( (((FLDword)ioreq->irData & 3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) ) + ioreq->irFlags |= DOCH_USE_DMA; +#endif /*FL_USE_DMA_ON_WRITE*/ + rc = flDOCHWritePartitionSectors(ioreq); + if(rc != DOCH_OK) + { + ioreq->irCount = dwOrigIrCount - ioreq->irCount; /*update number of sectors which is written */ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsWrite(): flDOCHWritePartitionSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + ioreq->irCount = dwOrigIrCount; + return flOK; +}/*TFFSAbsWrite()*/ + +/*----------------------------------------------------------------------*/ +/* f l A b s D e l e t e */ +/* */ +/* Marks absolute sectors by sector no. as deleted. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irSectorNo : First sector no. to delete */ +/* irSectorCount : Number of consecutive sectors to delete */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually deleted */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsDelete(IOreq* ioreq) +{ + /* FreeSectors does not perform any operation in mDoc H3 + therefore this call is removed*/ +#ifdef FL_SUPPORT_FREE_SECTORS + DOCH_Error rc; + + /*Free required sectors*/ + /*---------------------*/ + rc = flDOCHFreeSectors(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsDelete(): flDOCHFreeSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, TFFS_API_RET(rc)); + } +#endif /*FL_SUPPORT_FREE_SECTORS*/ + return flOK; +}/*TFFSAbsDelete*/ + +/*----------------------------------------------------------------------*/ +/* f l A b s S e c u r e D e l e t e */ +/* */ +/* Marks absolute sectors by sector no. as deleted making sure no */ +/* previous copy exists. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irSectorNo : First sector no. to delete */ +/* irSectorCount : Number of consecutive sectors to delete */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irSectorCount : Number of sectors actually deleted */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSAbsSecureDelete(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLDword numOfSectors; + FLStatus status; + + /* check parameters before initialize wipe operations */ + /*----------------------------------------------------*/ + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0, dochVol.intermediateBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSEraseBD(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc); + } + numOfSectors = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize; + + /* check partition limits */ + if ((FLDword)(ioreq->irSectorNo+ioreq->irSectorCount)>numOfSectors) + { + return flBadParameter; + } + + /* check protection */ + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0, NULL,0,0); + status = TFFSIdentifyProtection(&myIoreq); + if(status != flOK && status != flNotProtected) + return status; + if((myIoreq.irFlags & (WRITE_PROTECTED)) && ((myIoreq.irFlags & KEY_INSERTED)==0)) + return flHWProtection; + + tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,NULL,ioreq->irSectorNo,ioreq->irSectorCount); + rc = flDOCHWipeSectors(&myIoreq); + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSAbsSecureDelete(): flDOCHEraseSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, TFFS_API_RET(rc)); + } + return flOK; +}/*TFFSAbsSecureDelete()*/ + +#endif /*FL_READ_ONLY*/ +#endif /*FL_ABS_READ_WRITE*/ + +/*----------------------------------------------------------------------*/ +/* f l G e t P h y s i c a l I n f o */ +/* */ +/* Get physical information of the media. The information includes */ +/* JEDEC ID, unit size and media size. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* irData : Address of user buffer to read physical */ +/* information into. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irLength : Window base address. note mast be cast to */ +/* unsigned. */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSGetPhysicalInfo(IOreq* ioreq) +{ + IOreq myIoreq; + DOCH_Error rc = DOCH_OK; + PhysicalInfo FAR1 * physicalInfo = (PhysicalInfo FAR1 *)ioreq->irData; + + /*Retrieve extended disk info*/ + /*---------------------------*/ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Fill PhysicalInfo structure*/ + /*---------------------------*/ + physicalInfo->type = 0;/*docDeviceInfo.wFlashType;*/ + physicalInfo->mediaType = FL_H3; + physicalInfo->dwUnitSize = dochVol.dwVirtualUnitSizeInSectors; + physicalInfo->dwMediaSize = ((DOCH_DeviceInfo*)dochVol.intermediateBuf)->dwUnformattedCapacity; + physicalInfo->dwChipSize = physicalInfo->dwMediaSize; + physicalInfo->interleaving = 0; + + /* Return window base reg */ + /*------------------------*/ + tffsAPISetIoreq( &myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,0,0,0); + rc=flDOCHGetPhysicalAddress(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetPhysicalInfo(): DOCHGetPhysicalAddress failed with status: 0x%x "), rc)); + return (DOCH_DiskNotFound==rc) ? flAdapterNotFound : TFFS_API_RET(rc); + } + ioreq->irLength = myIoreq.irCount; + return flOK; +}/*TFFSGetPhysicalInfo()*/ + + + +#ifdef BDK_ACCESS + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkReadInit*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkReadInit(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + FLByte subPart; + IOreq myIoreq; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + DOCH_PartitionUserAttrWithBinary* pPartitionUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + + /* retrieve device information */ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadInit(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + for(subPart=0; + subPart < pPartitionUserAttrWithBinary->binPartHeader.bNumOfSubPartitions; + subPart++) + { + if (tffscmp(pPartitionUserAttrWithBinary->binPartHeader.subPartitions[subPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(subPart >= pPartitionUserAttrWithBinary->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadInit(): findSubPartBySignature failed with status: 0x%x "), rc)); + return flPartitionNotFound; + } + if( ((bdkStrct->length >>DOCH_SECTOR_SIZE_BITS) + (bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors)) > + pPartitionUserAttrWithBinary->binPartHeader.subPartitions[subPart].dwSize ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkReadInit(): recieved length exceeds partition size.\r\n"); + return flBadParameter; + } + /*Save operation init values for actual read operation*/ + dochVol.bdkInitValues.dwStartReadSector = bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors + + pPartitionUserAttrWithBinary->binPartHeader.subPartitions[subPart].dwOffset; + dochVol.bdkInitValues.dwCurrentReadByte = 0; + dochVol.bdkInitValues.dwReadLength = bdkStrct->length; + return flOK; +}/*TFFSbdkReadInit()*/ + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkReadBlock*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkReadBlock(IOreq* ioreq) +{ +#ifndef FL_ABS_READ_WRITE + return flFeatureNotSupported; +#else /*FL_ABS_READ_WRITE*/ + DOCH_Error dochErr = DOCH_FeatureNotSupported; + IOreq myIoreq; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + FLByte* buf = bdkStrct->bdkBuffer; + FLDword byteOffsetInSector = (dochVol.bdkInitValues.dwCurrentReadByte % DOCH_SECTOR_SIZE); + FLDword currentSector = dochVol.bdkInitValues.dwStartReadSector + + (dochVol.bdkInitValues.dwCurrentReadByte >> DOCH_SECTOR_SIZE_BITS); + FLDword fullSectorsToRead, bytesToPad; + FLWord wBytesToCopy; + + if (byteOffsetInSector != 0) + { + wBytesToCopy = (FLWord)TFFSMIN(DOCH_SECTOR_SIZE - byteOffsetInSector, bdkStrct->length); + fullSectorsToRead = (bdkStrct->length - wBytesToCopy)>>DOCH_SECTOR_SIZE_BITS; + bytesToPad = bdkStrct->length - wBytesToCopy - (fullSectorsToRead << DOCH_SECTOR_SIZE_BITS); + } + else + { + fullSectorsToRead = bdkStrct->length >>DOCH_SECTOR_SIZE_BITS; + bytesToPad = bdkStrct->length - (fullSectorsToRead << DOCH_SECTOR_SIZE_BITS); + } + + if (dochVol.bdkInitValues.dwCurrentReadByte + bdkStrct->length > dochVol.bdkInitValues.dwReadLength) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkReadBlock(): Attempted reading out of readInit aread.\r\n"); + return flBadParameter; + } + /*Read NOT from start of sector*/ + if(byteOffsetInSector != 0) + { + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + dochErr = flDOCHReadPartitionSectors(&myIoreq); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadBlock(): TFFSAbsRead failed with status: 0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(dochErr, flReadFault); + } + wBytesToCopy = (FLWord)TFFSMIN(DOCH_SECTOR_SIZE - byteOffsetInSector, bdkStrct->length); + tffscpy(buf, &dochVol.intermediateBuf[byteOffsetInSector], wBytesToCopy); + dochVol.bdkInitValues.dwCurrentReadByte += wBytesToCopy; + byteOffsetInSector = (byteOffsetInSector + wBytesToCopy)% DOCH_SECTOR_SIZE; + buf += wBytesToCopy; + if ((byteOffsetInSector % DOCH_SECTOR_SIZE) == 0) + currentSector++; + } + + /*Read requested sectors, use init values from TFFSbdkReadInit*/ + if(fullSectorsToRead > 0) + { + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,buf,currentSector,fullSectorsToRead); +#ifdef FL_DMA_CONFIG + if( (((FLDword)myIoreq.irData & 3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) ) + { + myIoreq.irFlags |= DOCH_USE_DMA; + } +#endif /* FL_DMA_CONFIG */ +#ifdef FL_USE_BURST_MODE_READ + if( ((FLDword)myIoreq.irData & 3) == 0) + { + myIoreq.irFlags |= DOCH_USE_BURST; + } +#endif /* FL_USE_BURST_MODE_READ */ + dochErr = flDOCHReadPartitionSectors(&myIoreq); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadBlock(): TFFSAbsRead failed with status: 0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(dochErr, flReadFault); + } + buf += (fullSectorsToRead<irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + dochErr = flDOCHReadPartitionSectors(&myIoreq); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadBlock(): TFFSAbsRead failed with status: 0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(dochErr, flReadFault); + } + tffscpy(buf, dochVol.intermediateBuf, bytesToPad); + dochVol.bdkInitValues.dwCurrentReadByte += bytesToPad; + } + + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadBlock(): TFFSAbsRead failed with status: 0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(dochErr, flReadFault); + } + return flOK; +#endif /*FL_ABS_READ_WRITE*/ +}/*TFFSbdkReadBlock()*/ + +#ifndef FL_READ_ONLY +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkWriteInit*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkWriteInit(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + FLByte subPart; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + DOCH_PartitionUserAttrWithBinary* attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf;; + + /* retrieve the unit size and other information */ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadInit(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + for(subPart=0; + subPart < attrSectorPtr->binPartHeader.bNumOfSubPartitions; + subPart++) + { + if (tffscmp(attrSectorPtr->binPartHeader.subPartitions[subPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(subPart >= attrSectorPtr->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkReadInit(): findSubPartBySignature failed with status: 0x%x "), rc)); + return flPartitionNotFound; + } + + if( ((bdkStrct->length >>DOCH_SECTOR_SIZE_BITS) + (bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors)) > + attrSectorPtr->binPartHeader.subPartitions[subPart].dwSize ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkWriteInit(): requested size exceeds subpartition size"); + return flBadParameter; + } + + /*Save operation init values for actual write operation*/ + dochVol.bdkInitValues.dwStartWriteSector = bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors + + attrSectorPtr->binPartHeader.subPartitions[subPart].dwOffset; + dochVol.bdkInitValues.dwCurrentWriteByte = 0; + dochVol.bdkInitValues.dwWriteLength = bdkStrct->length; + dochVol.bdkInitValues.bWriteSubPartitionNum = subPart; + return flOK; +}/*TFFSbdkWriteInit()*/ + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkWriteBlock*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkWriteBlock(IOreq* ioreq) +{ +#ifndef FL_ABS_READ_WRITE + return flFeatureNotSupported; +#else /*FL_ABS_READ_WRITE*/ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + DOCH_PartitionUserAttrWithBinary* attrSectorPtr; + FLByte* userBuf; + FLWord wBytesToCopy, wBytesToPad; + FLDword currentSector, byteOffsetInSector; + FLDword fullSectorsToWrite; + FLDword dwUsedSize; + + byteOffsetInSector = (dochVol.bdkInitValues.dwCurrentWriteByte % DOCH_SECTOR_SIZE); + currentSector = dochVol.bdkInitValues.dwStartWriteSector + + (dochVol.bdkInitValues.dwCurrentWriteByte >> DOCH_SECTOR_SIZE_BITS); + wBytesToCopy = (FLWord)TFFSMIN(DOCH_SECTOR_SIZE - byteOffsetInSector, bdkStrct->length); + userBuf = bdkStrct->bdkBuffer; + if (byteOffsetInSector) + { + fullSectorsToWrite = (bdkStrct->length - wBytesToCopy)>>DOCH_SECTOR_SIZE_BITS; + wBytesToPad = (FLWord)(bdkStrct->length - wBytesToCopy - (fullSectorsToWrite << DOCH_SECTOR_SIZE_BITS)); + } + else + { + fullSectorsToWrite = bdkStrct->length >>DOCH_SECTOR_SIZE_BITS; + wBytesToPad = (FLWord)(bdkStrct->length - (fullSectorsToWrite << DOCH_SECTOR_SIZE_BITS)); + } + + + /*If first sector is NOT aligned: + - Read it + - Copy contiguous data + - Write sector + ==============*/ + if(byteOffsetInSector != 0) + { + /*Read*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,currentSector,1); +#ifdef FL_USE_BURST_MODE_READ + /* TODO - update myIoreq.irFlags */ +#endif /*FL_USE_BURST_MODE_READ*/ + rc = flDOCHReadPartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Reading sector for padding failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + /*Copy*/ + wBytesToCopy = (FLWord)TFFSMIN(DOCH_SECTOR_SIZE - byteOffsetInSector, bdkStrct->length); + tffscpy(dochVol.intermediateBuf + byteOffsetInSector, userBuf, wBytesToCopy); + + /*Write*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + rc = flDOCHWritePartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Writing sector after padding failed with status: 0x%x \r\n"), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + userBuf += wBytesToCopy; + dochVol.bdkInitValues.dwCurrentWriteByte += wBytesToCopy; + + byteOffsetInSector = (byteOffsetInSector + wBytesToCopy)% DOCH_SECTOR_SIZE; + if (byteOffsetInSector == 0) + currentSector++; + + } + + /*Write requested sectors, use init values from TFFSbdkWriteInit*/ + if(fullSectorsToWrite > 0) + { + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,userBuf,currentSector,fullSectorsToWrite); +#ifdef FL_USE_DMA_ON_WRITE /*should be changed to #ifdef FL_DMA_CONFIG*/ + if( (((FLDword)userBuf & 3) == 0) && (gIsDMAEnabled == DOCH_GLOBAL_BOOL_PATTERN) ) + { + myIoreq.irFlags |= DOCH_USE_DMA; + } +#endif /*FL_USE_DMA_ON_WRITE*/ + rc = flDOCHWritePartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Writing contiguous sectors failed with status:0x%x \r\n"), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + userBuf += (fullSectorsToWrite<irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + rc = flDOCHReadPartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Reading sector for padding failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + /*Copy*/ + tffscpy(dochVol.intermediateBuf, userBuf, wBytesToPad); + + /*Write*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,currentSector,1); + rc = flDOCHWritePartitionSectors(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Writing sector after padding failed with status: 0x%x \r\n"), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + userBuf += wBytesToPad; + dochVol.bdkInitValues.dwCurrentWriteByte += wBytesToPad; + byteOffsetInSector = (byteOffsetInSector + wBytesToPad)% DOCH_SECTOR_SIZE; + if (byteOffsetInSector == 0) + currentSector++; + } + + /*write operation was successful, update usesize*/ + /*Retrieve current attributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Getting partition attributes failed with status: 0x%x \r\n"), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + dwUsedSize = attrSectorPtr->binPartHeader.subPartitions[dochVol.bdkInitValues.bWriteSubPartitionNum].dwUsedSize; + if ((dwUsedSize << DOCH_SECTOR_SIZE_BITS) < (FLDword)(dochVol.bdkInitValues.dwCurrentWriteByte)) + { + dwUsedSize = attrSectorPtr->binPartHeader.subPartitions[dochVol.bdkInitValues.bWriteSubPartitionNum].dwUsedSize; + dwUsedSize += fullSectorsToWrite + (wBytesToPad ? 1:0); + attrSectorPtr->binPartHeader.subPartitions[dochVol.bdkInitValues.bWriteSubPartitionNum].dwUsedSize = dwUsedSize; + + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkWriteBlock(): Getting partition attributes failed with status: 0x%x \r\n"), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + } + return flOK; +#endif /*FL_ABS_READ_WRITE*/ +}/*TFFSbdkWriteBlock()*/ + + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkErase*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkErase(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + FLSNative binPartNum = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + FLSNative unitsToDelete = bdkStrct->length;/*((bdkStrct->length / BDK_UNIT_SIZE) + 1);*/ + FLDword lastDeletedSector, dwSubPartOffset; + DOCH_PartitionUserAttrWithBinary* attrSectorPtr; + FLByte bSubPart; + + /*get unit size etc*/ + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkErase(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + for(bSubPart=0; + bSubPart < attrSectorPtr->binPartHeader.bNumOfSubPartitions; + bSubPart++) + { + if (tffscmp(attrSectorPtr->binPartHeader.subPartitions[bSubPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(bSubPart >= attrSectorPtr->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkErase(): findSubPartBySignature failed with status: 0x%x "), rc)); + return flPartitionNotFound; + } + + if (((bdkStrct->startingBlock + unitsToDelete) * dochVol.dwVirtualUnitSize) > + (attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize << DOCH_SECTOR_SIZE_BITS)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkErase(): Erase requested for more than partition size. "); + return flNoSpaceInVolume; + } + + /* save the offset */ + dwSubPartOffset = attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwOffset; + /* update used size */ + lastDeletedSector = ((bdkStrct->startingBlock + unitsToDelete) * dochVol.dwVirtualUnitSizeInSectors); + if(lastDeletedSector >= attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwUsedSize ) + { /*Update used size only if exceeds current used size*/ + attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwUsedSize = + (bdkStrct->startingBlock + dochVol.dwVirtualUnitSizeInSectors - 1) & (~(dochVol.dwVirtualUnitSizeInSectors - 1)); + + /*Set modified atttributes*/ + tffsAPISetIoreq( &myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq) + (binPartNum << 4),0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkErase(): flDOCHSetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + } + + + tffsset(&myIoreq,0,sizeof(IOreq)); + myIoreq.irHandle =ioreq->irHandle; + myIoreq.irSectorNo = (FLDword)(bdkStrct->startingBlock * dochVol.dwVirtualUnitSizeInSectors) + dwSubPartOffset; + myIoreq.irSectorCount =(FLDword)dochVol.dwVirtualUnitSizeInSectors; + rc = flDOCHWipeSectors(&myIoreq); + + + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkErase(): flDOCHWipeSectors failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, TFFS_API_RET(rc)); + } + + return flOK; +}/*TFFSbdkErase()*/ + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkCreate*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkCreate(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + FLByte bSubPart; + DOCH_PartitionUserAttrWithBinary* attrSectorPtr; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + FLDword reqLength; + FLByte newSPIndex; + + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkCreate(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + /*Check that this is actually a binary partition*/ + if(attrSectorPtr->bType != PARTITION_TYPE_BINARY) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkCreate(): Partition is NOT Binary \r\n"); + return flBadParameter; + } + + for(bSubPart=0; + bSubPart < attrSectorPtr->binPartHeader.bNumOfSubPartitions; + bSubPart++) + { + if (tffscmp(attrSectorPtr->binPartHeader.subPartitions[bSubPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(bSubPart >= attrSectorPtr->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkCreate(): findSubPartBySignature failed with status:0x%x "), rc)); + return flPartitionNotFound; + } + + /*If new SP size equals in size - simply replace signature and return*/ + reqLength = bdkStrct->length * dochVol.dwVirtualUnitSizeInSectors; + if( reqLength == 0 ) + { + DBG_PRINT_WRN(FLZONE_API, "TFFSbdkCreate(): zero size subpartition requested "); + return flNoSpaceInVolume;/*strange errors up to legacy devices*/ + } + + /* size match exactly -> replace signature */ + if(reqLength == attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize) + { + tffscpy(attrSectorPtr->binPartHeader.subPartitions[bSubPart].bSignature, + bdkStrct->newSign, BDK_SIGNATURE_NAME); + } + else + { + /*Check that there is enough space in the current SP*/ + /*Check that max number of SP was not exceeded*/ + if(reqLength > (attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize << DOCH_SECTOR_SIZE_BITS)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkCreate(): No Space In Volume \r\n"); + return flNoSpaceInVolume; + } + else + { + if(attrSectorPtr->binPartHeader.bNumOfSubPartitions >= (SUB_PARTITIONS_PER_BINARY-1)) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkCreate(): Too Many Binary Partitions \r\n"); + return flTooManyBinaryPartitions; + } + } + /*Assign new SP number*/ + newSPIndex = attrSectorPtr->binPartHeader.bNumOfSubPartitions; + + /*Set current and new SP atttributes*/ + attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize -= reqLength; + /*Set new SP atttributes*/ + attrSectorPtr->binPartHeader.subPartitions[newSPIndex].dwOffset = + attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwOffset + + attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize; + attrSectorPtr->binPartHeader.subPartitions[newSPIndex].dwSize = reqLength; + + tffscpy(attrSectorPtr->binPartHeader.subPartitions[newSPIndex].bSignature, + bdkStrct->newSign, + BDK_SIGNATURE_NAME); + /*Increment number of SP by 1*/ + attrSectorPtr->binPartHeader.bNumOfSubPartitions++; + } + + /*Set modified atttributes*/ + tffsAPISetIoreq( &myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkCreate(): flDOCHSetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + return flOK; +}/*TFFSbdkCreate()*/ + + +#endif /*FL_READ_ONLY*/ + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSbdkPartitionInfo*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSbdkPartitionInfo(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_OK; + IOreq myIoreq; + DOCH_PartitionUserAttrWithBinary* attrSectorPtr; + BDKStruct* bdkStrct = (BDKStruct*)(ioreq->irData); + FLDword dwPartititonSize, dwUsedUnits; + /*If oldSign was not found on the partition - return error*/ + FLByte bSubPart; + + TFFS_API_GET_UNIT_SIZE(myIoreq, ioreq, rc, flStatus); + + if( FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq) >= (dochVol.numOfBinaryPartitions+dochVol.otpExists+dochVol.iplExists) ) + { + return flBadDriveHandle; + } + + bdkStrct->flags = dochVol.numOfBinaryPartitions; /*total number of BDK on the media*/ + + tffsAPISetIoreq( &myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkPartitionInfo(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + dwPartititonSize = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->nPartitionSize << DOCH_SECTOR_SIZE_BITS; + + /*Retrieve current atttributes*/ + tffsAPISetIoreq( &myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHGetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSbdkPartitionInfo(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + attrSectorPtr = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + /*Check that this is actually a binary partition*/ + if(attrSectorPtr->bType != PARTITION_TYPE_BINARY) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkPartitionInfo(): Partition is NOT Binary \r\n"); + return flBadParameter; + } + + for(bSubPart=0; + bSubPart < attrSectorPtr->binPartHeader.bNumOfSubPartitions; + bSubPart++) + { + if (tffscmp(attrSectorPtr->binPartHeader.subPartitions[bSubPart].bSignature, + bdkStrct->oldSign, BDK_SIGNATURE_NAME) == 0) + break; + } + if(bSubPart >= attrSectorPtr->binPartHeader.bNumOfSubPartitions) + { /*If oldSign was not found on the partition - return error*/ + DBG_PRINT_ERR(FLZONE_API, "TFFSbdkPartitionInfo(): Sub partition not found."); + return flNoSpaceInVolume ; /* for compatibility with legacy devices */ + } + + /*Returned values*/ + dwUsedUnits = ((attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwUsedSize + dochVol.dwVirtualUnitSizeInSectors - 1)/ dochVol.dwVirtualUnitSizeInSectors); + bdkStrct->length = dwUsedUnits * dochVol.dwVirtualUnitSize; + if(bdkStrct->length == 0) /*Used size must be at least 1 unit*/ + bdkStrct->length = dochVol.dwVirtualUnitSizeInSectors << DOCH_SECTOR_SIZE_BITS; + + bdkStrct->startingBlock = attrSectorPtr->binPartHeader.subPartitions[bSubPart].dwSize << DOCH_SECTOR_SIZE_BITS; + ioreq->irLength = dwPartititonSize; + + return flOK; +}/*TFFSbdkPartitionInfo()*/ +#endif /*BDK_ACCESS*/ + +/*----------------------------------------------------------------------*/ +/* f l I n s e r t P r o t e c t i o n K e y */ +/* b d k I n s e r t P r o t e c t i o n K e y */ +/* */ +/* Insert the protection key in order to remove the protection of the */ +/* partition specified by the drive handle */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based), doch count */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : pointer to an 8 bytes key array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSInsertProtectionKey(IOreq* ioreq) +{ + IOreq myIoreq; + FLByte bPartNum; + FLStatus flStatus; + + /* Format DOCH_PartitionAcessPassword structure */ + /* Note that legacy devices has only 8 bytes passkey */ + /*-----------------------------------------------*/ + bPartNum = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + flStatus = tffsApiAuthPartition(&myIoreq, ioreq, bPartNum, (FLByte *)ioreq->irData, PROTECTION_KEY_LENGTH ); + if( flStatus == flNotProtected ) + flStatus = flOK; + + return flStatus; +}/*TFFSInsertProtectionKey()*/ + +#ifdef BDK_ACCESS + +#endif /* BDK_ACCESS */ + +#ifdef HW_OTP +/*----------------------------------------------------------------------*/ +/* f l O T P S i z e */ +/* */ +/* Get the OTP size and state */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* bits 3-0 - Socket # (zero based) */ +/* irLength : The size of the used OTP area in bytes */ +/* irCount : The size of the OTP area in bytes */ +/* irFlags : LOCKED_OTP for a locked area otherwise unlocked */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSOTPSize(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + /*Get partition (OTP) info*/ + /*----------------------*/ + tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4), + 0,0,dochVol.intermediateBuf,0,0); + rc = flDOCHPartitionInfo(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPSize(): flDOCHPartitionInfo failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + /*Returned values*/ + ioreq->irCount = TFFS_API_OTP_PART_SIZE; + ioreq->irFlags = ((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_PERM_LOCKED) == DOCH_CFSB_PERM_LOCKED); + if (ioreq->irFlags) + ioreq->irLength = TFFS_API_OTP_PART_SIZE; + else + ioreq->irLength = 0; + return flOK; +}/*TFFSOTPSize()*/ + +/*----------------------------------------------------------------------*/ +/* f l O T P R e a d */ +/* */ +/* Read OTP Partition */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Address of user buffer to read into */ +/* irCount : First byte to read. */ +/* irLength : Number of consecutive bytes to read */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSOTPRead(IOreq* ioreq) +{ +#ifndef FL_ABS_READ_WRITE + return flFeatureNotSupported; +#else /*FL_ABS_READ_WRITE*/ + FLStatus status = flReadFault; + IOreq myIoreq; + /*FLByte padSector[DOCH_SECTOR_SIZE];*/ + FLByte * padSector = dochVol.intermediateBuf; + FLByte* buf = (FLByte*)ioreq->irData; + FLDword firstByteInFirstSector = (ioreq->irCount % DOCH_SECTOR_SIZE); + FLDword firstSector = (ioreq->irCount >> DOCH_SECTOR_SIZE_BITS); + FLDword bytesToRead = ioreq->irLength; + /* FLBoolean lessThenOneSector = FALSE; */ + FLDword padBytesInFirstSector, bytesInUnfullSector,fullSectorsToRead,bytesToPad; + + if((firstByteInFirstSector + bytesToRead) < DOCH_SECTOR_SIZE) + { + /* lessThenOneSector = TRUE; */ + padBytesInFirstSector = (DOCH_SECTOR_SIZE - (firstByteInFirstSector + bytesToRead)); + if(firstByteInFirstSector == 0) + bytesInUnfullSector = bytesToRead; + else + bytesInUnfullSector = 0; + fullSectorsToRead = 0; + bytesToPad = padBytesInFirstSector; + } + else + { + padBytesInFirstSector = (firstByteInFirstSector == 0) ? 0 : (DOCH_SECTOR_SIZE - firstByteInFirstSector); + bytesInUnfullSector = ((ioreq->irLength - padBytesInFirstSector) % DOCH_SECTOR_SIZE); + fullSectorsToRead = ((ioreq->irLength - (padBytesInFirstSector + bytesInUnfullSector))>>DOCH_SECTOR_SIZE_BITS); + bytesToPad = (bytesInUnfullSector == 0) ? 0 : (DOCH_SECTOR_SIZE - bytesInUnfullSector); + } + + /*Read NOT from start of sector*/ + if(firstByteInFirstSector != 0) + { + tffsset(padSector, 0, sizeof(padSector)); + tffsAPISetIoreq( &myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4), + 0,0,padSector,firstSector,1); + status = TFFSAbsRead(&myIoreq, &(ioreq->irSectorCount)); + if(status != flOK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPRead(): TFFSAbsRead failed with status: 0x%x "), status)); + return status; + } + tffscpy(buf, &padSector[firstByteInFirstSector], (DOCH_SECTOR_SIZE - firstByteInFirstSector)); + buf += (DOCH_SECTOR_SIZE - firstByteInFirstSector); + firstSector++; + } + + if(fullSectorsToRead > 0) + { + tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4), + 0,0,buf,firstSector,fullSectorsToRead); + status = TFFSAbsRead(&myIoreq, &(ioreq->irSectorCount)); + if(status != flOK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPRead(): TFFSAbsRead failed with status: 0x%x "), status)); + return status; + } + buf += (fullSectorsToRead<irSectorCount)); + if(status != flOK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPRead(): TFFSAbsRead failed with status: 0x%x "), status)); + return status; + } + tffscpy(buf, padSector, bytesInUnfullSector); + } + return flOK; +#endif /*FL_ABS_READ_WRITE*/ +}/*TFFSOTPRead()*/ + +/*----------------------------------------------------------------------*/ +/* f l O T P W r i t e A n d L o c k */ +/* */ +/* Write data to OTP partition and lock the partition */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user data */ +/* irLength : The size to write, in bytes. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSOTPWriteAndLock(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4),0, + 0,ioreq->irData,0,(ioreq->irLength>>DOCH_SECTOR_SIZE_BITS)); + + /*1. Perform last write + 2. Lock the partition for writing (OTP) + ---------------------------------------*/ + rc = flDOCHWriteAndLock(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSOTPWriteAndLock(): flDOCHWriteAndLock failed with status: 0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + return flOK; +}/*TFFSOTPWriteAndLock()*/ + + +/*----------------------------------------------------------------------*/ +/* f l G e t U n i q u e I D */ +/* */ +/* Returns the 16 bytes device unique ID */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to a 16 bytes buffer to read into the */ +/* unique ID data */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irData : 16 bytes unique ID buffer */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSGetUniqueID(IOreq* ioreq) +{ + DOCH_Error rc = DOCH_GeneralFailure; + IOreq myIoreq; + + tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,dochVol.intermediateBuf,0,0); + + /*Get extended disk info*/ + /*----------------------*/ + rc = flDOCHIdentifyDiskOnChipDevice(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetUniqueID(): flDOCHIdentifyDiskOnChipDevice failed with status: 0x%x "), rc)); + return (rc==DOCH_DiskNotFound)? flUnknownMedia : TFFS_API_RET(rc); + } + + tffscpy(ioreq->irData, ((DOCH_DeviceInfo*)dochVol.intermediateBuf)->bUniqueID, + sizeof(((DOCH_DeviceInfo*)dochVol.intermediateBuf)->bUniqueID)); + return flOK; +}/*TFFSGetUniqueID()*/ + +/*----------------------------------------------------------------------*/ +/* f l G e t C u s t o m e r I D */ +/* */ +/* Returns the 4 bytes customer ID */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to a 4 bytes buffer to read into the */ +/* customer ID */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irData : 4 bytes unique ID buffer */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSGetCustomerID(IOreq* ioreq) +{ + FLStatus status; + IOreq tmpIoreq; + FLByte uniqueID[16]; + + /*Use local copy of ioreq*/ + /*-----------------------*/ + tffsAPISetIoreq(&tmpIoreq,ioreq->irHandle,0,0,uniqueID,0,0); + + /*Retrieve UniqueID*/ + /*-----------------*/ + status = TFFSGetUniqueID(&tmpIoreq); + if(status != flOK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSGetCustomerID(): TFFSGetUniqueID failed with status: 0x%x "), status)); + return status; + } + + /*Extract 1st 4 bytes (CustomerID)*/ + /*--------------------------------*/ + tffscpy(ioreq->irData, uniqueID, 8); + return flOK; +}/*TFFSGetCustomerID()*/ + +#endif /* HW_OTP */ + + + +/*----------------------------------------------------------------------*/ +/* f l R e c o v e r F r o m P o w e r L o s s */ +/* */ +/* Recover from a power OFF without full TrueFFS initialization. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSRecoverFromPowerLoss(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + tffsAPISetIoreq(&myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,0,0,0); + rc = flDOCHRecoverFromPowerLoss(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSRecoverFromPowerLoss(): flDOCHRecoverFromPowerLoss failed with status: 0x%x "), rc)); + return flBadParameter; + } + return flOK; +}/*TFFSRecoverFromPowerLoss()*/ + + +/*----------------------------------------------------------------------*/ +/* f l D e e p P o w e r D o w n M o d e */ +/* */ +/* Forces the device into and out of the deep power down mode */ +/* To set the Auto-DPD, ACTIVE/INACTIVE modes and timeout MUST be reset,*/ +/* by other API! */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irFlags : DEEP_POWER_DOWN forces the low power consumption */ +/* mode. otherwise turning to the regular mode */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSDeepPowerDownMode(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + tffsAPISetIoreq( &myIoreq,FL_GET_SOCKET_FROM_HANDLE(ioreq),0,0,0,gDpdSettings.timeOut, + (gDpdSettings.activeMode | gDpdSettings.inActiveMode) ); + if (ioreq->irFlags == DEEP_POWER_DOWN) /* enter DPD */ + { + /* reset modes + leave in inactive mode */ + myIoreq.irFlags = DOCH_PM_INACTIVE_MODE | DOCH_PM_SET_BOTH_MODES; + } + else/* exit DPD*/ + { + if( TFFS_API_IS_AUTO_DPD_ON(FL_GET_SOCKET_FROM_HANDLE(ioreq)) ) /* AutoDPD on */ + { + myIoreq.irFlags = DOCH_PM_INACTIVE_MODE | DOCH_PM_SET_BOTH_MODES; /* MUST be in inactive to allow all AutoDPDs*/ + } + else /* AutoDPD off*/ + { + myIoreq.irFlags = DOCH_PM_WORK_MODE | DOCH_PM_SET_BOTH_MODES;/* just put in active mode */ + } + } + + rc = DOCHSetPowerMode(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSDeepPowerDownMode(): DOCHSetPowerMode failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return TFFS_API_RET(rc); + } + return flOK; +}/*TFFSDeepPowerDownMode()*/ + +/*----------------------------------------------------------------------*/ +/* f l H w C o n f i g */ +/* */ +/* his routine enables to control DiskOnChip H/W features. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irFlags : Describing H/W configuration Type */ +/* irLength : New value to use - Different for each H/W */ +/* configuration type chosen. */ +/* */ +/* Returns: None */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSHwConfig(IOreq* ioreq) +{ + IOreq myIoreq; + DOCH_Error dochRC; + FLDword ctrl; + + switch(ioreq->irFlags) + { + case FL_DPD_TYPE:/*Configures the behavior of DiskOnChip DPD input pin*/ + tffsAPISetIoreq(&myIoreq,ioreq->irHandle,DOCH_POWER_DOWN,0,0,0,0); + switch(ioreq->irLength) + { + case FL_DPD_DISABLED: + myIoreq.irLength |= DOCH_DPD_PIN_DISABLED; + break; + + case FL_DPD_EXIT_RISE_EDGE: + myIoreq.irLength |= (DOCH_DPD_PIN_ENABLED | DOCH_DPD_PIN_POL_HIGH); + break; + + case FL_DPD_EXIT_FALL_EDGE: + myIoreq.irLength |= (DOCH_DPD_PIN_ENABLED | DOCH_DPD_PIN_POL_LOW); + break; + + case FL_DPD_ENTER_1_EXIT_0: + case FL_DPD_ENTER_0_EXIT_1: + default: + return flFeatureNotSupported; + } + + dochRC = DOCHConfigHW(&myIoreq); + if(dochRC != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwConfig(): flDOCHDPDMode failed...\r\n"); + return flBadFunction; + } + + break; + + case FL_PAGE_MODE_TYPE: + case FL_TURBO_MODE_TYPE: + case FL_DPS_2_COPIES_TYPE: + return flOK; + + case FL_IRQ_RB_TYPE : + /* Enable interrupts (if requested) */ + if(ioreq->irLength & FL_IRQ_EDGE_TYPE)/* Not supported in H3 */ + { + DBG_PRINT_WRN(FLZONE_API, "TFFSHwConfig(): EDGE interrupts not supported by mDOC H3 devices, LEVEL interrupt enabled.\r\n"); + } + /* save set configuration */ + gDochIrqEnabled[ioreq->irHandle] = (ioreq->irLength & FL_INT_RB_ENABLED); + break; + + case FL_DMA_TYPE: + tffsAPISetIoreq(&myIoreq,ioreq->irHandle,DOCH_DMA_ENABLE,0,0,0,0); + if (ioreq->irLength & FL_DMA_HW_ENABLED) + { + myIoreq.irLength = TRUE; + } + else + { + myIoreq.irLength = FALSE; + } + dochRC = DOCHConfigHW(&myIoreq); + if(dochRC != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwConfig(): Setting DMA enable status failed.\r\n"); + return (dochRC==DOCH_BadParameter) ? flBadParameter : flFeatureNotSupported; + } + ctrl = ((DOCH_DMA_PULSE_WIDTH)<<4) | DOCH_DMA_REQ_POL_LOW; + if (ioreq->irLength & FL_DMA_REQ_EDGE) + ctrl |= DOCH_DMA_REQ_EDGE; + if (ioreq->irLength & FL_NEGATED_0_ASSERTED_1) + ctrl &= ~DOCH_DMA_REQ_POL_LOW; + tffsAPISetIoreq(&myIoreq,ioreq->irHandle,DOCH_DMA_CTRL,0,0,ctrl, 0); + dochRC = DOCHConfigHW(&myIoreq); + if(dochRC != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwConfig(): Setting DMA enable status failed.\r\n"); + return (dochRC==DOCH_BadParameter) ? flBadParameter : flFeatureNotSupported; + } + break; + default: + DBG_PRINT_ERR(FLZONE_API, "TFFSHwConfig(): Not Supported \r\n"); + return flFeatureNotSupported; + } + + return flOK; +}/*TFFSHwConfig*/ + +#ifndef NO_IPL_CODE +/*----------------------------------------------------------------------*/ +/* f l W r i t e I P L */ +/* */ +/* Place a user buffer to both copies of the IPL area */ +/* */ +/* Note : */ +/* */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* 4 LSB - Socket number */ +/* irData : Pointer to user buffer */ +/* irLength : Size of the buffer */ +/* irFlags : See flags bellow */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSWriteIPL(IOreq* ioreq) +{ +#ifdef FL_READ_ONLY + return flFeatureNotSupported; +#else /*FL_READ_ONLY*/ + DOCH_Error rc = DOCH_GeneralFailure; + IOreq ioreq_WriteIpl; + IOreq ioreq_ReadIpl; + FLDword iplFlags, totalIPLSize, i , dwIPLSizeToWrite=0; + + if ((ioreq->irLength & (DOCH_SECTOR_SIZE - 1)) != 0) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): writeIPL must be done in buffers with N x 512B size (while n is a positive integer.\r\n"); + return flBadParameter; + } + if ((ioreq->irFlags & FL_IPL_128K_WINDOW_MODE) == 0) /*8KB window*/ + { + iplFlags = DOCH_IPL_MODE_8KB_WINDOW | DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT; + if (ioreq->irFlags & FL_IPL_VIRTUAL_RAM_MODE) + { + iplFlags |= DOCH_IPL_MODE_VIRTUAL_RAM; + totalIPLSize = TFFS_API_VIRTUAL_RAM_8K_IPL_SIZE; + } + else if (ioreq->irFlags & FL_DOC_IPL_PAGED_RAM_MODE) + { + iplFlags |= DOCH_IPL_MODE_PAGED_RAM; + totalIPLSize = TFFS_API_PAGED_IPL_SIZE; + } + else + { + totalIPLSize = TFFS_API_8K_NORMAL_IPL_SIZE; + } + } + else /*128KB window*/ + { + iplFlags = DOCH_IPL_MODE_NORMAL_RAM | DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT; + if (ioreq->irFlags & FL_IPL_VIRTUAL_RAM_MODE) + { + iplFlags |= DOCH_IPL_MODE_VIRTUAL_RAM; + totalIPLSize = TFFS_API_VIRTUAL_RAM_128K_IPL_SIZE; + } + else if (ioreq->irFlags & FL_DOC_IPL_PAGED_RAM_MODE) + { + iplFlags |= DOCH_IPL_MODE_PAGED_RAM; + totalIPLSize = TFFS_API_PAGED_IPL_SIZE; + } + else + { + totalIPLSize = TFFS_API_128K_NORMAL_IPL_SIZE; + } + } + if (ioreq->irFlags & FL_IPL_SWAP_BYTES_MODE) + { + iplFlags |= DOCH_IPL_MODE_ACTIVE_SWAP_BYTES; + } + if ((FLDword)(ioreq->irCount + ((ioreq->irLength) >> DOCH_SECTOR_SIZE_BITS)) > totalIPLSize) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): IPL size exceed current IPL mode allowed size."); + return flBadParameter; + } + if (iplFlags & DOCH_IPL_MODE_VIRTUAL_RAM) + { + /*virtual mode requires all IPL size to be written*/ + dwIPLSizeToWrite = totalIPLSize; + } + else + { + dwIPLSizeToWrite = (FLDword)(ioreq->irCount + ((ioreq->irLength) >> DOCH_SECTOR_SIZE_BITS)); + /*round to page size*/ + dwIPLSizeToWrite= (dwIPLSizeToWrite+DOCH_SECTORS_PER_PAGE-1) & (~(DOCH_SECTORS_PER_PAGE-1)); + if (dwIPLSizeToWrite > totalIPLSize) /*sanity check - should not fail*/ + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): IPL size exceed current IPL mode allowed size."); + return flBadParameter; + } + } + if (ioreq->irCount != 0) + { + for (i = 0; i < (FLDword)(ioreq->irCount);i++) + { + tffsAPISetIoreq(&ioreq_ReadIpl, FL_GET_SOCKET_FROM_HANDLE(ioreq),iplFlags,0,dochVol.intermediateBuf,1,i); + rc = flDOCHReadIPL(&ioreq_ReadIpl); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): Failed reading previous IPL copy. status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flReadFault); + } + + tffsAPISetIoreq(&ioreq_WriteIpl, FL_GET_SOCKET_FROM_HANDLE(ioreq),iplFlags,0,dochVol.intermediateBuf, + 1, dwIPLSizeToWrite); + if (i == 0) + ioreq_WriteIpl.irFlags |= DOCH_IPL_WRITE_FIRST_CHUNK; + rc = flDOCHWriteIPL(&ioreq_WriteIpl); + if (rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): Failed writing previous IPL copy. status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + } + } + + tffsAPISetIoreq(&ioreq_WriteIpl, FL_GET_SOCKET_FROM_HANDLE(ioreq),iplFlags,0,ioreq->irData, + ioreq->irLength >> DOCH_SECTOR_SIZE_BITS, dwIPLSizeToWrite); + if (ioreq->irCount == 0) + { + ioreq_WriteIpl.irFlags |= DOCH_IPL_WRITE_FIRST_CHUNK; + + ioreq_WriteIpl.irFlags |= (FL_IPL_DELAY_CELL_CONFIG_READ<<4); + ioreq_WriteIpl.irFlags |= (FL_IPL_DELAY_CELL_CONFIG_WRITE<<8); + } + + rc = flDOCHWriteIPL(&ioreq_WriteIpl); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): Failed writing new IPL data. status: "); + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): TFFSAbsWrite failed with status: "); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + /*Write remainder*/ + tffsset(dochVol.intermediateBuf, 0, DOCH_SECTOR_SIZE); + for (i = ((ioreq->irLength >> DOCH_SECTOR_SIZE_BITS)+ ioreq->irCount); i < dwIPLSizeToWrite ; i++) + { + rc = flDOCHWriteIPL(tffsAPISetIoreq( &ioreq_WriteIpl,FL_GET_SOCKET_FROM_HANDLE(ioreq),iplFlags, + 0,dochVol.intermediateBuf,1,totalIPLSize)); + if (rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSWriteIPL(): Failed writing previous IPL copy. status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + } + return flOK; +#endif /*FL_READ_ONLY*/ +}/*TFFSWriteIPL*/ + +/*----------------------------------------------------------------------*/ +/* r e a d I P L */ +/* */ +/* Read IPL to user buffer. */ +/* */ +/* Note : Read length must be a multiplication of 512 bytes */ +/* Note : Causes DiskOnChip Millennium Plus to download (i,e protection */ +/* key will be removed from all partitions. */ +/* */ +/* Parameters: */ +/* irHandle : Socket number (0,1,..) */ +/* 4 LSB - Socket number */ +/* irData : Pointer to user buffer */ +/* irLength : Size of the buffer */ +/* irCount : Used IPL size on the media */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSReadIPL(IOreq* ioreq) +{ + FLStatus rc = flReadFault; + DOCH_Error dochErr = DOCH_ReadFault; + FLDword fullSectorsToRead, bytesToPad = 0; + /*FLByte padBuffer[DOCH_SECTOR_SIZE];*/ + FLByte * padBuffer=dochVol.intermediateBuf; + IOreq ioreq_ipl; + + fullSectorsToRead = ioreq->irLength >> DOCH_SECTOR_SIZE_BITS; + bytesToPad = ioreq->irLength % DOCH_SECTOR_SIZE; + tffsset(&ioreq_ipl, 0, sizeof(ioreq_ipl)); + ioreq_ipl.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + ioreq_ipl.irCount = ioreq->irCount; + + if (fullSectorsToRead > 0) + { + ioreq_ipl.irLength = fullSectorsToRead; + ioreq_ipl.irData = ioreq->irData; + dochErr = flDOCHReadIPL(&ioreq_ipl); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSReadIPL(): TFFSAbsRead failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(rc, flReadFault); + } + } + + if ((bytesToPad > 0) || (ioreq->irLength == 0)) + { + ioreq_ipl.irLength = 1; + ioreq_ipl.irData = padBuffer; + dochErr = flDOCHReadIPL(&ioreq_ipl); + if(dochErr != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSReadIPL(): TFFSAbsRead failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), dochErr)); + TFFS_API_RET_PART_FLSTATUS(rc, flReadFault); + } + tffscpy((void*)(((FLByte*)ioreq->irData) + (fullSectorsToRead<irFlags = DOCH_IPL_MODE_NORMAL_RAM; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_PAGED_RAM) != 0) + ioreq->irFlags |= FL_DOC_IPL_PAGED_RAM_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_VIRTUAL_RAM) != 0) + ioreq->irFlags |= FL_IPL_VIRTUAL_RAM_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_ADDRESS_SHIFT_IN_AFFECT) == 0) + ioreq->irFlags |= FL_IPL_NO_ADDRESS_SHIFT_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_ACTIVE_SWAP_BYTES) != 0) + ioreq->irFlags |= FL_IPL_SWAP_BYTES_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_8KB_WINDOW) == 0) + { + ioreq->irFlags |= FL_IPL_128K_WINDOW_MODE; + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_VIRTUAL_RAM) != 0) + ioreq->irCount = TFFS_API_VIRTUAL_RAM_128K_IPL_SIZE << DOCH_SECTOR_SIZE_BITS; + else if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_PAGED_RAM) != 0) + ioreq->irCount = (TFFS_API_PAGED_IPL_SIZE << DOCH_SECTOR_SIZE_BITS); + else + ioreq->irCount = (TFFS_API_128K_NORMAL_IPL_SIZE << DOCH_SECTOR_SIZE_BITS); + } + else + { + if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_VIRTUAL_RAM) != 0) + ioreq->irCount = TFFS_API_VIRTUAL_RAM_8K_IPL_SIZE << DOCH_SECTOR_SIZE_BITS; + else if ((ioreq_ipl.irFlags & DOCH_IPL_MODE_PAGED_RAM) != 0) + ioreq->irCount = (TFFS_API_PAGED_IPL_SIZE << DOCH_SECTOR_SIZE_BITS); + else + ioreq->irCount = (TFFS_API_8K_NORMAL_IPL_SIZE << DOCH_SECTOR_SIZE_BITS); + } + return flOK; +}/*TFFSReadIPL()*/ + +#endif /*NO_IPL_CODE*/ + + +/*----------------------------------------------------------------------*/ +/* f l I d e n t i f y P r o t e c t i o n */ +/* b d k I d e n t i f y P r o t e c t i o n */ +/* */ +/* Returns the specified partitions protection attributes */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irFlags CHANGEABLE_PROTECTION - changeable protection type */ +/* PROTECTABLE - partition can receive protection */ +/* READ_PROTECTED - partition is read protected */ +/* WRITE_PROTECTED - partition is write protected */ +/* LOCK_ENABLED - HW lock signal is enabled */ +/* LOCK_ASSERTED - HW lock signal is asserted */ +/* KEY_INSERTED - key is inserted (not currently */ +/* protected. */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSIdentifyProtection(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLByte protectionType,guestAccessMode,lockControl,otpBit,hwLockSignal,sLockSignal,authenticated; +#ifdef FL_SOTP + FLByte sotp; + FLDword dwSOTPoffset=0; +#endif /*FL_SOTP*/ + + /*Retrieve partition info*/ + /*-----------------------*/ + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSIdentifyProtection(): flDOCHPartitionInfo failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + protectionType = (FLByte)(((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2 & DOCH_PA2B_PROTECTION_TYPE); + guestAccessMode = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2 & DOCH_PA2B_GUEST_MODE) + >> DOCH_PA2O_GUEST_MODE); + lockControl = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2 & DOCH_PA2B_LOCK_CTRL) + >> DOCH_PA2O_LOCK_CTRL); + otpBit = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_PERM_LOCKED) + >> DOCH_CFSO_PERM_LOCKED); + + hwLockSignal = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_HW_LOCK_ASSERTED) + >> DOCH_CFSO_HW_LOCK_ASSERTED); + sLockSignal = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_SW_LOCK_ASSERTED) + >> DOCH_CFSO_SW_LOCK_ASSERTED); + + authenticated = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_USER_AUTHENTICATED) + >> DOCH_CFSO_USER_AUTHENTICATED); +#ifdef FL_SOTP + sotp = (FLByte)((((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwCommandFlagsOrStatuses & DOCH_CFSB_SOTP_LOCKED) + >> DOCH_CFSO_SOTP_LOCKED); + if (sotp) + { + /*return SOTP offset*/ + ioreq->irCount=((DOCH_PartitionInfo*)dochVol.intermediateBuf)->dwSOTPoffset; + } + else + { + /*illegal offset returned in case of non SOTP partition*/ + ioreq->irCount=0xFFFFFFFF; + } +#endif /*FL_SOTP*/ + + /*Retrieve partition attributes*/ + /*-----------------------------*/ + tffsset(dochVol.intermediateBuf, 0, sizeof(DOCH_PartitionUserAttrWithBinary)); + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq,ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0 )); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSIdentifyProtection(): flDOCHGetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + /*Set popper bits in irFlags according to partition attributes*/ + /*------------------------------------------------------------*/ + ioreq->irFlags=0; + + /*Set PROTECTABLE and CHANGEABLE_PROTECTION to user attributes*/ + /*------------------------------------------------------------*/ + ioreq->irFlags |= (((DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf)->bProtected * PROTECTABLE); + ioreq->irFlags |= (((DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf)->bChangableProtection * CHANGEABLE_PROTECTION); + + if(protectionType != DOCH_PARTITION_NOT_PROTECTED) + { + /*Default access mode (without authentication)*/ + /*--------------------------------------------*/ + if(guestAccessMode == DOCH_PART_ACCESS_MODE_NONE) + ioreq->irFlags |= (READ_PROTECTED | WRITE_PROTECTED); + else if(guestAccessMode == DOCH_PART_ACCESS_MODE_RO) + ioreq->irFlags |= WRITE_PROTECTED; + } + + /*Lock signal enabled/disabled*/ + /*----------------------------*/ + if(lockControl == DOCH_LOCK_ACTIVE) + ioreq->irFlags |= LOCK_ENABLED; + + /*Lock signal asserted*/ + /*--------------------*/ + if(hwLockSignal) + ioreq->irFlags |= LOCK_ASSERTED; + + /*Key inserted*/ + /*------------*/ + if(authenticated && protectionType != DOCH_PARTITION_NOT_PROTECTED) + ioreq->irFlags |= KEY_INSERTED; + + + /* SLOCK signal */ + /*--------------------------*/ + if(sLockSignal) + ioreq->irFlags |= STICKY_LOCK_ASSERTED; + + if( ((ioreq->irFlags & (WRITE_PROTECTED | READ_PROTECTED)) == 0) && + (protectionType != DOCH_PARTITION_NOT_PROTECTED) && (otpBit==0) ) + { + ioreq->irFlags |= KEY_INSERTED; + } + + /*OTW (Indicated by OTP Bit)*/ + /*--------------------------*/ + if(otpBit == 1) + { +#ifdef FL_SOTP + if (!sotp) + { +#endif /*FL_SOTP*/ + /* WRITE_PROTECTED and CHANGEABLE_PROTECTION added for compatibility with non-mDOC H3 devices */ + ioreq->irFlags |= (OTW_PROTECTED|WRITE_PROTECTED|CHANGEABLE_PROTECTION); +#ifdef FL_SOTP + } + else + { + ioreq->irFlags |= (OTW_PROTECTED); + } +#endif /*FL_SOTP*/ + } +#ifdef FL_SOTP + /* SOTP partition*/ + if (sotp) + { + ioreq->irFlags |= IDENTIFIED_SEQUENTIAL_OTP; + } +#endif /*FL_SOTP*/ + + /* check that no protection applied at all */ + if( (protectionType == DOCH_PARTITION_NOT_PROTECTED) && (ioreq->irFlags==0)) + return flNotProtected; + + return flOK; +}/*TFFSIdentifyProtection()*/ + + +/*----------------------------------------------------------------------*/ +/* f l R e m o v e P r o t e c t i o n K e y */ +/* b d k R e m o v e P r o t e c t i o n K e y */ +/* */ +/* Remove the protection key making the partition protected again */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSRemoveProtectionKey(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLByte bPartNum; + DOCH_PartitionInfo * pDOCH_PartitionInfo = (DOCH_PartitionInfo*)dochVol.intermediateBuf; + + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0, dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + /*If already protected - return DOCH_OK*/ + if(rc == DOCH_ProtectionFault) + return flOK; + + DBG_PRINT_ERR(FLZONE_API, "TFFSRemoveProtectionKey(): flDOCHPartitionInfo Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return TFFS_API_RET(rc); + } + if( (pDOCH_PartitionInfo->partitionAttributes2&DOCH_PA2B_PROTECTION_TYPE) == DOCH_PARTITION_NOT_PROTECTED) + { + if( (pDOCH_PartitionInfo->partitionAttributes2&DOCH_PA2B_LOCK_CTRL)!=0 ) + { + if( ((pDOCH_PartitionInfo->partitionAttributes2&DOCH_PA2B_GUEST_MODE)==DOCH_PART_ACCESS_MODE_FULL ) && + ((pDOCH_PartitionInfo->partitionAttributes2&DOCH_PA2B_USER_MODE) ==DOCH_PART_ACCESS_MODE_FULL ) ) + {/* both user and guest have full protection -> write protection not applied */ + return flOK; /* return OK for backward compatibility */ + } + } + else + { + return flNotProtected; /* trying to remove key from not-protected partition */ + } + }/* not protected partition */ + + + tffsset(&myIoreq,0,sizeof(myIoreq)); + myIoreq.irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq); + bPartNum = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(&myIoreq, bPartNum); + myIoreq.irFlags = DOCH_ACCESS_USER_PASSWORD; + /*Disable partition authentication*/ + /*--------------------------------*/ + rc = flDOCHDisablePartAccess(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSRemoveProtectionKey(): flDOCHDisablePartAccess Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + + return TFFS_API_RET(rc); + } + return flOK; +}/*TFFSRemoveProtectionKey()*/ + +/*----------------------------------------------------------------------*/ +/* f l C h a n g e P r o t e c t i o n K e y */ +/* b d k C h a n g e P r o t e c t i o n K e y */ +/* */ +/* Changes the current protection key with a new one. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to the new 8 bytes key array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSChangeProtectionKey(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + DOCH_PartitionUserAttrWithBinary* pPartitionUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + DOCH_PartitionProtectionAPI * pPartitionProtectionAPI = (DOCH_PartitionProtectionAPI *)dochVol.intermediateBuf; + + /*Retrieve partition info*/ + /*-----------------------*/ + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq, ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionKey(): flDOCHGetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + if( pPartitionUserAttrWithBinary->bChangableProtection == FALSE ) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionKey(): Can't change protection of unchangeable protection partition.\n"); + return flUnchangeableProtection; + } + + /*-----------------------*/ + /*Change passkey to new one*/ + /*-------------------------*/ + tffsset(dochVol.intermediateBuf, 0, sizeof(DOCH_PartitionProtectionAPI)); + tffscpy(pPartitionProtectionAPI->bPasskey, ioreq->irData, PROTECTION_KEY_LENGTH); + + /*Set new partition info (with new passkey) back to DOCH*/ + /*------------------------------------------------------*/ + rc = flDOCHSetParitionProtection(tffsAPISetIoreq(&myIoreq, ioreq->irHandle,DOCH_PASSKEY_VALID,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionKey(): flDOCHSetParitionProtection Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc) ; + } + return flOK; +}/*TFFSChangeProtectionKey()*/ + + +/*----------------------------------------------------------------------*/ +/* f l C h a n g e P r o t e c t i o n T y p e */ +/* b d k C h a n g e P r o t e c t i o n T y p e */ +/* */ +/* Changes the protection attributes of the partitions. */ +/* In order for a partition to change its protection type (without */ +/* reformatting the media) it must have the CHANGEABLE_PRTOECTION */ +/* attribute. */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Partition # (zero based) */ +/* bits 3-0 - Socket # (zero based) */ +/* irFlags : CHANGEABLE_PROTECTION - changeable protection type */ +/* PROTECTABLE - partition can receive protection */ +/* READ_PROTECTED - partition is read protected */ +/* WRITE_PROTECTED - partition is write protected */ +/* LOCK_ENABLED - HW lock signal is enabled */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSChangeProtectionType(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + IOreq ioreq3; + FLBoolean read_protect, write_protect, locked; + FLDword guestAccessMode; + FLDword partitionAttr; + FLByte otwAsserted = ((ioreq->irFlags & OTW_PROTECTED) == OTW_PROTECTED); + DOCH_PartitionUserAttrWithBinary* pPartitionUserAttrWithBinary = (DOCH_PartitionUserAttrWithBinary*)dochVol.intermediateBuf; + DOCH_PartitionProtectionAPI * pPartitionProtectionAPI = (DOCH_PartitionProtectionAPI *)dochVol.intermediateBuf; + + /*Retrieve partition info*/ + /*-----------------------*/ + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq,ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0) ); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHgetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + if (pPartitionUserAttrWithBinary->bChangableProtection == FALSE) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): Can't change protection of unchangeable protection partition.\n"); + return flUnchangeableProtection; + } + + /*If OTW_PROTECTED was asserted - lock the partition from further writing*/ + /*-----------------------------------------------------------------------*/ + if(otwAsserted) + { + if(ioreq->irFlags == (OTW_PROTECTED | PROTECTABLE | WRITE_PROTECTED)) + { + + /*Retrieve partition user attributes*/ + /*----------------------------------*/ + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHGetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + /* change partition protection to non-changable */ + pPartitionUserAttrWithBinary->bChangableProtection = 0; + + /*Set attributes back to device*/ + /*----------------------------------*/ + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHSetParitionUserAttributes Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + /*Lock the partition as OTP */ + /*--------------------------*/ + tffsset(dochVol.intermediateBuf, 0, sizeof(DOCH_PartitionProtectionAPI)); + tffsAPISetIoreq(&myIoreq, ioreq->irHandle,DOCH_LOCK_AS_OTP,0,dochVol.intermediateBuf,0,0); + rc = flDOCHSetParitionProtection(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): DOCHSetParitionProtection failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + TFFS_API_RET_PART_FLSTATUS(rc, flWriteFault); + } + + return flOK; + } + else + { + return flBadParameter; + } + }/*OTW protection*/ + + /*Retrieve current partition info from DOCH*/ + /*-----------------------------------------*/ + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHPartitionInfo Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + partitionAttr = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2; + + /*Retrieve partition user attributes*/ + /*----------------------------------*/ + rc = flDOCHGetParitionUserAttributes(tffsAPISetIoreq(&myIoreq, ioreq->irHandle, 0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHGetParitionUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + /*Change protection type + (only relevant fields are changed from the retrieved values!) + =============================================================*/ + pPartitionUserAttrWithBinary->bChangableProtection = + (((ioreq->irFlags & CHANGEABLE_PROTECTION) == CHANGEABLE_PROTECTION) + && (pPartitionUserAttrWithBinary->bChangableProtection == 1)); + + pPartitionUserAttrWithBinary->bProtected = ((ioreq->irFlags & PROTECTABLE) == PROTECTABLE); + + /*Set attributes back to device*/ + rc = flDOCHSetParitionUserAttributes(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHSetParitionUserAttributes Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + + tffsset(dochVol.intermediateBuf, 0, (DOCH_SECTOR_SIZE)); + + /*Default access mode*/ + /*-------------------*/ + read_protect = ((ioreq->irFlags & READ_PROTECTED) == READ_PROTECTED); + write_protect = ((ioreq->irFlags & WRITE_PROTECTED) == WRITE_PROTECTED); + locked = ((ioreq->irFlags & LOCK_ENABLED) == LOCK_ENABLED); + if(read_protect) + guestAccessMode = DOCH_PART_ACCESS_MODE_NONE; + else if(write_protect) + guestAccessMode = DOCH_PART_ACCESS_MODE_RO; + else + guestAccessMode = DOCH_PART_ACCESS_MODE_FULL; + + DOCH_SetBits(&partitionAttr, DOCH_PA2B_GUEST_MODE, DOCH_PA2O_GUEST_MODE, guestAccessMode); + + if(guestAccessMode != DOCH_PART_ACCESS_MODE_FULL) + DOCH_SetBits(&partitionAttr, DOCH_PA2B_PROTECTION_TYPE, DOCH_PA2O_PROTECTION_TYPE, 1); + + /*Fill partPropApi structure*/ + /*--------------------------*/ + pPartitionProtectionAPI->dwProtectionType = + ((partitionAttr & DOCH_PA2B_PROTECTION_TYPE) >> DOCH_PA2O_PROTECTION_TYPE); + pPartitionProtectionAPI->dwUserAccessMode = + ((partitionAttr & DOCH_PA2B_USER_MODE) >> DOCH_PA2O_USER_MODE); + pPartitionProtectionAPI->dwGuestAccessMode = + ((partitionAttr & DOCH_PA2B_GUEST_MODE) >> DOCH_PA2O_GUEST_MODE); + pPartitionProtectionAPI->dwMasterControl = + ((partitionAttr & DOCH_PA2B_MASTER_CTRL) >> DOCH_PA2O_MASTER_CTRL); + pPartitionProtectionAPI->dwEncryptionType = + ((partitionAttr & DOCH_PA2B_ENCRYPT_TYPE) >> DOCH_PA2O_ENCRYPT_TYPE); + pPartitionProtectionAPI->dwLockControl = + ((partitionAttr & DOCH_PA2B_LOCK_CTRL) >> DOCH_PA2O_LOCK_CTRL); + pPartitionProtectionAPI->dwMaxNumOfAuthAttempts = + ((partitionAttr & DOCH_PA2B_MAX_AUTH_ATTEMPTS) >> DOCH_PA2O_MAX_AUTH_ATTEMPTS); + + if(locked == TRUE) + pPartitionProtectionAPI->dwLockControl = DOCH_LOCK_ACTIVE; + else + pPartitionProtectionAPI->dwLockControl = DOCH_LOCK_NOT_ACTIVE; + + /*Set new partition info (with new protection type) back to DOCH*/ + /*--------------------------------------------------------------*/ + rc = flDOCHSetParitionProtection(tffsAPISetIoreq(&myIoreq,ioreq->irHandle,DOCH_ATTRIBUTES_VALID,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSChangeProtectionType(): flDOCHSetParitionProtection Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return rc==DOCH_ProtectionFault ? flHWProtection : TFFS_API_RET(rc); + } + + /*If all is well, disable access to the partition*/ + /* (Is reset needed???? - TBD)*/ + return TFFSRemoveProtectionKey(tffsAPISetIoreq(&ioreq3,ioreq->irHandle,0,0,0,0,0)); +}/*TFFSChangeProtectionType()*/ + +/*----------------------------------------------------------------------*/ +/* f l A p p l y S t i c k y L o c k */ +/* */ +/* Enable the sticky lock mode to all relevant partitions */ +/* */ +/* Parameters: */ +/* irHandle : Drive number (0, 1, ...) */ +/* bits 7-4 - Must be set to 0 */ +/* bits 3-0 - Socket # (zero based) */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSApplyStickyLock(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + + rc = DOCHConfigHW(tffsAPISetIoreq(&myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), DOCH_SLOCK, 0,0,DOCH_SLOCK_ACTIVE,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSApplyStickyLock(): DOCHConfigHW Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return flBadFunction; + } + + return flOK; +}/*TFFSApplyStickyLock*/ + + +/*-----------------------------------------*/ +/* Function name : TFFSHwProtectionLock*/ +/* Description : */ +/* Return type : static FLStatus */ +/* Argument : IOreq* ioreq*/ +/*-----------------------------------------*/ +static FLStatus TFFSHwProtectionLock(IOreq* ioreq) +{ + DOCH_Error rc; + IOreq myIoreq; + FLDword partitionAttr; + DOCH_PartitionProtectionAPI * pPartitionProtectionAPI = (DOCH_PartitionProtectionAPI*)dochVol.intermediateBuf; + + /*Retrieve current partition info from DOCH*/ + /*-----------------------------------------*/ + rc = flDOCHPartitionInfo(tffsAPISetIoreq(&myIoreq, ioreq->irHandle,0,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwProtectionLock(): flDOCHPartitionInfo Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } + partitionAttr = ((DOCH_PartitionInfo*)dochVol.intermediateBuf)->partitionAttributes2; + + memset(dochVol.intermediateBuf, 0, sizeof(DOCH_PartitionProtectionAPI)); + + /*Lock signal*/ + /*-----------*/ + if((ioreq->irFlags & LOCK_ENABLED) == LOCK_ENABLED) + DOCH_SetBits(&partitionAttr, DOCH_PA2B_LOCK_CTRL, DOCH_PA2O_LOCK_CTRL, DOCH_LOCK_ACTIVE); + else + DOCH_SetBits(&partitionAttr, DOCH_PA2B_LOCK_CTRL, DOCH_PA2O_LOCK_CTRL, DOCH_LOCK_NOT_ACTIVE); + + /*Fill partPropApi structure*/ + /*--------------------------*/ + pPartitionProtectionAPI->dwProtectionType = + ((partitionAttr & DOCH_PA2B_PROTECTION_TYPE) >> DOCH_PA2O_PROTECTION_TYPE); + pPartitionProtectionAPI->dwUserAccessMode = + ((partitionAttr & DOCH_PA2B_USER_MODE) >> DOCH_PA2O_USER_MODE); + pPartitionProtectionAPI->dwGuestAccessMode = + ((partitionAttr & DOCH_PA2B_GUEST_MODE) >> DOCH_PA2O_GUEST_MODE); + pPartitionProtectionAPI->dwMasterControl = + ((partitionAttr & DOCH_PA2B_MASTER_CTRL) >> DOCH_PA2O_MASTER_CTRL); + pPartitionProtectionAPI->dwEncryptionType = + ((partitionAttr & DOCH_PA2B_ENCRYPT_TYPE) >> DOCH_PA2O_ENCRYPT_TYPE); + pPartitionProtectionAPI->dwLockControl = + ((partitionAttr & DOCH_PA2B_LOCK_CTRL) >> DOCH_PA2O_LOCK_CTRL); + pPartitionProtectionAPI->dwMaxNumOfAuthAttempts = + ((partitionAttr & DOCH_PA2B_MAX_AUTH_ATTEMPTS) >> DOCH_PA2O_MAX_AUTH_ATTEMPTS); + + /*Set modified partition info*/ + /*---------------------------*/ + rc = flDOCHSetParitionProtection(tffsAPISetIoreq(&myIoreq, ioreq->irHandle,DOCH_ATTRIBUTES_VALID,0,dochVol.intermediateBuf,0,0)); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "TFFSHwProtectionLock(): flDOCHSetParitionProtection Failed with status : "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return (rc==DOCH_ProtectionFault) ? flHWProtection : TFFS_API_RET(rc) ; + } + return flOK; +}/*TFFSHwProtectionLock()*/ +#ifdef FL_SLPP +/*----------------------------------------------------------------------*/ +/* f l S L P P U n l o c k R a n g e */ +/* */ +/* Unlock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to unlock */ +/* irLength : Number of sectors to unlock */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPUnlockRange(IOreq* ioreq) +{ + DOCH_Error rc; + + rc = flDOCHSLPPUnlockRange(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPUnlockRange(): flDOCHSLPPUnlockRange failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + return flOK; +}/*TFFSSLPPUnlockRange*/ + +/*----------------------------------------------------------------------*/ +/* f l S L P P L o c k R a n g e */ +/* */ +/* Lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to lock */ +/* irLength : Number of sectors to lock */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPLockRange(IOreq* ioreq) +{ + DOCH_Error rc; + + rc = flDOCHSLPPLockRange(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPLockRange(): flDOCHSLPPLockRange failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + return flOK; +}/*TFFSSLPPLockRange*/ + +/*----------------------------------------------------------------------*/ +/* f l S L P P U n l o c k E n t i r e P a r t i t i o n */ +/* */ +/* Unlock all sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to an 8 bytes passkey array */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPUnlockEntirePartition(IOreq* ioreq) +{ + DOCH_Error rc; + + rc = flDOCHSLPPUnlockEntirePartition(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPUnlockEntirePartition(): flDOCHSLPPUnlockEntirePartition failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + return flOK; +}/*TFFSSLPPUnlockEntirePartition*/ + +/*----------------------------------------------------------------------*/ +/* f l S L P P S t i c k y L o c k R a n g e */ +/* */ +/* Sticky lock a range of sectors on a sector protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irCount : First sector to sticky lock */ +/* irLength : Number of sectors to sticky lock */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPStickLockRange(IOreq* ioreq) +{ + DOCH_Error rc; + + rc = flDOCHSLPPStickyLockRange(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPStickLockRange(): flDOCHSLPPStickyLockRange failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + return flOK; +}/*TFFSSLPPStickLockRange*/ + +/*----------------------------------------------------------------------*/ +/* f l S L P P R e p o r t L o c k e d R a n g e s */ +/* */ +/* Report currently defined unlocked/stick locked ranges on a sector */ +/* protected partition. */ +/* */ +/* Parameters: */ +/* irHandle : Bits 3-0 - Socket # (zero based) */ +/* irData : Pointer to DOCH_SLPPReport structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/* irCount : Number of currently defined ranges */ +/*----------------------------------------------------------------------*/ +static FLStatus TFFSSLPPReportLockedRanges(IOreq* ioreq) +{ + DOCH_Error rc; + + DOCH_SLPPReport* slppRep = (DOCH_SLPPReport*)ioreq->irData; + + rc = flDOCHSLPPReportRanges(ioreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("TFFSSLPPReportLockedRanges(): flDOCHSLPPStickyLockRange failed with status: 0x%x \r\n\r\n"), rc)); + + if(rc == DOCH_ProtectionFault) + return flHWProtection; + else + return flGeneralFailure; + } + + ioreq->irCount = slppRep->numOfActiveRanges; + + return flOK; +}/*TFFSSLPPReportLockedRanges*/ +#endif /*FL_SLPP*/ + +/*----------------------------------------------------------------------*/ +/* Function name : TFFSPassThrough*/ +/* Description : calls to DOCH pass through command with converted */ +/* parameters */ +/* Return type : FLStatus */ +/* Argument : IOreq FAR2 *ioreq*/ +/* irHandle : Socket number ( 0,1,2... ) */ +/* 4 LSB - Socket number */ +/* irData : pointer to user buffer (for DATA IN and DATA out */ +/* commands) */ +/* irLength : number of sectors in buffer, pointed to by irData*/ +/* irCount : bits 0..1 - pass through operation flow, where */ +/* 0 - No Data(CTRL), 1 - Data IN, 2 - Data OUT */ +/* bit 2 - 1, when interrupt should be used, */ +/* 0 - otherwise */ +/* bits 4..7 - frame size exponent, should be set */ +/* to 0 for now - 1 sector */ +/* irPath : pointer to buffer from type DOCH_Registers* */ +/* IN - input registers, OUT - out registers */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +FLStatus TFFSPassThrough(IOreq FAR2 *ioreq) +{ + DOCH_Error rc; + /*IOreq myIoreq;*/ + FLSNative snFlow = (FLSNative)(ioreq->irCount & 0x00000003); + FLBoolean fUseInterrupt = (FLBoolean)((ioreq->irCount&0x00000004)>>2); + /*FLDword dwMultSectorFrame = (FLDword)(ioreq->irCount&0x00000f0)>>4);*/ + /*DOCH_Socket* pDev = DOCH_get_socket(FL_GET_SOCKET_FROM_HANDLE(ioreq));*/ + + /* TODO - add retrieve current transfer mode from device */ + + rc = DOCHAtaPassThrough( FL_GET_SOCKET_FROM_HANDLE(ioreq), snFlow, + (DOCH_Registers*)ioreq->irPath, (DOCH_Registers*)ioreq->irPath, + (FLNative)ioreq->irLength, (void*)ioreq->irData, fUseInterrupt); + + return (rc==DOCH_ATA_NO_ERROR)?flOK : flGeneralFailure; +}/*TFFSPassThrough()*/ + + +/*----------------------------------------------------------------------*/ +/* b d C a l l B C T o S D K */ +/* */ +/* Performs needed general operations before calling actual function */ +/* Calls appropriate TFFS function (that will convert to SDK routine(s))*/ +/* */ +/* Parameters: */ +/* functionNo : DOCH SDK function to run */ +/* ioreq : DOCH ioreq structure */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +FLStatus bdCallTFFSToDOCH(FLFunctionNo functionNo, IOreq FAR2 *ioreq) +{ + FLStatus rc = flFeatureNotSupported; + DOCH_Error dochRc; + IOreq myIoreq; + FLByte partNum; + FLByte partNumTemp = 0; + FLHandle origIrHandle; + DOCH_DiskUserAttrWithBinary* pDiskUserAttrWithBinary; + IOreq ioreq1; + + /*Sanity Check*/ + /*------------*/ + if(ioreq == NULL) + { + DBG_PRINT_ERR(FLZONE_BLKDEV,"bdCallTFFSToDOCH: - Ioreq is NULL"); + return flBadParameter; + } + + origIrHandle = ioreq->irHandle; + + /* Actions to take on the first time bdCallTFFSToDOCH is invoked */ + /*---------------------------------------------------------------*/ + if(dochBdCallWasCalled == FALSE) + { + checkStatus(flInit()); + tffsset (&dochVol, 0, sizeof(dochVol)); + checkStatus(flCreateMutex(&dochVol.mutex)); + dochBdCallWasCalled = TRUE; + dochVol.intermediateBuf = (FLByte*)FL_MALLOC(DOCH_SECTOR_SIZE); + if (dochVol.intermediateBuf == NULL) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallTFFSToDOCH(): Can't allocate intermediate buffer.\r\n"); + return flNotEnoughMemory; + } + + /*Retrieve diskAttributes at least once*/ + /*(numOfBinaryPartitions, iplExists, otpExists will be further updated + by TFFSflashFormat if called) + ---------------------------*/ + dochRc = flDOCHGetDiskUserAttributes(tffsAPISetIoreq(&myIoreq, 0,0,0,dochVol.intermediateBuf,0,0)); + if(dochRc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallTFFSToDOCH(): flDOCHGetDiskUserAttributes failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); +#ifdef CHECK_POWER_ON_EVERY_COMMAND + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + return flSuspendModeDetected; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + return flBadFunction; + } + + pDiskUserAttrWithBinary =(DOCH_DiskUserAttrWithBinary*)dochVol.intermediateBuf; + + dochVol.numOfBinaryPartitions = pDiskUserAttrWithBinary->bNumOfBinaryPartitions; + dochVol.iplExists = pDiskUserAttrWithBinary->bIplPresent; + dochVol.otpExists = pDiskUserAttrWithBinary->bOtpPresent; + }/* dochBdCallWasCalled was called */ + + /* get partition number and check it up to call type */ + partNum = FL_GET_FLASH_PARTITION_FROM_HANDLE(ioreq); + if((functionNo >= INDEX_BINARY_START) && (functionNo <= INDEX_BINARY_END)) + {/* binary partition */ + + /* check that the number of binary partition not exceeded number of BDK on the device */ + if( partNum >= dochVol.numOfBinaryPartitions ) + return flBadDriveHandle; + + rc = actualPartitionNum(&partNum, PARTITION_TYPE_BINARY, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + if(rc != flOK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallTFFSToDOCH(): actualPartitionNum failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return rc; + } + ioreq->irHandle &= (0xFFFFFF0F); + ioreq->irHandle |= (partNum << 4); + } + else + { + if((functionNo >= INDEX_NEED_PARTITION_0_START) && (functionNo <= INDEX_NEED_PARTITION_0_END)) + {/* calls, which required partition number zero */ + if( partNum!=0 ) + return flBadDriveHandle; + } + else + { + if(functionNo > INDEX_NEED_PARTITION_0_END) + {/* BDTL partition */ + rc = actualPartitionNum(&partNum, PARTITION_TYPE_BDTL, FL_GET_SOCKET_FROM_HANDLE(ioreq)); + if(rc != flOK) + { + DBG_PRINT_ERR(FLZONE_API, "bdCallTFFSToDOCH(): actualPartitionNum failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return rc; + } + ioreq->irHandle &= (0xFFFFFF0F); + ioreq->irHandle |= (partNum << 4); + } + /* otherwise -> Files calls - different treatment */ + } + } + + /*make sure specific function precondition*/ + if (!flTakeMutex(&dochVol.mutex)) + return flDriveNotAvailable; + switch(functionNo) + { + case FL_ABS_READ: + case FL_ABS_WRITE: + case FL_ABS_DELETE: + case FL_ABS_SECURE_DELETE: + case FL_SECTORS_IN_VOLUME: + if (dochVol.mountCount[partNum] == 0) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("bdCallTFFSToDOCH(): Media must be mounted before calling 0x%d function\r\n"), functionNo)); + flFreeMutex(&dochVol.mutex); + return flNotMounted; + } + break; + case BD_ERASE_BD: + if (dochVol.mountCount[partNum] != 0) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("bdCallTFFSToDOCH(): Media must be unmounted before calling 0x%d function\r\n"), functionNo)); + flFreeMutex(&dochVol.mutex); + return flNoWriteAccess; + } + break; + + case BD_FLASH_FORMAT: + case BD_UNFORMAT: + for (partNumTemp = 0; partNumTemp < DOCH_MAX_PARTITIONS; partNumTemp++) + { + if (dochVol.mountCount[partNumTemp] != 0) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("bdCallTFFSToDOCH(): All partitions must be unmounted before calling 0x%d function\n"), functionNo)); + flFreeMutex(&dochVol.mutex); + return flNoWriteAccess; + } + } + default: + break; + } + + /*Branch to appropriate TFFS routine according to function#*/ + /*---------------------------------------------------------*/ + + switch(functionNo) + { +#ifdef FL_EXTENDED_DISK_INFO + case FL_GET_EXTENDED_DISK_INFO: + rc = TFFSGetExtendedDiskInfo(ioreq); + break; + +#endif /* FL_EXTENDED_DISK_INFO */ + case FL_VOLUME_INFO: + rc = TFFSVolumeInfo(ioreq); + break; + + case FL_COUNT_VOLUMES: + rc = TFFSCountVolumes(ioreq); + break; + + case FL_SECTORS_IN_VOLUME: + rc = TFFSSectorsInVolume(ioreq); + break; + +/* Quick mount routines */ +#ifndef FL_NO_QUICK_MOUNT_FEATURE + case FL_CLEAR_QUICK_MOUNT_INFO: + rc = TFFSClearQuickMountInfo(ioreq); + break; + + case FL_WRITE_QUICK_MOUNT_INFO: + rc = TFFSWriteQuickMountInfo(ioreq); + break; + + case FL_GET_QUICK_MOUNT_STATUS: + rc = TFFSGetQuickMountStatus(ioreq); + break; + +#endif /* FL_NO_QUICK_MOUNT_FEATURE */ + +/* Volume mounting routines */ + case FL_ABS_MOUNT: + rc = TFFSAbsMountVolume(ioreq); + break; + + case FL_DISMOUNT_VOLUME: + rc = TFFSAbsDismountVolume(ioreq); + break; + + case FL_CHECK_VOLUME: + rc = TFFSCheckVolume(ioreq); + break; + +/* Media */ +#ifndef FL_READ_ONLY + case FL_DEFRAGMENT_VOLUME: + rc = TFFSDefragmentVolume(ioreq); + break; + + +#ifdef FL_FORMAT_VOLUME + case BD_FLASH_FORMAT: + rc = TFFSflashFormat(ioreq); + break; + + case BD_UNFORMAT: + rc = TFFSUnFormat(ioreq); + break; + + case BD_ERASE_BD: + rc = TFFSEraseBD(ioreq); + break; + + +#endif /* FL_FORMAT_VOLUME */ +#endif /* FL_READ_ONLY */ + +/* IO */ +#ifdef FL_ABS_READ_WRITE + case FL_ABS_READ: + ioreq->irFlags = 0; + rc = TFFSAbsRead(ioreq, &(ioreq->irSectorCount)); + break; + + case FL_ABS_ADDRESS: + rc = TFFSAbsAddress(ioreq); + break; + + +#ifndef FL_READ_ONLY + case FL_ABS_WRITE: + ioreq->irFlags = 0; + rc = TFFSAbsWrite(ioreq); + break; + + case FL_ABS_DELETE: + rc = TFFSAbsDelete(ioreq); + break; + + case FL_ABS_SECURE_DELETE: + rc = TFFSAbsSecureDelete(ioreq); + break; + +#endif /* FL_READ_ONLY */ +#endif /* FL_ABS_READ_WRITE */ + + case FL_GET_PHYSICAL_INFO: + rc = TFFSGetPhysicalInfo(ioreq); + break; + +/* BDK routines (obsolete) */ +#ifdef BDK_ACCESS + case FL_BINARY_READ_INIT: + rc = TFFSbdkReadInit(ioreq); + break; + + case FL_BINARY_READ_BLOCK: + rc = TFFSbdkReadBlock(ioreq); + break; + +#ifndef FL_READ_ONLY + case FL_BINARY_WRITE_INIT: + rc = TFFSbdkWriteInit(ioreq); + break; + + case FL_BINARY_WRITE_BLOCK: + rc = TFFSbdkWriteBlock(ioreq); + break; + + case FL_BINARY_ERASE: + rc = TFFSbdkErase(ioreq); + break; + + case FL_BINARY_CREATE: + rc = TFFSbdkCreate(ioreq); + break; +#endif /* FL_READ_ONLY */ + + case FL_BINARY_PARTITION_INFO: + rc = TFFSbdkPartitionInfo(ioreq); + break; +#endif /* BDK_ACCESS */ + +/* OTP routines */ +#ifdef HW_OTP + case FL_OTP_SIZE: + rc = TFFSOTPSize(ioreq); + break; + + case FL_OTP_READ: + rc = TFFSOTPRead(ioreq); + break; + + case FL_OTP_WRITE: + rc = TFFSOTPWriteAndLock(ioreq); + break; + + case FL_UNIQUE_ID: + rc = TFFSGetUniqueID(ioreq); + break; + + case FL_CUSTOMER_ID: + rc = TFFSGetCustomerID(ioreq); + break; + +#endif /* HW_OTP */ + + case FL_RECOVER_FROM_POWER_LOSS: + rc = TFFSRecoverFromPowerLoss(ioreq); + break; + + case FL_DEEP_POWER_DOWN_MODE: + rc = TFFSDeepPowerDownMode(ioreq); + break; + + case FL_HW_CONFIG: + rc = TFFSHwConfig(ioreq); + break; + + +/* IPL routines */ +#ifndef NO_IPL_CODE + case FL_WRITE_IPL: + rc = TFFSWriteIPL(ioreq); + break; + + case FL_READ_IPL: + rc = TFFSReadIPL(ioreq); + break; +#endif /*NO_IPL_CODE*/ + + +/* Protection routines */ + case FL_PROTECTION_GET_TYPE: + case FL_BINARY_PROTECTION_GET_TYPE: + case FL_IPL_PROTECTION_GET_TYPE: + rc = TFFSIdentifyProtection(ioreq); + break; + + case FL_IPL_PROTECTION_INSERT_KEY:/* dont break after inserting default key */ + /* don't insert default key in order not to reduce number of authentication tries*/ + /*TFFSInsertProtectionKey(tffsAPISetIoreq(&ioreq1, 0, 0,0,(void*)DEFAULT_KEY,0,0));*/ + case FL_PROTECTION_INSERT_KEY: + case FL_BINARY_PROTECTION_INSERT_KEY: + rc = TFFSInsertProtectionKey(ioreq); + break; + + case FL_PROTECTION_REMOVE_KEY: + case FL_BINARY_PROTECTION_REMOVE_KEY: + case FL_IPL_PROTECTION_REMOVE_KEY: + rc = TFFSRemoveProtectionKey(ioreq); + break; + + case FL_IPL_PROTECTION_CHANGE_KEY: /* dont break after inserting default key */ + TFFSInsertProtectionKey(tffsAPISetIoreq(&ioreq1, 0, 0,0,(void*)DEFAULT_KEY,0,0)); + case FL_PROTECTION_CHANGE_KEY: + case FL_BINARY_PROTECTION_CHANGE_KEY: + rc = TFFSChangeProtectionKey(ioreq); + break; + + case FL_IPL_PROTECTION_CHANGE_TYPE:/* dont break after inserting default key */ + TFFSInsertProtectionKey(tffsAPISetIoreq(&ioreq1, 0, 0,0,(void*)DEFAULT_KEY,0,0)); + case FL_PROTECTION_CHANGE_TYPE: + case FL_BINARY_PROTECTION_SET_TYPE: + rc = TFFSChangeProtectionType(ioreq); + break; + + case FL_PROTECTION_STICKY_LOCK: + rc = TFFSApplyStickyLock(ioreq); + break; + + case FL_PROTECTION_SET_LOCK: + case FL_BINARY_PROTECTION_CHANGE_LOCK: + rc = TFFSHwProtectionLock(ioreq); + break; +#ifdef FL_SLPP + case FL_SLPP_UNLOCK_RANGE: + rc = TFFSSLPPUnlockRange(ioreq); + break; + + case FL_SLPP_LOCK_RANGE: + rc = TFFSSLPPLockRange(ioreq); + break; + + case FL_SLPP_UNLOCK_ENTIRE_PARTITION: + rc = TFFSSLPPUnlockEntirePartition(ioreq); + break; + + case FL_SLPP_STICKY_LOCK_RANGE: + rc = TFFSSLPPStickLockRange(ioreq); + break; + + case FL_SLPP_REPORT_LOCKED_RANGES: + rc = TFFSSLPPReportLockedRanges(ioreq); + break; +#endif /*FL_SLPP*/ + + case FL_DOCH_PASS_THROUGH: + rc = TFFSPassThrough(ioreq); + break; + + default: + DBG_PRINT_ERR_PRM(FLZONE_BLKDEV,(FLTXT("bdCallTFFSToDOCH: - Undefined Function# %d.\r\n"),functionNo)); + rc = flFeatureNotSupported; + break; + } + + /*Reset irHandle to original value*/ + ioreq->irHandle = origIrHandle; + flFreeMutex(&dochVol.mutex); +#ifdef CHECK_POWER_ON_EVERY_COMMAND + if( gDeviceTurnedOff==DOCH_GLOBAL_BOOL_PATTERN ) + return flSuspendModeDetected; +#endif /*CHECK_POWER_ON_EVERY_COMMAND*/ + return rc; +} + + +/*static +FLStatus TFFSCheckBeforeWrite(IOreq* ioreq) { return flFeatureNotSupported;}*/ + + +/*----------------------------------------------------------------------*/ +/* f l S e t D o c B u s R o u t i n e */ +/* */ +/* Set user defined memory access routines for DOCH. */ +/* */ +/* Parameters: */ +/* socket : Socket number to install routine for. */ +/* structPtr : Pointer to function structure. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API FLStatus NAMING_CONVENTION DochSetDocBusRoutine(FLByte socket, + FLAccessStruct FAR1 * structPtr) +{ + return flOK; +} + +/*----------------------------------------------------------------------*/ +/* f l G e t D o c B u s R o u t i n e */ +/* */ +/* Get currently installed memory access routines for DOCH. */ +/* */ +/* Parameters: */ +/* socket : Socket number to install routine for. */ +/* structPtr : Pointer to function structure. */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failed */ +/*----------------------------------------------------------------------*/ +TFFS_DLL_API FLStatus NAMING_CONVENTION DochGetDocBusRoutine(FLByte socket, + FLAccessStruct FAR1 * structPtr) +{ + return flOK; +} + + +/*----------------------------------------------------------------------*/ +/* f l R e g i s t e r D O C H 3 S O C */ +/* */ +/* Register DOCH3 socket */ +/* */ +/* Parameters: */ +/* dwAddress : Address were DOCH socket is located */ +/* */ +/* Returns: */ +/* DOCH_Error : 0 on success, otherwise failure */ +/* 'noOfSockets' is incremented in case a socket was found */ +/*----------------------------------------------------------------------*/ +FLStatus flRegisterDOCH3SOC(FLDword dwAddress) +{ + DOCH_Error rc; + +#ifndef DOCH_USE_FUNC + DOCHFlash->win = (volatile FLByte FAR0*)physicalToPointer(dwAddress, DOCH_MEM_WIN_SIZE, 0); +#endif /*DOCH_USE_FUNC*/ + + rc = DochRegisterSocket(dwAddress); + if(rc != DOCH_OK) + return flAdapterNotFound; + + noOfSockets++; + return flOK; +}/*flRegisterDOCH3SOC*/ + +/*----------------------------------------------------------------------*/ +/* t f f s A p i E x i t */ +/* */ +/* Exit routine for tffs_api.c layer */ +/* */ +/* Parameters: */ +/* NONE */ +/* */ +/* Returns: */ +/* FLStatus : 0 on success, otherwise failure */ +/*----------------------------------------------------------------------*/ +FLStatus tffsApiExit(void) +{ + DBG_PRINT_FLOW(FLZONE_ABS, "tffsApiExit() Invoked \r\n\n"); + + if( dochVol.intermediateBuf!=NULL ) + { + FL_FREE(dochVol.intermediateBuf); + dochVol.intermediateBuf = NULL; + } + noOfSockets = 0; + DochSDKExit(); + flDeleteMutex(&dochVol.mutex); + return flOK; +} + + +/*----------------------------------------------------------------------*/ +/* Function name : tffsApiSetAutoDpd*/ +/* Description : sets */ +/* Return type : FLStatus */ +/* Argument : FLSDword dwsSocket*/ +/* Argument : FLDword value*/ +/* Argument : FLDword FAR2 *prevValue*/ +/*----------------------------------------------------------------------*/ +FLStatus tffsApiSetAutoDpd( FLEnvVars envVarType, FLSDword dwsSocket, FLDword value, FLDword FAR2 *prevValue ) +{ + IOreq myIoreq; + +#ifdef DOCH_AUTO_DPD_BY_HOST + + if( envVarType!=TFFS_API_IS_AUTO_DPD_ON(dwsSocket) ) + return flFeatureNotSupported; + + (*prevValue) = TFFS_API_IS_AUTO_DPD_ON(dwsSocket) ? TRUE : FALSE; + + tffsAPISetIoreq( &myIoreq, dwsSocket, DOCH_ENV_AUTO_DPD_BY_HOST, 0,0, value, 0); + if (flDOCHSetEnvVar(&myIoreq) != DOCH_OK) + return flFeatureNotSupported; + + TFFS_API_SAVE_POWER_MODES(dwsSocket) = 0xFFFFFFFF; + return flOK; + +#else /*DOCH_AUTO_DPD_BY_HOST*/ + FLDword dwMode; + FLBoolean bAutoDpdOn = TFFS_API_IS_AUTO_DPD_ON(dwsSocket) ? TRUE : FALSE; + DOCH_Error rc; + + switch( envVarType) /* set IOREQ values */ + { + case FL_SET_AUTO_DPD_MODE: + dwMode = gDpdSettings.activeMode; + if( value == FL_ON )/*DPD is ON, device may be in DPD, idle or Active state */ + { + /* fix active mode to enable auto DPD */ + if( dwMode == DOCH_WM_NORMAL ) + dwMode = DOCH_WM_NORMAL_AND_AUTO_STBY; + if( dwMode == DOCH_WM_LOW_FREQ ) + dwMode = DOCH_WM_LOW_FREQ_AND_AUTO_STBY; + + tffsAPISetIoreq( &myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES|DOCH_PM_INACTIVE_MODE), + 0,0, gDpdSettings.timeOut, (dwMode | gDpdSettings.inActiveMode)); + } + else /* set the device to 'always ON' mode */ + { + /* fix active mode to disable auto DPD */ + if( dwMode == DOCH_WM_NORMAL_AND_AUTO_STBY ) + dwMode = DOCH_WM_NORMAL; + if( dwMode == DOCH_WM_LOW_FREQ_AND_AUTO_STBY ) + dwMode = DOCH_WM_LOW_FREQ; + + tffsAPISetIoreq( &myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES|DOCH_PM_INACTIVE_MODE), + 0,0,gDpdSettings.timeOut, (dwMode | gDpdSettings.inActiveMode)); + } + + (*prevValue) = bAutoDpdOn; + TFFS_API_SAVE_POWER_MODES(dwsSocket); + break; + + case FL_SET_ACTIVE_DPD_MODE: + dwMode = value; /* copy value to init this variable */ + if(bAutoDpdOn == FL_ON ) + { + if( value == DOCH_WM_NORMAL ) + dwMode = DOCH_WM_NORMAL_AND_AUTO_STBY; + if( value == DOCH_WM_LOW_FREQ ) + dwMode = DOCH_WM_LOW_FREQ_AND_AUTO_STBY; + } + else + { + if( value == DOCH_WM_NORMAL_AND_AUTO_STBY ) + dwMode = DOCH_WM_NORMAL; + if( value == DOCH_WM_LOW_FREQ_AND_AUTO_STBY ) + dwMode = DOCH_WM_LOW_FREQ; + } + + (*prevValue) = gDpdSettings.activeMode; + tffsAPISetIoreq(&myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES | DOCH_PM_INACTIVE_MODE), + 0,0, gDpdSettings.timeOut, (dwMode|gDpdSettings.inActiveMode) ); + break; + + case FL_SET_INACTIVE_DPD_MODE: + (*prevValue) = gDpdSettings.inActiveMode; + /* must leave device in inactive mode */ + tffsAPISetIoreq(&myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES | DOCH_PM_INACTIVE_MODE), + 0,0, gDpdSettings.timeOut, (value|gDpdSettings.activeMode) ); + break; + + case FL_SET_TIMEOUT_DPD: + /* reset both modes + set timeout */ + (*prevValue) = gDpdSettings.timeOut; + tffsAPISetIoreq( &myIoreq, dwsSocket, (DOCH_PM_SET_BOTH_MODES|DOCH_PM_INACTIVE_MODE),0,0, + value, (gDpdSettings.activeMode|gDpdSettings.inActiveMode) ); + break; + + default: + return flFeatureNotSupported; + }/*switch*/ + + rc = DOCHSetPowerMode(&myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR(FLZONE_API, "tffsApiSetAutoDpd(): DOCHSetPowerMode failed with status: "); + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("0x%x "), rc)); + return TFFS_API_RET(rc); + } + return flOK; +#endif /*DOCH_AUTO_DPD_BY_HOST*/ +}/*tffsApiSetAutoDpd()*/ + + +/************************************************************************/ +/* internal functions */ +/************************************************************************/ + +/************************************************************************/ +/* Function name : tffsApiAuthPartition*/ +/* Description : authenticates H3 partition */ +/* Return type : FLStatus - flOK, flWrongKey or flGeneralFailure*/ +/* Argument : IOreq * myIoreq*/ +/* Argument : IOreq * ioreq*/ +/* Argument : FLByte bPartNo - number of partition up to H3 count */ +/* Argument : FLByte * pKey - key */ +/* Argument : FLWord wKeyLen - length of the key pointed to by pKey*/ +/************************************************************************/ +static FLStatus tffsApiAuthPartition(IOreq * myIoreq, IOreq * ioreq, FLByte bPartNo, FLByte * pKey, FLWord wKeyLen) +{ + DOCH_Error rc; + DOCH_PartitionAcessPassword * pPartitionAcessPassword = (DOCH_PartitionAcessPassword *)(dochVol.intermediateBuf); + DOCH_PartitionInfo * partInfoPtr = (DOCH_PartitionInfo *)dochVol.intermediateBuf; + + + /* non mDOC H3 devices return flOK, when wrong key inserted to partition with CHNAGABLE + protection only. So first determine, which protection we have */ + tffsAPISetIoreq(myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0, 0, dochVol.intermediateBuf, 0, 0); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE( myIoreq, bPartNo ); + rc = flDOCHPartitionInfo(myIoreq); + if( rc != DOCH_OK ) + { + /*In case of Read and Write protection, we might not be able to retrieve the partition info*/ + if(rc == DOCH_ProtectionFault) + goto authenticateOnly; + + return (rc==DOCH_ProtectionFault) ? flHWProtection : ((rc==DOCH_PartitionNotFound) ? flPartitionNotFound : TFFS_API_RET(rc)); + } +#ifndef FL_OTP + if( (partInfoPtr->dwCommandFlagsOrStatuses & DOCH_CFSB_PERM_LOCKED)!=0 ) /* OTW protected partition should return wrong key */ +#else /*FL_OTP*/ + if( (partInfoPtr->dwCommandFlagsOrStatuses & (DOCH_CFSB_PERM_LOCKED|DOCH_CFSB_SOTP_LOCKED))==DOCH_CFSB_PERM_LOCKED) /* OTW protected partition should return wrong key */ +#endif /*FL_OTP*/ + { + return flWrongKey; + } + + if( (partInfoPtr->partitionAttributes2&DOCH_PA2B_PROTECTION_TYPE)==DOCH_PARTITION_NOT_PROTECTED) + { + return flNotProtected; + } + + /* password protected */ + if( ((partInfoPtr->partitionAttributes2&DOCH_PA2B_PROTECTION_TYPE)==DOCH_PARTITION_PWD_PROTECTED) || + ((partInfoPtr->partitionAttributes2&DOCH_PA2B_LOCK_CTRL)!=0) ) + { + if( ((partInfoPtr->partitionAttributes2&DOCH_PA2B_GUEST_MODE)==DOCH_PART_ACCESS_MODE_FULL ) && + ((partInfoPtr->partitionAttributes2&DOCH_PA2B_USER_MODE) ==DOCH_PART_ACCESS_MODE_FULL ) ) + {/* both user and guest have full protection -> write protection not applied */ + return flNotProtected; + } + } + +authenticateOnly: + tffsset(dochVol.intermediateBuf, 0, DOCH_SECTOR_SIZE); + tffscpy(pPartitionAcessPassword->bPassword, pKey, wKeyLen); + tffsAPISetIoreq( myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq),DOCH_ACCESS_USER_PASSWORD, 0, dochVol.intermediateBuf, 0,0); + DOCH_SET_PARTITION_TO_IOREQ_HANDLE(myIoreq, bPartNo); + /*Authenticate the partition*/ + rc = flDOCHAccessPartWithPwd(myIoreq); + if (rc != DOCH_OK) + { + return (rc==DOCH_ProtectionFault) ? flWrongKey : TFFS_API_RET(rc); + } + return flOK; +}/* tffsApiAuthPartition() */ + + +#ifndef FL_READ_ONLY +/************************************************************************/ +/* Function name : tffsApiAddOtpIPL*/ +/* Description : adds IPL or OTP partition*/ +/* Return type : static FLStatus - flOK, flGeneralFailure, flHWProtection*/ +/* Argument : FLBoolean bIPL - TRUE, when IPL should be added, FALSE, when OTP*/ +/* Argument : IOreq * myIoreq */ +/************************************************************************/ +static FLStatus tffsApiAddOtpIPL(FLBoolean bIPL, IOreq * myIoreq, IOreq * ioreq) +{ + DOCH_Error rc = DOCH_OK; + FLStatus flStatus; + FLByte * intBuf = dochVol.intermediateBuf; + DOCH_PartitionFormatInfoAPI * pPartitionFormatInfoAPI = (DOCH_PartitionFormatInfoAPI *)intBuf; + + tffsset(intBuf, 0, sizeof(DOCH_PartitionFormatInfoAPI)); + + TFFS_API_SET_MIG_STD_PART_PRMS(pPartitionFormatInfoAPI,0);/* protection type dont matter */ + + /* Protection features */ + pPartitionFormatInfoAPI->dwOtpEnabled = TRUE; /* enable OTP -> IPL can be OTW protected */ + if( bIPL==TRUE ) + { + flStatus = tffsFormatSetProtectionAttribs( CHANGEABLE_PROTECTION|PROTECTABLE, pPartitionFormatInfoAPI, + (FLByte*)DEFAULT_KEY, sizeof(DEFAULT_KEY)); + if( flOK != flStatus ) + return flStatus; + } + else + { + pPartitionFormatInfoAPI->dwProtectionType = DOCH_PARTITION_NOT_PROTECTED; + pPartitionFormatInfoAPI->dwUserAccessMode = DOCH_PART_ACCESS_MODE_FULL; + pPartitionFormatInfoAPI->dwGuestAccessMode = DOCH_PART_ACCESS_MODE_FULL; + } + pPartitionFormatInfoAPI->dwLockControl = DOCH_LOCK_NOT_ACTIVE; + + + /*Partition size (must be FL_LENGTH_IN_BYTES)*/ + pPartitionFormatInfoAPI->nPartitionSize = + (bIPL==TRUE) ? IPL_PARTITION_SIZE_SECTORS : (TFFS_API_OTP_PART_SIZE >> DOCH_SECTOR_SIZE_BITS); + + /*Add partition*/ + tffsAPISetIoreq(myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf, 0,0); + rc = flDOCHAddPartition(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHAddPartition (IPL) failed with status: 0x%x "), rc)); + return TFFS_API_RET(rc); + } + + /*Retrieve current attributes*/ + tffsset(myIoreq, 0, sizeof(IOreq)); + if( bIPL == TRUE ) + myIoreq->irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq) + (DOCH_IPL_PARTITION_NUM << 4); + else + myIoreq->irHandle = FL_GET_SOCKET_FROM_HANDLE(ioreq) + (TFFS_API_OTP_PARTITION_NUM << 4); + myIoreq->irData = intBuf; + rc = flDOCHGetParitionUserAttributes(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHGetParitionUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + + /*Set type to IPL or OTP*/ + ((DOCH_PartitionUserAttrWithBinary*)intBuf)->bType = (bIPL == TRUE) ? PARTITION_TYPE_IPL:PARTITION_TYPE_OTP; + /* set IPL partition to be changeable */ + ((DOCH_PartitionUserAttrWithBinary*)intBuf)->bChangableProtection = bIPL; + /* set IPL partition to be protectable */ + ((DOCH_PartitionUserAttrWithBinary*)intBuf)->bProtected = bIPL; + /*Set attributes back to device*/ + rc = flDOCHSetParitionUserAttributes(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + + tffsAPISetIoreq(myIoreq, FL_GET_SOCKET_FROM_HANDLE(ioreq), 0,0, intBuf, 0,0); + rc = flDOCHGetDiskUserAttributes(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHGetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + + if(bIPL == TRUE) + ((DOCH_DiskUserAttrWithBinary*)intBuf)->bIplPresent = 1; + else + ((DOCH_DiskUserAttrWithBinary*)intBuf)->bOtpPresent = 1; + rc = flDOCHSetDiskUserAttributes(myIoreq); + if(rc != DOCH_OK) + { + DBG_PRINT_ERR_PRM(FLZONE_API, (FLTXT("tffsApiAddOtpIPL(): flDOCHSetDiskUserAttributes failed with status: 0x%x "), rc)); + return (rc==DOCH_ProtectionFault)? flHWProtection : TFFS_API_RET(rc); + } + return flOK; +}/*tffsApiAddOtpIPL*/ +#endif /*FL_READ_ONLY*/ + +/************************************************************************/ +/* Function name : tffsAPISetIoreq */ +/* Description : */ +/* Return type : IOreq * */ +/* Argument : IOreq * pIoreq*/ +/* Argument : FLHandle irHandle*/ +/* Argument : FLDword irFlags*/ +/* Argument : void* irPath*/ +/* Argument : void * irData*/ +/* Argument : FLSDword irLength*/ +/* Argument : FLSDword irCount*/ +/************************************************************************/ +static IOreq * tffsAPISetIoreq(IOreq * pIoreq, FLHandle irHandle, FLDword irFlags, void* irPath, void * irData, FLSDword irLength, FLSDword irCount) +{ + pIoreq->irCount = irCount; + pIoreq->irData = irData; + pIoreq->irFlags = irFlags; + pIoreq->irHandle = irHandle; + pIoreq->irLength = irLength; + pIoreq->irPath = irPath; + return pIoreq; +}/*tffsAPISetIoreq*/ + +/* end of file tffs_api.c */ + + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs_api.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs_api.h new file mode 100755 index 00000000..ef631bae --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffs_api.h @@ -0,0 +1,224 @@ +/******************************************************************************/ +/* */ +/* Copyright (C), 1995-2007, SanDisk IL Ltd. 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 SanDisk IL nor the names of its contributors may be*/ +/* used to endorse or promote products derived from this software without */ +/* specific prior written permission. */ +/* */ +/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ +/* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED */ +/* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */ +/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */ +/* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */ +/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */ +/* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR */ +/* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ +/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ +/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ +/* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* */ +/* NOTWITHSTANDING ANYTHING STATED TO THE CONTRARY, SANDISK'S TOTAL LIABILITY*/ +/* ARISING OUT OF OR RELATED TO THE SOFTWARE OR ANY SUPPORT SERVICES */ +/* PROVIDED WITH RESPECT THERETO SHALL NOT EXCEED $100. */ +/* */ +/* The laws of the State of California, United States of America, exclusive */ +/* of conflict-of-laws provisions, shall govern this license in all respects.*/ +/* The the federal or state courts of competent jurisdiction in the State */ +/* of California shall have exclusive jurisdiction with respect to all */ +/* actions commenced in relation to the software. Licensee agrees not */ +/* to export or re-export, directly or indirectly any technical data */ +/* acquired from SanDisk or any products utilizing such data in violation */ +/* of applicable export laws and regulations. */ +/* */ +/******************************************************************************/ +/* + * $Log: V:/PVCSDB/DiskOnChip/archives/Test for 7.x/src/H3/tffs_api.h-arc $ + * + * Rev 1.32 Dec 11 2007 12:30:54 einat.avidan + * Add format start and format complete signatures in disk user attributes + * + * Rev 1.31 Oct 22 2007 11:34:56 einat.avidan + * update copyrights header + * + * Rev 1.30 Jun 20 2007 12:09:20 einat.avidan + * when DOCH_AUTO_DPD_BY_HOST is enabeled: wrong macro name was used(TFFS_API_IS_DPD_ON instead of TFFS_API_IS_AUTO_DPD_ON) + * + * Rev 1.29 Sep 11 2006 13:45:28 yaniv.iarovici + * Legal header added + * + * Rev 1.28 Aug 16 2006 09:57:50 Yaniv.Iarovici + * Fix compilation error due to PVCS comment + * + * Rev 1.26 Aug 16 2006 08:48:40 Yaniv.Iarovici + * Change OTP partition size to 256KB (#define TFFS_API_OTP_PART_SIZE 0x40000 -> 256KB). + * + * Rev 1.25 Aug 09 2006 17:26:50 Polina.Marimont + * initial for DOC Driver 1.0 + * + * Rev 1.24.1.0 Aug 08 2006 15:55:34 Polina.Marimont + * DOC Driver 1.0 initial + * + * Rev 1.23 Jun 18 2006 13:09:16 Polina.Marimont + * AutoDPD and DPD parameters storage moved to SA SDK + * + * Rev 1.22 Jun 14 2006 18:00:18 Polina.Marimont + * structures definitions moved to this file + * + * Rev 1.21 May 18 2006 09:48:50 polina.marimont + * 1. added function for autoDPD support + * 2. actual partition number API changed + * + * Rev 1.20 Apr 11 2006 13:17:22 tal.heller + * add DOCH_SECURE_DELETE_DATA_OFFSET define + * + * Rev 1.19 Mar 22 2006 17:35:46 DoronC + * Bug fix - add signature to disk attributes in order to use only + * format made by TrueFFS 7.1 and not by host SDK. + * Other format will force reformating of the media. + * + * Rev 1.18 Mar 15 2006 16:18:18 DoronC + * Bug fix - normal IPL of 8KB window was wrong. + * + * Rev 1.17 Mar 15 2006 11:28:18 DoronC + * Bug fix - IPL write was not working properly. + * + * Rev 1.16 Mar 14 2006 09:54:16 DoronC + * Bug fix - IPL size was limited to 1KB when righting normal node + * IPL instead of 2KB + * + * Rev 1.15 Mar 02 2006 08:30:54 DoronC + * Bug fix - IPL was not working since size should be in sectors. + * + * Rev 1.14 Feb 14 2006 10:50:02 DoronC + * Remove large variables from stack. use one global buffer for + * all large buffers needs. + */ + +/***********************************************************************************/ +/* */ +/* Header file for sdk_api module */ +/* */ +/***********************************************************************************/ + +#ifndef _TFFS_API +#define _TFFS_API + +FLStatus bdCallTFFSToDOCH(FLFunctionNo functionNo, IOreq FAR2 *ioreq); + +#ifdef BDK_ACCESS +typedef struct { + FLDword dwStartReadSector; + FLDword dwCurrentReadByte; + FLDword dwReadLength; + FLDword dwStartWriteSector; + FLDword dwCurrentWriteByte; + FLDword dwWriteLength; + FLByte bWriteSubPartitionNum; +} sBdkInitValues; +#endif /*BDK_ACCESS*/ + +typedef struct __DocHVolume +{ + FLMutex mutex; + FLByte numOfBinaryPartitions; + FLByte iplExists; + FLByte otpExists; + FLBoolean verifyWrite; + FLByte *intermediateBuf; + FLDword mountCount[DOCH_MAX_PARTITIONS]; +#ifdef BDK_ACCESS + sBdkInitValues bdkInitValues; +#endif /*BDK_ACCESS*/ + FLDword dwVirtualUnitSize; + FLDword dwVirtualUnitSizeInSectors; + FLDword dwNumOfUnits; + FLDword dwUnformattedCapacity; + + FLDword dwPowerMode[FL_SOCKETS]; /* saves power modes */ +}DocHVolume; + +/* MACRO: TFFS_API_IS_AUTO_DPD_ON - determines whether one of Auto DPD modes defined */ +#define TFFS_API_IS_AUTO_DPD_ON(socket) ( ((gDpdSettings.activeMode & DOCH_WM_NORMAL_AND_AUTO_STBY) == DOCH_WM_NORMAL_AND_AUTO_STBY) || \ + ((gDpdSettings.activeMode & DOCH_WM_LOW_FREQ_AND_AUTO_STBY) == DOCH_WM_LOW_FREQ_AND_AUTO_STBY) || \ + ((gDpdSettings.inActiveMode & DOCH_IM_IDLE_2_DPD) == DOCH_IM_IDLE_2_DPD) ) +/* MACRO: TFFS_API_SAVE_DPD_STATES(socket) - saves the power modes into global variable */ +#define TFFS_API_SAVE_POWER_MODES(socket) dochVol.dwPowerMode[socket] = gDpdSettings.inActiveMode | gDpdSettings.activeMode; + +/********************/ +/* Defines */ +/********************/ + +#define DOCH_SECTORS_IN_UNIT_BITS 9 +#define DOCH_SECTORS_IN_UNIT (1<= PAGE_OFFSET) && ((vaddr) < (unsigned long)high_memory)) +#endif + + +/* + * static routines + */ +static void __dmasw_bread (int off, void *vbuf, unsigned int bytes); +static void __dmasw_bwrite (int off, void *vbuf, unsigned int bytes); + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a s w * + * * + * Transfer data between DiskOnChip's and RAM buffer. * + * This routines handles any kind of virtual buffer (linearly mapped or * + * vmalloc() allocated, spanning multiple memory pages, containing * + * multiple sectors). * + * * + * Parameters: * + * win pointer to DiskOnChip's I/O window * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * read DMA direction: '1' for DiskOnChip->RAM, or zero * + * for RAM->DiskOnChip * + * * + *-----------------------------------------------------------------------*/ + +void tffs_dmasw ( char * win, + int off, + void * vbuf, + unsigned int bytes, + int read ) +{ + /* We check if 'vbuf' is linearly mapped kernel virtual address (and + * is therefore laid out in consecutive physical pages). If 'vbuf' + * is not linearly mapped (i.e. came from user space or allocated + * via vmalloc()), we check if it entirely fits into a single memory + * page. + */ + if ((virt_addr_valid((unsigned long)vbuf)) /* linearly mapped kernel virtual address */ + || + (Align(vbuf,PAGE_SIZE) == Align((unsigned long)vbuf + bytes,PAGE_SIZE))) + { + if (read == 1) + __dmasw_bread (off, vbuf, bytes); + else + __dmasw_bwrite (off, vbuf, bytes); + } + else /* 'vbuf' crosses memory page boundary */ + { + if (bytes >= (FL_SECTOR_SIZE * 2)) /* two or more sectors */ + { + register unsigned long bytes_on_this_page; + + /* Do multiple DMA transfers, each one fitting into a single + * memory page. + */ + do + { + bytes_on_this_page = PAGE_SIZE - ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (bytes_on_this_page > bytes) + bytes_on_this_page = bytes; + + if (read == 1) + __dmasw_bread (off, vbuf, bytes_on_this_page); + else + __dmasw_bwrite (off, vbuf, bytes); + + bytes -= bytes_on_this_page; + vbuf = (char *)vbuf + bytes_on_this_page; + + } while (bytes > 0); + } + else /* single sector; don't bother with DMA ... */ + { + if (read == 1) + tffs_readw ((unsigned long)(win + off), vbuf, (bytes / sizeof(short))); + else + tffs_writew ((unsigned long)(win + off), vbuf, (bytes / sizeof(short))); + } + } +} + + + + + +#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) + +/*_____________________________________________________________________________ + | | + | | + | Intel PXA27x ("Mainstone") board | + | | + |____________________________________________________________________________| +*/ + + +# include +# include +# include + + +/* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears + * to be buggy: it seems to constantly shoot past the end of the address + * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some + * bogus data into this RAM address range while invalidating it in D-cache. + */ +# define PXA27X_DCACHE_BUG_WORKAROUND + + +/* + * static routines for PXA27x + */ + +static void tffs_dma_init (int resume); +static void tffs_dma_release (void); +static void tffs_dma_intr (int dma, void *dummy, struct pt_regs *regs); + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s a r c h _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required board resources; if 'resume' * + * is TRUE, this routine does minimal required re-initialization of * + * these resources after power suspend. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + * Returns: * + * always '1' (success) * + * * + *-----------------------------------------------------------------------*/ + +unsigned char tffsarch_init ( int resume ) +{ + /* chip select that DiskOnChip is connected to */ +#define PXA27X_CS 5 + + /* Value to write to chip select's conf register. Possible values are: + * + * 0x099C VLIO DiskOnChip adapter and DiskOnChip G4/G3/H3 device + * 0x0AAC VLIO DiskOnChip adapter and DiskOnChip H1 device + * 0xA998 sync DiskOnChip adapter and DiskOnChip G4/G3/H3 device + * 0xAAA8 sync DiskOnChip adapter and DiskOnChip H1 device + * + * Register description: + * + * 31 0 - slow device (VLIO); 1 - fast device + * 30:28 The value of this bit is half the number of memory clock cycles + * from the time that chip select is de-asserted after a read or + * write until the next chip select (of a different static memory + * bank) or nSDCS is asserted + * 27:24 ROM Delay Next Access The RDN field is encoded as follows: + * ENCODED (Programmed) Value -----> DECODED (Actual) Value + * 0-11 -----> 0-11 + * 12 -----> 15 + * 13 -----> 20 + * 14 -----> 26 + * 15 -----> 30 + * RDNx * 2 = amount of time nOE or nPWE is deasserted to address + * hold and address setup to nOE or nPWE assertion time + * 23:20 This determines the minimum number of memory clock cycles + * (minus 1) of nOE (nPWE) assert time for each beat of read (write) + * 19 ROM Bus Width (1 = 16 bits) + * 16-18 0 - Synchronous flash; 2 - burst 4; 3 - burst 8; 4 - Variable-latency + * I/O (VLIO) + */ + +#define PXA27X_CS_VAL 0x026C /* andrayk Nov 242 006: originally was 0x044C */ + + int cs = PXA27X_CS; + unsigned long val; + + if (resume == FALSE) + { PrintkInfo ("use Chip Select %d", cs); } + + /* Line below configures GPIO33 as output. + * Without this line, DiskOnChip driver fails to detect DiskOnChip G4. + */ + GPDR1 |= 0x2; /* was: GPDR1 = 0xfc3fab83 */ + + /* read chip select config reg */ + val = __REG(0x48000008 + ((cs / 2) * sizeof(long))); + + if (cs & 1) + val = ((PXA27X_CS_VAL << 16) | (val & 0xffff)); + else + val = ((val & 0xffff0000) | PXA27X_CS_VAL); + + /* write chip select config reg */ + __REG(0x48000008 + ((cs / 2) * sizeof(long))) = val; + + /* if DMA is requested, configure it */ + if (tffs_dma_mode > 0) + { + tffs_dma_init (resume); + } + + return 1; +} + + + +void TffsHWRelease(void) +{ + /* if DMA was actually used, release all DMA resources */ + if (tffs_dma_mode > 0) + { + tffs_dma_release (); + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required DMA resources; if 'resume' is * + * TRUE, this routine does minimal required re-initialization of DMA * + * channel after power suspend. * + * * + * Parameters: * + * resume FALSE (module initialization) or TRUE (power resume) * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_init (int resume) +{ + if (resume == FALSE) + { + /* We use single DMA channel for both 'read' and + * 'write' operations, so we allocate it here. + */ + if ((tffsInfo.channel = pxa_request_dma(TFFS_DEVICE_NAME, + DMA_PRIO_LOW, tffs_dma_intr, NULL)) < 0) + { + /* failed to allocate DMA channel, won't use DMA */ + tffs_dma_mode = 0; + + PrintkError ("can't get DMA chan"); + return; + } + PrintkInfo ("use DMA channel %d", tffsInfo.channel); + } + + DRCMR(tffsInfo.channel) = (DRCMR_MAPVLD | (tffsInfo.channel & 0x1f)); + __REG(0x400000a0) |= (1 << tffsInfo.channel); + + /* clear any pending DMA errors/interrupts */ + DCSR(tffsInfo.channel) = (DCSR_NODESC | DCSR_ENDINTR | DCSR_STARTINTR | DCSR_BUSERR); + + if (resume == FALSE) + { + tffsInfo.dma_buf_vptr = NULL; + tffsInfo.dma_buf_size = 0; + + if ((tffs_dma_mode >= 1) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || !defined(PXA27X_DCACHE_BUG_WORKAROUND) + && (tffs_dma_mode <= 3) +#endif + ) + { + /* allocate intermediate DMA buffer (we assume one MMU page will be enough) */ + tffsInfo.dma_buf_size = PAGE_SIZE; + + tffsInfo.dma_buf_vptr = +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_alloc ((GFP_KERNEL | GFP_DMA), tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr); +#else + dma_alloc_coherent (NULL, tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr, (GFP_KERNEL | GFP_DMA)); +#endif + if (tffsInfo.dma_buf_vptr == NULL) + { + /* failed to allocate intermediate DMA buffer, won't use DMA */ + tffs_dma_mode = 0; + + pxa_free_dma (tffsInfo.channel); + + tffsInfo.channel = -1; + tffsInfo.dma_buf_size = 0; + + PrintkError ("can't alloc DMA buffer, won't use DMA"); + } + } + } +} + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ r e l e a s e * + * * + * Release all previously allocated DMA resources (channel, intermediate * + * DMA buffer etc.). For Intel PXA27x (Mainstone) board. * + * * + *-----------------------------------------------------------------------*/ + +static +void tffs_dma_release(void) +{ + /* if previously was allocated, release DMA channel */ + if (tffsInfo.channel >= 0) + { + pxa_free_dma (tffsInfo.channel); + + tffsInfo.channel = -1; + } + + /* if previously was allocated, release intermediate DMA buffer */ + if (tffsInfo.dma_buf_vptr != NULL) + { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_free (tffsInfo.dma_buf_vptr, PAGE_SIZE, tffsInfo.dma_buf_paddr); +#else + dma_free_coherent (NULL, PAGE_SIZE, tffsInfo.dma_buf_vptr, tffsInfo.dma_buf_paddr); +#endif + tffsInfo.dma_buf_vptr = NULL; + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b r e a d * + * * + * Transfer data from DiskOnChip's I/O reguster to RAM buffer. * + * Example implementation For Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bread ( int off, + void * vbuf, + unsigned int bytes ) +{ + int chan = tffsInfo.channel; + u_int tmp; + register int waiting; + register int direct_dma; + + profiling[2]++; + + direct_dma = ((tffs_dma_mode & 4) ? TRUE : FALSE); + + /* Due to a bug in kernel routine blk_dma_inv_range_harvard() + * (arch/arm/mm/blockops.c), we allow direct DMA to destination + * buffer 'vbuf' only when it's aligned at CPU's cache line boundary. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(PXA27X_DCACHE_BUG_WORKAROUND) + if ((u32)vbuf & 31) + direct_dma = FALSE; +#endif + + /* Set source physical address for DMA transfer (this would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + DSADR(chan) = tffs_addr[0] + off; + + /* Set target physical address for DMA transfer. + * This would be physical address of intermediate DMA buffer (for + * DMA modes 1/2/3), or physical address of the destination buffer + * (for DMA modes 5/6/7). + */ + if (direct_dma == TRUE) /* do DMA transfer directly into 'vbuf' */ + { + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + DTADR(chan) = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (k_vbuf == NULL) + { + PrintkError ("error, DMA requested on high memory page"); + return; + } + + DTADR(chan) = __pa (k_vbuf); + + /* andrayk Nov 22 2006: possible bug. Routine consistent_alloc() + * (arch/arm/mm/consistent.c) applies __pa() macro to it's 'vbuf' + * argument (see below). This might cause CPU exception. + */ + } + + /* Write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */ + /* Possible options: + * consistent_sync(vbuf, bytes, DMA_FROM_DEVICE); ARM/SH + * dma_cache_inv((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86 + */ + +#ifdef PXA27X_DCACHE_BUG_WORKAROUND + + /* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears + * to be buggy: it seems to constantly shoot past the end of the address + * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some + * bogus data into this RAM address range while invalidating it in D-cache. + */ + consistent_sync (vbuf, bytes - 1, DMA_FROM_DEVICE); +#else + consistent_sync (vbuf, bytes, DMA_FROM_DEVICE); +#endif + } + else /* transfer into intermediate DMA buffer */ + { + DTADR(chan) = tffsInfo.dma_buf_paddr; + } + + /* specify parameters of DMA transfer */ + tmp = DCMD_INCTRGADDR | /* increment target address */ + DCMD_WIDTH2 | /* 16-bit data path */ + /* DCMD_ENDIRQEN | */ /* don't generate interrupt at the end of transfer */ + bytes; + + if ((bytes & 31) == 0) + tmp |= DCMD_BURST32; /* 32-bytes burst */ + + DCMD(chan) = tmp; + + /* clear all status bits, and start DMA transfer */ + DCSR(chan) = (DCSR_RUN | DCSR_NODESC | DCSR_ENDINTR | DCSR_STOPSTATE | DCSR_BUSERR); + + /* poll DMA channel's status register for end of DMA transfer */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + /* read Channel Status Register to find out status of DMA transfer */ + tmp = DCSR (chan); + + if (tmp & (DCSR_STOPSTATE | DCSR_BUSERR)) + { + if ((tmp & DCSR_BUSERR) == 0) + { + /* DMA transfer completed, move data from the intermediate DMA + * buffer to the destination buffer (in case it was used). + */ + if (direct_dma == FALSE) + memcpy (vbuf, tffsInfo.dma_buf_vptr, bytes); + } + else + { + PrintkError ("Bus error, DMA transfer failed"); + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + } + return; + } + } + + PrintkError ("DMA transfer timed out"); +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b w r i t e * + * * + * Transfer data from RAM buffer to DiskOnChip's I/O reguster. * + * Example implementation for Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bwrite ( int off, + void * vbuf, + unsigned int bytes ) +{ + int chan = tffsInfo.channel; + u_int tmp; + register int waiting; + + profiling[3]++; + + /* Set target physical address for DMA transfer (this would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + DTADR(chan) = tffs_addr[0] + off; + + /* set source physical address for DMA transfer */ + + if (tffs_dma_mode & 4) /* do DMA transfer directly from 'vbuf' */ + { + /* Write (if dirty) contents of 'vbuf' from CPU D-cache to RAM. + * Possible options: + * consistent_sync(vbuf, bytes, DMA_TO_DEVICE); ARM/SH + * dma_cache_wback((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86 + */ + consistent_sync (vbuf, bytes, DMA_TO_DEVICE); + + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + DSADR(chan) = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (k_vbuf == NULL) + { + PrintkError ("error, DMA requested on high memory page"); + return; + } + + DSADR(chan) = __pa (k_vbuf); + } + } + else /* use intermediate DMA buffer */ + { + /* move data from RAM buffer to the intermediate DMA buffer */ + memcpy (tffsInfo.dma_buf_vptr, vbuf, bytes); + + DSADR(chan) = tffsInfo.dma_buf_paddr; + } + + /* specify parameters of DMA transfer */ + tmp = DCMD_INCSRCADDR | /* increment source address */ + DCMD_WIDTH2 | /* 16-bit data path */ + /* DCMD_ENDIRQEN | */ /* don't generate interrupt at the end of transfer */ + bytes; + + if ((bytes & 31) == 0) + tmp |= DCMD_BURST32; /* 32-bytes burst */ + + DCMD(chan) = tmp; + + /* clear all status bits, and start DMA transfer */ + DCSR(chan) = (DCSR_RUN | DCSR_NODESC | DCSR_ENDINTR | DCSR_STOPSTATE | DCSR_BUSERR); + + /* poll DMA channel's status register for end of DMA transfer */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + /* read Channel Status Register to find out status of DMA transfer */ + tmp = DCSR (chan); + + if (tmp & (DCSR_STOPSTATE | DCSR_BUSERR)) + { + if (tmp & DCSR_BUSERR) + { + PrintkError ("Bus error, DMA transfer failed"); + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + } + else + { + /* DMA transfer successful */ + } + return; + } + } + + PrintkError ("DMA transfer timed out"); +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n t r * + * * + * Handle DMA interrupt on Intel PXA27x (Mainstone) board. * + * * + * Parameters: * + * dma interrupting DMA channel * + * dummy not used * + * regs not used * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_intr ( int dma, + void * dummy, /* not used */ + struct pt_regs * regs ) /* not used */ +{ + register u_int tmp; + + profiling[4]++; + + /* check if interrupt came from our DMA channel */ + if (dma == tffsInfo.channel) + { + /* check if DMA transfer was successful */ + if ((tmp = DCSR(dma)) & DCSR_BUSERR) + { + /* andrayk Mar 24 2006: DMA transfer failed, find way to let MTD know this */ + PrintkError ("Bus error, DMA transfer failed"); + } + + /* clear DMA interrupt from this channel */ + DCSR(dma) = (tmp | (DCSR_BUSERR | DCSR_ENDINTR)); + } + else + { PrintkError ("received DMA interrupt on wrong channel"); } +} + + + + +#elif defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2) + +/*_____________________________________________________________________________ + | | + | | + | Texas Instruments OMAP-1610 (H2) board | + | | + |____________________________________________________________________________| +*/ + +# include +# include + + /* + + EMIFS: Extended Memory Interface Slow. This 16-bit wide bus can interface + with and handle all transactions to flash memory, ROM, asynchronous + memories, and synchronous burst flash. + The EMIFS can support 16-bit interface width only. + TC: traffic controller + The EMIFS supports 8-,16-, or 32-bit asynchronous and synchronous + read, 4- x 32-bit synchronous burst read and 8-, 16-, or 32-bit + asynchronous write. + + EMIFS_PRIOR EMIFS LRU priority register FFFECC04 + EMIFS_CONFIG EMIFS configuration register FFFECC0C + EMIFS_CCS2 EMIFS chip-select configuration CS2 FFFECC18 + 7:4 RDWST Controls the wait states cycle number for asynchronous read operation and the initial idle time for asynchronous read page mode and synchronous read mode. + 15:12 PGWST/WELEN Controls the wait states cycle number between accesses in a page for asynchronous page mode. Controls the WE pulse length during a write access. When PGWSTEN is 0, this bit specifies both PGWST/WELEN. When PGWSTEN is 1, this bit specifies only WELEN + EMIFS_PTOR1 EMIFS dynamic priority time-out 1 FFFECC28 + EMIFS_PTOR2 EMIFS dynamic priority time-out 2 FFFECC2C + EMIFS_PTOR3 EMIFS dynamic priority time-out 3 FFFECC30 + EMIFS_DWS EMIFS dynamic wait states FFFECC40 + EMIFS_AADDR EMIFS abort address FFFECC44 + EMIFS_ATYPER EMIFS abort type FFFECC48 + EMIFS_ATOR EMIFS abort time-out FFFECC4C + EMIFS_ACS2 Advanced EMIFS chip-select configuration nCS2 FFFECC58 + + + EMIFS_CS2_CONFIG 0xFFFECC18 + BSP sets the reg val 0xf800f22a, but the val after kernel starts is 0xff80fff3 + + */ + + + + +/* + * static routines for OMAP1610 + */ + +static void tffs_dma_init (int resume); +static void tffs_dma_release (void); + + + +/* + * static vars + */ + +static dma_regs_t * dma_regs = NULL; + + + +/*-----------------------------------------------------------------------* + * * + * t f f s a r c h _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required board resources; if 'resume' * + * is TRUE, this routine does minimal required re-initialization of * + * these resources after power suspend. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + * Returns: * + * always '1' (success) * + * * + *-----------------------------------------------------------------------*/ + +unsigned char tffsarch_init (int resume) +{ + register unsigned short tmp16; + register unsigned long tmp32; + + /* Configure Chip Select that DiskOnChip is connected to. + * + * NOTE. Code below configures Chip Select to set duration of + * DiskOnChip access cycle to 70 nanosecond, which is + * appropriate for the case when DiskOnChip is connected to + * OMAP1610 board via M-Systems' adapters. If you solder + * DiskOnChip into your board, consider changing Chip Select + * settings to significantly shorten DiskOnChip acecss cycle. + * This should have significant positive efefct on + * DiskOnChip's 'read' performance. + */ + tmp32 = (1 << 27) | /* wait states between accesses in a page for async. page mode */ + (1 << 23) | /* idle cycles for bus turn around */ + (0 << 16) | /* asynchronous read */ + (1 << 12) | /* WE length */ + (0 << 8) | /* wait states in write operation */ + (0 << 4) | /* wait states in read operation */ + 2; /* REF_CLK = TC_CK / 2 */ + +#define OMAP1610_H2_CS 2 /* chip select that DiskOnChip is connected to */ + + outl (tmp32, (EMIFS_CS0_CONFIG + (OMAP1610_H2_CS * sizeof(unsigned long)))); + + if (tffs_irq >= 0) + { + /* Configure GPIO-9 as input. This is actually a default state + * after reset, but just to be sure ... + */ + tmp16 = inw (GPIO_DIRECTION_REG); + outw ((tmp16 | (1 << (tffs_irq - IH_GPIO_BASE))), GPIO_DIRECTION_REG); + + /* configure DiskOnChip IRQ as GPIO-9, disable PullDown */ + outl( (inl(PULL_DWN_CTRL_2) | (1 << 23)), PULL_DWN_CTRL_2); + + /* select function W8 pin as GPIO-9 */ + outl( (inl(FUNC_MUX_CTRL_B) & 0xFF1FFFFF), FUNC_MUX_CTRL_B); + } + +# if 0 + volatile unsigned long*reg; + unsigned long ulTemp; + + /* configure DMAREQ# as MPUIO4, disable PullDown */ + ulTemp = *(volatile unsigned long*) 0xFFFE1044; + ulTemp |= 0x00002000; /* 0x1<<13; */ + *(volatile unsigned long *)0xFFFE1044 = (unsigned long)ulTemp; + + /* select function DMA_REQ tffsInfo.channel 6 */ + ulTemp = *(volatile unsigned long*) 0xFFFE1020; + ulTemp |= 0x8000; /* 0x1<<15; */ + *(volatile unsigned long *)0xFFFE1020 = (unsigned long)ulTemp; + + /* configure mDoc IRQ# as GPIO-9, disable PullDown */ + /* TH: For H2 Platform */ + ulTemp = *(volatile unsigned long*) 0xFFFE1048; + ulTemp |= 0x800000; /* 0x1<<23; */ + *(volatile unsigned long *)0xFFFE1048 = (unsigned long)ulTemp; + + /* select function W8 pin as GPIO-9 */ + ulTemp = *(volatile unsigned long*) (0xFFFE1030); + ulTemp &= 0xFF1FFFFF; + *(volatile unsigned long *)(0xFFFE1030) = (unsigned long)ulTemp; + + reg=(unsigned long*)EMIFS_CONFIG_REG; + PrintkInfo("EMIFS_CONFIG_REG=0x%lx",*reg); + *reg=0x0c; + reg=(unsigned long*)EMIFS_CONFIG_REG; + PrintkInfo("EMIFS_CONFIG_REG=0x%lx",*reg); + + reg=(unsigned long*)EMIFS_CS2_CONFIG2; + PrintkInfo("EMIFS_CS2_CONFIG2=0x%lx",*reg); + + reg=(unsigned long*)EMIFS_CS2_CONFIG; + PrintkInfo("EMIFS_CS2_CONFIG=0x%lx",*reg); + *reg=0x8070; + reg=(unsigned long*)EMIFS_CS2_CONFIG; + PrintkInfo("EMIFS_CS2_CONFIG=0x%lx",*reg); +# endif + + /* if DMA is requested, configure it */ + if (tffs_dma_mode > 0) + { + tffs_dma_init (resume); + } + + return 1; +} + + + +void TffsHWRelease(void) +{ + /* if DMA was actually used, release all DMA resources */ + if (tffs_dma_mode > 0) + { + tffs_dma_release (); + } +} + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required DMA resources; if 'resume' is * + * TRUE, this routine does minimal required re-initialization of DMA * + * channel after power suspend. * + * * + * Parameters: * + * resume FALSE (module initialization) or TRUE (power resume) * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_init (int resume) +{ + u32 tmp; + + if (resume == FALSE) + { + /* We use single DMA channel for both 'read' and 'write' operations, + * so we allocate it here. We don't use DMA interrupts, so we won't + * need DMA callback. + */ + tffsInfo.channel = + omap_request_dma (eDMANotSync, /* not connected to any DMA line */ + TFFS_DEVICE_NAME, + NULL, /* no callback when DMA completes */ + NULL, /* data to pass to DMA callback */ + &dma_regs); + if ((tffsInfo.channel != 0) || (dma_regs == NULL)) + { + /* failed to allocate DMA channel, won't use DMA */ + tffs_dma_mode = 0; + + PrintkError ("can't get DMA chan"); + return; + } + } + + /* Logical Channel Control Register. + * Specify peripheral DMA transfer. + */ + dma_regs->lch_ctrl = LCH_TYPE_P; + + /* Channel Element Number Register. + * Specify single element (16-bit word) per DMA frame. + */ + dma_regs->cen = 1; + + /* Channel Control Register 2. + * Specify block synchronization. + */ + dma_regs->ccr2 = (1 << 2); + + /* Channel Interrupt Control Register. + * Enable time-out interrupt, disable all others. + */ + dma_regs->cicr = /* (1 << 5) | */ /* end-of-block interrupt */ + 1; /* timeout interrupt */ + + /* read Channel Status register to clear it */ + tmp = dma_regs->csr; + + if (resume == FALSE) + { + tffsInfo.dma_buf_vptr = NULL; + tffsInfo.dma_buf_size = 0; + + if ((tffs_dma_mode >= 1) && (tffs_dma_mode <= 3)) + { + /* allocate intermediate DMA buffer (we assume one MMU page will be enough) */ + tffsInfo.dma_buf_size = PAGE_SIZE; + + tffsInfo.dma_buf_vptr = +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_alloc ((GFP_KERNEL | GFP_DMA), tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr); +#else + dma_alloc_coherent (NULL, tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr, (GFP_KERNEL | GFP_DMA)); +#endif + if (tffsInfo.dma_buf_vptr == NULL) + { + /* failed to allocate intermediate DMA buffer, won't use DMA */ + tffs_dma_mode = 0; + + omap_free_dma (dma_regs); + dma_regs = NULL; + + tffsInfo.dma_buf_size = 0; + PrintkError ("can't alloc DMA buffer"); + } + } + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ r e l e a s e * + * * + * Release all previously allocated DMA resources (channel, intermediate * + * DMA buffer etc.). For OMAP1610 (H2) board. * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_release(void) +{ + /* if previously was allocated, release DMA channel */ + if (tffsInfo.channel == 0) + { + omap_free_dma (dma_regs); + dma_regs = NULL; + + tffsInfo.channel = -1; + } + + /* if previously was allocated, release intermediate DMA buffer */ + if (tffsInfo.dma_buf_vptr != NULL) + { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_free (tffsInfo.dma_buf_vptr, PAGE_SIZE, tffsInfo.dma_buf_paddr); +#else + dma_free_coherent (NULL, PAGE_SIZE, tffsInfo.dma_buf_vptr, tffsInfo.dma_buf_paddr); +#endif + tffsInfo.dma_buf_vptr = NULL; + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b r e a d * + * * + * Transfer data from DiskOnChip's I/O reguster to RAM buffer. * + * Example implementation For Texas Instruments OMAP1610 H2 board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bread ( int off, + void * vbuf, + unsigned int bytes ) +{ + register u32 tmp; + register int waiting; + + profiling[2]++; + + /* Channel Source/Destination Parameters. + * Specify 16-bit port width, EMIFS source, allow source packing, + * 4-words burst allowed for source, EMIFF destination. allow + * destination packing, 4-words burst allowed for destination. + */ + dma_regs->csdp = (BURST_4 << 14) | /* dest.: use 4-word burst */ + DCSDP_DST_PACK | /* pack dest. */ + (PORT_EMIFF << 9) | /* dest. is EMIFF (RAM) */ + (BURST_4 << 7) | /* source: use 4-word burst */ + DCSDP_SRC_PACK | /* pack source */ + (PORT_EMIFS << 2) | /* source is EMIFS (DiskOnChip) */ + DATA_TYPE_S16; /* 16-bit data path */ + + /* Channel Control Register. + * Specify no synchronization, no OMAP 3.0/3.1 compatibility, no + * frame synchronization, high priority, constant source address, + * post-increment destination address. + */ + dma_regs->ccr = (AMODE_POST_INC << 14) | /* dest (RAM): post-increment */ + (AMODE_CONST << 12) | /* source (DiskOnChip) : const addr. */ + DCCR_N31COMP | /* no OMAP 3.0/3.1 compatibility */ + DCCR_PRIO; /* high priority */ + + /* Channel Frame Number Register. + * We assume that frame consists of single element, and element + * consists of single 16-bit word. + */ + dma_regs->cfn = (bytes / sizeof(u16)); + + /* Channel Source Start Address Registers. This would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + tmp = tffs_addr[0] + off; + dma_regs->cssa_u = (tmp >> 16); + dma_regs->cssa_l = (tmp & 0xffff); + + /* Channel Destination Start Address Registers */ + if (tffs_dma_mode & 4) /* do DMA transfer directly into 'vbuf' */ + { + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + tmp = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + tmp = __pa (k_vbuf); + } + + /* write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */ +#if 1 + /* D-cache only. Possible options: + * flush_dcache_range((unsigned long)vbuf, (unsigned long)(vbuf + bytes)); ARM/PPC + * consistent_sync(vbuf, bytes, PCI_DMA_BIDIRECTIONAL); ARM/PPC + * dma_cache_wback_inv((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/SH/x86 + */ + flush_dcache_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes)); +#else + /* both D- and I-caches */ + cpu_cache_clean_invalidate_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes), 1); +#endif + } + else /* transfer into intermediate DMA buffer */ + { + tmp = tffsInfo.dma_buf_paddr; + } + dma_regs->cdsa_u = (tmp >> 16); + dma_regs->cdsa_l = (tmp & 0xffff); + + /* start DMA channel */ + dma_regs->ccr |= DCCR_EN; + + /* wait for DMA transfer to finish */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if (((tmp = dma_regs->ccr) & DCCR_EN) == 0) + { + /* read Channel Status Register to clear it */ + if (((tmp = dma_regs->csr) & DCSR_ERROR) == 0) + { + /* DMA transfer completed, move data from the intermediate DMA + * buffer to the destination buffer (in case it was used). + */ + if ((tffs_dma_mode & 4) == 0) + memcpy (vbuf, tffsInfo.dma_buf_vptr, bytes); + } + else /* andrayk June 13 2006: DMA transfer failed, find way to let MTD know this */ + { + PrintkError ("Bus error, DMA transfer failed"); + } + return; + } + } + + PrintkError ("DMA transfer timed out"); +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b w r i t e * + * * + * Transfer data from RAM buffer to DiskOnChip's I/O reguster. * + * Example implementation For Texas Instruments OMAP1610 H2 board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bwrite ( int off, + void * vbuf, + unsigned int bytes ) +{ + register u32 tmp; + register int waiting; + + profiling[3]++; + + /* Channel Source/Destination Parameters. + * Specify 16-bit port width, EMIFF source, allow source packing, + * 4-words burst allowed for source, EMIFS destination. allow + * destination packing, 4-words burst allowed for destination. + */ + dma_regs->csdp = (BURST_4 << 14) | /* dest.: use 4-word burst */ + DCSDP_DST_PACK | /* pack dest. */ + (PORT_EMIFS << 9) | /* dest. is EMIFS (DiskOnChip) */ + (BURST_4 << 7) | /* source: use 4-word burt */ + DCSDP_SRC_PACK | /* pack source */ + (PORT_EMIFF << 2) | /* source is EMIFF (RAM) */ + DATA_TYPE_S16; /* 16-bit data path */ + + /* Channel Control Register. + * Specify no synchronization, no OMAP 3.0/3.1 compatibility, no + * frame synchronization, high priority, constant dest. address, + * post-increment source address. + */ + dma_regs->ccr = (AMODE_CONST << 14) | /* dest. (DiskOnChip): const addr. */ + (AMODE_POST_INC << 12) | /* source (RAM): post-increment */ + DCCR_N31COMP | /* no OMAP 3.1/3.0 compatibility */ + DCCR_PRIO; /* high priority */ + + /* Channel Frame Number Register. + * We assume that frame consists of single elemnt, and element consists + * of single 16-bit word. + */ + dma_regs->cfn = (bytes / sizeof(u16)); + + /* Channel Source Start Address Registers */ + if (tffs_dma_mode & 4) /* do DMA transfer directly from 'vbuf' */ + { + /* Write (if dirty) contents of 'vbuf' from CPU D-cache to RAM. + * Possible options: + * clean_dcache_range((unsigned long)vbuf, (unsigned long)(vbuf + bytes)); ARM/PPC + * consistent_sync(vbuf, bytes, PCI_DMA_TODEVICE); ARM/PPC + * dma_cache_wback((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/SH/x86 + */ + clean_dcache_range ((unsigned long)vbuf, (unsigned long)(vbuf + bytes)); + + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + tmp = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + tmp = __pa (k_vbuf); + } + } + else /* use intermediate DMA buffer */ + { + /* move data from RAM buffer to the intermediate DMA buffer */ + memcpy (tffsInfo.dma_buf_vptr, vbuf, bytes); + + tmp = tffsInfo.dma_buf_paddr; + } + dma_regs->cssa_u = (tmp >> 16); + dma_regs->cssa_l = (tmp & 0xffff); + + /* Channel Destination Start Address Regist.This would be DiskOnChip's + * I/O register which is located at offset 'off' from the DiskOnChip's + * base address as specified by tffs_addr[0]). + */ + tmp = tffs_addr[0] + off; + dma_regs->cdsa_u = (tmp >> 16); + dma_regs->cdsa_l = (tmp & 0xffff); + + /* start DMA channel */ + dma_regs->ccr |= DCCR_EN; + + /* poll DMA channel's status register for end of DMA transfer */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if (((tmp = dma_regs->ccr) & DCCR_EN) == 0) + { + if ((tmp = dma_regs->csr) & DCSR_ERROR) /* andrayk June 14 2006: DMA transfer failed, find way to let MTD know this */ + { + PrintkError ("Bus error, DMA transfer failed"); + } + return; + } + } + + PrintkError ("DMA transfer timed out"); +} + + + +#elif defined(CONFIG_ARCH_OMAP24XX) + +/*_____________________________________________________________________________ + | | + | | + | Texas Instruments OMAP-2420 (H4) board | + | | + |____________________________________________________________________________| +*/ + +# include +# include +/* # include */ /* conflicts with */ +# include +# include + +/* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears + * to be buggy: it seems to constantly shoot past the end of the address + * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some + * bogus data into this RAM address range while invalidating it in D-cache. + */ +# define OMAP2420_DCACHE_BUG_WORKAROUND + + +# ifndef OMAP_DMA4_CCR_EN +# define OMAP_DMA4_CCR_EN (1 << 7) +# endif + +# define GPMC_CONFIG1_CS2 0xC0 /* phys. addr. 0x6800A0C0 */ +# define GPMC_CONFIG2_CS2 (GPMC_CONFIG1_CS2 + 0x4) /* phys. addr. 0x6800A0C4 */ +# define GPMC_CONFIG3_CS2 (GPMC_CONFIG1_CS2 + 0x8) /* phys. addr. 0x6800A0C8 */ +# define GPMC_CONFIG4_CS2 (GPMC_CONFIG1_CS2 + 0xC) /* phys. addr. 0x6800A0CC */ +# define GPMC_CONFIG5_CS2 (GPMC_CONFIG1_CS2 + 0x10) /* phys. addr. 0x6800A0D0 */ +# define GPMC_CONFIG6_CS2 (GPMC_CONFIG1_CS2 + 0x14) /* phys. addr. 0x6800A0D4 */ +# define GPMC_CONFIG7_CS2 (GPMC_CONFIG1_CS2 + 0x18) /* phys. addr. 0x6800A0D8 */ + +# ifndef OMAP2420_GPIO_SET_IRQENABLE1 +# define OMAP2420_GPIO_SET_IRQENABLE1 0x0064 +# endif +# ifndef OMAP2420_GPIO_CLEAR_IRQENABLE1 +# define OMAP2420_GPIO_CLEAR_IRQENABLE1 0x0060 +# endif +# ifndef OMAP2420_GPIO_IRQSTATUS1 +# define OMAP2420_GPIO_IRQSTATUS1 0x0018 +# endif +# ifndef OMAP2420_GPMC_BASE +# define OMAP2420_GPMC_BASE OMAP24XX_GPMC_BASE +# endif + +/* layout of DMA channel's registers */ +typedef struct { + volatile u32 ccr; /* Channel Control Register */ + volatile u32 clnk; /* Channel Link Control */ + volatile u32 cicr; /* Channel Interrupt Control Register */ + volatile u32 csr; /* Channel Status Register */ + volatile u32 csdp; /* Channel Source / Destination Parameters */ + volatile u32 cen; /* Channel Element Number */ + volatile u32 cfn; /* Channel Frame Number */ + volatile u32 cssa; /* Channel Source Start Address */ + volatile u32 cdsa; /* Channel Destination Start Address */ + volatile u32 csei; /* Channel Source Element Index */ + volatile u32 csfi; /* Channel Source Frame Index */ + volatile u32 cdei; /* Channel Destination Element Index */ + volatile u32 cdfi; /* Channel Destination Frame Index */ + volatile u32 csac; /* Channel Source Address Counter */ + volatile u32 cdac; /* Channel Destination Address Counter */ + volatile u32 ccen; /* Channel Current Element Number */ + volatile u32 ccfn; /* Channel Current Frame Number */ +} __dma_reg_t; + + +/* + * static routines for OMAP2420 + */ +static void tffs_dma_init (int resume); +static void tffs_dma_release (void); + + +/* + * static vars + */ +static __dma_reg_t * dma_regs_vptr = NULL; + + + +void omap24xx_enable_gpio_irq (int gpio_irq, int enable) +{ + register u32 gpio_line = gpio_irq - IH_GPIO_BASE; + register u32 bit = OMAP_GPIO_BIT(gpio_line); + register u32 base_reg = OMAP_GPIO_BASE_REG(gpio_line); + unsigned int val = 0; + + if (enable == TRUE) + { + writel (bit, (base_reg + OMAP2420_GPIO_SET_IRQENABLE1)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */ + + omap_set_gpio_edge_ctrl (gpio_line, OMAP_GPIO_LEVEL_LOW); + } + else + { + omap_set_gpio_edge_ctrl (gpio_line, 0); + + writel (bit, (base_reg + OMAP2420_GPIO_CLEAR_IRQENABLE1)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */ + + writel (bit, (base_reg + OMAP2420_GPIO_IRQSTATUS1)); + __asm__ __volatile__("mcr p15, 0, %0, c7, c10, 4"::"r"(val)); /* memory barrier */ + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s a r c h _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required board resources; if 'resume' * + * is TRUE, this routine does minimal required re-initialization of * + * these resources after power suspend. For OMAP2420 (H4) board. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + * Returns: * + * always '1' (success) * + * * + *-----------------------------------------------------------------------*/ + +unsigned char tffsarch_init (int resume) +{ + register int tmp; + char * vp; + + if ((vp = (char *)ioremap_nocache(OMAP2420_GPMC_BASE, PAGE_SIZE)) == NULL) + { + PrintkError ("ioremap_nocache failed"); + } + else + { + /* Configure Chip Select that DiskOnChip is connected to. + * + * NOTE. Code below configures Chip Select to set duration of + * DiskOnChip access cycle to 65 nanosecond, which is + * appropriate for the case when DiskOnChip is connected to + * OMAP2420 board via M-Systems' adapters. If you solder + * DiskOnChip into your board, consider changing Chip Select + * settings to significantly shorten DiskOnChip acecss cycle. + * This should have significant positive efefct on + * DiskOnChip's 'read' performance. + */ + + tmp = (0 << 31) | /* synchronous wrapping burst not supported */ + (0 << 30) | /* single access */ + (0 << 29) | /* asynchronous read */ + (0 << 28) | /* single access */ + (0 << 27) | /* write asynchronous */ + (0 << 25) | /* start access time at first rising edge of GPMC.CLK */ + (0 << 23) | /* burst length 4 words */ + (0 << 22) | /* wait pin not monitored for read access */ + (0 << 21) | /* wait pin not monitored for write access */ + (0 << 18) | /* wait pin is monitored with valid data */ + (0 << 16) | /* wait input pin is WAIT0 */ + (1 << 12) | /* 16-bit device */ + (0 << 10) | /* NOR flash, pSRAM, or asynchronous device */ + (1 << 9) | /* address/data multiplexed attached device */ + (0 << 4) | /* x1 latencies */ + (3 << 0); /* GPMC.CLK = GPMC_FCLK/4 */ + writel (tmp /* 0x00001203 */, vp + GPMC_CONFIG1_CS2); + + tmp = (6 << 16) | /* nCS assertion time for write access */ + (6 << 8) | /* nCS assertion time for read access */ + (0 << 7) | /* nCS timing sygnal is not delayed */ + (0 << 0); /* nCS assertion time */ + writel (tmp /* 0x00060600 */, vp + GPMC_CONFIG2_CS2); + + tmp = (1 << 16) | /* nADV deassertion time for write access */ + (1 << 8) | /* nADV deassertion time for read access */ + (0 << 7) | /* nADV timing control sygnal is not delayed */ + (0 << 0); /* nADV assertion time */ + writel (tmp /* 0x00010100 */, vp + GPMC_CONFIG3_CS2); + + tmp = (5 << 24) | /* nWE deassertion time */ + (0 << 23) | /* nWE timing control sygnal is not delayed */ + (2 << 16) | /* nWE assertion time */ + (6 << 8) | /* nOE deassertion time */ + (0 << 7) | /* nOE timing control sygnal is not delayed */ + (2 << 0); /* nOE assertion time */ + writel (tmp /* 0x05020602 */, vp + GPMC_CONFIG4_CS2); + + tmp = (1 << 24) | /* delay between successive words in multiple access */ + (5 << 16) | /* delay between start-cycle and first data valid */ + (7 << 8) | /* total write cycle time in GPMC_FCLK cycles */ + (7 << 0); /* total read cycle time in GPMC_FCLK cycles */ + writel (tmp /* 0x01050707 */, vp + GPMC_CONFIG5_CS2); + + /* Map Chips Select CS2 at physical address 0x10000000 (as + * specified by macro TFFS_PHYS_ADDR). + */ + tmp = 0x00000F50; + writel (tmp, vp + GPMC_CONFIG7_CS2); + + iounmap (vp); + } + + if (tffs_irq >= 0) + { + register int gpio_line = (tffs_irq - IH_GPIO_BASE); + + if( omap_request_gpio(gpio_line) == 0 ) + { + register u8 x = readb (OMAP24XX_VA_SYSTEM_CONTROL_BASE + 0x10c); + + /* set GPIO function (mux mode 3), disable pullup/pulldown */ + x &= ~(MUXMODE_MASK); + x |= 3; + x &= ~(PULL_UD_ENABLE_MASK); + writeb (x, OMAP24XX_VA_SYSTEM_CONTROL_BASE + 0x10c); + + /* configure this GPIO line as input */ + omap_set_gpio_direction (gpio_line, TRUE); + + /* configure GPIO interrupt as level-low for this GPIO line */ +#if 0 + omap_set_gpio_edge_ctrl (gpio_line, /* OMAP_GPIO_LEVEL_LOW */ OMAP_GPIO_FALLING_EDGE); +#endif + } + else + { + PrintkWarning ("failed to get IRQ %d", tffs_irq); + tffs_irq = -1; + } + } + + /* if DMA is requested, configure it */ + if (tffs_dma_mode > 0) + { + tffs_dma_init (resume); + } + + return 1; +} + + + + +void TffsHWRelease(void) +{ + /* if DMA was actually used, release all DMA resources */ + if (tffs_dma_mode > 0) + { + tffs_dma_release (); + } + + /* if IRQ was actually used, release respective GPIO resources */ + if (tffs_irq >= 0) + { + register int gpio_line = (tffs_irq - IH_GPIO_BASE); + + omap_free_gpio (gpio_line); + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ i n i t * + * * + * This routine is called during module initialization time with 'resume'* + * argument set to FALSE, and from Power Manager's 'resume' routine with * + * 'resume' argument set to TRUE. If 'resume' is FALSE, this routine * + * allocates and initializes all required DMA resources; if 'resume' is * + * TRUE, this routine does minimal required re-initialization of DMA * + * channel after power suspend. For OMAP2420 (H4) board. * + * * + * Parameters: * + * suspend FALSE (module initialization) or TRUE (power resume) * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_init (int resume) +{ + register u32 tmp; + int rc; + + if (resume == FALSE) + { + /* We use single DMA channel for both 'read' and 'write' operations, + * so we allocate it here. We don't use DMA interrupts, so we won't + * need DMA callback. + */ + rc = omap_request_dma (0, + TFFS_DEVICE_NAME, + NULL, /* no callback when DMA completes */ + NULL, /* data to pass to DMA callback */ + &tffsInfo.channel); + + if ((rc != 0) || (tffsInfo.channel < 0) || + (tffsInfo.channel >= OMAP24XX_LOGICAL_DMA_CH_COUNT)) + { + /* failed to allocate DMA channel, won't use DMA */ + tffs_dma_mode = 0; + + PrintkError ("can't get DMA chan"); + return; + } + else + { + PrintkInfo ("use DMA channel %d", tffsInfo.channel); + + /* virt. address of DMA channel's register set */ + dma_regs_vptr = (__dma_reg_t *) + (OMAP_DMA4_BASE + (0x60 * tffsInfo.channel) + 0x80); + } + } + + /* Channel Control Register */ + tmp = (0 << 25) | /* buffering enabled */ + (0 << 24) | /* destination triggers DMA request */ + (1 << 23) | /* prefetch enabled */ + (0 << 21) | /* secure mode disabled */ + (0 << 19) | /* no synchronization */ + (1 << 18) | /* block synchronization */ + (0 << 17) | /* transaparent copy disabled */ + (0 << 16) | /* constant fill disabled */ + (1 << 14) | /* post-increment destination address */ + (0 << 12) | /* constant source address */ + (0 << 8) | /* ignore MSUSPEND */ + (0 << 7) | /* channel disabled (stopped) */ + (1 << 6) | /* high priority channel */ + (0 << 5) | /* no frame synchronization */ + (0 << 0); /* no synchronization (i.e. s/w DMA) */ + writel (tmp, &dma_regs_vptr->ccr); + + /* Channel Frame Number Register. + * We assume that frame consists of single element. + */ + writel (1, &dma_regs_vptr->cfn); + + /* Channel Interrupt Control Register. + * Disable all interrupts - we will be polling DMA controller. + */ + tmp = /* OMAP_DMA_DROP_IRQ | */ /* synchronization drop */ + /* OMAP_DMA_BLOCK_IRQ | */ /* end-of-block interrupt */ + /* (1 << 11) | */ /* misaligned address error */ + /* (1 << 8) | */ /* transaction error */ + 0; + writel (tmp, &dma_regs_vptr->cicr); + + /* Channel Status Register. + * Write all-ones to clear any pending interrupts. + */ + writel (~0, &dma_regs_vptr->csr); + + if (resume == FALSE) + { + tffsInfo.dma_buf_vptr = NULL; + tffsInfo.dma_buf_size = 0; + + if ((tffs_dma_mode >= 1) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) || !defined(OMAP2420_DCACHE_BUG_WORKAROUND) + && (tffs_dma_mode <= 3) +#endif + ) + { + /* allocate intermediate DMA buffer (we assume one MMU page will be enough) */ + tffsInfo.dma_buf_size = PAGE_SIZE; + + tffsInfo.dma_buf_vptr = +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_alloc ((GFP_KERNEL | GFP_DMA), tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr); +#else + dma_alloc_coherent (NULL, tffsInfo.dma_buf_size, + &tffsInfo.dma_buf_paddr, (GFP_KERNEL | GFP_DMA)); +#endif + if (tffsInfo.dma_buf_vptr == NULL) + { + /* failed to allocate intermediate DMA buffer, won't use DMA */ + tffs_dma_mode = 0; + + omap_free_dma (tffsInfo.channel); + + tffsInfo.channel = -1; + tffsInfo.dma_buf_size = 0; + + dma_regs_vptr = NULL; + + PrintkError ("can't alloc DMA buffer, won't use DMA"); + } + } + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * t f f s _ d m a _ r e l e a s e * + * * + * Release all previously allocated DMA resources (channel, intermediate * + * DMA buffer etc.). For OMAP2420 (H4) board. * + * * + *-----------------------------------------------------------------------*/ +static +void tffs_dma_release(void) +{ + /* if previously was allocated, release DMA channel */ + if (tffsInfo.channel >= 0) + { + omap_free_dma (tffsInfo.channel); + + tffsInfo.channel = -1; + dma_regs_vptr = NULL; + } + + /* if previously was allocated, release intermediate DMA buffer */ + if (tffsInfo.dma_buf_vptr != NULL) + { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + consistent_free (tffsInfo.dma_buf_vptr, PAGE_SIZE, tffsInfo.dma_buf_paddr); +#else + dma_free_coherent (NULL, PAGE_SIZE, tffsInfo.dma_buf_vptr, tffsInfo.dma_buf_paddr); +#endif + tffsInfo.dma_buf_vptr = NULL; + } +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b r e a d * + * * + * Transfer data from DiskOnChip's I/O reguster to RAM buffer. * + * Example implementation For Texas Instruments OMAP2420 H4 board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bread ( int off, + void * vbuf, + unsigned int bytes ) +{ + register __dma_reg_t * regs = dma_regs_vptr; + register u32 tmp, tmp2; + register int waiting; + register int direct_dma; + + profiling[2]++; + + direct_dma = ((tffs_dma_mode & 4) ? TRUE : FALSE); + + /* Due to a bug in kernel routine blk_dma_inv_range_harvard() + * (arch/arm/mm/blockops.c), we allow direct DMA to destination + * buffer 'vbuf' only when it's aligned at CPU's cache line boundary. + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined(OMAP2420_DCACHE_BUG_WORKAROUND) + if ((u32)vbuf & 31) + direct_dma = FALSE; +#endif + + /* Channel Source/Destination Parameters */ + tmp = (0 << 21) | /* little-endian source (DiskOnChip) */ + (1 << 20) | /* source endianism lock */ + (0 << 19) | /* little-endian destination (SDRAM) */ + (1 << 18) | /* destination endianism adapt */ + (1 << 16) | /* writes (to SDRAM) posted */ + (3 << 14) | /* 64-byte burst on destination (SDRAM) */ + (1 << 13) | /* destination (SDRAM) packed */ + (3 << 7) | /* 64-byte burst on source (DiskOnChip) */ + (1 << 6) | /* source (DiskOnChip) packed */ + (1 << 0) ; /* 16-bit data port width */ + writel (tmp, ®s->csdp); + + /* Channel Control Register */ + tmp2 = (0 << 25) | /* buffering enabled */ + (0 << 24) | /* destination triggers DMA request */ + (1 << 23) | /* prefetch enabled */ + (0 << 21) | /* secure mode disabled */ + (0 << 19) | /* no synchronization */ + (1 << 18) | /* block synchronization */ + (0 << 17) | /* transaparent copy disabled */ + (0 << 16) | /* constant fill disabled */ + (1 << 14) | /* post-increment destination address */ + (0 << 12) | /* constant source address */ + (0 << 8) | /* ignore MSUSPEND */ + (0 << 7) | /* channel disabled (stopped) */ + (1 << 6) | /* high priority channel */ + (0 << 5) | /* no frame synchronization */ + (0 << 0); /* no synchronization (i.e. s/w DMA) */ + writel (tmp2, ®s->ccr); + + /* Channel Element Number Register */ + writel ((bytes >> 1), ®s->cen); + + /* Channel Source Start Address Register. + * This would be DiskOnChip's I/O register which is located at offset + * 'off' from the DiskOnChip's base address as specified by tffs_addr[0]). + */ + writel ((tffs_addr[0] + off), ®s->cssa); + + /* Channel Destination Start Address Register. + * This would be physical address of intermediate DMA buffer (for + * DMA modes 1 and 3), or physical address of the destination buffer + * (for DMA modes 5 and 7). + */ + if (direct_dma == TRUE) /* do DMA transfer directly into 'vbuf' */ + { + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + tmp = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (k_vbuf == NULL) + { + PrintkError ("error, DMA requested on high memory page"); + return; + } + + tmp = __pa (k_vbuf); + } + + /* Write (if dirty) and purge contents of 'vbuf' from CPU cache(s) */ + /* Possible options: + * consistent_sync(vbuf, bytes, DMA_FROM_DEVICE); ARM/SH + * dma_cache_inv((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86 + */ +#ifdef OMAP2420_DCACHE_BUG_WORKAROUND + /* Routine blk_dma_inv_range_harvard() (arch/arm/mm/blockops.c) appears + * to be buggy: it seems to constantly shoot past the end of the address + * range [vbuf..vbuf+bytes] by 32 bytes. It also appears to write some + * bogus data into this RAM address range while invalidating it in D-cache. + */ + consistent_sync (vbuf, bytes - 1, DMA_FROM_DEVICE); +#else + consistent_sync (vbuf, bytes, DMA_FROM_DEVICE); +#endif + + } + else /* transfer into intermediate DMA buffer */ + { + tmp = tffsInfo.dma_buf_paddr; + } + writel (tmp, ®s->cdsa); + + /* Channel Status Register. + * Write all-ones to clear any pending interrupts. + */ + writel (~0, ®s->csr); + + /* start DMA channel by setting ENABLED bit in Channel Control Register */ + writel ((tmp2 | OMAP_DMA4_CCR_EN), ®s->ccr); + + /* we don't want to see any of these DMA errors */ + tmp2 = (1 << 11) | /* misaligned error */ + (1 << 9) | /* secure transaction error */ + (1 << 8) | /* transaction error */ + (1 << 1); /* synchronization drop */ + + /* Wait for DMA transfer to finish (ENABLED bit in + * Channel Control Register changes to zero). + */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if( readl(®s->ccr) & OMAP_DMA4_CCR_EN ) + continue; + + /* read Channel Status Register to find out status of DMA transfer */ + tmp = readl(®s->csr) & tmp2; + + /* write all-ones to clear any pending interrupts */ + writel (~0, ®s->csr); + + /* any errors ? */ + if (tmp == 0) + { + /* DMA transfer successfully completed, move data from intermediate + * DMA buffer to destination buffer (in case it was used). + */ + if (direct_dma == FALSE) + memcpy (vbuf, tffsInfo.dma_buf_vptr, bytes); + } + else /* andrayk June 13 2006: DMA transfer failed, find way to let MTD know this */ + { + PrintkError ("DMA transfer failed"); + } + return; + } + + PrintkError ("DMA transfer timed out"); +} + + + + +/*-----------------------------------------------------------------------* + * * + * _ _ d m a s w _ b w r i t e * + * * + * Transfer data from RAM buffer to DiskOnChip's I/O reguster. * + * Example implementation For Texas Instruments OMAP2420 H4 board. * + * * + * Parameters: * + * off offset of DiskOnChip's I/O register from the base * + * of DiskOnChip window * + * vbuf virtual address of RAM buffer * + * bytes bytes to transfer * + * * + *-----------------------------------------------------------------------*/ +static +void __dmasw_bwrite ( int off, + void * vbuf, + unsigned int bytes ) +{ + register __dma_reg_t * regs = dma_regs_vptr; + register u32 tmp, tmp2; + register int waiting; + + profiling[3]++; + + /* Channel Source/Destination Parameters */ + tmp = (0 << 21) | /* little-endian source (SDRAM) */ + (1 << 20) | /* source endianism locked */ + (0 << 19) | /* little-endian dest. (DiskOnChip) */ + (1 << 18) | /* destination endianism locked */ + (1 << 16) | /* writes (to DiskOnChip) posted */ + (0 << 14) | /* 64-byte burst on dest. (DiskOnChip) */ + (1 << 13) | /* destination (DiskOnChip) packed */ + (3 << 7) | /* 64-byte burst on source (SDRAM) */ + (1 << 6) | /* source (SDRAM) packed */ + (1 << 0) ; /* 16-bit data port width */ + writel (tmp, ®s->csdp); + + /* Channel Control Register */ + tmp2 = (0 << 25) | /* buffering enabled */ + (1 << 24) | /* source triggers DMA request */ + (1 << 23) | /* prefetch enabled */ + (0 << 21) | /* secure mode disabled */ + (0 << 19) | /* no synchronization */ + (1 << 18) | /* block synchronization */ + (0 << 17) | /* transaparent copy disabled */ + (0 << 16) | /* constant fill disabled */ + (0 << 14) | /* constant destination address */ + (1 << 12) | /* post-increment source address */ + (0 << 8) | /* ignore MSUSPEND */ + (0 << 7) | /* channel disabled (stopped) */ + (1 << 6) | /* high priority channel */ + (0 << 5) | /* no frame synchronization */ + (0 << 0); /* no synchronization (i.e. s/w DMA) */ + writel (tmp2, ®s->ccr); + + /* Channel Element Number Register */ + writel ((bytes >> 1), ®s->cen); + + /* Channel Source Start Address Register. + * This would be physical address of intermediate DMA buffer (for + * DMA modes 2 and 3), or physical address of the destination buffer + * (for DMA modes 6 and 7). + */ + if (tffs_dma_mode & 4) /* do DMA transfer directly from 'vbuf' */ + { + /* Write (if dirty) contents of 'vbuf' from CPU D-cache to RAM. + * Possible options: + * consistent_sync(vbuf, bytes, DMA_TO_DEVICE); ARM/SH + * dma_cache_wback((unsigned long)vbuf, (unsigned long)bytes); MIPS/PPC/x86 + */ + consistent_sync (vbuf, bytes, DMA_TO_DEVICE); + + if (virt_addr_valid((unsigned long)vbuf)) /* 'vbuf' is in low memory */ + { + tmp = __pa (vbuf); + } + else /* 'vbuf' is in high memory */ + { + char * k_vbuf = (char *) page_address(vmalloc_to_page(vbuf)) + + ((unsigned long)vbuf & (PAGE_SIZE - 1)); + if (k_vbuf == NULL) + { + PrintkError ("error, DMA requested on high memory page"); + return; + } + + tmp = __pa (k_vbuf); + } + } + else /* use intermediate DMA buffer */ + { + /* move data from RAM buffer to the intermediate DMA buffer */ + memcpy (tffsInfo.dma_buf_vptr, vbuf, bytes); + + tmp = tffsInfo.dma_buf_paddr; + } + writel (tmp, ®s->cssa); + + /* Channel Destination Start Address Register. + * This would be DiskOnChip's I/O register which is located at offset + * 'off' from the DiskOnChip's base address as specified by tffs_addr[0]). + */ + writel ((tffs_addr[0] + off), ®s->cdsa); + + /* Channel Status Register. + * Write all-ones to clear any pending interrupts. + */ + writel (~0, ®s->csr); + + /* start DMA channel by setting ENABLED bit in Channel Control Register */ + writel ((tmp2 | OMAP_DMA4_CCR_EN), ®s->ccr); + + /* we don't want to see any of these DMA errors */ + tmp2 = (1 << 11) | /* misaligned error */ + (1 << 9) | /* secure transaction error */ + (1 << 8) | /* transaction error */ + (1 << 1); /* synchronization drop */ + + /* Wait for DMA transfer to finish (ENABLED bit in + * Channel Control Register changes to zero). + */ + for (waiting = 100000; waiting > 0; waiting--) /* hope this is long enough ... */ + { + if( readl(®s->ccr) & OMAP_DMA4_CCR_EN ) + continue; + + /* read Channel Status Register to find out status of DMA transfer */ + tmp = readl(®s->csr) & tmp2; + + /* write all-ones to clear any pending interrupts */ + writel (~0, ®s->csr); + + /* any errors ? */ + if (tmp != 0) /* andrayk June 13 2006: DMA transfer failed, find way to let MTD know this */ + { + PrintkError ("DMA transfer failed"); + } + return; + } + + PrintkError ("DMA transfer timed out"); +} + + + + +#elif defined(CONFIG_OMAP_OSK) + +/*_____________________________________________________________________________ + | | + | | + | Texas Instruments OMAP OSK board | + | | + |____________________________________________________________________________| +*/ + + +unsigned char tffsarch_init (int resume) +{ + (*(short*)0xFFFEC808) = 0x00F5; + (*(short*)0xFFFEC808) = 0x00A0; + return 1; +} + +void TffsHWRelease(void) +{ } + +static void __dmasw_bread (int off, void * vbuf, unsigned int bytes) +{ } + +static void __dmasw_bwrite (int off, void * vbuf, unsigned int bytes) +{ } + + + + +#elif defined(CONFIG_ARCH_LUBBOCK) + +/*_____________________________________________________________________________ + | | + | | + | Intel PXA25x ("Lubbock") board | + | | + |____________________________________________________________________________| +*/ + +# define MSC2_CNTR_REG_ADDR 0x48000000 +# define MSC2_OFFSET 0x10 +# define MCS5_INIT_VAL 0xFFF80000 + +unsigned char tffsarch_init (int resume) +{ + volatile void *myMSC2ptr; + unsigned long msc2Val; + + myMSC2ptr = (volatile void *)ioremap_nocache(MSC2_CNTR_REG_ADDR, 0x1000); + /* MSC2 Static Memory Control Register - 16-bit mode for CS5 */ + msc2Val = readl( myMSC2ptr + MSC2_OFFSET ); + writel( ((msc2Val & 0x0000FFFF) | MCS5_INIT_VAL), myMSC2ptr + MSC2_OFFSET ); + /* *(myMCS5 + 4) = MCS5_INIT_VAL; */ + iounmap( (void *)myMSC2ptr); + + return 1; +} + +static void __dmasw_bread (int off, void * vbuf, unsigned int bytes) +{ } + +static void __dmasw_bwrite (int off, void * vbuf, unsigned int bytes) +{ } + + + + +#else /* ARCH */ + +/*_____________________________________________________________________________ + | | + | | + | All other boards | + | | + |____________________________________________________________________________| +*/ + +unsigned char tffsarch_init (int resume) +{ + return 1; +} + +void TffsHWRelease(void) +{ } + +static void __dmasw_bread (int off, void * vbuf, unsigned int bytes) +{ } + +static void __dmasw_bwrite (int off, void * vbuf, unsigned int bytes) +{ } + +#endif /* ARCH */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsarch.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsarch.h new file mode 100755 index 00000000..dce399c3 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsarch.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef TFFSARCH_H +#define TFFSARCH_H + + + +/* + * includes + */ + +#include +//#include +#include + + +/* + * Physical address of DiskOnChip device. + * + * M-Systems provides default values for variety of popular boards (see also + * documentation for respective DiskOnChip adaptors for these boards). If you + * are using different board, you'll need to define TFFS_PHYS_ADDR as + * appropriate for your system. + */ +#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) +# define TFFS_PHYS_ADDR 0x14000000 /* chip select CS5 on Intel PXA27x Mainstone */ +#elif defined(CONFIG_ARCH_LUBBOCK) +# define TFFS_PHYS_ADDR 0x14000000 +#elif defined(CONFIG_ARCH_OMAP24XX) +# define TFFS_PHYS_ADDR 0x10000000 /* chip select CS2 on Texas Instruments OMAP2420 */ +#elif defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2) +# define TFFS_PHYS_ADDR 0x8000000 +#elif defined(CONFIG_OMAP_OSK) +# define TFFS_PHYS_ADDR 0x6000000 +#elif defined(CONFIG_M386) || defined(CONFIG_M486) || defined(CONFIG_M586) || defined(CONFIG_M586TSC) || defined(CONFIG_M586MMX) || defined(CONFIG_M686) || defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUM4) +# define TFFS_PHYS_ADDR 0xd0000 +#else +# define TFFS_PHYS_ADDR 0 +#endif +extern unsigned long tffs_addr []; + + +/* + * Board's IRQ line that DiskOnChip's IREQ is connected to. + * + * M-Systems provides default values for variety of popular boards (see also + * documentation for respective DiskOnChip adaptors for these boards). If you + * are using different board, you'll need to define TFFS_IRQ as + * appropriate for your system, or set it to (-1) if you don't want to use + * DiskOnChip IREQ. + */ +#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) +# define TFFS_IRQ MAINSTONE_IRQ(7) /* Intel PXA27x ("Mainstone") */ +#elif defined(CONFIG_ARCH_LUBBOCK) +# define TFFS_IRQ (-1) +#elif defined(CONFIG_ARCH_OMAP24XX) +# define TFFS_IRQ (-1) /* OMAP_GPIO_IRQ_NO(94), if using GPIO line 94 */ +#elif defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2) /* Texas Instruments OMAP1610 SDP ("H2") */ +# define TFFS_IRQ (-1) /* was INT_GPIO_9, or numerically 169 */ +#elif defined(CONFIG_OMAP_OSK) +# define TFFS_IRQ (-1) +#elif defined(CONFIG_M386) || defined(CONFIG_M486) || defined(CONFIG_M586) || defined(CONFIG_M586TSC) || defined(CONFIG_M586MMX) || defined(CONFIG_M686) || defined(CONFIG_MPENTIUMIII) || defined(CONFIG_MPENTIUM4) +# define TFFS_IRQ (-1) +#else +# define TFFS_IRQ (-1) +#endif + + +/* # define FL_XSCALE_BOOT_MODE */ + + +/* DiskOnChip driver uses 'flRead512Bytes' macro to transfer 512-bytes of + * data from DiskOnChip to destination RAM buffer. We check if s/w DMA + * is enabled for 'read' operations, and if buffer is properly aligned. + * If they are, we use s/w DMA to transfer data; otherwise we use TrueFFS' + * internal C loops to transfer data in 16-bit short words. + */ + extern int tffs_dma_mode; + + extern void tffs_readw (unsigned long io_vaddr, short *vbuf, int words); + extern void tffs_writew (unsigned long io_vaddr, short *vbuf, int words); + extern void tffs_dmasw (char *win, int off, void *vbuf, unsigned int bytes, int read); + +#if defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) || defined(CONFIG_OMAP_H2) || defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_ARCH_OMAP24XX) + +# define flReadEvenNumberOfBytes(flash,off,vbuf,bytes) \ + ( \ + ((tffs_dma_mode & 1) && ((bytes) >= 512) && ((((long)(vbuf)) & (sizeof(long) - 1)) == 0)) \ + ? \ + tffs_dmasw(((char*)((flash)->win)),(off),(vbuf),(bytes),1) \ + : \ + tffs_readw(((unsigned long)(((char *)((flash)->win)) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) \ + ) + +# define flWriteEvenNumberOfBytes(flash,off,vbuf,bytes) \ + ( \ + ((tffs_dma_mode & 2) && ((bytes) >= 512) && ((((long)(vbuf)) & (sizeof(long) - 1)) == 0)) \ + ? \ + tffs_dmasw(((char*)((flash)->win)),(off),(vbuf),(bytes),0) \ + : \ + tffs_writew(((unsigned long)((char*)((flash)->win) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) \ + ) + +#else /* not Mainstone/OMAP1610/OMAP2420 */ + +# define flReadEvenNumberOfBytes(flash,off,vbuf,bytes) \ + tffs_readw(((unsigned long)((char*)((flash)->win) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) + +# define flWriteEvenNumberOfBytes(flash,off,vbuf,bytes) \ + tffs_writew(((unsigned long)((char*)((flash)->win) + (off))),((short*)(vbuf)),((bytes) / sizeof(short))) + +#endif /* ARCH */ + + + +/* DiskOnChip driver uses DOCHBLK_READ and DOCHBLK_WRITE macros to transfer + * data from and from (respectively) DiskOnChip H3 devices. + */ +# define DOCHBLK_READ(reg_base,vbuf,sectors) dochblk_read((vbuf),(sectors)) +# define DOCHBLK_WRITE(reg_base,vbuf,sectors) dochblk_write((vbuf),(sectors)) + +# if 0 /* andrayk June 23 2006: added for H3 burst */ +# define DOCHREAD_BURST(reg_base,offset,vbuf,sectors) dochblk_read((vbuf),(sectors)) +# define DOCHWRITE_BURST(reg_base,offset,vbuf,sectors) dochblk_write((vbuf),(sectors)) +#endif + +extern int dochblk_read (void *vbuf, unsigned int sectors); +extern int dochblk_write (void *vbuf, unsigned int sectors); + + +extern unsigned char tffsarch_init (int resume_flag); +extern void TffsHWRelease (void); + + +#ifdef CONFIG_ARCH_OMAP24XX + extern void omap24xx_enable_gpio_irq (int gpio_irq, int enable); +#endif + + +#endif /* TFFSARCH_H */ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsdrv.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsdrv.h new file mode 100755 index 00000000..5d7a2bf2 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsdrv.h @@ -0,0 +1,312 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef __TFFSDRV_H__ +#define __TFFSDRV_H__ + +/* this driver is for 2.[4/5/6].x versions of Linux kernels */ +#include +#ifndef KERNEL_VERSION +# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,7,0)) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) +# error "unsupported Linux kernel version" +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)) +# include +#endif + +#if (LINUX_VERSION_CODE +# else +# include +# endif +# endif +#endif + +#include + +#if (LINUX_VERSION_CODE>KERNEL_VERSION(2,5,0)) +# include +#endif + +#include /* kmalloc() */ +#include /* HDIO_GETGEO */ +#include /* ...lock_kernel() */ +#include /* ...mem_region() */ +#include +#include /* ok_access(), put_usr(), get_user() */ +#include +#include /* struct ext2_super_block */ /* only for ext filter */ +#include /* mdelay() */ +#include +#include +#include /* blk_ioctl() */ +#include /* for SIOCDEVPRIVATE */ /* only for 2.6.x */ +#include /* 2.4.18 for lubbock don't want to work w/o this */ + +//#include +#include + +#include + +#include +#include +#include + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) +# include +# include +#endif + +#include "flcustom.h" +#include "tffsarch.h" + +#ifdef CONFIG_PROC_FS +# include +#endif + +/* definitions for blk.h */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +extern int tffs_major; +# define MAJOR_NR tffs_major +# define DEVICE_ON +# define DEVICE_OFF(d) +# define DEVICE_NR(device) (MINOR(device)>>DEV2PART_SHIFT) +# define DEVICE_NO_RANDOM +# include +#else +# include +#endif +/* end of blk.h definitions */ + +#ifdef TFFS_DEBUG_DRIVER +# define PrintkDebug(fmt,args...) printk(KERN_DEBUG TFFS_DEVICE_NAME": "fmt"\n",## args) +/* # define PrintkDebug(fmt,args...) printk(KERN_ERR TFFS_DEVICE_NAME": "fmt"\n",## args) */ +#else /* TFFS_DEBUG_DRIVER */ +# define PrintkDebug(fmt,args...) +#endif /* TFFS_DEBUG_DRIVER */ +#define PrintkInfo(fmt,args...) printk(KERN_INFO TFFS_DEVICE_NAME": "fmt"\n",## args) +#define PrintkError(fmt,args...) printk(KERN_ERR TFFS_DEVICE_NAME": "fmt"\n",## args) +#define PrintkWarning(fmt,args...) printk(KERN_WARNING TFFS_DEVICE_NAME": "fmt"\n",## args) + +#ifdef TFFS_STATISTIC + +typedef struct +{ + unsigned long dwReadReq; /* total 'read' requests received by driver */ + unsigned long dwReadReqNoThread; /* number of these requests done by DeviceRequest() */ + unsigned long dwAbsReadSec; /* total sectors read */ + unsigned long dwAlReadSec; /* aligned 512-byte sectors read */ + unsigned long dwUnalReadSec; /* unaligned 512-byte sectors read */ + unsigned long dwAlReadShared; /* aligned shared 512-byte sectors read */ + unsigned long dwUnalReadShared; /* unaligned shared 512-byte sectors read */ + unsigned long dwAbsRead; /* total flAbsRead() calls */ + unsigned long dwWriteReq; /* total 'write' requests received by driver */ + unsigned long dwAbsWriteSec; /* total sectors written */ + unsigned long dwAlWriteSec; /* aligned 512-byte sectors written */ + unsigned long dwUnalWriteSec; /* unaligned 512-byte sectors written */ + unsigned long dwAlWriteShared; /* aligned shared 512-byte sectors written */ + unsigned long dwUnalWriteShared; /* unaligned shared 512-byte sectors written */ + unsigned long dwAbsWrite; /* total flAbsWrite() calls */ +}TffsStatistic; + +#endif /* TFFS_STATISTIC */ + +struct tagDeviceInfo; + +typedef struct +{ + struct tagDeviceInfo*pDevices; + unsigned short wDevices; /* should be WORD to allow left shift to 5 */ + struct list_head requestsList; /* list of requests from IO queue */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + spinlock_t request_list_lock; +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + struct completion wait_for_io_thread; /* wait for socket's I/O thread to start/stop */ + struct completion wait_for_irq; /* wait for DiskOnChip interrupt */ +#else + struct semaphore threadSemaphore; /* wait for socket's I/O thread to start/stop */ + struct semaphore sleep_sem; /* used to wait for erase/write completion */ +#endif + + wait_queue_head_t waitQueueHead; /* wait queue for thread and flSleep */ + int io_thread_state; + unsigned char bHandle; /* socket, as ioreq.irHandle */ + char * pCache; + int fFound; + unsigned long dwPhysAddr,dwVirtAddr,dwMappedLen; + int fMemRequested; +}SocketInfo; + +/* #ifdef TFFS_USE_EXT_FILTER */ +struct tagSectInfo; +typedef struct tagSectInfo +{ + unsigned long dwSector; /* no of sector on device */ + unsigned short bSectors; /* length */ + struct tagSectInfo*pParent,*pPrev,*pNext; + unsigned char bFlag; +#define EXTF_PT 0x01 /* empty part table space */ +#define EXTF_HAS_PT 0x02 /* has written part table */ +#define EXTF_SB 0x04 /* empty super block space */ +#define EXTF_HAS_SB 0x08 /* has superblock written, but no group descriptors */ +#define EXTF_HAS_GD 0x10 /* has superblock and group descriptors */ +#define EXTF_BB 0x20 /* block bitmap was allocated and waiting for group description */ +#define EXTF_HAS_BB 0x40 /* has block bitmap */ +#ifdef TFFS_DEBUG_DRIVER + int no; /* part no */ + unsigned long dwOffset; /* PT */ + unsigned long dwFirstSectorOfBitmap; /* BB */ + unsigned long dwExt3Flags; /* SB */ +#else + unsigned long dw; +#define dwOffset dw +#define dwFirstSectorOfBitmap dw +#define dwExt3Flags dw +#endif /* TFFS_DEBUG_DRIVER */ + unsigned long dwBlocksPerBitmap; /* SB and BB */ + unsigned char bSect2BlockShift; /* SB */ + unsigned short wGroups; /* SB */ +}SectInfo; +/* #endif TFFS_USE_EXT_FILTER */ + +typedef struct tagDeviceInfo +{ + SocketInfo*pSocket; + unsigned char diskNo; /* disk # (zero-based) */ + unsigned char bHandle; /* socket & partition, as ioreq.irHandle */ + unsigned long dwSize; /* device size */ + int in_use; + unsigned short wHWSectorSize; /* hw sector size in driver */ + unsigned short wTffsHWSectorSizeShift; /* shared sectors size in tffs */ + unsigned char fAbsMounted; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + struct gendisk * gd; /* struct gendisk allocated for this disk */ + struct request_queue * rq; /* disk's request queue */ + spinlock_t rq_lock; /* request queue lock */ +#else + request_queue_t requestQueue; +#endif + +/* #ifdef TFFS_USE_EXT_FILTER */ + SectInfo sect[2]; + SectInfo **pCache; +/* #endif */ + + unsigned short wCyl; + unsigned char bHead,bSect; + +#ifdef TFFS_STATISTIC + TffsStatistic stat; /* various disk statistics */ +#endif + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry * pProcFile; +#endif +}DeviceInfo; + +typedef struct +{ + unsigned char wDevices; + SocketInfo sockets[FL_SOCKETS]; + DeviceInfo*ppDevices[FL_VOLUMES]; + +#if defined(TFFS_PARTITIONABLE) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) + struct gendisk genDisk; +#endif + +#ifdef CONFIG_PROC_FS + struct proc_dir_entry*pProcDir; +#endif + + int channel; /* assume only one DMA connected */ + dma_addr_t dma_buf_paddr; /* physical address of DMA buffer */ + void * dma_buf_vptr; /* virtual address of DMA buffer */ + int dma_buf_size; /* size of DMA buffer in bytes */ + +}TffsInfo; + +extern TffsInfo tffsInfo; +extern int tffs_sg_bufsize; + +#define VMalloc(size) vmalloc((size)+4) +#define KMalloc(size) kmalloc((size)+4,GFP_KERNEL) + +/* DiskOnChip driver's minor version number */ +#define TFFS_DRV_VER 85 + + +/* driver's generic suspend/resume power management routines */ +extern void tffs_suspend (void); +extern void tffs_resume (void); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +# ifdef CONFIG_PM +# include + extern int tffs_pm_init (void); + extern int tffs_pm_exit (void); + extern int tffs_pm_allowed (SocketInfo * pSoc, int flag); +# endif + +# ifdef CONFIG_DPM +# include + extern int tffs_dpm_register (void); + extern int tffs_dpm_unregister (void); +# endif +#endif + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && defined (CONFIG_PM) +# include +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +# include +# endif + extern int tffs_pm_init (void); + extern int tffs_pm_exit (void); +#endif + + +#endif /* __TFFSDRV_H__*/ diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsdrv26.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsdrv26.c new file mode 100755 index 00000000..6594868f --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsdrv26.c @@ -0,0 +1,1902 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#include "tffsdrv.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + +#include "tffs2lnx.h" +#include "flbase.h" + + + +MODULE_AUTHOR("M-Systems"); +MODULE_DESCRIPTION("TrueFFS driver"); +MODULE_LICENSE("GPL"); +MODULE_SUPPORTED_DEVICE(TFFS_SUPPORTED_DEVICE); + + + +/* + * module parameters + */ + +/* major device # to use */ +int tffs_major = 100; +module_param(tffs_major, int, S_IRUGO); +MODULE_PARM_DESC(tffs_major, "major device number, zero to use dynamic."); + +/* priority of driver's I/O threads */ +static int tffs_prio = 0; /* max -20, min 19 */ +module_param(tffs_prio, int, (S_IRUGO | S_IWUSR)); +MODULE_PARM_DESC(tffs_prio,"priority of DiskOnChip I/O thread."); + +/* interrupt line that DiskOnChip's IREQ is connected to */ +int tffs_irq = TFFS_IRQ; +module_param(tffs_irq, int, S_IRUGO); +MODULE_PARM_DESC(tffs_irq, "Interrupt line DiskOnChip's IREQ is connected to."); + +/* DMA mode. Allowed modes are: + * 0 (don't use DMA) + * 1 (use s/w DMA in read operations only; uses intermediate DMA buffer) + * 2 (use s/w DMA in write operations only; uses intermediate DMA buffer) + * 3 (combined 1 and 2) + * 5 (use s/w DMA for direct transfers from user source buffers) + * 6 (use s/w DMA for direct transfers to user dest. buffers) + * 7 (combined 5 and 6) + * Default is don't use DMA. + */ +int tffs_dma_mode = 0; +module_param(tffs_dma_mode, int, S_IRUGO); +MODULE_PARM_DESC(tffs_dma_mode, "DMA mode (0, 1, 2, 3, 5, 6 or 7)."); + +/* Automatic Deep PowerDown mode. Allowed modes are 0 (default; disabled), + * or 1 (enabled). When enabled, Automatic Deep PowerDown mode will cause + * DiskOnChip driver to power down DiskOnChip after completion of every + * read/write operation, and power it up again before starting the next one. + */ +int tffs_auto_dpd = FL_OFF; +module_param(tffs_auto_dpd, int, S_IRUGO); +MODULE_PARM_DESC(tffs_auto_dpd, "Powerdown DiskOnChip after every operation (1), or don't (0)."); + +/* Upon completion of every read/write access, DiskOnChip H3 devices + * immediately switch from the normal mode into the idle mode, and stay + * in the idle mode for 'DOCH_DPD_DEFAULT_DPD_TIMEOUT' milliseconds before + * switching into deep-power-down mode. + */ +int tffs_dpd_timeout = 1; +module_param(tffs_dpd_timeout, int, S_IRUGO); +MODULE_PARM_DESC(tffs_dpd_timeout, "Time (in milliseconds) before DiskOnChip automatically powers itself down."); + +/* Read data from DiskOnChip into scatter/gather buffer, then scatter it to + * destination buffers. Allowed values are TRUE (scatter data) or FALSE (don't). + */ +int tffs_sg_read = TRUE; +module_param(tffs_sg_read, int, S_IRUGO); +MODULE_PARM_DESC(tffs_sg_read, "Use scatter/gather during read operations."); + +/* Gather data from source buffers into scatter/gather buffer before writing + * it to DiskOnChip. Allowed values are TRUE (gather data) or FALSE (don't). + */ +int tffs_sg_write = TRUE; +module_param(tffs_sg_write, int, S_IRUGO); +MODULE_PARM_DESC(tffs_sg_write, "Use scatter/gather during write operations."); + +/* size of scatter/gather buffer in bytes; must be multiple of PAGE_SIZE */ +int tffs_sg_bufsize = (16 * PAGE_SIZE); +module_param(tffs_sg_bufsize, int, S_IRUGO); +MODULE_PARM_DESC(tffs_sg_bufsize, "Size of scatter/gather buffer, in bytes."); + + + + +/* + * macros + */ +#ifndef _MIN +# define _MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + + + + +/* + * types + */ +struct scatter_t /* scatter buffer for READ requests */ +{ + char * buf; /* starting address */ + char * pcurrent; + unsigned int size; /* size of buffer in bytes */ + unsigned int remaining_bytes; + sector_t start_sector; /* starting disk sector # */ + unsigned int sectors; /* remaining sectors in this request */ +}; + +struct gather_t /* gather buffer for WRITE requests */ +{ + char * buf; /* starting address */ + char * free; /* free part fo the buffer */ + unsigned int size; /* size of buffer in bytes */ + unsigned int free_bytes; /* remaining free space in bytes */ + sector_t start_sector; /* starting disk sector # */ +}; + + + + +/* + * global vars + */ +int write_requests = 0; + + + + +/* + * static routines + */ +static int /* __init */ __tffs_module_init (void); +static void /* __init */ init_socket (SocketInfo *psoc); +static void /* __init */ init_disk (DeviceInfo *pdisk); +static void /* __exit */ release_socket (SocketInfo *psoc); +static void /* __exit */ release_disk (DeviceInfo * pdisk); +static void cleanup (int STEP); + +static void disk_request_queue_handler (struct request_queue * q); +static int socket_io_thread (void *arg); +static int requests_to_do (SocketInfo *psoc); +static void do_requests_list (SocketInfo *psoc); +static int do_write_request (struct request *r); +static int do_read_request (struct request *r); +static int rw_bio_no_sg (struct request * r, DeviceInfo *pdisk, int rw); +static int write_bio (struct request * r, struct gather_t *gather, DeviceInfo *pdisk); +static int read_bio (struct request * r, struct scatter_t *scatter, DeviceInfo *pdisk); + + +static int disk_open (struct block_device *blk_dev, fmode_t mode); +static int disk_close (struct gendisk *gd, fmode_t mode); +static int disk_ioctl (struct block_device *blk_dev, fmode_t mode, unsigned int cmd, unsigned long arg); + +static irqreturn_t interrupt_handler (int irq, void *psoc/*, struct pt_regs *regs*/); + +#ifdef CONFIG_PROC_FS + static int /* __init */ procfs_register (DeviceInfo *pdisk); + static int /* __exit */ procfs_unregister (DeviceInfo *pdisk); + static int procfs_write (struct file* file, const char* buffer, unsigned long count, void* data); + static int procfs_read (char* buffer, char** start, off_t offset, int length, int* eof, void* data); +#endif + + + + +/* + * static vars + */ +static struct semaphore open_close_mutex; /* used to serialize disk open/close calls */ + +static char tffs_str[] = TFFS_DEVICE_NAME; + +static struct block_device_operations tffs_bdev_ops = +{ + .open = disk_open, + .release = disk_close, + .ioctl = disk_ioctl, + .owner = THIS_MODULE +}; + +/* for tracking enabled/disabled state of IRQ that DiskOnChip is connected to */ +static spinlock_t __irq_lock = SPIN_LOCK_UNLOCKED; +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_MAINSTONE) || defined(CONFIG_MACH_MAINSTONE) + static int __irq_enabled = TRUE; +#else + static int __irq_enabled = FALSE; +#endif + + + + +/******************************************************************************* + * * + * t f f s _ m o d u l e _ i n i t * + * * + * Module initialization routine. * + * * + * Parameters: none * + * * + * Returns: zero if success, otherwise standard negative error code * + * * + *******************************************************************************/ + +int /* __init */ tffs_module_init (void) +{ +# ifdef TRACE32 /* needed for section relocation in TRACE32 */ + extern int trace32_data; + extern int trace32_bss; + extern const int trace32_rodata; + printk ("\n\nTRACE32 section relocation: .data=0x%lx .bss=0x%lx .rodata=0x%lx\n\n", + (long)(&trace32_data), (long)(&trace32_bss), (long)(&trace32_rodata)); +# endif + + return __tffs_module_init(); +} + +module_init(tffs_module_init); + + + + +/******************************************************************************* + * * + * t f f s _ m o d u l e _ e x i t * + * * + * Module cleanup and routine; called when module is unloaded. * + * * + * Parameters: none * + * * + *******************************************************************************/ + +void /* __exit */ tffs_module_exit (void) +{ + cleanup (100); +} + +module_exit(tffs_module_exit); + + + + +/******************************************************************************* + * * + * _ _ t f f s _ m o d u l e _ i n i t * + * * + * Initialize DiskOnChip driver. * + * * + * Parameters: none * + * * + * Returns: zero if success, otherwise standard negative error code * + * * + *******************************************************************************/ +static +int /* __init */ __tffs_module_init (void) +{ + int STEP, iSoc, tmp; + + STEP = 0; + + PrintkInfo ("mDOC driver %s.%d", TrueFFSVersion, TFFS_DRV_VER); + + memset (tffsInfo.sockets, 0, sizeof(tffsInfo.sockets)); + + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + { + init_completion (&tffsInfo.sockets[iSoc].wait_for_irq); /* sema_init (&tffsInfo.sockets[iSoc].sleep_sem, 0); */ + + init_waitqueue_head (&tffsInfo.sockets[iSoc].waitQueueHead); + } + + STEP++; /* 1 */ + + /* if requested, install handler for DiskOnChip interrupts */ + if (tffs_irq >= 0) + { + if( request_irq(tffs_irq, interrupt_handler, 0 /* SA_INTERRUPT */, + tffs_str, &tffsInfo.sockets[0]) == 0 ) + { + tffs_irq_disable (TRUE); + + PrintkInfo ("use IRQ %d", tffs_irq); + } + else /* can't install interrupt handler, won't use IRQ */ + { + PrintkWarning ("failed to get IRQ %d", tffs_irq); + tffs_irq = -1; + } + } + else { PrintkInfo ("will not use IRQ"); } + + STEP++; /* 2 */ + + /* Find all DiskOnChip sockets, find out how many disks are on + * each socket, and abs.mount each disk. + */ + if( TffsInit() <= 0 ) + { + PrintkError ("No DiskOnChips found"); + return -ENODEV; + } + + STEP++; /* 3 */ + + if (tffs_irq >= 0) + { + /* enable interrupt generation in DiskOnChip */ + TffsEnableIRQ (&tffsInfo.sockets[0]); + } + + STEP++; /* 4 */ + + /* Register our major device # (or accept dynamically allocated + * major #). + */ + if ((tmp = register_blkdev(tffs_major, tffs_str)) < 0) + { + PrintkError ("Can't get major %d", tffs_major); + cleanup (STEP); + return -EBUSY; + } + if (tffs_major == 0) /* we asked for dynamic major #, and we got it */ + tffs_major = tmp; + PrintkInfo ("use major device number %d", tffs_major); + + STEP++; /* 5 */ + +#ifdef CONFIG_PROC_FS + if ((tffsInfo.pProcDir = proc_mkdir(tffs_str, NULL)) == NULL) + { PrintkWarning ("Can't create /proc/%s", tffs_str); } +#endif + + STEP++; /* 6 */ + + /* initialize Open/Close mutex in "available" state */ + sema_init (&open_close_mutex, 1); + + /* init sockets */ + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + init_socket (&tffsInfo.sockets[iSoc]); + + STEP++; /* 7 */ + +#ifdef CONFIG_PM + tffs_pm_init (); /* register with Power Manager */ +#endif + + STEP++; /* 8 */ + + return 0; +} + + + + +/******************************************************************************* + * * + * i n i t _ s o c k e t * + * * + * Initialize socket's I/O thread and all socket's disks. * + * * + * Parameters: * + * psoc pointer to socket being initialized * + * * + *******************************************************************************/ +static +void /* __init */ init_socket ( SocketInfo * psoc ) +{ + int iDisk; + + if (psoc->fFound == 0) + return; + + init_completion (&psoc->wait_for_io_thread); /* sema_init (&psoc->threadSemaphore, 0); */ + + /* Tell I/O thread to wake us up once it gets up and running */ + psoc->io_thread_state = 2; + + /* start socket's I/O thread */ + kernel_thread (socket_io_thread, (void *)psoc, 0); + + /* wait until socket's I/O thread is up and running */ + wait_for_completion (&psoc->wait_for_io_thread); /* down_interruptible (&psoc->threadSemaphore); */ + + /* socket's I/O thread has been started, and is currently waiting for + * I/O requests to be posted to psoc->waitQueueHead. + */ + for (iDisk = 0; iDisk < psoc->wDevices; iDisk++) + init_disk (&psoc->pDevices[iDisk]); +} + + + + +/******************************************************************************* + * * + * i n i t _ d i s k * + * * + * Initialize individual disk. s). * + * * + * Parameters: * + * pdisk pointer to disk * + * * + *******************************************************************************/ +static +void /* __init */ init_disk ( DeviceInfo * pdisk ) +{ + struct gendisk * gd; + int max_partitions; + + /* nobody has opened this disk yet */ + pdisk->in_use = 0; + +#ifdef TFFS_STATISTIC + memset (&pdisk->stat, 0, sizeof(pdisk->stat)); +#endif + +#ifdef CONFIG_PROC_FS + procfs_register (pdisk); +#endif + + /* allocate request queue for this disk */ + spin_lock_init (&pdisk->rq_lock); + + pdisk->rq = blk_init_queue (disk_request_queue_handler, &pdisk->rq_lock); + if (pdisk->rq == NULL) + { + PrintkError ("blk_init_queue() failed for disk 0x%x", pdisk->bHandle); + return; + } + else + pdisk->rq->queuedata = pdisk; + + /* Maximum number of file system partitions that we allow + * on the disk (this doesn't include "raw" disk). + */ + max_partitions = ((1 << DEV2PART_SHIFT) - 1); + + /* allocate struct gendisk for this disk */ + if ((gd = alloc_disk(max_partitions)) == NULL) + { + /* return previously allocated request queue to the system */ + blk_cleanup_queue (pdisk->rq); + pdisk->rq = NULL; + + PrintkError ("alloc_disk() failed for disk 0x%x", pdisk->bHandle); + return; + } + else + pdisk->gd = gd; + + gd->major = tffs_major; + gd->first_minor = (pdisk->diskNo * (max_partitions + 1/*"raw" disk entry*/)); + gd->fops = &tffs_bdev_ops; + gd->queue = pdisk->rq; + gd->private_data = pdisk; + + /* name this disk */ + snprintf (gd->disk_name, sizeof(gd->disk_name), "%s%c", + tffs_str, ('a' + (char)(pdisk->diskNo))); + + /* specify disk's capacity in 512-byte sectors */ + set_capacity (gd, pdisk->dwSize); + + /* Tell kernel about this disk. Before add_disk() returns, + * kernel will attempt to read Master Boot Record and parse + * partition table(s) on this disk; it will post I/O requests + * to pdisk->rq, and call disk_request_queue_handler() + * to handle these request. + */ + add_disk (gd); +} + + + + +/******************************************************************************* + * * + * c l e a n u p * + * * + * Free all data structures alocated during driver's startup. * + * * + * Parameters: * + * STEP specifies which resources to free * + * * + * Returns: void * + * * + *******************************************************************************/ +static +void cleanup ( int STEP ) +{ + int iSoc; + + if (STEP >= 8) + { +#ifdef CONFIG_PM + tffs_pm_exit (); /* unregister from Power Manager */ +#endif + } + + if (STEP >= 7) + { + /* For every socket, flush all socket's disks, and sleep until socket's + * I/O thread handled all outstanding I/O requests and exited. + */ + for (iSoc = 0; iSoc < FL_SOCKETS; iSoc++) + { + if (tffsInfo.sockets[iSoc].fFound != 0) + release_socket (&tffsInfo.sockets[iSoc]); + } + } + + if (STEP >= 6) + { +#ifdef CONFIG_PROC_FS + remove_proc_entry (tffs_str, NULL); + tffsInfo.pProcDir = NULL; +#endif + } + + if (STEP >= 5) + { + unregister_blkdev (tffs_major, tffs_str); + } + + if (STEP >= 4) + { + /* disable_irq (tffs_irq); */ + + /* We should tell DiskOnChip to disable interrupt generation, but + * unfortunately TrueFFS currently doesn't provide API for that. + */ + } + + if (STEP >= 3) + { + /* For all disks of all DiskOnChip sockets, write Quick Mount + * records to them, abs.unmount them, and shut down TrueFFS. + */ + TffsCleanup (); + } + + if (STEP >= 2) + { + /* if previously installed, remove DiskOnChip interrupt handler */ + if (tffs_irq >= 0) + free_irq (tffs_irq, &tffsInfo.sockets[0]); + } +} + + + + +/******************************************************************************* + * * + * r e l e a s e _ s o c k e t * + * * + * Release DiskOnChip socket. * + * * + * Parameters: * + * psoc pointer to socket being released * + * * + * Returns: void * + * * + *******************************************************************************/ +static +void /* __exit */ release_socket ( SocketInfo * psoc ) +{ + int iDisk; + + if (psoc->fFound == 0) + return; + + /* Release all socket's disks; this involves flushing all partitions + * on all these disks. + */ + for (iDisk = 0; iDisk < psoc->wDevices; iDisk++) + release_disk (&psoc->pDevices[iDisk]); + + if (psoc->io_thread_state == 1) /* I/O thread is running */ + { + init_completion (&psoc->wait_for_io_thread); + + /* Tell I/O thread to complete handling of all outstanding I/O requests, + * wake us up, and exit. + */ + psoc->io_thread_state = 2; + + /* in case socket's I/O thread is currently sleeping, wake it up */ + wake_up (&psoc->waitQueueHead); + + /* now wait for I/O thread to exit */ + wait_for_completion (&psoc->wait_for_io_thread); /* down_interruptible (&psoc->threadSemaphore); */ + } +} + + + + +/******************************************************************************* + * * + * r e l e a s e _ d i s k * + * * + * Release disk. * + * * + * Parameters: * + * pdisk pointer to disk being released * + * * + * Returns: void * + * * + *******************************************************************************/ +static +void /* __exit */ release_disk (DeviceInfo * pdisk) +{ + if (pdisk->gd != NULL) + { + del_gendisk (pdisk->gd); + pdisk->gd = NULL; + } + + if (pdisk->rq != NULL) + { + blk_cleanup_queue (pdisk->rq); + pdisk->rq = NULL; + } + +#ifdef CONFIG_PROC_FS + procfs_unregister (pdisk); +#endif +} + + + + +/******************************************************************************* + * * + * d i s k _ o p e n * + * * + * Open disk (i.e. block_device_operations.open()). * + * * + * Parameters: * + * * + * blk_dev block_device pointer * + * filp file pointer * +static int disk_open (struct block_device *blk_dev, fmode_t mode); + * * + * Returns: zero if success, otherwise negative error code * + * * + *******************************************************************************/ +static +int disk_open ( struct block_device * blk_dev, + fmode_t mode ) +{ + int rc = 0; /* assume success */ + struct gendisk * gd = blk_dev->bd_disk; + DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; + + if (pdisk == NULL) + return -ENODEV; + + /* one Open/Close at a time */ + if( down_interruptible(&open_close_mutex) != 0 ) + return -ERESTARTSYS; /* wait was interrupted by signal */ + + /* can't open write-protected disk for writing */ + if (mode & O_RDWR) + { +#ifndef TFFS_RO + if( TffsIsWriteProtected(pdisk) ) +#endif + { + rc = -EROFS; goto quit; + } + } + + if (pdisk->in_use == 0) + { + if( TffsOpenDevice(pdisk) == 0 ) + { + PrintkError("Open() failed on %s(0x%x)", gd->disk_name, pdisk->bHandle); + + rc = -ENODEV; goto quit; + } + } + + /* success opening this disk */ + //filp->private_data = pdisk; + + /* one more user for this device, as well as for DiskOnChip driver */ + pdisk->in_use++; + + quit: + + /* allow other Open/Close calls to proceed */ + up (&open_close_mutex); + + return rc; +} + + + + +/******************************************************************************* + * * + * d i s k _ c l o s e * + * * + * Release disk (i.e. block_device_operations.release()). * + * * + * Parameters: * + * * + * blk_dev block_device pointer * + * filp file pointer (could be NULL) * +static int disk_close (struct gendisk *gd, fmode_t mode); + * * + * Returns: zero if success, otherwise negative error code * + * * + *******************************************************************************/ +static +int disk_close ( struct gendisk *gd, + fmode_t mode ) +{ + DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; + + /* one Open/Close at a time */ + if( down_interruptible(&open_close_mutex) != 0 ) + return -ERESTARTSYS; /* wait was interrupted by signal */ + + if (--pdisk->in_use == 0) /* last user had just closed this disk */ + { + if( TffsCloseDevice(pdisk) == 0 ) + { + PrintkDebug("Release() failed on %s(0x%x)", gd->disk_name, pdisk->bHandle); + } + } + + /* allow other Open/Close calls to proceed */ + up (&open_close_mutex); + + return 0; +} + + + + +/******************************************************************************* + * * + * d i s k _ i o c t l * + * * + * Handle IOCTLs to disk (i.e. device_operations.ioctl()). * + * * + * Parameters: * + * * + * blk_dev block_device pointer * + * filp file pointer (could be NULL) * + * cmd IOCTL command * + * arg argument to IOCTL command * +static int disk_ioctl (struct block_device *blk_dev, fmode_t mode, unsigned int cmd, unsigned long arg); + * * + * Returns: zero if success, otherwise negative error code * + * * + *******************************************************************************/ +static +int disk_ioctl ( struct block_device * blk_dev, + fmode_t mode, + unsigned int cmd, + unsigned long arg ) +{ + struct gendisk * gd = blk_dev->bd_disk; + DeviceInfo * pdisk = (DeviceInfo *) gd->private_data; + int rc = -ENOTTY; + + /* sanity check */ +/*my + if ((filp != NULL) && (filp->private_data != pdisk)) + return -ENODEV; +*/ + if (cmd >= SIOCDEVPRIVATE) /* driver specific (TrueFFS) IOCTL code */ + { + rc = TffsIoctl (pdisk, (cmd - SIOCDEVPRIVATE), arg); + + if (rc < 0) + PrintkError("ioctl=0x%x error=0x%x on %s", cmd, rc, gd->disk_name); + + if (rc == 1) /* unrecognized TrueFFS IOCTL code */ + rc = -ENOTTY; + } + else /* standard Linux IOCTL code */ + { + switch (cmd) + { + case HDIO_GETGEO: + { + struct hd_geometry geo; + + geo.heads = pdisk->bHead; + geo.sectors = pdisk->bSect; + geo.cylinders = pdisk->wCyl; + geo.start = get_start_sect (blk_dev->bd_inode->i_bdev); + + if ((void *)arg == NULL) + { rc = -EINVAL; break; } + + if( !access_ok(VERIFY_WRITE, (void *)arg, sizeof(geo))) + { rc = -EFAULT; break; } + + if( copy_to_user((void *)arg, &geo, sizeof(geo)) != 0 ) + { rc = -EFAULT; break; } + + rc = 0; /* success */ + } + break; + + default: /* unknown Linux IOCTL code */ + { + PrintkError("unknown ioctl=0x%x on %s", cmd, gd->disk_name); + } + } + } + + return rc; +} + + + + +/******************************************************************************* + * * + * i n t e r r u p t _ h a n d l e r * + * * + * DiskOnChip interupt handler. * + * * + * Parameters: * + * * + * irq not used * + * psoc socket pointer * + * regs not used * + * * + * Returns: always IRQ_HANDLED * + * * + *******************************************************************************/ +static +irqreturn_t interrupt_handler ( int irq, /* not used */ + void * psoc/*, + struct pt_regs * regs*/ ) /* not used */ +{ + tffs_irq_disable (FALSE); + + profiling[1]++; + + /* wake up socket's I/O thread */ + complete (&((SocketInfo *)psoc)->wait_for_irq); /* up (&((SocketInfo *)psoc)->sleep_sem); */ + return IRQ_HANDLED; +} + + + + +/******************************************************************************* + * * + * t f f s _i r q _ e n a b l e * + * * + * Enable IRQ that DiskOnChip is connected to. * + * * + * Parameters: * + * * + * lock if TRUE, use __irq_lock; otherwise don't * + * * + *******************************************************************************/ +void tffs_irq_enable (int lock) +{ + unsigned long flags; + + if (lock == TRUE) + spin_lock_irqsave (&__irq_lock, flags); + + if (__irq_enabled == FALSE) + { + __irq_enabled = TRUE; + + enable_irq (tffs_irq); + +#ifdef CONFIG_ARCH_OMAP24XX + omap24xx_enable_gpio_irq (tffs_irq, TRUE); +#endif + } + + if (lock == TRUE) + spin_unlock_irqrestore (&__irq_lock, flags); +} + + + +/******************************************************************************* + * * + * t f f s _i r q _ d i s a b l e * + * * + * Disable IRQ that DiskOnChip is connected to. * + * * + * Parameters: * + * * + * lock if TRUE, use __irq_lock; otherwise don't * + * * + *******************************************************************************/ +void tffs_irq_disable (int lock) +{ + unsigned long flags; + + if (lock == TRUE) + spin_lock_irqsave (&__irq_lock, flags); + + if (__irq_enabled == TRUE) + { + __irq_enabled = FALSE; + +#ifdef CONFIG_ARCH_OMAP24XX + omap24xx_enable_gpio_irq (tffs_irq, FALSE); +#endif + + disable_irq (tffs_irq); + } + + if (lock == TRUE) + spin_unlock_irqrestore (&__irq_lock, flags); +} + + + + +/******************************************************************************* + * * + * d i s k _ r e q u e s t _ q u e u e _ h a n d l e r * + * * + * This routine implements request handling function for per-disk request * + * queue. It's called by generic_unplug_device (drivers/block/ll_rw_block.c) * + * with request queue's lock held, and both hardware and software interrupts * + * disabled (so it must be fast). * + * * + * Parameters: * + * q disk's request queue * + * * + *******************************************************************************/ +static +void disk_request_queue_handler (struct request_queue * q) +{ + struct request * r; + SocketInfo * psoc; + DeviceInfo * pdisk; + int lock_taken = FALSE; + + /* we run with hardware and software interrupts disabled */ + + while ((r = blk_peek_request(q)) != NULL) + { + /* take this request off disk's request queue */ + blk_start_request (r); + + if (lock_taken == FALSE) + { + pdisk = r->rq_disk->private_data; + psoc = pdisk->pSocket; + + spin_lock (&psoc->request_list_lock); + lock_taken = TRUE; + } + + /* Append this request to socket's request list. Socket's + * I/O thread will take it from there, handle it, and cycle + * it back to this queue. + */ + list_add_tail (&r->queuelist, &psoc->requestsList); + } + + if (lock_taken == TRUE) + { + spin_unlock (&psoc->request_list_lock); + + /* in case socket's I/O thread is currently sleeping, wake it up */ + wake_up (&psoc->waitQueueHead); + } +} + + + + +/******************************************************************************* + * * + * s o c k e t _ i o _ t h r e a d * + * * + * This routine implements per-socket I/O thread. It runs as a kernel thread, * + * and processes I/O requests that disk_request_queue_handler() put to * + * socket's request list. This routine can (and often does) sleep. * + * * + * Parameters: * + * arg socket pointer * + * * + *******************************************************************************/ +static +int socket_io_thread (void * arg) +{ + SocketInfo * psoc = (SocketInfo *) arg; + char name[32]; + + current->flags |= (PF_MEMALLOC | PF_NOFREEZE); + + sprintf (name, "%s%c", tffs_str, '0' + (char)psoc->bHandle); + daemonize (name); + + /* we don't want to receive any signals */ + spin_lock_irq (¤t->sighand->siglock); + sigfillset (¤t->blocked); + recalc_sigpending (); + spin_unlock_irq (¤t->sighand->siglock); + + /* adjist thread's priority if necessary */ + if (tffs_prio != 0) + set_user_nice (current, tffs_prio); + + /* initially socket's request list is empty */ + spin_lock_init (&psoc->request_list_lock); + INIT_LIST_HEAD (&psoc->requestsList); + + /* If somebody is waiting for socket's I/O thread to start up and + * get ready for processing I/O requests, let them know that we did. + */ + if (psoc->io_thread_state == 2) + complete (&psoc->wait_for_io_thread); /* up (&psoc->threadSemaphore); */ + + /* socket's I/O thread is ready to receive I/O requests */ + psoc->io_thread_state = 1; + + while (psoc->io_thread_state == 1) + { + /* wait 5 clock ticks for I/O requests to arrive */ + wait_event_interruptible_timeout (psoc->waitQueueHead, requests_to_do(psoc), 5); + + /* handle all I/O requests (if any) in socket's request ist */ + do_requests_list (psoc); + } + + /* If somebody is waiting for socket's I/O thread to terminate, + * let them know that it did. + */ + if (psoc->io_thread_state == 2) + complete (&psoc->wait_for_io_thread); /* up (&psoc->threadSemaphore); */ + + /* socket's I/O thread terminated */ + psoc->io_thread_state = 0; + + return 0; +} + + + + +/******************************************************************************* + * * + * d o _ r e q u e s t s _ l i s t * + * * + * This routine handles all requests in socket's request list. * + * * + * Parameters: * + * psoc socket pointer * + * * + *******************************************************************************/ +static +void do_requests_list ( SocketInfo * psoc ) +{ + struct request * r; + struct gendisk * gd; + DeviceInfo * pdisk; + unsigned long flags; + unsigned int nr_sectors; + + /* lock socket's request list */ + spin_lock_irqsave (&psoc->request_list_lock, flags); + + /* if socket's request list isn't empty, process all requests there */ + while( !(list_empty(&psoc->requestsList)) ) + { + /* take next request off socket's request list */ + r = list_entry_rq (psoc->requestsList.next); + list_del_init (&r->queuelist); + + /* unlock socket's request list */ + spin_unlock_irqrestore (&psoc->request_list_lock, flags); + + /* Mark all non-filesystem request, and those filesystem requests + * that don't pass sanity check, as not-uptodate (i.e. failed). + */ + if( !blk_fs_request(r) || + ((gd = r->rq_disk) == NULL) || + ((pdisk = gd->private_data) == NULL) || + (pdisk->gd != gd) || + (blk_rq_pos(r) + blk_rq_sectors(r) > pdisk->dwSize) + ) + { + nr_sectors = blk_rq_cur_sectors(r); + __blk_end_request(r, 0, nr_sectors << 9); + /* + end_that_request_first (r, 0, r->hard_cur_sectors);*/ + } + else /* legitimate filesystem request; handle it */ + { + if (rq_data_dir(r) == WRITE) + { + write_requests++; + + do_write_request (r); + } + else /* READ request */ + { + do_read_request (r); + } + } + + /* mark this request as done */ + spin_lock_irqsave (&pdisk->rq_lock, flags); /* spin_lock (&pdisk->rq_lock); */ + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,24)) + blk_end_request_all(r, (r->errors == 0) ? 0 : -EIO); +#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)) + end_that_request_last (r, /* success */ 1); +#else + end_that_request_last (r); +#endif +#endif + + + spin_unlock_irqrestore (&pdisk->rq_lock, flags); /* spin_unlock (&pdisk->rq_lock); */ + + /* lock socket's request list */ + spin_lock_irqsave (&psoc->request_list_lock, flags); + } + + /* unlock socket's request list */ + spin_unlock_irqrestore (&psoc->request_list_lock, flags); +} + + + + +/******************************************************************************* + * * + * d o _ w r i t e _ r e q u e s t * + * * + * This routine handles single WRITE request. * + * * + * Parameters: * + * psoc socket pointer * + * * + * Returns: * + * zero if I/O error was encountered, otherwise '1'. * + * * +sector = blk_rq_pos(r) +nr_sectors= blk_rq_sectors(r) + +*******************************************************************************/ +static +int do_write_request ( struct request * r ) +{ + DeviceInfo * pdisk = (DeviceInfo *) r->rq_disk->private_data; + /*struct bio * bio;*/ + struct gather_t gather; + unsigned long total_sectors; + int success = 1; + unsigned int nr_sectors ; + + total_sectors = blk_rq_sectors(r); + + /* in case we are going to use gather buffer, mark it as empty */ + if ((tffs_sg_bufsize > 0) && (tffs_sg_write != FALSE)) + { + gather.buf = + gather.free = pdisk->pSocket->pCache; + gather.size = + gather.free_bytes = tffs_sg_bufsize; + + /* first disk sector # for this request */ + gather.start_sector = blk_rq_pos(r); + } + + /* do all bio's of this request */ + + /*rq_for_each_bio (bio, r) */ + { + if( write_bio(r, &gather, pdisk) < 0) + success = 0; /* I/O error */ + } + + /* flush remaining data (if any) from gather buffer to disk */ + if ((tffs_sg_bufsize > 0) && (tffs_sg_write != FALSE) + && (gather.free > gather.buf)) + { + int ns = ((gather.free - gather.buf) >> 9); /* remaining sectors in buf */ + + if( TffsWrite (pdisk, gather.buf, gather.start_sector, ns) == 0 ) + success = 0; /* I/O error */ + } + + /* Note that if we encountered I/O error in the middle of + * request processing, we mark the entire request as failed. + * Not very smart but hopefully will do for now ... + */ + nr_sectors = blk_rq_cur_sectors(r); + __blk_end_request(r, success, nr_sectors << 9); + + /*end_that_request_first (r, success, total_sectors);*/ + + return success; +} + + + + +/******************************************************************************* + * * + * d o _ r e a d _ r e q u e s t * + * * + * This routine handles single READ request. * + * * + * Parameters: * + * psoc socket pointer * + * * + * Returns: * + * zero if I/O error was encountered, otherwise '1'. * + * * + *******************************************************************************/ +static +int do_read_request ( struct request * r ) +{ + DeviceInfo * pdisk = (DeviceInfo *) r->rq_disk->private_data; + /*struct bio * bio;*/ + struct scatter_t scatter; + unsigned long total_sectors; + int success = 1; + unsigned int nr_sectors ; + + total_sectors = blk_rq_sectors(r); + /* read in data from disk into scatter buffer */ + if ((tffs_sg_bufsize > 0) && (tffs_sg_read != FALSE)) + { + int ns = _MIN(blk_rq_sectors(r), (tffs_sg_bufsize >> 9)); + + scatter.buf = pdisk->pSocket->pCache; + scatter.size = tffs_sg_bufsize; + + if( TffsRead (pdisk, scatter.buf, blk_rq_pos(r), ns) == 0 ) + { + success = 0; /* I/O error */ + goto out; + } + + scatter.pcurrent = scatter.buf; + scatter.remaining_bytes = (ns << 9); + scatter.sectors = blk_rq_sectors(r) - ns; + scatter.start_sector = blk_rq_pos(r) + ns; + } + + /* do all bio's of this request */ + /*rq_for_each_bio (bio, r)*/ + { + if( read_bio(r, &scatter, pdisk) < 0) + success = 0; /* I/O error */ + } + +out: + + /* Note that if we encountered I/O error in the middle of + * request processing, we mark the entire request as failed. + * Not very smart but hopefully will do for now ... + */ +/* end_that_request_first (r, success, total_sectors); */ + nr_sectors = blk_rq_cur_sectors(r); + __blk_end_request(r, success, nr_sectors << 9); + + return success; +} + + + + +/******************************************************************************* + * * + * w r i t e _ b i o * + * * + * This routine handles single 'struct bio' WRITE operation using gather * + * buffer. * + * * + * Parameters: * + * bio pointer to 'struct bio' to WRITE * + * gather pointer to gather buffer * + * pdisk disk pointer * + * * + * Returns: * + * zero if success otherwise -EIO negative error code * + * * + *******************************************************************************/ +static +int write_bio ( struct request * r, + /*struct bio * bio, */ + struct gather_t * gather, + DeviceInfo * pdisk ) +{ + struct bio_vec * bv; + int rc = 0; + struct req_iterator iter; + + if ((tffs_sg_bufsize == 0) || (tffs_sg_write == FALSE)) + { + /* we don't use gather buffer; do one I/O segment at a time */ + + printk("rw_bio_no_sg!!!!!!!!!!!!!!!!!!\n"); + rc = rw_bio_no_sg (r, pdisk, WRITE); + + } + else /* use gather buffer */ + { + /*bio_for_each_segment (bv, bio, i)*/ + rq_for_each_segment(bv, r, iter) + { + unsigned int n = bv->bv_len; /* bytes in this I/O segment */ + char * p; + + /* If segment's page resides in high memory, map it into + * kernel's address space temporarily. + */ + if (PageHighMem(bv->bv_page)) + p = kmap (bv->bv_page) + bv->bv_offset; + else /* segment's page resides in low memory */ + p = page_address (bv->bv_page) + bv->bv_offset; + + for (; n >= gather->free_bytes; ) + { + /* This I/O segment won't fit into the remaining space in + * gather buffer. Copy the part that does fit into gather + * buffer (making it full), then flush entire gather buffer + * to disk. + */ + if (gather->free_bytes > 0) + { + memcpy (gather->free, p, gather->free_bytes); + + p += gather->free_bytes; + n -= gather->free_bytes; + } + + /* flush entire gather buffer to disk */ + if( TffsWrite (pdisk, gather->buf, gather->start_sector, + (gather->size >> 9)) == 0 ) + rc = -EIO; /* I/O error */ + + /* gather buffer is empty */ + gather->free = gather->buf; + gather->free_bytes = gather->size; + gather->start_sector += (gather->size >> 9); + } + + /* remaining part of this segment fits into gather buffer */ + if (n > 0) + { + memcpy (gather->free, p, n); + + gather->free += n; + gather->free_bytes -= n; + } + + /* If segment's page resides in high memory, cancel + * previously established mapping. + */ + if (PageHighMem(bv->bv_page)) + kunmap (bv->bv_page); + } + } + + return rc; +} + + + + +/******************************************************************************* + * * + * r e a d _ b i o * + * * + * This routine handles single 'struct bio' READ operation using scatter * + * buffer. * + * * + * Parameters: * + * bio pointer to 'struct bio' to WRITE * + * scatter pointer to scatter buffer * + * pdisk disk pointer * + * * + * Returns: * + * zero if success otherwise -EIO negative error code * + * * + *******************************************************************************/ +static +int read_bio ( struct request * r, + /*struct bio * bio, */ + struct scatter_t * scatter, + DeviceInfo * pdisk ) +{ + struct bio_vec * bv; + int rc = 0; + struct req_iterator iter; + + if ((tffs_sg_bufsize == 0) || (tffs_sg_read == FALSE)) + { + /* we don't use scatter buffer; do one I/O segment at a time */ + printk("rw_bio_no_sg 2 !!!!!!!!!!!!!!!!!!\n"); + + rc = rw_bio_no_sg (r, pdisk, READ); + } + else /* use gather buffer */ + { + rq_for_each_segment(bv, r, iter) + { + unsigned int n = bv->bv_len; /* bytes in this I/O segment */ + unsigned int ns; + char * p; + + /* If segment's page resides in high memory, map it into + * kernel's address space temporarily. + */ + if (PageHighMem(bv->bv_page)) + p = kmap (bv->bv_page) + bv->bv_offset; + else /* segment's page resides in low memory */ + p = page_address (bv->bv_page) + bv->bv_offset; + + for (; n >= scatter->remaining_bytes; ) + { + /* This I/O segment is larger then number of remaining bytes + * in scatter buffer. Copy all these remaining bytes (making + * scatter buffer empty), then re-fill scatter buffer from disk. + */ + if (scatter->remaining_bytes > 0) + { + memcpy (p, scatter->pcurrent, scatter->remaining_bytes); + + p += scatter->remaining_bytes; + n -= scatter->remaining_bytes; + } + + /* scatter buffer is empty now */ + scatter->remaining_bytes = 0; + scatter->pcurrent = scatter->buf; + + /* end of this request ? */ + if ((ns = _MIN(scatter->sectors, (tffs_sg_bufsize >> 9))) == 0) + break; + + /* re-fill scatter buffer from disk */ + if( TffsRead (pdisk, scatter->buf, scatter->start_sector, ns) == 0 ) + rc = -EIO; /* I/O error */ + + scatter->remaining_bytes = (ns << 9); + scatter->sectors -= ns; + scatter->start_sector += ns; + } + + /* Remaining part of this segment can be entirely taken + * from the scatter buffer. + */ + if (n > 0) + { + memcpy (p, scatter->pcurrent, n); + + scatter->pcurrent += n; + scatter->remaining_bytes -= n; + } + + /* If segment's page resides in high memory, cancel + * previously established mapping. + */ + if (PageHighMem(bv->bv_page)) + kunmap (bv->bv_page); + } + } + + return rc; +} + + + + +/******************************************************************************* + * * + * r w _ b i o _ n o _ s g * + * * + * This routine handles single 'struct bio' without using scatter/gather * + * buffers. It issues TrueFFS I/O call for each segment of this 'struct bio'. * + * * + * Parameters: * + * bio pointer to 'struct bio' to handle * + * pdisk disk pointer * + * rw READ or WRITE * + * * + * Returns: * + * zero if success otherwise -EIO negative error code * + * * + *******************************************************************************/ +static +int rw_bio_no_sg ( struct request * r, + /* struct bio * bio, */ + DeviceInfo * pdisk, + int rw ) +{ + sector_t sector = r->bio->bi_sector; /* starting disk sector for this bio */ + struct bio_vec * bv; + char * p; + int rc = 0; + unsigned int ns; + struct req_iterator iter; + + /*bio_for_each_segment (bv, bio, i)*/ + rq_for_each_segment(bv, r, iter) + { + if ((ns = (bv->bv_len >> 9)) > 0) /* sectors in this segment */ + { + /* If segment's page resides in high memory, map it into + * kernel's address space temporarily. + */ + if (PageHighMem(bv->bv_page)) + p = kmap (bv->bv_page) + bv->bv_offset; + else /* segment's page resides in low memory */ + p = page_address (bv->bv_page) + bv->bv_offset; + + if (rw == READ) + { + if( TffsRead (pdisk, p, sector, ns) == 0 ) + rc = -EIO; /* I/O error */ + } + else + { + if( TffsWrite (pdisk, p, sector, ns) == 0 ) + rc = -EIO; /* I/O error */ + } + + /* If segment's page resides in high memory, cancel + * previously established mapping. + */ + if (PageHighMem(bv->bv_page)) + kunmap (bv->bv_page); + + sector += ns; + } + } + + return rc; +} + + + + +/******************************************************************************* + * * + * r e q u e s t s _ t o _ d o * + * * + * This routine checks if there are any requests in socket's request list. * + * * + * Parameters: * + * psoc socket pointer * + * * + * Returns: * + * FALSE if list is empty, otherwise TRUE * + * * + *******************************************************************************/ +static +int requests_to_do ( SocketInfo * psoc ) +{ + unsigned long flags; + int rc = FALSE; /* assume list is empty */ + + spin_lock_irqsave (&psoc->request_list_lock, flags); + + if( !list_empty(&psoc->requestsList) ) + rc = TRUE; + + spin_unlock_irqrestore (&psoc->request_list_lock, flags); + + return rc; +} + + + +/******************************************************************************* + * * + * t f f s _ s u s p e n d * + * * + * This routine is intended to be called by various Linux Power Managers to * + * power down all DiskOnChip devices when system goes into powerdown mode. * + * * + * Parameters: none * + * * + * Returns: void * + * * + *******************************************************************************/ +void tffs_suspend (void) +{ + SocketInfo * psoc; + int i; + + for (i = 0; i < FL_SOCKETS; i++) + { + psoc = &tffsInfo.sockets[i]; + + if (psoc->fFound == 0) + continue; + + init_completion (&psoc->wait_for_io_thread); + + /* Tell I/O thread to finish all outstanding I/O requests, wake + * up us, and exit. + */ + psoc->io_thread_state = 2; + + /* in case socket's I/O thread is currently sleeping, wake it up */ + wake_up (&psoc->waitQueueHead); + + /* wait for I/O thread to exit */ + wait_for_completion (&psoc->wait_for_io_thread); /* down_interruptible (&psoc->threadSemaphore); */ + + /* tell TrueFFS to power down DiskOnChip */ + TffsSuspend (psoc); + } + + /* disable DiskOnChip interrupts */ + if (tffs_irq >= 0) + { + tffs_irq_disable (TRUE); + } +} + + + + +/******************************************************************************* + * * + * t f f s _ r e s u m e * + * * + * This routine is intended to be called by various Linux Power Managers to * + * power up all DiskOnChip devices when system comes up from powerdown mode. * + * * + * Parameters: none * + * * + * Returns: void * + * * + *******************************************************************************/ +void tffs_resume (void) +{ + SocketInfo * psoc; + int i; + + /* We are doing 'resume' after previous power 'suspend', not + * full scale board initialization, hence TRUE flag below. + */ + tffsarch_init (TRUE); + + /* enable DiskOnChip interrupts */ + if (tffs_irq >= 0) + { + tffs_irq_enable (TRUE); + } + + for (i = 0; i < FL_SOCKETS; i++) + { + psoc = &tffsInfo.sockets[i]; + + if (psoc->fFound == 0) + continue; + + /* Tell TrueFFS to power up DiskOnChip. This call takes around 20 + * milliseconds (DiskOnChip driver will not yield CPU during this time). + */ + TffsResume (psoc); + + /* restore multi-sector poleld I/O mode in DiskOnChip h3 devices */ + TffsSetPIO (psoc); + + init_completion (&psoc->wait_for_io_thread); + + /* tell I/O thread to wake us up once it gets running */ + psoc->io_thread_state = 2; + + /* start I/O thread */ + kernel_thread (socket_io_thread, (void *)psoc, 0); + + /* wait for I/O thread to get running */ + wait_for_completion (&psoc->wait_for_io_thread); /* down_interruptible (&psoc->threadSemaphore); */ + } +} + + + + +#ifdef CONFIG_PROC_FS + +/******************************************************************************* + * * + * p r o c f s _ r e g i s t e r * + * * + * Create disk's entry in /proc/. * + * * + * Parameters: * + * * + * pdisk disk pointer * + * * + * Returns: zero if success otherwise negative error code. * + * * + *******************************************************************************/ +static +int /* __init */ procfs_register ( DeviceInfo * pdisk ) +{ + char name[] = "a"; + + name[0] += (char)(pdisk->diskNo); + + if ((pdisk->pProcFile = create_proc_entry(name, 0, tffsInfo.pProcDir)) == NULL) + { + PrintkWarning("Can't create /proc/tffs/%s", name); + return -EBUSY; + } + + pdisk->pProcFile->read_proc = procfs_read; + pdisk->pProcFile->write_proc = procfs_write; + pdisk->pProcFile->data = pdisk; + + return 0; +} + + + + +/******************************************************************************* + * * + * p r o c f s _ u n r e g i s t e r * + * * + * Delete disk's entry in /proc/. * + * * + * Parameters: * + * * + * pdisk disk pointer * + * * + * Returns: always zero (success). * + * * + *******************************************************************************/ +static +int /* __exit */ procfs_unregister ( DeviceInfo * pdisk ) +{ + char name[] = "a"; + + name[0] += (char)(pdisk->diskNo); + + remove_proc_entry (name, tffsInfo.pProcDir); + pdisk->pProcFile = NULL; + + return 0; +} + + + + +/******************************************************************************* + * * + * p r o c f s _ w r i t e * + * * + * Called when disk's entry in /proc/ is wriiten to. * + * * + * Parameters: * + * * + * file not used * + * buffer not used * + * count not used * + * data disk pointer * + * * + * Returns: always zero (success). * + * * + *******************************************************************************/ +static +int procfs_write ( struct file * file, + const char * buffer, + unsigned long count, + void * data ) +{ +# ifdef TFFS_STATISTIC + DeviceInfo * pdisk = (DeviceInfo *)data; + + memset (&pdisk->stat, 0, sizeof(pdisk->stat)); +# endif + + return count; +} + + + + +/******************************************************************************* + * * + * p r o c f s _ r e a d * + * * + * Called when disk's entry in /proc/ is read from. * + * * + * Parameters: * + * * + * buf buffer to put data to * + * start not used * + * offset not used * + * length not used * + * eof End-of-File indicator * + * data disk pointer * + * * + * Returns: number of characters written to buffer 'buf' * + * * + *******************************************************************************/ +static +int procfs_read ( char * buf, + char ** start, + off_t offset, + int length, + int * eof, + void * data ) +{ + char * p = buf; + int i; + +# ifdef TFFS_STATISTIC + + { DeviceInfo * pdisk = (DeviceInfo *)data; + TffsStatistic * stat = &pdisk->stat; + + p += sprintf (p, "flAbsRead calls %ld\n", stat->dwAbsRead); + p += sprintf (p, "total %ld read requests (%ld by disk_request_queue_handler)\n", + stat->dwReadReq, stat->dwReadReqNoThread); + p += sprintf (p, "total %ld sectors read (aligned %ld, unaligned %ld)\n", + stat->dwAbsReadSec, stat->dwAlReadSec, stat->dwUnalReadSec); + p += sprintf (p, "read shared sectors: aligned %ld, unaligned %ld\n", + stat->dwAlReadShared, stat->dwUnalReadShared); + + p += sprintf (p,"flAbsWrite calls %ld\n", stat->dwAbsWrite); + p += sprintf (p, "total %ld write requests\n", stat->dwWriteReq); + p += sprintf (p,"total %ld sectors written (aligned %ld, unaligned %ld)\n", + stat->dwAbsWriteSec, stat->dwAlWriteSec, stat->dwUnalWriteSec); + p += sprintf (p,"written shared sectors: aligned %ld, unaligned %ld\n", + stat->dwAlWriteShared, stat->dwUnalWriteShared); + } + +# endif /* TFFS_STATISTIC */ + + p += sprintf (p, "profiling:"); + for (i = 0; i < 10; i++) + p += sprintf (p, " %d", profiling[i]); + p += sprintf (p, "\n"); + + *eof = 1; + + return (p - buf); +} + +#endif /* CONFIG_PROC_FS */ + +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsioct.h b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsioct.h new file mode 100755 index 00000000..8aae1ca3 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/tffsioct.h @@ -0,0 +1,55 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#ifndef TFFSIOCT_H +#define TFFSIOCT_H + +#include "_tffsioct.h" +#include + + +#define FL_IOCTL_LNX (SIOCDEVPRIVATE + 0) +#define FL_IOCTL_START (SIOCDEVPRIVATE + 1) + +#include "flioctl.h" + +/* replicas of enums in doch_api.h */ +#define DOCH_PASSTHRU_DATA_OUT 0x02 +#define DOCH_DOWNLOAD_MICROCODE 0x92 +#define DOCH_DLMCODE_DOWNLOAD_AND_SAVE 0x7 + +#endif /* TFFSIOCT_H */ + diff --git a/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/trace32.c b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/trace32.c new file mode 100755 index 00000000..eba22825 --- /dev/null +++ b/kernel-2.6.33/arch/arm/mach-pxa/g900/ttfs/trace32.c @@ -0,0 +1,48 @@ +/****************************************************************************** + * * + * Project: DOC Driver for Linux 2.6 Block device driver for mDOC H3 family * + * of devices under Linux kernel 2.6. * + * * + * Version: 1.0 * + * Email questions to: oemsupport@sandisk.com * + * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * + * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * + * * + ****************************************************************************** + * * + * 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 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, which is set forth in the readme.txt file. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., 51 * + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * * + * This License does not grant you any right to use the trademarks, service * + * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * + * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * + * licensors, hereby reserves all intellectual property rights in the program,* + * except for the rights expressly granted in this License. * + * * + ******************************************************************************/ + +/* + * $Log$ + */ + + +#include +#include +#include + +/* + * These variables reside at the beginning of respective sections +*/ +int trace32_data = 0x11223344; /* beginning of .data section */ +int trace32_bss; /* beginning of .bss section */ +const int trace32_rodata = 0x55667788; /* beginning of .rodata section */ + + diff --git a/kernel-2.6.33/drivers/input/touchscreen/ak4183.c b/kernel-2.6.33/drivers/input/touchscreen/ak4183.c index 9bd06b18..01320c04 100755 --- a/kernel-2.6.33/drivers/input/touchscreen/ak4183.c +++ b/kernel-2.6.33/drivers/input/touchscreen/ak4183.c @@ -183,7 +183,7 @@ static u32 ak4183_read_values(struct ak4183 *tsc, struct ts_event *tc) //s32 x,y; tc->x = ak4183_xfer(tsc, READ_X);//x tc->y = ak4183_xfer(tsc, READ_Y);//y - //printk(KERN_INFO "AK4183: %5i;%5i;", + //devdbg(KERN_INFO "AK4183: %5i;%5i;", // tc->x,tc->y); tc->z1 = ak4183_xfer(tsc,READ_Z1);//z1 tc->z2 = ak4183_xfer(tsc,READ_Z2);//z2 @@ -195,7 +195,7 @@ static u32 ak4183_read_values(struct ak4183 *tsc, struct ts_event *tc) if (rt<5000){rt=5000;} // max rt=(6350-rt)*3;//0xFFF max if (rt>=0xFFF) {rt=0xFFE;}//max - // printk(KERN_INFO "AK4183: %5u;%5u;%5u;%5u;%5u;", + // devdbg(KERN_INFO "AK4183: %5u;%5u;%5u;%5u;%5u;", // tc->x,tc->y,tc->z1,tc->z2,rtt); }else{ rt=0;//no touch @@ -337,23 +337,21 @@ static int __devinit ak4183_probe(struct i2c_client *client, int err; if (!pdata) { - dev_err(&client->dev, "platform data is required!\n"); - printk(KERN_ERR "ak4183: platform data is required!\n"); return -EINVAL; } if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) { - printk(KERN_ERR "ak4183: err i2c_check_functionality!\n"); + dev_err(&client->dev, "err i2c_check_functionality!\n"); return -EIO; } ts = kzalloc(sizeof(struct ak4183), GFP_KERNEL); input_dev = input_allocate_device(); if (!ts || !input_dev) { err = -ENOMEM; - printk(KERN_ERR "ak4183: err input_allocate_device!\n"); + dev_err(&client->dev, "err input_allocate_device!\n"); goto err_free_mem; } @@ -393,7 +391,6 @@ static int __devinit ak4183_probe(struct i2c_client *client, if (err < 0) { dev_err(&client->dev, "irq %d busy?\n", ts->irq); - printk(KERN_ERR "ak4183: err irq %d busy?\n",ts->irq); goto err_free_mem; } @@ -401,13 +398,13 @@ static int __devinit ak4183_probe(struct i2c_client *client, /* err = ak4183_xfer(ts, PWRDOWN); if (err < 0){ goto err_free_irq; - printk(KERN_ERR "ak4183: err ak4183_xfer\n"); + dev_err(&client->dev, "err ak4183_xfer\n"); } */ err = input_register_device(input_dev); if (err){ goto err_free_irq; - printk(KERN_ERR "ak4183: err input_register_device\n"); + dev_err(&client->dev, "err input_register_device\n"); } i2c_set_clientdata(client, ts); @@ -441,7 +438,7 @@ static int __devexit ak4183_remove(struct i2c_client *client) } static struct i2c_device_id ak4183_idtable[] = { - { "ak4183", 0 }, + { "ak4183", 0x48 }, { } }; diff --git a/kernel-2.6.33/drivers/video/Kconfig b/kernel-2.6.33/drivers/video/Kconfig index 42357dc6..70f0d8ee 100755 --- a/kernel-2.6.33/drivers/video/Kconfig +++ b/kernel-2.6.33/drivers/video/Kconfig @@ -1831,18 +1831,6 @@ config FB_G900 To compile this driver as a module, choose M here: the module will be called g900fb. -config FB_G900_NEW - tristate "New FB for Toshiba G900 frame buffer support" - depends on FB && ARM - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MODE_HELPERS - ---help--- - Say Y here if you have a Toshiba G900 PDA. - - To compile this driver as a module, choose M here: the - module will be called g900fb. config FB_MBX tristate "2700G LCD framebuffer support" diff --git a/kernel-2.6.33/drivers/video/Makefile b/kernel-2.6.33/drivers/video/Makefile index ec70868e..115c99e4 100755 --- a/kernel-2.6.33/drivers/video/Makefile +++ b/kernel-2.6.33/drivers/video/Makefile @@ -100,7 +100,6 @@ obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o obj-$(CONFIG_FB_PXA) += pxafb.o obj-$(CONFIG_FB_PXA168) += pxa168fb.o obj-$(CONFIG_FB_G900) += g900fb.o -obj-$(CONFIG_FB_G900_NEW) += g900fb2.o obj-$(CONFIG_FB_W100) += w100fb.o obj-$(CONFIG_FB_TMIO) += tmiofb.o obj-$(CONFIG_FB_AU1100) += au1100fb.o diff --git a/kernel-2.6.33/drivers/video/g900fb.c b/kernel-2.6.33/drivers/video/g900fb.c index 1bc9c8c7..dd4b0567 100755 --- a/kernel-2.6.33/drivers/video/g900fb.c +++ b/kernel-2.6.33/drivers/video/g900fb.c @@ -1,4 +1,8 @@ -/*linux/drivers/video/g900fb.c -- Toshiba g900 Simple Frame Buffer device +/*linux/drivers/video/g900fb2.c -- + * + * Copyright (C) 2010 Angell Fear + * + * Copyright (C) 2010 Kosyak * * Copyright (C) 2008 El Tuba * @@ -6,7 +10,9 @@ * * Copyright (C) 2008 Vladimir Chernichkin * - * Copyright (C) 2002 James Simmons + * Copyright (C) 2007, Google Inc. + * + * Copyright (C) 2002 James Simmons * * Copyright (C) 1997 Geert Uytterhoeven * @@ -29,199 +35,148 @@ #include #include #include +#include + + +#define FB_WIDTH 480 +#define FB_HEIGHT 800 +#define VIDEOMEMSTART 0x0a000000 /* vram variable value from HaRET */ +#define FB_NUMBER_OF_BUFFERS 1 +#define FB_BYTES_PER_PIXEL 2 +#define VIDEOMEMBUFSIZE FB_WIDTH * FB_HEIGHT * FB_BYTES_PER_PIXEL +#define VIDEOMEMSIZE VIDEOMEMBUFSIZE * FB_NUMBER_OF_BUFFERS + + -#define VIDEOMEMSIZE (4*800*480) /* screen size KB */ -#define VIDEOMEMSTART 0x0a000020 //vram variable value from HaRET static void *videomemory; -static u_long videomemorysize = VIDEOMEMSIZE; +static u_long videomemorysize = VIDEOMEMSIZE * FB_NUMBER_OF_BUFFERS; module_param(videomemorysize, ulong, 0); +struct g900_fb { + int rotation; + struct fb_info fb; + u32 cmap[16]; +}; static struct fb_var_screeninfo g900fb_default __initdata = { - .xres = 480, - .yres = 800, - .xres_virtual = 480, - .yres_virtual = 800, + .xres = FB_WIDTH, + .yres = FB_HEIGHT, + .xres_virtual = FB_WIDTH, + .yres_virtual = FB_HEIGHT, .bits_per_pixel = 16, .red = { 11, 5, 0 }, .green = { 5, 6, 0 }, .blue = { 0, 5, 0 }, - .height = -1, - .width = -1, + .height = FB_HEIGHT, + .width = FB_WIDTH, .accel_flags = FB_ACCEL_NONE, - //The following values seem to not affect the screeen behavior - .pixclock = 10, - .left_margin = 1, - .right_margin = 0, - .upper_margin = 0, - .lower_margin = 0, -// .hsync_len = 96, - .hsync_len = 2, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED + }; static struct fb_fix_screeninfo g900fb_fix __initdata = { - .id = "g900 FB", - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_TRUECOLOR, - .xpanstep = 8, - .accel = FB_ACCEL_NONE, - .ypanstep = 1, - .ywrapstep = 0, - .smem_start = VIDEOMEMSTART, - .smem_len = VIDEOMEMSIZE, + .id = "g900 FB", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .accel = FB_ACCEL_NONE, + .xpanstep = 1, + .ypanstep = 1, + .ywrapstep = 0, + .smem_start = VIDEOMEMSTART, + .smem_len = VIDEOMEMSIZE, + .line_length = FB_WIDTH * FB_BYTES_PER_PIXEL, }; static int g900fb_enable __initdata = 1; /* disabled by default */ module_param(g900fb_enable, bool, 0); -static int g900fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info); -static int g900fb_set_par(struct fb_info *info); -static int g900fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info); +static int g900fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); +//static int g900fb_set_par(struct fb_info *info); +static int g900fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info); static int g900fb_pan_display(struct fb_var_screeninfo *var,struct fb_info *info); +//static int g900fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); + +static void g900fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); +static void g900fb_copyarea(struct fb_info *info, const struct fb_copyarea *region); +static void g900fb_imageblit(struct fb_info *info, const struct fb_image *image); + +static void g900fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ +/* Метод уÑÐºÐ¾Ñ€ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ñмоугольника линиÑми пикÑелей */ +/* похоже вообще не иÑпользуетьÑÑ */ + cfb_fillrect(info,rect); + +}; +static void g900fb_copyarea(struct fb_info *info, const struct fb_copyarea *region) +{ +/* Метод уÑÐºÐ¾Ñ€ÐµÐ½Ð¸Ñ ÐºÐ¾Ð¿Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¾Ð´Ð½Ð¾Ð¹ прÑмоугольной облаÑти в другую */ +/* похоже вообще не иÑпользуетьÑÑ */ + cfb_copyarea(info,region); +}; +static void g900fb_imageblit(struct fb_info *info, const struct fb_image *image) +{ +/* Метод уÑÐºÐ¾Ñ€ÐµÐ½Ð¸Ñ Ñ€Ð¸ÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð½Ð° Ñкране картинки */ +/* Без Ñтого даже не отображаетьÑÑ ÐºÐ¾Ð½Ñоль !!! */ + cfb_imageblit(info,image); +}; + + +static int g900fb_mmap(struct fb_info *info, struct vm_area_struct *vma) +{}; static struct fb_ops g900fb_ops = { - .fb_check_var = g900fb_check_var, - .fb_set_par = g900fb_set_par, - .fb_setcolreg = g900fb_setcolreg, - .fb_pan_display = g900fb_pan_display, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, + .fb_check_var = g900fb_check_var, /* Проверка параметров */ + //.fb_set_par = g900fb_set_par, /* Программирование региÑтров контроллера */ + .fb_setcolreg = g900fb_setcolreg, /* УÑтановка карты цветов */ + .fb_pan_display = g900fb_pan_display, /* переключение Ñтраниц буферов */ + .fb_fillrect = g900fb_fillrect, + .fb_copyarea = g900fb_copyarea, + .fb_imageblit = g900fb_imageblit, + //.fb_ioctl = g900fb_ioctl, /* ЗавиÑÐ¸Ð¼Ð°Ñ Ð¾Ñ‚ уÑтройÑтва ioctl */ + //.fb_blank = g900fb_blank, /* Включение/выключение Ñкрана */ + //.fb_mmap = g900fb_mmap, }; - /* - * Internal routines - */ - -static u_long get_line_length(int xres_virtual, int bpp) +static inline u32 convert_bitfield(int val, struct fb_bitfield *bf) { - u_long length; + unsigned int mask = (1 << bf->length) - 1; - length = xres_virtual * bpp; - length = (length + 31) & ~31; - length >>= 3; - return (length); + return (val >> (16 - bf->length) & mask) << bf->offset; } - /* - * Setting the video mode has been split into two parts. - * First part, xxxfb_check_var, must not write anything - * to hardware, it should only verify and adjust var. - * This means it doesn't alter par but it does use hardware - * data from it to check this var. - */ + static int g900fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { - u_long line_length; - if (!var->xres) - var->xres = 1; - if (!var->yres) - var->yres = 1; - if (var->xres > var->xres_virtual) - var->xres_virtual = var->xres; - if (var->yres > var->yres_virtual) - var->yres_virtual = var->yres; - if (var->bits_per_pixel <= 1) - var->bits_per_pixel = 1; - else if (var->bits_per_pixel <= 8) - var->bits_per_pixel = 8; - else if (var->bits_per_pixel <= 16) - var->bits_per_pixel = 16; - else if (var->bits_per_pixel <= 24) - var->bits_per_pixel = 24; - else if (var->bits_per_pixel <= 32) - var->bits_per_pixel = 32; - else - return -EINVAL; - - if (var->xres_virtual < var->xoffset + var->xres) - var->xres_virtual = var->xoffset + var->xres; - if (var->yres_virtual < var->yoffset + var->yres) - var->yres_virtual = var->yoffset + var->yres; - - /* - * Memory limit - */ - line_length = - get_line_length(var->xres_virtual, var->bits_per_pixel); - if (line_length * var->yres_virtual > videomemorysize) - return -ENOMEM; - - /* - * Now that we checked it we alter var. The reason being is that the video - * mode passed in might not work but slight changes to it might make it - * work. This way we let the user know what is acceptable. - */ - switch (var->bits_per_pixel) { - case 1: - case 8: - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 0; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - break; - case 16: /* RGBA 5551 */ - if (var->transp.length) { - var->red.offset = 0; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 5; - var->blue.offset = 10; - var->blue.length = 5; - var->transp.offset = 15; - var->transp.length = 1; - } else { /* RGB 565 */ - var->red.offset = 0; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 11; - var->blue.length = 5; - var->transp.offset = 0; - var->transp.length = 0; + if((var->rotate & 1) != (info->var.rotate & 1)) { + if((var->xres != info->var.yres) || + (var->yres != info->var.xres) || + (var->xres_virtual != info->var.yres) || + (var->yres_virtual > + info->var.xres * FB_NUMBER_OF_BUFFERS) || + (var->yres_virtual < info->var.xres )) { + return -EINVAL; + } + } else { + if((var->xres != info->var.xres) || + (var->yres != info->var.yres) || + (var->xres_virtual != info->var.xres) || + (var->yres_virtual > + info->var.yres * FB_NUMBER_OF_BUFFERS) || + (var->yres_virtual < info->var.yres )) { + return -EINVAL; } - break; - case 24: /* RGB 888 */ - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 16; - var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - break; - case 32: /* RGBA 8888 */ - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 16; - var->blue.length = 8; - var->transp.offset = 24; - var->transp.length = 8; - break; } - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - var->transp.msb_right = 0; - + if((var->xoffset != info->var.xoffset) || + (var->bits_per_pixel != info->var.bits_per_pixel) || + (var->grayscale != info->var.grayscale)) { + return -EINVAL; + } return 0; } @@ -229,12 +184,18 @@ static int g900fb_check_var(struct fb_var_screeninfo *var, * the hardware state info->par and fix which can be affected by the * change in par. For this driver it doesn't do much. */ + /* static int g900fb_set_par(struct fb_info *info) { - info->fix.line_length = get_line_length(info->var.xres_virtual, info->var.bits_per_pixel); + struct g900_fb *fb = container_of(info, struct g900_fb, fb); + if(fb->rotation != fb->fb.var.rotate) { + fb->rotation = fb->fb.var.rotate; + //TODO: Dynamic Rotation!!! + } + return 0; } - +*/ /* * Set a single color register. The values supplied are already * rounded down to the hardware's capabilities (according to the @@ -244,127 +205,99 @@ static int g900fb_set_par(struct fb_info *info) static int g900fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { - if (regno >= 256) /* no. of hw registers */ - return 1; - /* - * Program hardware... do anything you want with transp - */ + struct g900_fb *fb = container_of(info, struct g900_fb, fb); - /* grayscale works only partially under directcolor */ - /* grayscale = 0.30*R + 0.59*G + 0.11*B */ - if (info->var.grayscale) {red = green = blue =(red * 77 + green * 151 + blue * 28) >> 8;} - - /* Directcolor: - * var->{color}.offset contains start of bitfield - * var->{color}.length contains length of bitfield - * {hardwarespecific} contains width of RAMDAC - * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset) - * RAMDAC[X] is programmed to (red, green, blue) - * - * Pseudocolor: - * uses offset = 0 && length = RAMDAC register width. - * var->{color}.offset is 0 - * var->{color}.length contains widht of DAC - * cmap is not used - * RAMDAC[X] is programmed to (red, green, blue) - * Truecolor: - * does not use DAC. Usually 3 are present. - * var->{color}.offset contains start of bitfield - * var->{color}.length contains length of bitfield - * cmap is programmed to (red << red.offset) | (green << green.offset) | - * (blue << blue.offset) | (transp << transp.offset) - * RAMDAC does not exist - */ -#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) - switch (info->fix.visual) { - case FB_VISUAL_TRUECOLOR: - case FB_VISUAL_PSEUDOCOLOR: - red = CNVT_TOHW(red, info->var.red.length); - green = CNVT_TOHW(green, info->var.green.length); - blue = CNVT_TOHW(blue, info->var.blue.length); - transp = CNVT_TOHW(transp, info->var.transp.length); - break; - case FB_VISUAL_DIRECTCOLOR: - red = CNVT_TOHW(red, 8); /* expect 8 bit DAC */ - green = CNVT_TOHW(green, 8); - blue = CNVT_TOHW(blue, 8); - /* hey, there is bug in transp handling... */ - transp = CNVT_TOHW(transp, 8); - break; - } -#undef CNVT_TOHW - /* Truecolor has hardware independent palette */ - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 v; - - if (regno >= 16) - return 1; - - v = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset) | - (transp << info->var.transp.offset); - - switch (info->var.bits_per_pixel) { - case 8: - break; - case 16: - ((u32 *) (info->pseudo_palette))[regno] = v; - break; - case 24: - case 32: - ((u32 *) (info->pseudo_palette))[regno] = v; - break; - } + if (regno < 16) { + fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) | + convert_bitfield(blue, &fb->fb.var.blue) | + convert_bitfield(green, &fb->fb.var.green) | + convert_bitfield(red, &fb->fb.var.red); return 0; } - return 0; + else { + return 1; + } } - /* - * Pan or Wrap the Display - * - * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag - */ - static int g900fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - u32 total; - - if (var->vmode & FB_VMODE_YWRAP) { - if (var->yoffset < 0 - || var->yoffset >= info->var.yres_virtual - || var->xoffset) - return -EINVAL; - } else { - if (var->xoffset + var->xres > info->var.xres_virtual || - var->yoffset + var->yres > info->var.yres_virtual) - return -EINVAL; - } - info->var.xoffset = var->xoffset; - info->var.yoffset = var->yoffset; - if (var->vmode & FB_VMODE_YWRAP) - info->var.vmode |= FB_VMODE_YWRAP; - else - info->var.vmode &= ~FB_VMODE_YWRAP; - - - -// var->xoffset = 20; - var->xoffset = 0; - total = var->yoffset * info->fix.line_length + var->xoffset; - - // Needs to be rewritten - info->fix.smem_start=VIDEOMEMSTART - total; - - - return 0; + struct fb_copyarea fbca; + return 0; } +/* + * Initialisation + */ +static int __init g900fb_probe(struct platform_device *dev) +{ + struct g900_fb *fb; + int retval = -ENOMEM; + + fb = kzalloc(sizeof(*fb), GFP_KERNEL); + if(fb == NULL) + goto err; + + if (!request_mem_region(VIDEOMEMSTART, videomemorysize, "g900fb")) { + printk(KERN_INFO"g900fb: cannot get framebuffer\n"); + goto err1; + } + + fb->fb.flags = FBINFO_FLAG_DEFAULT; + fb->fb.fbops = &g900fb_ops; + fb->fb.pseudo_palette = fb->cmap; + fb->fb.fix = g900fb_fix; + fb->fb.var = g900fb_default; + + fb->fb.screen_base = ioremap(VIDEOMEMSTART, videomemorysize); + + retval = fb_set_var(&fb->fb, &fb->fb.var); + if(retval) + goto err1; + + retval = register_framebuffer(&fb->fb); + if (retval < 0) + goto err2; + + platform_set_drvdata(dev, &fb->fb); + + printk(KERN_INFO "fb%d: g900 frame buffer device, using %ldK of video memory\n", + fb->fb.node, videomemorysize >> 10); + + return 0; + +err2: + framebuffer_release(&fb->fb); +err1: + kfree(fb); +err: + iounmap(videomemory); + return retval; +} + +static int g900fb_remove(struct platform_device *dev) +{ + struct g900_fb *fb = platform_get_drvdata(dev); + + if (fb) { + unregister_framebuffer(&fb->fb); + iounmap(videomemory); + framebuffer_release(&fb->fb); + kfree(fb); + } + return 0; +} + +static struct platform_driver g900fb_driver = { + .probe = g900fb_probe, + .remove = g900fb_remove, + .driver = { + .name = "g900fb", + }, +}; #ifndef MODULE static int __init g900fb_setup(char *options) @@ -386,74 +319,6 @@ static int __init g900fb_setup(char *options) } #endif /* MODULE */ - /* - * Initialisation - */ - -static int __init g900fb_probe(struct platform_device *dev) -{ - struct fb_info *info; - int retval = -ENOMEM; - - info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev); - if (!info) - goto err; - - if (!request_mem_region(VIDEOMEMSTART, VIDEOMEMSIZE,"g900fb")) { - printk(KERN_INFO"g900fb: cannot get framebuffer\n"); - goto err2; - } - - - - info->screen_base = ioremap(VIDEOMEMSTART,videomemorysize); - info->fbops = &g900fb_ops; - info->var = g900fb_default; - info->fix = g900fb_fix; - info->pseudo_palette = info->par; - info->par = NULL; - info->flags = FBINFO_FLAG_DEFAULT; - - retval = fb_alloc_cmap(&info->cmap, 256, 0); - if (retval < 0) - goto err1; - - retval = register_framebuffer(info); - if (retval < 0) - goto err2; - platform_set_drvdata(dev, info); - - printk(KERN_INFO"fb%d: g900 frame buffer device, using %ldK of video memory\n", - info->node, videomemorysize >> 10); - return 0; -err2: - fb_dealloc_cmap(&info->cmap); -err1: - framebuffer_release(info); -err: - iounmap(videomemory); - return retval; -} - -static int g900fb_remove(struct platform_device *dev) -{ - struct fb_info *info = platform_get_drvdata(dev); - - if (info) { - unregister_framebuffer(info); - iounmap(videomemory); - framebuffer_release(info); - } - return 0; -} - -static struct platform_driver g900fb_driver = { - .probe = g900fb_probe, - .remove = g900fb_remove, - .driver = { - .name = "g900fb", - }, -}; static struct platform_device *g900fb_device; @@ -501,7 +366,7 @@ static void __exit g900fb_exit(void) } module_exit(g900fb_exit); -MODULE_AUTHOR("El Tuba "); -MODULE_DESCRIPTION("Framebuffer driver for the Toshiba g900"); +MODULE_AUTHOR("Angell "); +MODULE_DESCRIPTION("Framebuffer driver for the Toshiba g900 "); MODULE_LICENSE("GPL"); -#endif /* MODULE */ +#endif diff --git a/ramfs-android/default.prop b/ramfs-android/default.prop index cb83448f..14c7ca8a 100644 --- a/ramfs-android/default.prop +++ b/ramfs-android/default.prop @@ -5,7 +5,6 @@ ro.secure=0 ro.allow.mock.location=1 ro.debuggable=1 persist.service.adb.enable=1 -#ro.sf.lcd_density=180 ro.sf.lcd_density=210 #dalvik.vm.heapsize=10m diff --git a/ramfs-android/init b/ramfs-android/init index 415bfd13..a3a0efc6 100755 --- a/ramfs-android/init +++ b/ramfs-android/init @@ -62,7 +62,7 @@ if [ ! -e /sys/block/mmcblk0/mmcblk0p1 ] ; then fi echo "Mounting SD card to /sdcard" -/bin/mount -t vfat /dev/block/mmcblk0p1 /sdcard +/bin/mount -t vfat -o rw,umask=0,codepage=866,iocharset=cp1251 /dev/block/mmcblk0p1 /sdcard [ $? -eq 0 ] || fail "Failed to Mount SD Card" #echo "Dumping kernel log." @@ -102,20 +102,33 @@ fi #/bin/losetup /dev/block/loop2 /sdcard/ANDROID/extram.img #[ $? -eq 0 ] && /bin/swapon /dev/block/loop2 -if [ -e /sdcard/ANDROID/userscript.sh ] ; then - cp /sdcard/ANDROID/userscript.sh /data - /bin/chmod 777 /data/userscript.sh - /data/userscript.sh +#mkdir /cache + +#echo "Mapping file 'cache.img' to 'loop' device /dev/loop2" +#/bin/losetup /dev/block/loop2 /sdcard/ANDROID/cache.img +#[ $? -eq 0 ] || fail "Failed to find cache.img on SD Card" + +#echo "Mount '/dev/loop2' to /cache" +#/bin/mount -t ext2 /dev/block/loop2 /cache +#[ $? -eq 0 ] || fail "Failed to mount /cache" + + + +if [ -e /sdcard/ANDROID/bootscript.sh ] ; then + cp /sdcard/ANDROID/bootscript.sh /data + /bin/chmod 777 /data/bootscript.sh + /data/bootscript.sh fi -export LD_PRELOAD=/system/lib/libts.so:/system/lib/ts/pthres.so +dmesg > /sdcard/ANDROID/kernel.log -if [ -f /sdcard/ts ] ; then - echo "EXECUTE CALIBRATE TOUCHSCREEN!!!" - /bin/mkdir -m 0777 /data/system/tslib - /system/bin/ts_calibrate - /bin/rm /sdcard/ts -fi +#export LD_PRELOAD=/system/lib/libts.so:/system/lib/ts/pthres.so +#if [ -f /sdcard/ts ] ; then +# echo "EXECUTE CALIBRATE TOUCHSCREEN!!!" +# /bin/mkdir -m 0777 /data/system/tslib +# /system/bin/ts_calibrate +# /bin/rm /sdcard/ts +#fi #exec /bin/sh diff --git a/ramfs-android/init.rc b/ramfs-android/init.rc index cd21201f..d6245b0b 100755 --- a/ramfs-android/init.rc +++ b/ramfs-android/init.rc @@ -177,6 +177,8 @@ on boot hostname localhost domainname localdomain + alsa_ctl init + # set RLIMIT_NICE to allow priorities from 19 to -20 setrlimit 13 40 40 @@ -211,7 +213,7 @@ on boot setprop alsa.mixer.playback.speaker Master ### RIL - #setprop rild.libpath "/system/lib/libreference-ril.so" +# setprop rild.libpath "/system/lib/g900-ril.so" setprop rild.libpath "/system/lib/libhtcgeneric-ril.so" setprop rild.libargs "-d /dev/ttyS0" @@ -419,10 +421,6 @@ on property:init.svc.wpa_supplicant=stopped ### SOUND HACK!!!!!!!!! -service alsa-init /system/bin/alsa_ctl init - oneshot - user root - group root service alsa-set /system/bin/alsa_amixer sset "Master" "100,0" "on" oneshot diff --git a/ramfs-android/init_1 b/ramfs-android/init_1 index 0fd2a64e1101819556dfbf8881829cae1c1b2514..e1854c2fb2f4c4cb7bf5d5898b1089d979ca48a2 100755 GIT binary patch literal 107412 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

      ?$Cr@}+ia2+F;wM!+7|4BS$eauOVgsQ?@1Eo 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Πe_TtWpzb6) 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
      J!zm6bdbc(_DUsjm~>)oD&@A~~c# zqwaC19u9OhM;_4(PIIKG>k*A9_&w)Q@bQ!`PJ1vd2AVb`&gipD5808{1)l3o=JW)eC;6qDC~Ye78RW)KdEK90 z_Y*Htp7eX_;5t43{~N8{q|;iV#%oRuJQ^k$UxxBYo^#g$Z$E!^*fjoFsGgUY5x7$f&a_1QP8{p>w9=+*0zKpU*k>J1;W`kuMV3RLNDea2F29+ z@G55@JnD`1@W&VnlKU7R#1o;hMg3k6bP?7&-N!vNDZuyhL@BVl_|EG!L+3npr9Pql zHiVNS&Or}`56GMUSALj`e1VY*jOWH>v&@m1grxkdo{~5`!e)<9oi=$3%3a`XxedVU`B7EM1=L{HP;Q!NHC(Y4&KaHJ9 z-F48H??G=}LD z-k%o|I=Hu+^t$%t8wO^(gMWLIj$cOeb>tUjD3jWdD1p}So!SX3PFUpVf5=CS1MI#^ z)VIdRp^wQfI){7x_9EGXbPqb4?v2A(x%=+{OP%hu;9hHXG@fFv`*UfHM;>Lxymvu!}U( zZ$CYwye;|HMGSAxaozvcy)KOR4#Vq^HK4~p@&@F2T^G*ZQ`&X?f-y*=`t8S+mRK7emk)YJUlO+68-VCexXFp>4f z+w6bF|H3oEMm5M7(@NO23dXl45T0pfUo@FaT2sS1t$A)HW_Q2{1-7FuD{B4kRNf1mK6$u4J}dK=IB{a3R=zl48{xk6t&M~v&~6v7Z@b6S`uz{6%q zBe`neYBh@gff$^?yj|7Zp9knwALn79PY(4b8zixFV+8Mko;P+wz5_cKSeNK0ia)|o z*8kr!nS@w!z^?tpGEojNG+_e+?^hbt&7%(eWdlo7$8yxmMf*9}<)GIzL*AP_&uV{~ zC+T?EGHAIeKy$r#E-)<;UyJ(Jz#ge=)E>EIwf0tJ06Pa8V4DZRUm)Lj9iLI_V(lo8 zt&Y@k*fo!LftiT-OL8QEVrhYAEJ(-IPLELh9sEAc<33ljIsy#u^(1$gLiQEn7688# zhj(>3Ks-V*P;KZ_eaviVW9=a;#;9u?p5gmR!mcf^ZSJO+8V@+An**D>ze75x5#qC-+B_KFjh@w!@pu<9r)v~Gjh^~Q zF2>EH-=p>s_BycmftSrV#2@>&{<(mBsV>wv)JIYLwjeLe3r=%Q=tsg6t;M@Uo0Y4d zv(~NFSfCa8F6gQRZ_>LIr|_7e7v~fGgeuO*SO@q7^cjr>rTGi;O~&{Bary7Qa_PBE zYU|dZU*bFz4+A*&ka@kh#EcOyrIH@UX9_;4ok{pi2k!Btem<8$Yn9U?;8mS=ji?Xl zei{R$2OTg+9@=x<)7E_)WlA#^)gw<-RY%rlN{0QXtD()3y zJcy>@&!PNy?8-KoFqe1Xx!y03W2oQr<*cEj($k=0C%02xs4ISV<36s<7^7ZYf{Eml z?kT`e_oPLtq&AZc_|#;pQ~u?iHWQEUBn$9<8ooQGpx!7`A7c~RLEqyr&IWwn+Ebe4J=I1ct$Yt(x94p6Fh>OZ6*+{V(82Su(!7fbeDh94Np2q(dM`OrNhv*aX z$B1XR?+CJn$oqZwtbO+~k{cpN`tI3q53*Hou`Cf=VhZAq8nsms*|SQI zIm0Q08UO0ZM?V7=K6DSo-|mmu^z-MQlX1VIXB$o?p^nT0U4b!@F+L`=kK_`KSE3EH zgz=>{C9-Ww&<|$F5&As|vYvbzv>rrhtdRdi1B9zx`3>QOQ*7qSG*%l3L!W?N+3C1i z&=uZ=>-`I)4?p@DXb^EHNM9JWx(M~xfd8HuF;w=pfiP}c{`tSRfoXxRWaN*S1d&a* z!`6Ww5ZZz5jdm4B5F-d>G!EF^U5@eyH#{y7;Nt`Eoe=#6)~D6x?;c3FqMzpf7hSFBr7NN-IX}C* zw_dxuzaSn$nIyaV>E_D1uo_^aqdr6*qtOO4=?qGX-!ukq;$9ru(M&W0{-bzAdOQiF zfsgt06sZ~gQ`b#>b1TU%@FCTm;-TyPM7)l6aA*hejpvX~L7wnSo;Dy~DuZagf1E9- zE2X1;A|3{ho;E@TeMO^hWgZDo?7yGdnw>uDChQ1-%)os?V+qV5D-Z}Up-h7E; zFW~dbmpQf)T7t&oT|6VX_7?IsR0YBXXipYCIq+O6KTzX2U`BUtO6MShjGeUuZAgpx zl*14|Fj4?n_6q9u67n$F=D^1jKn&nHsOOxtXDPpxM3Zy6a`5Rwo`}WDOYj$(q_rCQ zEc`gxGk6XK{iXmW8;19%i8*FZy;$6i8^I-2#S&r~F z+^6@@f9ol>E5`;9%|kaphoOHs&l_FEp4#IiTMeFi$d`uh9q2ps>1kei13Idq8@3H- zVjjtjWBsxa>En%_H}yP%c)wXsQ>Bju(Z*{0hHZm+0Ah!tY`WK=r&*xe?q2Xx@9%kC zwwfhx6o4o67zLgH`DTu-t%1zK_tkmz8u2;N3)PA1+;qawS%1O^pD@QNDTc}jOI{uN zYaY$(j@eM2sWafTbq27uvp*J7fY&{=_vS8=H z4z7m{Sk+a4z98D7y3a!0i~g-W6?%K-b;&4~+C#sup?*W(UPb+>!cT&W#@6InqY-Vu zep^qvhja(!ZABlp=hYs^lJXagkdM^X+4#N&bzMDstyVx|rl8)?pXhV&K+6e=Kf@_S zu+!@!)NWw$J2>Ymt&wdcn(Ox9eX=vK)^wU^0`%Jgo7bW1yuNa6DA$u;d%PTJ7vA0* zr>_LxsXQvHpT3Q3Q##MB8LZPc>Q7}+84J->U_!Y3H!Ng8Sy=E@5kF}@x1vY zj`N&~rQmd)w)>8 zz*UE<8P{H1&*FL=R|r=a*VjFLd1%N3mlIbWu4%Yt8Tv|J>s9<7&&tjM z{2m_Ht$c>x8Nyr?b2!Aiu`i;=SN4+_bl-wG?*n?S%`?6Zj15wOy=wLWz0N!3C4>i5 zpueG?oq+map5N66eMTzo*!LXD#4w+oXr7VY2|D}dFHm=KT~pcFB!ueg(gd zwIP0sn7@0tiS@!9BoFI_3K@tsX`raUSt$dYJFxfBvgaJgI8-LP9rP)di~aR`C~ICN z#-$3UE2m%eo`>Kc)|`XiOaOo0G>nHT}BaqhudGOxvf-pqP1%?qf*Pcq6h4KnE4PK561(+)vT1Ch^B#2-f;aw{aKZ$;k89t&rF z)~b_pim)dzY(*~8oRTwa1wM5z2eyC@KK6{?KrVH|a*Tpp%=voB%{gx+ZSKHt!H4}6 z#dnU;$tdci?Bv}eL1&pUuh}ycyhl(D%BK!btUwv9Rl6y-aQF&kUu+*3@quj_b;26( zE!O7{_H2qQtY1(sq(AT+crcKueDe&CTW6N7kI8R4@?-h>n*2~tofq=$Q`WMl13rVc zHWKqb&h3ie%lJD;hq^`Buh~a)L8q@6ATRC9fiK9j@H>yF7yB;#U;)a+-y8V?_JK}D zS=_xmt||0ymtDRmXA$-`W3&VHyEAQK&IYBWlVcdi%QjhrbMV-n-GwckU9#mWo^5t{ z9NZSxwiPX1-$y+>g5NR1KJckHXJ$If@||3EPRmKBPH#Esq?Id98rqDx*8G-}`oZoC z1pWCVz0S$QJdATOPY2c)cy z*!!(EoEWwH2o~I=P?2 z^dZ)Zb#HFz8iAX(N;>xyCgK_Q_HxT_>1rw{fR5&CJ(l5bV^MFdN4z6~dShNwmfIBQ z%x`eIhHip9$m|a})sVq(o-5zc^m9QkM!5@CujsljUG4>1zSEp;r(En4s&YH4%L*Ky zYA4FQ80pz&>2^Z7NoTnSq|1%=>esK6zpJI%%aoh#MHW+nFi>Tm8U!|!mPhx(p8Y^AbGmVv*o zd#Wj4zFY5%^6mXl>-9doO$9%Xv#V)#C zm)x>oX909Gd>iJ%1t{bGZCx_+*If_fc{^{s2lSlZ)1qyEIp{;nTe=EcS9aY)9|HN@_oTl1w|uwLQ{~$JSCIFN zvHe?aEh{uWgtG5NdfH~*O!Q~muG~7%3tLxpHRb2yJmD+KCY3znLrA0U`z&y}eyMy2 z&cRTx9LV&*hg^yD(t$OCsbAmNVxf-VHw#fmRTvR>H5a*P1lz+Ro~b*%lfulhqFMP{uJ;1M*Pc{*)IBboL22UFWx=9FWDmpBYS#aDTVFO`1Lsbhb~wW|p_F zDsNw$uc-EEx-VT`(o}hyZYk>*t5<7M$}Kf=)9qvA9{T{ksu}I0eBIT$eJIbgPXXnb z_JOZ}&zR5mx^6usN}qA1@)zS9pR~&+@?_$4{ z#^O<5X<}KTbg>2NCBA4R5e?bBXkiq(7a?KCgWgai+KX80P1v;%)r;u!#^XUd-iyY3LQ${(IC8)( zT|8Q%TPC9lVSgwXv1QV@i&?*kmXG?cskf6rri zsGK6HP)H_SU}{85wi5|f!|O|;J+0yxgeEA|2VaW|}GU zp%u5UPX*(4!ZJpfA4@Vvv{fsa zES#x$JQa!1ZqaT0c5SM@9%`{A?FPL5+N{QJchOBTR-FU9GF7*bJR94(hrr?}mf=Y9v zER-pkN>FuW81wvNhP_hsR5CdqKDE+OQfTz27v38NCh8|=v!jK5Tu zGlsDxqrez&mXL&mNR)1RS_R9Xofi6A2$`2EV~YDspg2*2u5|8i4*S&Okg+V% zs6{nkG3*XW2)iSZVKD;`VwvMk+#MIwHp{}(_~OY_Obsh=dgf%Af5o)kB-l|kb0UIxIGFHZMpIv-X$To^xNo$m*YAfNhGCyFdW^EY;zTJPQK$4o#R; zj<#x3brZFhRNA<~jz@Kw>o`y>9UbRZ6i(XbAuG9%tZAZ(ilwHRwKMNu-S z!obpTexvlo^$8=~AN1C17KUoP@$f}DYRX&#_xmYAjU7=wT8T!XX3w8(rj>}yoNvOI zw4s?y;t(Y3pj#9ZwY{cHXmQODOV@xQ6d)1ndC=Q1k{2b*#*8yrEDo1nbm0XxelJ=! z(wpXW?cA%F#${m|SCeL{4SUB-FqQCy$6Zi1wzsrcU7azuP_RCbOxT!lX6QNQ3)e*5 zinF#P1Wk$DxG!lMfCSjA&Vi9|%&kz$AG9MryT&`FZ0rS^AsO?IEgMtrht;z4kl&l~ z$1o+%j0dANY59SqZ?xAJ#WW&l6urc6o6z+az>H0p{U)tx6EV3k77jMJwv-6_jdD2o zuHo=yvcEozkMyuy2)HcappgQa(PJ`EcHx+^aLQP9EN0p_nTpT>qWiJ4m9h_VrWdp0 z%I-6xr6ox_9P1gGuTTcbnZ;6!UABcZiC`j$PRcP%N#H{!Qe%RJ8G#*-N22I^nIn9U z9E_N7L0JWHP@w<_2jU=<)Gep%^obrb>!Bu*VnSo{3g)ay{YUv3GRwJCKXHLM8 zc?|_k#3UmzI_yniGR`R%=LMW!Ff}Kke$1I-D8G&r3T!_^`8`s48W)Y{P7T3qT~nO6 z*23ym$-;zfVlSKM5dh7jBwTk|emfGxoQ;W)zeQV_NMq0nQ^kha2JM8hjCdGEQl_n> zJ{C{t5DgzgLW$HT!X;_5iDL|ks#N|+g0q|w!3>#Gt`Z3>Es>=mZ=^*00bi^{mc$t3 zq`8E{U5S`lmB4G4#5uaV#)xwDWZ`o4Jhgo(^qXZ6mI}u>Rn1tc_N)Yy`I+Y8lu!>` z>8VB!V=97$&0;Hxh33D*&XFn$qdTXbj$VVt&E&9_29q#`sGqCh=&(^-6U7nqBd8{~ zDqJYFp_Gl4UNRtXlTa&^Bv??!I9e|a)&-RwB^W`KG2Di241$sf*a-W)z5sST>|{-C z5@Qgixh5hBKc-^-n)p(xU$DT%${P+C%lo8aiF=nSG>M|MQNJ0sYibt5elf9rDI+;AY&!C6@+TsM4@uJojh_Dk(w0dNK!`Ms0QmfH`7oFCtMRH;8rHkd_ zu@E{~;tgTJV-jc{S_&T3N1!FYUQMAxvCt zE@9$mmJg!03woEx)TyxNp?8^D$EgzA4H&7oBY>`&#PCok*U;PH-?cpj&)jT)oOpdI zj4^~dg2OS3d-QkqbT#EOUaRM!7dtyJF8TvV)yrjiwg@cLTW?Qvm(Y{q$>p{7@}NIt zUu;b>jAf%Qytq)f#Aau-pv#o4b&eeXO!Mk(tIQg0T?o5|y&-944p8I2%0kQ5eM7t2 z%tC8A7ty^qygr|eMV94FqOV~i0##3>VzCn4$Djmm@1PSVKCOpj$o3)y_AS)18ca}G zdQYj>{tyMgbD~uuOFkt?jlwiDt&Mb(Ac0!AW=$~4N-m4pSS-U~bBjc`Vmb*Qru8~Z zZF~%~u>K#GNW#^GVXexYd|FM4Of9*FZdkO@`n)lGHa>)=6JG#BD*jhKSXo4kT7zk; zK^P;cyUG^56NDW*Zk^!2STvs0?I6LrRE+Kko=$>c^}toRgcmapD46>~MtuY@5ZL#L z@lY^~HLmF#7@)%R%^awFp~cA?R8>XIn$SKm79Cq0_@7zAU4}5ohK!x*$z6IKS65rs z<0j1Rj~XJhI(C12toytF)OTjsrMdVC_}u5jb3W-wvku|UyInb-ho3;!kN%-$yO^0~ zi^-R?SC00SJ(DMs{`zO|Wb(V=4ufp?x=Uxsz-sH^;e^%O?!N;4=pTZwfRP^mu_lp@}m*!#zo>g{h-iv|rO!!pk z?jG`Q+^(F@!%oOr>(S+LF*D7Tc<#nW<@SVK8gVsVU~%Iu|DsMVkBc3U{kF-UdGlUq zXtgHa>kKl@MCAWA?i&p4OUTzj_@0dX{e5&hff{G{ZD?g>zWJyJGTnM$*@zDLOc` zLgUpME55C9^)ni;JEG88RWem@Z9mzkaMd5~RcOET649z@$(aV+zhvfx#0S@$5e8Q5 zTU+)Zu<1)%H@^-Xf8Ga+2TaGG{9U;0nW@vIW#>&-jbAcdw#}&z|EhhuOulo`-UVIL zD{gd${$rb3dGQ(d35@SN`+FACA5M-rHX;cCp}T;rZJNVP>3@EyI{oC)lAvxnYg?Hr3}?)=BvDwo_!F43bmjG#L!to*`evm#5B@ zFUeVA$=QM*DV3p8Ecnc_43`o30QdPaN=8eGluDV5k+CvP#>)h`KrWPWxkx6;mt~Sn zmWySIRESq<#U~gcrB3PvpRkwfWU*kzE)j|1SGlj3xL^ZWQnEyrN`owu8{``NLie@u zRs2HHqW`P(Uz6pqk8en$IC7(`kd?AZZjzhjo3dJNkz3_9xn1s%Z^^gu)t)=$F1cIQ z$amx({2*(y+$Z?)QCTbZ%LDR#X^|hugYuB9lOM{DD7 z%iHpf9FlkCJ$YXa%LnqId?ZKYWBEk>AxGt(a!k*%BU|Pl_PdIceLgJ~ITG*;x77M#4p){Y~JLaquyUbYi z;9%X%W33Q&w$h6^nSn{8h0`nSk8n#1JCW0HFs2F+Nrh|eI7O;MAon=OPDnKlX1w)y zH$diQuC(x(q2qQqlrXmh(|Bl&b(=aQG3z0}RO&cNieg4naU7u3rV`8K5^j^>&?tfR z)AV>Wkr-`Ks`;m@DNREelUPXhsB0D$9hp(Huyp70T6mJX&=!xG>O#?_Qtck;s!1p{ zkT7yN;a5}KxKv{usI}8mNVPDAXj^GNhW$({WY=-=Vk#@MaK>Jb1F?i{FP3>YV;UWe zgqCSJddsILcUCVU)8f&^ICP5zW46rpVza_6x@Fe3`rQn!a_dsqgjGCHAl{)+HWjzA ztBb8=RYzoLH0wv+suh;1wN%uHjT@~DwNP@G_^b$z+~R($_#v+uPeVcnRxRA9 z-U^+kD(^aCI8$!Lz?8k({d1QjL4OsoZ9g(h;6xS>3f9KGIRBlh9`jHdn?upG&+pAt z0&b{8_e^B&Euou8v&&Si5K6(Z13Mv$$O@~MSbAm2U1yYy73GcsZKqde#;=B!rQKTX zGVI4CXwEoq`mCV|Qk2i(UX(t>hYsc|t4t_AXPPJNGq_ulkooR5jXPpe>(R()y?p~4 z$H`Pg+lCouAYN^?`DM28E2?3!bJ=4rOW_)z3U1`Et&Om>IkE0N9l95p8(7$2VcB)b zln^H9dD44$Pt#SWfvZYT0DPc77R9>`J%y^nD>)byddr%shi{y{fBK1wU zYMi&cA#`;AGPW-?=(Z#_6|se?R0EB{yxc)~j_$$iq<-$)WW-b0E=8|bZr>&2O}SVM z$#LQzG3Hil`@G1B-dlUr`O&&0&%7}s0lgQmx0ahz(|Z!D6sjJ!o@(GkyAJ*+p@z|( zHmLrT-dJL{uBJ3-lQTZd5y+u6sr3amAiR0>JkW86l;XyMr7HrrJR zZbn1LJ@w&1i=V?%CJ`yA2${)E(6pj4#DdRehvX}m8IwY{T4+KvZ#{IB$aso(h}gL4 zC-ZUmU|VzG=+vwY-i2Gc=viiDqFcc`W!O+v?@7&}ZCeXw%$c=7ZLsUHR;A_WpdTdc zFy6huj(g_NKTA0&IKj*$#<|TZooo8<<*6vf7mRkwo9W@*A54YO(fF3dRjTLls01YC zR(pC28pdbiZA8phbPwjs-vGQO|`P7PZNuDKo35*UX!B zncg(zD=2&ywrTB>hA?hHOtH(AwSY$K8@~ zw;|kN;!gsf!c8O(!`bdFp!0V5LI`K_GaSQxd|Kv}#J$zrltJFlx}V3h8*u*)_YT}F zCut1xW;)8?olOSmEQ9-uao%p+t@k%TV;(DTQ*I^?d09`lu5Q}T!_`RhE!=Bxe-}6U zGv@((6@Rc1Jc^jt;%Zif6! z9-Y^EmDdXLc-AYKI;_jD!fstMf19&KVXL#1i021^?fLgQ$#0P_$7vy=e60pI8{BSi zhryl1_ClxX+nT=`D64Xu7~`OC0e1egyYWbqj!(MlSmQ3nfvo4KyP2-dX#i3$1J;l) z&sj$VeZRt1XYh9n9}(r-25f;GxmU**62b2%Y<1QudY&WAd_L4k0^6sQIOX5dd`TkY z3|Xu5Z2&U;R$}{k&ddjhqnv>ck>2WzBDNPe%?fjzhINdi9107Zzz-SEb2cmdlC$CA zV~qn)zE~^hZMn|S^+3q?0|oT)Z94rHBIr8}j%p`8&uJ!tew2vzso21Hhf@utp4Kvs z{N=}_Lq7`JoSDE4N4pz~9^vymXVRmZ?;sKS&g(eV*o^1pkLh?TuzgCNvuUH|8~hU> z@=Ypibyh3vaMm1$YfZd`hYeBSCb z8Qi3>&DjBDJ&zdr;7yvZjM!e}90cYlICl9 z`B-D@BS|41xy4*i8#=xqNh z`CFa+z;T!5!dA!nr%pdqVTV&`&~I>+ z!F2|=8r*9z?-Z!(hYg2*A7p&l3SFcF<`J2 zNWKNRphF*96c#$6K03ZlVV<)lpYZ{X6cF>BP(L8_v6cw`GP6*}mlN@PXn$gkvtOa* zG@q{HgU=uz{5`RKuv1Y?Ji$3Kj9B0ljL`8dBZ1JvPKE7`bw1-59~8Db4GPiz3Ok%; z6W?Isk1K3*wj26>BFa-WO4s*sAj`2!;deeB@G^so3?>zJI587NodypX zEEsR(5y3yx#1|239LJhKdWSPyA;uAfKX77(zRqBW!N(15Hn`Q`iw5@_Jail$HSw|w zbbgZzE-<)AVTD% z;RJ|}<~vnWNN;mm6+YrTUcvYyPQ^5X(}^3LH9(H{+f}^7d69^G7gq8)?E7Eh2B&C- z=HE+vw7{vH$#ff>qr^uGo#dsAqZ|rR-plm!irL+bkHSBd&C$~MwvS+C1f9P0{$c~|p!t25qU zgTd8A)cc@`SA9kEB@MRp!Zv4@inloh*O0HxsURYKtHGfQHN8P0#z7+Lx8qu3zB7K2 z<_{?x;_OwJ=Tv){uGR4?Y;!7Wb$q75kis^n*~B*yk#Cugd~MDVBJ%0*6APVYo0#u3 z)$w_&vxW$Msn_}`0Mb9NB|>j4CO#n0-I#nAz7N;{+yq<>91zs$8;ERIg_w^T+@=uz z-Qa$MMb|MM=JQ0PD_gAP3=HY`LWQl4LX6ujVbWWjbws4w9MN%w@TUu-q~|+MoLJ~= zP3ri924aD;a224e4T_`whySTHauT zWd<9FXvYqP4><*QG2ZG7Ahz{!I*6_PoK7I;2W5Bb=Q9eVv^KM}0@9+p4h5DY~b-G4KxNl|X6l9>z8#R4X7HmE7F=wZt6Is541`h)t z!SleA-HqgH0d_o^=M4Ng{2|JRtp0QTM+5)Sz<)IG9}WC})BwK0u3pb04jQAj)A7D$ z5AE}cQu{p8G*ixE3fi<#Ufw(la{>#bPMrY`8?yQdc`B_!9!{T zzJ5+wO+cO?v;iseDInjw{qMsbyq^r&i1YB^AP`we?g0 z1AYNm1v~**3p^1R0rJ>w6%gM=l(j&7pHNzXrvRS<;#-XJ91!2Dl{bL+Ed|*RJPr6U za4_%-Z+X-^!Dj>UEkqd${338F5Z~&TDj>eoC;{M?fGOZvz}tWp@VmgXfjPq3BVNa0$>yHLf`{Hd|Oi<2I9NIvKjbg;B!Fy zHiG;Gi0=-|dq5s^=DqE~ySVrv3t$ECeBe~zEZ{U?4RAUz2CM|$44eVH2Y3l^9q_+^ zTYxixF9Y#yVA&1)Z{P>OOMwON;CuSO65wp$EZ`hq9T4BDlCJ}+fa`#l1D^xpJ67^0 za6a(#LmsIHP61v4yaI@CJ0T%*KeAk2bhegf< zeib+wSOdHYxCnR?&v+ERi#c)#ScT{NfwO|}HA8dc&ycmi%8^N+=bf1& zmmz%l@161<6Yym?)cg?5FZy$>GVyy~*h zz5$v8c?ZD5o7ZhwX!n}5v?Z7CA8e7$%1NINqNtuzbmqAau-S!naJ&=zH( zML}a*X7<5lpgn19!`106S@`bCLR*`K_Mkp2gJ$Y?2e2lv^{iOH* z^wqo{dc%|MzmH~wf0hycRYv$X8Q~W)!f#}RSN%bcJIt{QbXO;T%Lu=d5gzf!9-a#_ z!tZDBe0*H^LsQ@G3_8PZo%0}PJ14cc`e%fTGQwwPIBt^-B;x44eb}09XxVoxcM7J#Z@cUI8vb{AZZJhk;K4lfaL_{|zAZ zwF3At@HXJj@w^GR8Q2Vb8h9Ff-wDI;hjWOZ2s}6>N8N{kypNiD+wXP#se?QIs>7Z< z$U*r2)gn1L&;i1Cn(%7K&`S&3_$mDyFX}_uI?`NbvitxUhHJ$BKd=uv5 zkbeweRW?9QXHPlb+0_$%7vbVnI_<&3J^Y1+KNos93E{tk#{-#z5xx&$mfu1+j4<;m zz`R!F1^#xFX9noh?N1Rt$%IFO|6NnZu?X)o;fV-8VZ!)z`m~&x2wx96^O}ROcZCkm zN4TE}UybmyH)?tf!s`)czP~=;kvAOtEhoYO(A~0G$6aN|Uwbh>{~PAenAdF?h{U+K zZfqE)!-|0aP|aQ!=a8H?at_J4DCdb=Fi-s7Tm_=b>84qiMdpkDOPPggwe3oT|IH$E z=f5Gd66tawhV@jX#G;z(?)xL2^q#_mm=3S|0BcGU-iYwj;b8RI`22x*xHj%Hp?Zeo z=M{MRc}~t7=o#cWEqAczbPqg#3I7~J@NpWAi2(jm1%KltB~$0kF2UbsF~~u#Dlf`&Y+a=J4Jw6yi#3KkH4J3m!KN(zfKn(Lv?d@`M73d8Q6AG1gTAWKZQ|VEdg_V(k4bow$K?wQ%8|f#JYr$Ia4%Q%Oc1DZmTxuIb*o#@=ZCvoJ^g!( f=HZfBUE~|#Mu5zVm#Y&U!+W&gyVZ>VUB3SV+9S=X literal 106576 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�jL5dmbY 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%0A3++glt*0;}1aW=4 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 Ss9CQ#dN(_x{a@3h*Z%?KQt_(* diff --git a/ramfs-android/sbin/adbd b/ramfs-android/sbin/adbd index 539b231af33840a82eda91a3d642bb511707b69c..58b85849c35d042a5b4233a1682f6aa906012c32 100755 GIT binary patch literal 138352 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%0D*&$S!99r5$B*JadDG*W7hOr1N5Ci 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

      +UjOK-5la|Kf)bjmr1wTFoit1*oJNTkc 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 z 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

      7$>?YyYfSchU@F0{W*%nN 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

    ?G*2A{m_LuFZy>!G_^d?Ge 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¥5V|{a@~-sIyLmvf&HppLAQj*MIspdY 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�@fjgtGP@eD5mr~yf zXih40qwi{FyX#}WY!}q&%@U+BYXs^B9tsXgjY+jiKa&2R2w990DLLw=Vq(RrII-HO z#D{#3&HpmXoP?9PqCYFm7j+|XbYFS)zk+BoL7Fc zG_pM6@}rKQSH#4Aq#Qy*Jec@2;UZ%Y%TdV4!wWncblLk_-$;9+ZT{b&^LtFpgl(wc zoMSj4_9K&x%QhYfin+7#tnjY#y5u4aC2{*}q>&`Ob2ua^oB8oc8Dn%=^_y|AF*=rd zH!(BeGNz$()VHS!r(Cv=rl&sJ+w9%qmApcB_YEBAT~##HvJ zn#Ug)anC6M&KKSjzf$V^A6I2Q6FKh=%wp2PE2HR&PsYwI>UqAgbJQ=T`lVd%yVlW` zh1P^zWXy57GEwWfV9%iWzli?MEs8IXyA-MKY+-A1ThgT@Md@Kyyo}3fKO6`I~h~8jaAWC-S>d6gU{oS z`Y-yufv18?qWhyKq8Fm~#cISJjCF}U6T3H2Gx1#Fg~Yf-fn>4NeW~W@j_K{`ed(j= z-_wE2oSAtu%VbtkDa`*3+jQrXyTO;AdE^|9>by%lDz;PSl(q%McIq!h=aAS=avJj1 zeG-`zaoMTAg?A;&CS1nr_-#r^Y`p&NJrQ|2;xdrBXL;(6dfb|~zjp_+U)fWWPz!Pv z4l#uL9rM07q@;! zlMI*fyy3E+OF^+}ddmw_V)Z>C^))__{62jk{Zrb?3}@!b%$NDk{4#H+Y?H~|urfLi z_eM