aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch
diff options
context:
space:
mode:
authorKoen Kooi <koen@openembedded.org>2009-09-13 16:30:10 +0200
committerKoen Kooi <koen@openembedded.org>2009-09-15 19:26:15 +0200
commitd861047e32eacf91974108a5eeba1f847bad5b9f (patch)
treeac07eaf5fe935b4f58aae20528f3cf101b712549 /recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch
parent72c1fd8a2b6ab59a28467c033ec7fa18cfb67225 (diff)
downloadopenembedded-d861047e32eacf91974108a5eeba1f847bad5b9f.tar.gz
linux-omap 2.6.29: add support for the omap3-touchbook
Diffstat (limited to 'recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch')
-rw-r--r--recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch66715
1 files changed, 66715 insertions, 0 deletions
diff --git a/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch
new file mode 100644
index 0000000000..621ae93d3b
--- /dev/null
+++ b/recipes/linux/linux-omap-2.6.29/omap3-touchbook/dspbridge.patch
@@ -0,0 +1,66715 @@
+From ea83ad971e877ef8e9b1304f2678469c2fc74c67 Mon Sep 17 00:00:00 2001
+From: Tim Yamin <plasm@roo.me.uk>
+Date: Sun, 26 Apr 2009 18:58:30 -0700
+Subject: [PATCH] Merge in tidspbridge from git://gitorious.org/tidspbridge/mainline.git
+ revisions fe30e75..20f5ca.
+
+Made a few changes so this compiles clean against a 2.6.29 non-PM
+tree.
+
+Signed-off-by: Tim Yamin <plasm@roo.me.uk>
+---
+ Documentation/tidspbridge/README | 70 +
+ arch/arm/Kconfig | 2 +
+ arch/arm/mach-omap2/Makefile | 2 +
+ arch/arm/mach-omap2/dspbridge.c | 74 +
+ arch/arm/mach-omap2/io.c | 3 +
+ arch/arm/plat-omap/devices.c | 28 +
+ arch/arm/plat-omap/include/dspbridge/_chnl_sm.h | 212 ++
+ arch/arm/plat-omap/include/dspbridge/_dcd.h | 187 +
+ arch/arm/plat-omap/include/dspbridge/brddefs.h | 54 +
+ arch/arm/plat-omap/include/dspbridge/cfg.h | 339 ++
+ arch/arm/plat-omap/include/dspbridge/cfgdefs.h | 126 +
+ arch/arm/plat-omap/include/dspbridge/chnl.h | 170 +
+ arch/arm/plat-omap/include/dspbridge/chnl_sm.h | 168 +
+ arch/arm/plat-omap/include/dspbridge/chnldefs.h | 92 +
+ arch/arm/plat-omap/include/dspbridge/chnlpriv.h | 136 +
+ arch/arm/plat-omap/include/dspbridge/clk.h | 155 +
+ arch/arm/plat-omap/include/dspbridge/cmm.h | 420 +++
+ arch/arm/plat-omap/include/dspbridge/cmmdefs.h | 135 +
+ arch/arm/plat-omap/include/dspbridge/cod.h | 433 +++
+ arch/arm/plat-omap/include/dspbridge/csl.h | 135 +
+ arch/arm/plat-omap/include/dspbridge/dbc.h | 66 +
+ arch/arm/plat-omap/include/dspbridge/dbdcd.h | 388 +++
+ arch/arm/plat-omap/include/dspbridge/dbdcddef.h | 94 +
+ arch/arm/plat-omap/include/dspbridge/dbdefs.h | 580 ++++
+ arch/arm/plat-omap/include/dspbridge/dbg.h | 110 +
+ arch/arm/plat-omap/include/dspbridge/dbl.h | 354 ++
+ arch/arm/plat-omap/include/dspbridge/dbldefs.h | 155 +
+ arch/arm/plat-omap/include/dspbridge/dbll.h | 70 +
+ arch/arm/plat-omap/include/dspbridge/dblldefs.h | 509 +++
+ arch/arm/plat-omap/include/dspbridge/dbof.h | 117 +
+ arch/arm/plat-omap/include/dspbridge/dbreg.h | 113 +
+ arch/arm/plat-omap/include/dspbridge/dbtype.h | 103 +
+ arch/arm/plat-omap/include/dspbridge/dehdefs.h | 42 +
+ arch/arm/plat-omap/include/dspbridge/dev.h | 785 +++++
+ arch/arm/plat-omap/include/dspbridge/devdefs.h | 35 +
+ arch/arm/plat-omap/include/dspbridge/disp.h | 236 ++
+ arch/arm/plat-omap/include/dspbridge/dispdefs.h | 45 +
+ arch/arm/plat-omap/include/dspbridge/dmm.h | 85 +
+ arch/arm/plat-omap/include/dspbridge/dpc.h | 167 +
+ arch/arm/plat-omap/include/dspbridge/drv.h | 449 +++
+ arch/arm/plat-omap/include/dspbridge/drvdefs.h | 34 +
+ arch/arm/plat-omap/include/dspbridge/dspdrv.h | 106 +
+ .../plat-omap/include/dspbridge/dynamic_loader.h | 505 +++
+ arch/arm/plat-omap/include/dspbridge/errbase.h | 509 +++
+ arch/arm/plat-omap/include/dspbridge/gb.h | 85 +
+ arch/arm/plat-omap/include/dspbridge/getsection.h | 118 +
+ arch/arm/plat-omap/include/dspbridge/gh.h | 37 +
+ arch/arm/plat-omap/include/dspbridge/gs.h | 64 +
+ arch/arm/plat-omap/include/dspbridge/gt.h | 315 ++
+ arch/arm/plat-omap/include/dspbridge/host_os.h | 96 +
+ arch/arm/plat-omap/include/dspbridge/io.h | 132 +
+ arch/arm/plat-omap/include/dspbridge/io_sm.h | 335 ++
+ arch/arm/plat-omap/include/dspbridge/iodefs.h | 45 +
+ arch/arm/plat-omap/include/dspbridge/kfile.h | 216 ++
+ arch/arm/plat-omap/include/dspbridge/ldr.h | 51 +
+ arch/arm/plat-omap/include/dspbridge/list.h | 296 ++
+ arch/arm/plat-omap/include/dspbridge/mbx_sh.h | 213 ++
+ arch/arm/plat-omap/include/dspbridge/mem.h | 340 ++
+ arch/arm/plat-omap/include/dspbridge/memdefs.h | 52 +
+ arch/arm/plat-omap/include/dspbridge/mgr.h | 234 ++
+ arch/arm/plat-omap/include/dspbridge/mgrpriv.h | 55 +
+ arch/arm/plat-omap/include/dspbridge/msg.h | 106 +
+ arch/arm/plat-omap/include/dspbridge/msgdefs.h | 43 +
+ arch/arm/plat-omap/include/dspbridge/nldr.h | 81 +
+ arch/arm/plat-omap/include/dspbridge/nldrdefs.h | 307 ++
+ arch/arm/plat-omap/include/dspbridge/node.h | 619 ++++
+ arch/arm/plat-omap/include/dspbridge/nodedefs.h | 40 +
+ arch/arm/plat-omap/include/dspbridge/nodepriv.h | 202 ++
+ arch/arm/plat-omap/include/dspbridge/ntfy.h | 146 +
+ arch/arm/plat-omap/include/dspbridge/proc.h | 648 ++++
+ arch/arm/plat-omap/include/dspbridge/procpriv.h | 35 +
+ arch/arm/plat-omap/include/dspbridge/pwr.h | 129 +
+ arch/arm/plat-omap/include/dspbridge/pwr_sh.h | 41 +
+ arch/arm/plat-omap/include/dspbridge/reg.h | 257 ++
+ .../plat-omap/include/dspbridge/resourcecleanup.h | 88 +
+ arch/arm/plat-omap/include/dspbridge/rmm.h | 199 ++
+ arch/arm/plat-omap/include/dspbridge/rms_sh.h | 125 +
+ arch/arm/plat-omap/include/dspbridge/rmstypes.h | 40 +
+ arch/arm/plat-omap/include/dspbridge/services.h | 63 +
+ arch/arm/plat-omap/include/dspbridge/std.h | 143 +
+ arch/arm/plat-omap/include/dspbridge/strm.h | 441 +++
+ arch/arm/plat-omap/include/dspbridge/strmdefs.h | 57 +
+ arch/arm/plat-omap/include/dspbridge/sync.h | 340 ++
+ arch/arm/plat-omap/include/dspbridge/util.h | 122 +
+ arch/arm/plat-omap/include/dspbridge/utildefs.h | 51 +
+ arch/arm/plat-omap/include/dspbridge/uuidutil.h | 74 +
+ arch/arm/plat-omap/include/dspbridge/wcd.h | 61 +
+ arch/arm/plat-omap/include/dspbridge/wcdioctl.h | 519 +++
+ arch/arm/plat-omap/include/dspbridge/wmd.h | 1193 +++++++
+ arch/arm/plat-omap/include/dspbridge/wmdchnl.h | 90 +
+ arch/arm/plat-omap/include/dspbridge/wmddeh.h | 64 +
+ arch/arm/plat-omap/include/dspbridge/wmdio.h | 53 +
+ arch/arm/plat-omap/include/dspbridge/wmdioctl.h | 91 +
+ arch/arm/plat-omap/include/dspbridge/wmdmsg.h | 70 +
+ drivers/Makefile | 1 +
+ drivers/dsp/bridge/Kbuild | 39 +
+ drivers/dsp/bridge/Kconfig | 36 +
+ drivers/dsp/bridge/dynload/cload.c | 1854 ++++++++++
+ drivers/dsp/bridge/dynload/dlclasses_hdr.h | 41 +
+ drivers/dsp/bridge/dynload/dload_internal.h | 237 ++
+ drivers/dsp/bridge/dynload/doff.h | 347 ++
+ drivers/dsp/bridge/dynload/getsection.c | 412 +++
+ drivers/dsp/bridge/dynload/header.h | 59 +
+ drivers/dsp/bridge/dynload/module_list.h | 161 +
+ drivers/dsp/bridge/dynload/params.h | 231 ++
+ drivers/dsp/bridge/dynload/reloc.c | 425 +++
+ drivers/dsp/bridge/dynload/reloc_table.h | 102 +
+ drivers/dsp/bridge/dynload/reloc_table_c6000.c | 258 ++
+ drivers/dsp/bridge/gen/_gt_para.c | 107 +
+ drivers/dsp/bridge/gen/gb.c | 182 +
+ drivers/dsp/bridge/gen/gh.c | 191 ++
+ drivers/dsp/bridge/gen/gs.c | 108 +
+ drivers/dsp/bridge/gen/gt.c | 348 ++
+ drivers/dsp/bridge/gen/uuidutil.c | 238 ++
+ drivers/dsp/bridge/hw/EasiGlobal.h | 42 +
+ drivers/dsp/bridge/hw/GlobalTypes.h | 325 ++
+ drivers/dsp/bridge/hw/IPIAccInt.h | 41 +
+ drivers/dsp/bridge/hw/IVA2RegAcM.h | 28 +
+ drivers/dsp/bridge/hw/MLBAccInt.h | 132 +
+ drivers/dsp/bridge/hw/MLBRegAcM.h | 200 ++
+ drivers/dsp/bridge/hw/MMUAccInt.h | 76 +
+ drivers/dsp/bridge/hw/MMURegAcM.h | 253 ++
+ drivers/dsp/bridge/hw/PRCMAccInt.h | 300 ++
+ drivers/dsp/bridge/hw/PRCMRegAcM.h | 669 ++++
+ drivers/dsp/bridge/hw/hw_defs.h | 73 +
+ drivers/dsp/bridge/hw/hw_dspssC64P.c | 55 +
+ drivers/dsp/bridge/hw/hw_dspssC64P.h | 48 +
+ drivers/dsp/bridge/hw/hw_mbox.c | 244 ++
+ drivers/dsp/bridge/hw/hw_mbox.h | 323 ++
+ drivers/dsp/bridge/hw/hw_mmu.c | 598 ++++
+ drivers/dsp/bridge/hw/hw_mmu.h | 177 +
+ drivers/dsp/bridge/hw/hw_prcm.c | 167 +
+ drivers/dsp/bridge/hw/hw_prcm.h | 168 +
+ drivers/dsp/bridge/pmgr/chnl.c | 260 ++
+ drivers/dsp/bridge/pmgr/chnlobj.h | 71 +
+ drivers/dsp/bridge/pmgr/cmm.c | 1291 +++++++
+ drivers/dsp/bridge/pmgr/cod.c | 683 ++++
+ drivers/dsp/bridge/pmgr/dbl.c | 1385 ++++++++
+ drivers/dsp/bridge/pmgr/dbll.c | 1564 +++++++++
+ drivers/dsp/bridge/pmgr/dev.c | 1476 ++++++++
+ drivers/dsp/bridge/pmgr/dmm.c | 692 ++++
+ drivers/dsp/bridge/pmgr/io.c | 205 ++
+ drivers/dsp/bridge/pmgr/ioobj.h | 52 +
+ drivers/dsp/bridge/pmgr/msg.c | 173 +
+ drivers/dsp/bridge/pmgr/msgobj.h | 52 +
+ drivers/dsp/bridge/pmgr/wcd.c | 1647 +++++++++
+ drivers/dsp/bridge/rmgr/dbdcd.c | 1573 +++++++++
+ drivers/dsp/bridge/rmgr/disp.c | 916 +++++
+ drivers/dsp/bridge/rmgr/drv.c | 1893 +++++++++++
+ drivers/dsp/bridge/rmgr/drv_interface.c | 777 +++++
+ drivers/dsp/bridge/rmgr/drv_interface.h | 40 +
+ drivers/dsp/bridge/rmgr/dspdrv.c | 276 ++
+ drivers/dsp/bridge/rmgr/mgr.c | 491 +++
+ drivers/dsp/bridge/rmgr/nldr.c | 1967 +++++++++++
+ drivers/dsp/bridge/rmgr/node.c | 3544 ++++++++++++++++++++
+ drivers/dsp/bridge/rmgr/proc.c | 1985 +++++++++++
+ drivers/dsp/bridge/rmgr/pwr.c | 184 +
+ drivers/dsp/bridge/rmgr/rmm.c | 604 ++++
+ drivers/dsp/bridge/rmgr/strm.c | 1066 ++++++
+ drivers/dsp/bridge/services/cfg.c | 483 +++
+ drivers/dsp/bridge/services/clk.c | 375 +++
+ drivers/dsp/bridge/services/csl.c | 173 +
+ drivers/dsp/bridge/services/dbg.c | 119 +
+ drivers/dsp/bridge/services/dpc.c | 274 ++
+ drivers/dsp/bridge/services/kfile.c | 338 ++
+ drivers/dsp/bridge/services/list.c | 285 ++
+ drivers/dsp/bridge/services/mem.c | 599 ++++
+ drivers/dsp/bridge/services/ntfy.c | 329 ++
+ drivers/dsp/bridge/services/reg.c | 196 ++
+ drivers/dsp/bridge/services/regsup.c | 368 ++
+ drivers/dsp/bridge/services/regsup.h | 58 +
+ drivers/dsp/bridge/services/services.c | 193 ++
+ drivers/dsp/bridge/services/sync.c | 602 ++++
+ drivers/dsp/bridge/wmd/_cmm.h | 59 +
+ drivers/dsp/bridge/wmd/_deh.h | 46 +
+ drivers/dsp/bridge/wmd/_msg_sm.h | 158 +
+ drivers/dsp/bridge/wmd/_tiomap.h | 384 +++
+ drivers/dsp/bridge/wmd/_tiomap_mmu.h | 53 +
+ drivers/dsp/bridge/wmd/_tiomap_pwr.h | 102 +
+ drivers/dsp/bridge/wmd/_tiomap_util.h | 46 +
+ drivers/dsp/bridge/wmd/chnl_sm.c | 1100 ++++++
+ drivers/dsp/bridge/wmd/io_sm.c | 2011 +++++++++++
+ drivers/dsp/bridge/wmd/mmu_fault.c | 172 +
+ drivers/dsp/bridge/wmd/mmu_fault.h | 45 +
+ drivers/dsp/bridge/wmd/msg_sm.c | 643 ++++
+ drivers/dsp/bridge/wmd/tiomap3430.c | 2149 ++++++++++++
+ drivers/dsp/bridge/wmd/tiomap3430_pwr.c | 731 ++++
+ drivers/dsp/bridge/wmd/tiomap_io.c | 427 +++
+ drivers/dsp/bridge/wmd/tiomap_io.h | 112 +
+ drivers/dsp/bridge/wmd/tiomap_sm.c | 195 ++
+ drivers/dsp/bridge/wmd/ue_deh.c | 329 ++
+ 191 files changed, 65137 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/tidspbridge/README
+ create mode 100644 arch/arm/mach-omap2/dspbridge.c
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/_dcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/brddefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cfg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/clk.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/cod.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/csl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbll.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dblldefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbof.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbreg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dbtype.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dehdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dev.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/devdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/disp.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dispdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dpc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/drv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/drvdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dspdrv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/errbase.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gb.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/getsection.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/gt.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/host_os.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/io.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/io_sm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/iodefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/kfile.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/ldr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/list.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mem.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/memdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mgr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/msg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/msgdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nldr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/node.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nodedefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/nodepriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/ntfy.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/proc.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/procpriv.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/pwr.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/reg.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rmm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rms_sh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/rmstypes.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/services.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/std.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/strm.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/strmdefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/sync.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/util.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/utildefs.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/uuidutil.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wcd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmd.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmddeh.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdio.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+ create mode 100644 arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+ create mode 100644 drivers/dsp/bridge/Kbuild
+ create mode 100644 drivers/dsp/bridge/Kconfig
+ create mode 100644 drivers/dsp/bridge/dynload/cload.c
+ create mode 100644 drivers/dsp/bridge/dynload/dlclasses_hdr.h
+ create mode 100644 drivers/dsp/bridge/dynload/dload_internal.h
+ create mode 100644 drivers/dsp/bridge/dynload/doff.h
+ create mode 100644 drivers/dsp/bridge/dynload/getsection.c
+ create mode 100644 drivers/dsp/bridge/dynload/header.h
+ create mode 100644 drivers/dsp/bridge/dynload/module_list.h
+ create mode 100644 drivers/dsp/bridge/dynload/params.h
+ create mode 100644 drivers/dsp/bridge/dynload/reloc.c
+ create mode 100644 drivers/dsp/bridge/dynload/reloc_table.h
+ create mode 100644 drivers/dsp/bridge/dynload/reloc_table_c6000.c
+ create mode 100644 drivers/dsp/bridge/gen/_gt_para.c
+ create mode 100644 drivers/dsp/bridge/gen/gb.c
+ create mode 100644 drivers/dsp/bridge/gen/gh.c
+ create mode 100644 drivers/dsp/bridge/gen/gs.c
+ create mode 100644 drivers/dsp/bridge/gen/gt.c
+ create mode 100644 drivers/dsp/bridge/gen/uuidutil.c
+ create mode 100644 drivers/dsp/bridge/hw/EasiGlobal.h
+ create mode 100644 drivers/dsp/bridge/hw/GlobalTypes.h
+ create mode 100644 drivers/dsp/bridge/hw/IPIAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/IVA2RegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/MLBAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/MLBRegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/MMUAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/MMURegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/PRCMAccInt.h
+ create mode 100644 drivers/dsp/bridge/hw/PRCMRegAcM.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_defs.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_dspssC64P.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_dspssC64P.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_mbox.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_mbox.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_mmu.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_mmu.h
+ create mode 100644 drivers/dsp/bridge/hw/hw_prcm.c
+ create mode 100644 drivers/dsp/bridge/hw/hw_prcm.h
+ create mode 100644 drivers/dsp/bridge/pmgr/chnl.c
+ create mode 100644 drivers/dsp/bridge/pmgr/chnlobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/cmm.c
+ create mode 100644 drivers/dsp/bridge/pmgr/cod.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dbl.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dbll.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dev.c
+ create mode 100644 drivers/dsp/bridge/pmgr/dmm.c
+ create mode 100644 drivers/dsp/bridge/pmgr/io.c
+ create mode 100644 drivers/dsp/bridge/pmgr/ioobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/msg.c
+ create mode 100644 drivers/dsp/bridge/pmgr/msgobj.h
+ create mode 100644 drivers/dsp/bridge/pmgr/wcd.c
+ create mode 100644 drivers/dsp/bridge/rmgr/dbdcd.c
+ create mode 100644 drivers/dsp/bridge/rmgr/disp.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.c
+ create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.h
+ create mode 100644 drivers/dsp/bridge/rmgr/dspdrv.c
+ create mode 100644 drivers/dsp/bridge/rmgr/mgr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/nldr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/node.c
+ create mode 100644 drivers/dsp/bridge/rmgr/proc.c
+ create mode 100644 drivers/dsp/bridge/rmgr/pwr.c
+ create mode 100644 drivers/dsp/bridge/rmgr/rmm.c
+ create mode 100644 drivers/dsp/bridge/rmgr/strm.c
+ create mode 100644 drivers/dsp/bridge/services/cfg.c
+ create mode 100644 drivers/dsp/bridge/services/clk.c
+ create mode 100644 drivers/dsp/bridge/services/csl.c
+ create mode 100644 drivers/dsp/bridge/services/dbg.c
+ create mode 100644 drivers/dsp/bridge/services/dpc.c
+ create mode 100644 drivers/dsp/bridge/services/kfile.c
+ create mode 100644 drivers/dsp/bridge/services/list.c
+ create mode 100644 drivers/dsp/bridge/services/mem.c
+ create mode 100644 drivers/dsp/bridge/services/ntfy.c
+ create mode 100644 drivers/dsp/bridge/services/reg.c
+ create mode 100644 drivers/dsp/bridge/services/regsup.c
+ create mode 100644 drivers/dsp/bridge/services/regsup.h
+ create mode 100644 drivers/dsp/bridge/services/services.c
+ create mode 100644 drivers/dsp/bridge/services/sync.c
+ create mode 100644 drivers/dsp/bridge/wmd/_cmm.h
+ create mode 100644 drivers/dsp/bridge/wmd/_deh.h
+ create mode 100644 drivers/dsp/bridge/wmd/_msg_sm.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_mmu.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_pwr.h
+ create mode 100644 drivers/dsp/bridge/wmd/_tiomap_util.h
+ create mode 100644 drivers/dsp/bridge/wmd/chnl_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/io_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.c
+ create mode 100644 drivers/dsp/bridge/wmd/mmu_fault.h
+ create mode 100644 drivers/dsp/bridge/wmd/msg_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap3430.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.c
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_io.h
+ create mode 100644 drivers/dsp/bridge/wmd/tiomap_sm.c
+ create mode 100644 drivers/dsp/bridge/wmd/ue_deh.c
+
+diff --git a/Documentation/tidspbridge/README b/Documentation/tidspbridge/README
+new file mode 100644
+index 0000000..df6d371
+--- /dev/null
++++ b/Documentation/tidspbridge/README
+@@ -0,0 +1,70 @@
++ Linux DSP/BIOS Bridge release
++
++DSP/BIOS Bridge overview
++========================
++
++DSP/BIOS Bridge is designed for platforms that contain a GPP and one or more
++attached DSPs. The GPP is considered the master or "host" processor, and the
++attached DSPs are processing resources that can be utilized by applications
++and drivers running on the GPP.
++
++The abstraction that DSP/BIOS Bridge supplies, is a direct link between a GPP
++program and a DSP task. This communication link is partitioned into two
++types of sub-links: messaging (short, fixed-length packets) and data
++streaming (multiple, large buffers). Each sub-link operates independently,
++and features in-order delivery of data, meaning that messages are delivered
++in the order they were submitted to the message link, and stream buffers are
++delivered in the order they were submitted to the stream link.
++
++In addition, a GPP client can specify what inputs and outputs a DSP task
++uses. DSP tasks typically use message objects for passing control and status
++information and stream objects for efficient streaming of real-time data.
++
++GPP Software Architecture
++=========================
++
++A GPP application communicates with its associated DSP task running on the
++DSP subsystem using the DSP/BIOS Bridge API. For example, a GPP audio
++application can use the API to pass messages to a DSP task that is managing
++data flowing from analog-to-digital converters (ADCs) to digital-to-analog
++converters (DACs).
++
++From the perspective of the GPP OS, the DSP is treated as just another
++peripheral device. Most high level GPP OS typically support a device driver
++model, whereby applications can safely access and share a hardware peripheral
++through standard driver interfaces. Therefore, to allow multiple GPP
++applications to share access to the DSP, the GPP side of DSP/BIOS Bridge
++implements a device driver for the DSP.
++
++Since driver interfaces are not always standard across GPP OS, and to provide
++some level of interoperability of application code using DSP/BIOS Bridge
++between GPP OS, DSP/BIOS Bridge provides a standard library of APIs which
++wrap calls into the device driver. So, rather than calling GPP OS specific
++driver interfaces, applications (and even other device drivers) can use the
++standard API library directly.
++
++DSP Software Architecture
++=========================
++
++For DSP/BIOS, DSP/BIOS Bridge adds a device-independent streaming I/O (STRM)
++interface, a messaging interface (NODE), and a Resource Manager (RM) Server.
++The RM Server runs as a task of DSP/BIOS and is subservient to commands
++and queries from the GPP. It executes commands to start and stop DSP signal
++processing nodes in response to GPP programs making requests through the
++(GPP-side) API.
++
++DSP tasks started by the RM Server are similar to any other DSP task with two
++important differences: they must follow a specific task model consisting of
++three C-callable functions (node create, execute, and delete), with specific
++sets of arguments, and they have a pre-defined task environment established
++by the RM Server.
++
++Tasks started by the RM Server communicate using the STRM and NODE interfaces
++and act as servers for their corresponding GPP clients, performing signal
++processing functions as requested by messages sent by their GPP client.
++Typically, a DSP task moves data from source devices to sink devices using
++device independent I/O streams, performing application-specific processing
++and transformations on the data while it is moved. For example, an audio
++task might perform audio decompression (ADPCM, MPEG, CELP) on data received
++from a GPP audio driver and then send the decompressed linear samples to a
++digital-to-analog converter.
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index e7fb201..2060772 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -1331,6 +1331,8 @@ if ARCH_OMAP
+ source "drivers/cbus/Kconfig"
+ endif
+
++source "drivers/dsp/bridge/Kconfig"
++
+ endmenu
+
+ source "fs/Kconfig"
+diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
+index 9b270d8..e52e01e 100644
+--- a/arch/arm/mach-omap2/Makefile
++++ b/arch/arm/mach-omap2/Makefile
+@@ -34,6 +34,8 @@ obj-$(CONFIG_OMAP_SMARTREFLEX) += smartreflex.o
+ obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o
+ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
+
++obj-$(CONFIG_MPU_BRIDGE) += dspbridge.o
++
+ # DSP
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
+ mailbox_mach-objs := mailbox.o
+diff --git a/arch/arm/mach-omap2/dspbridge.c b/arch/arm/mach-omap2/dspbridge.c
+new file mode 100644
+index 0000000..221e8ff
+--- /dev/null
++++ b/arch/arm/mach-omap2/dspbridge.c
+@@ -0,0 +1,74 @@
++/*
++ * TI's dspbridge platform device registration
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ * Copyright (C) 2009 Nokia Corporation
++ *
++ * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/platform_device.h>
++#include <dspbridge/host_os.h>
++
++static struct platform_device *dspbridge_pdev;
++
++#ifdef CONFIG_BRIDGE_DVFS
++#include <mach/omap-pm.h>
++static struct dspbridge_platform_data dspbridge_pdata __initdata = {
++ .dsp_set_min_opp = omap_pm_dsp_set_min_opp,
++ .dsp_get_opp = omap_pm_dsp_get_opp,
++ .cpu_set_freq = omap_pm_cpu_set_freq,
++ .cpu_get_freq = omap_pm_cpu_get_freq,
++};
++#else
++static struct dspbridge_platform_data dspbridge_pdata;
++#endif
++
++static int __init dspbridge_init(void)
++{
++ struct platform_device *pdev;
++ int err = -ENOMEM;
++ struct dspbridge_platform_data *pdata = &dspbridge_pdata;
++
++ pdata->phys_mempool_base = dspbridge_get_mempool_base();
++
++ if (pdata->phys_mempool_base) {
++ pdata->phys_mempool_size = CONFIG_BRIDGE_MEMPOOL_SIZE;
++ pr_info("%s: %x bytes @ %x\n", __func__,
++ pdata->phys_mempool_size, pdata->phys_mempool_base);
++ }
++
++ pdev = platform_device_alloc("C6410", -1);
++ if (!pdev)
++ goto err_out;
++
++ err = platform_device_add_data(pdev, pdata, sizeof(*pdata));
++ if (err)
++ goto err_out;
++
++ err = platform_device_add(pdev);
++ if (err)
++ goto err_out;
++
++ dspbridge_pdev = pdev;
++ return 0;
++
++err_out:
++ platform_device_put(pdev);
++ return err;
++}
++module_init(dspbridge_init);
++
++static void __exit dspbridge_exit(void)
++{
++ platform_device_unregister(dspbridge_pdev);
++}
++module_exit(dspbridge_exit);
++
++MODULE_AUTHOR("Hiroshi DOYU");
++MODULE_DESCRIPTION("TI's dspbridge platform device registration");
++MODULE_LICENSE("GPL v2");
+diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
+index a04e3ee..40488ae 100644
+--- a/arch/arm/mach-omap2/io.c
++++ b/arch/arm/mach-omap2/io.c
+@@ -38,6 +38,8 @@
+ #include <mach/clockdomain.h>
+ #include "clockdomains.h"
+
++#include <dspbridge/host_os.h>
++
+ /*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+@@ -192,6 +194,7 @@ void __init omap2_map_common_io(void)
+ omap2_check_revision();
+ omap_sram_init();
+ omapfb_reserve_sdram();
++ dspbridge_reserve_sdram();
+ }
+
+ void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
+diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
+index 6b742a8..e66dd8a 100644
+--- a/arch/arm/plat-omap/devices.c
++++ b/arch/arm/plat-omap/devices.c
+@@ -15,6 +15,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/i2c/menelaus.h>
++#include <linux/bootmem.h>
+
+ #include <mach/hardware.h>
+ #include <asm/mach-types.h>
+@@ -89,6 +90,33 @@ EXPORT_SYMBOL(dsp_kfunc_device_register);
+ static inline void omap_init_dsp(void) { }
+ #endif /* CONFIG_OMAP_DSP */
+
++#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
++
++static unsigned long dspbridge_phys_mempool_base;
++
++void dspbridge_reserve_sdram(void)
++{
++ void *va;
++ unsigned long size = CONFIG_BRIDGE_MEMPOOL_SIZE;
++
++ if (!size)
++ return;
++
++ va = __alloc_bootmem_nopanic(size, SZ_1M, 0);
++ if (!va) {
++ pr_err("%s: Failed to bootmem allocation(%lu bytes)\n",
++ __func__, size);
++ return;
++ }
++ dspbridge_phys_mempool_base = virt_to_phys(va);
++}
++
++unsigned long dspbridge_get_mempool_base(void)
++{
++ return dspbridge_phys_mempool_base;
++}
++EXPORT_SYMBOL(dspbridge_get_mempool_base);
++#endif
+ /*-------------------------------------------------------------------------*/
+ #if defined(CONFIG_KEYBOARD_OMAP) || defined(CONFIG_KEYBOARD_OMAP_MODULE)
+
+diff --git a/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+new file mode 100644
+index 0000000..28af799
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/_chnl_sm.h
+@@ -0,0 +1,212 @@
++/*
++ * _chnl_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _chnl_sm.h ========
++ * Description:
++ * Private header file defining channel manager and channel objects for
++ * a shared memory channel driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ * Shared between the modules implementing the shared memory channel class
++ * library.
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Oct-2002 kc Removed legacy PERF code.
++ *! 12-Jan-2002 ag Removed unused gppReqIO & ddmaChnlId DDMA fields.
++ *! Added zero-copy chnl descriptor array: zchnldesc.
++ *! 21-Dec-2001 ag Moved descPaGpp to private chnl obj from chnl descriptor.
++ *! 20-May-2001 ag/jeh Removed fShmSyms field from CHNL_MGR.
++ *! 04-Feb-2001 ag DSP-DMA support added.
++ *! 26-Oct-2000 jeh Added arg and resvd to SHM control structure. Added dwArg
++ *! to CHNL_IRP.
++ *! 16-Oct-2000 jeh Removed #ifdef DEBUG from around channel object's cIOCs
++ *! field, added cIOReqs.
++ *! 20-Jan-2000 ag: Incorporated code review comments.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 03-Nov-1999 ag: Added szEventName[] to CHNL object for name event support.
++ *! 02-Nov-1999 ag: _SHM_BEG & _END Syms from COFF now used for IO and SM CLASS.
++ *! 27-Oct-1999 jeh Define SHM structure to work for 16-bit targets.
++ *! 25-May-1999 jg: Added target side symbol names for share memory buffer
++ *! 03-Jan-1997 gp: Added fSharedIRQ field.
++ *! 22-Oct-1996 gp: Made dwProcessID a handle.
++ *! 09-Sep-1996 gp: Added dwProcessID field to CHNL_OBJECT.
++ *! 13-Aug-1996 gp: Created.
++ */
++
++#ifndef _CHNL_SM_
++#define _CHNL_SM_
++
++#include <dspbridge/wcd.h>
++#include <dspbridge/wmd.h>
++#include <dspbridge/dpc.h>
++
++#include <dspbridge/list.h>
++#include <dspbridge/ntfy.h>
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of shared memory buffer. They are defined in the *cfg.cmd file by
++ * cdb code.
++ */
++#define CHNL_SHARED_BUFFER_BASE_SYM "_SHM_BEG"
++#define CHNL_SHARED_BUFFER_LIMIT_SYM "_SHM_END"
++#define BRIDGEINIT_BIOSGPTIMER "_BRIDGEINIT_BIOSGPTIMER"
++#define BRIDGEINIT_LOADMON_GPTIMER "_BRIDGEINIT_LOADMON_GPTIMER"
++
++#ifndef _CHNL_WORDSIZE
++#define _CHNL_WORDSIZE 4 /* default _CHNL_WORDSIZE is 2 bytes/word */
++#endif
++
++#define MAXOPPS 16
++
++struct oppTableEntry {
++ u32 voltage;
++ u32 frequency;
++ u32 minFreq;
++ u32 maxFreq;
++} ;
++
++struct oppStruct {
++ u32 currOppPt;
++ u32 numOppPts;
++ struct oppTableEntry oppPoint[MAXOPPS];
++} ;
++
++/* Request to MPU */
++struct oppRqstStruct {
++ u32 rqstDspFreq;
++ u32 rqstOppPt;
++};
++
++/* Info to MPU */
++struct loadMonStruct {
++ u32 currDspLoad;
++ u32 currDspFreq;
++ u32 predDspLoad;
++ u32 predDspFreq;
++};
++
++ enum SHM_DESCTYPE {
++ SHM_CURROPP = 0,
++ SHM_OPPINFO = 1,
++ SHM_GETOPP = 2, /* Get DSP requested OPP info */
++ } ;
++
++/* Structure in shared between DSP and PC for communication.*/
++ struct SHM {
++ u32 dspFreeMask; /* Written by DSP, read by PC. */
++ u32 hostFreeMask; /* Written by PC, read by DSP */
++
++ u32 inputFull; /* Input channel has unread data. */
++ u32 inputId; /* Channel for which input is available. */
++ u32 inputSize; /* Size of data block (in DSP words). */
++
++ u32 outputFull; /* Output channel has unread data. */
++ u32 outputId; /* Channel for which output is available. */
++ u32 outputSize; /* Size of data block (in DSP words). */
++
++ u32 arg; /* Arg for Issue/Reclaim (23 bits for 55x). */
++ u32 resvd; /* Keep structure size even for 32-bit DSPs */
++
++ /* Operating Point structure */
++ struct oppStruct oppTableStruct;
++ /* Operating Point Request structure */
++ struct oppRqstStruct oppRequest;
++ /* load monitor information structure*/
++ struct loadMonStruct loadMonInfo;
++ char dummy[184]; /* padding to 256 byte boundary */
++ u32 shm_dbg_var[64]; /* shared memory debug variables */
++ } ;
++
++ /* Channel Manager: only one created per board: */
++ struct CHNL_MGR {
++ u32 dwSignature; /* Used for object validation */
++ /* Function interface to WMD */
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR *hIOMgr; /* IO manager */
++ /* Device this board represents */
++ struct DEV_OBJECT *hDevObject;
++
++ /* These fields initialized in WMD_CHNL_Create(): */
++ u32 dwOutputMask; /* Host output channels w/ full buffers */
++ u32 dwLastOutput; /* Last output channel fired from DPC */
++ /* Critical section object handle */
++ struct SYNC_CSOBJECT *hCSObj;
++ u32 uWordSize; /* Size in bytes of DSP word */
++ u32 cChannels; /* Total number of channels */
++ u32 cOpenChannels; /* Total number of open channels */
++ struct CHNL_OBJECT **apChannel; /* Array of channels */
++ u32 dwType; /* Type of channel class library */
++ /* If no SHM syms, return for CHNL_Open */
++ DSP_STATUS chnlOpenStatus;
++ } ;
++
++/*
++ * Channel: up to CHNL_MAXCHANNELS per board or if DSP-DMA supported then
++ * up to CHNL_MAXCHANNELS + CHNL_MAXDDMACHNLS per board.
++ */
++ struct CHNL_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /* Pointer back to channel manager */
++ struct CHNL_MGR *pChnlMgr;
++ u32 uId; /* Channel id */
++ u32 dwState; /* Current channel state */
++ u32 uMode; /* Chnl mode and attributes */
++ /* Chnl I/O completion event (user mode) */
++ HANDLE hUserEvent;
++ /* Abstract syncronization object */
++ struct SYNC_OBJECT *hSyncEvent;
++ /* Name of Sync event */
++ char szEventName[SYNC_MAXNAMELENGTH + 1];
++ u32 hProcess; /* Process which created this channel */
++ u32 pCBArg; /* Argument to use with callback */
++ struct LST_LIST *pIORequests; /* List of IOR's to driver */
++ s32 cIOCs; /* Number of IOC's in queue */
++ s32 cIOReqs; /* Number of IORequests in queue */
++ s32 cChirps; /* Initial number of free Irps */
++ /* List of IOC's from driver */
++ struct LST_LIST *pIOCompletions;
++ struct LST_LIST *pFreeList; /* List of free Irps */
++ struct NTFY_OBJECT *hNtfy;
++ u32 cBytesMoved; /* Total number of bytes transfered */
++
++ /* For DSP-DMA */
++
++ /* Type of chnl transport:CHNL_[PCPY][DDMA] */
++ u32 uChnlType;
++ } ;
++
++/* I/O Request/completion packet: */
++ struct CHNL_IRP {
++ struct LST_ELEM link; /* Link to next CHIRP in queue. */
++ /* Buffer to be filled/emptied. (User) */
++ u8 *pHostUserBuf;
++ /* Buffer to be filled/emptied. (System) */
++ u8 *pHostSysBuf;
++ u32 dwArg; /* Issue/Reclaim argument. */
++ u32 uDspAddr; /* Transfer address on DSP side. */
++ u32 cBytes; /* Bytes transferred. */
++ u32 cBufSize; /* Actual buffer size when allocated. */
++ u32 status; /* Status of IO completion. */
++ } ;
++
++#endif /* _CHNL_SM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/_dcd.h b/arch/arm/plat-omap/include/dspbridge/_dcd.h
+new file mode 100644
+index 0000000..b6a8d9e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/_dcd.h
+@@ -0,0 +1,187 @@
++/*
++ * _dcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _dcd.h ========
++ * Description:
++ * Includes the wrapper functions called directly by the
++ * DeviceIOControl interface.
++ *
++ * Public Functions:
++ * WCD_CallDevIOCtl
++ * WCD_Init
++ * WCD_InitComplete2
++ * WCD_Exit
++ * <MOD>WRAP_*
++ *
++ * Notes:
++ * Compiled with CDECL calling convention.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 30-Jan-2002 ag Renamed CMMWRAP_AllocBuf to CMMWRAP_CallocBuf.
++ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data to acquire PERF stats.
++ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
++ *! NODEWRAP_GetMessageStream.
++ *! 10-Oct-2000 ag: Added user CMM wrappers.
++ *! 04-Aug-2000 rr: MEMWRAP and UTIL_Wrap added.
++ *! 27-Jul-2000 rr: NODEWRAP, STRMWRAP added.
++ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
++ *! 03-Dec-1999 rr: WCD_InitComplete2 enabled for BRD_AutoStart.
++ *! 09-Nov-1999 kc: Added MEMRY.
++ *! 02-Nov-1999 ag: Added CHNL.
++ *! 08-Oct-1999 rr: Utilwrap_Testdll fxn added
++ *! 24-Sep-1999 rr: header changed from _wcd.h to _dcd.h
++ *! 09-Sep-1997 gp: Created.
++ */
++
++#ifndef _WCD_
++#define _WCD_
++
++#include <dspbridge/wcdioctl.h>
++
++/*
++ * ======== WCD_CallDevIOCtl ========
++ * Purpose:
++ * Call the (wrapper) function for the corresponding WCD IOCTL.
++ * Parameters:
++ * cmd: IOCTL id, base 0.
++ * args: Argument structure.
++ * pResult:
++ * Returns:
++ * DSP_SOK if command called; DSP_EINVALIDARG if command not in IOCTL
++ * table.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS WCD_CallDevIOCtl(unsigned int cmd,
++ union Trapped_Args *args,
++ u32 *pResult);
++
++/*
++ * ======== WCD_Init ========
++ * Purpose:
++ * Initialize WCD modules, and export WCD services to WMD's.
++ * This procedure is called when the class driver is loaded.
++ * Parameters:
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern bool WCD_Init(void);
++
++/*
++ * ======== WCD_InitComplete2 ========
++ * Purpose:
++ * Perform any required WCD, and WMD initialization which
++ * cannot not be performed in WCD_Init(void) or DEV_StartDevice() due
++ * to the fact that some services are not yet
++ * completely initialized.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Allow this device to load
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * WCD initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS WCD_InitComplete2(void);
++
++/*
++ * ======== WCD_Exit ========
++ * Purpose:
++ * Exit all modules initialized in WCD_Init(void).
++ * This procedure is called when the class driver is unloaded.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * WCD_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in WCD_Init(void) are freed.
++ */
++ extern void WCD_Exit(void);
++
++/* MGR wrapper functions */
++ extern u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args);
++ extern u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args);
++ extern u32 MGRWRAP_RegisterObject(union Trapped_Args *args);
++ extern u32 MGRWRAP_UnregisterObject(union Trapped_Args *args);
++ extern u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args);
++
++#ifndef RES_CLEANUP_DISABLE
++ extern u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args);
++#endif
++
++
++/* CPRC (Processor) wrapper Functions */
++ extern u32 PROCWRAP_Attach(union Trapped_Args *args);
++ extern u32 PROCWRAP_Ctrl(union Trapped_Args *args);
++ extern u32 PROCWRAP_Detach(union Trapped_Args *args);
++ extern u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args);
++ extern u32 PROCWRAP_EnumResources(union Trapped_Args *args);
++ extern u32 PROCWRAP_GetState(union Trapped_Args *args);
++ extern u32 PROCWRAP_GetTrace(union Trapped_Args *args);
++ extern u32 PROCWRAP_Load(union Trapped_Args *args);
++ extern u32 PROCWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 PROCWRAP_Start(union Trapped_Args *args);
++ extern u32 PROCWRAP_ReserveMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_Map(union Trapped_Args *args);
++ extern u32 PROCWRAP_UnMap(union Trapped_Args *args);
++ extern u32 PROCWRAP_FlushMemory(union Trapped_Args *args);
++ extern u32 PROCWRAP_Stop(union Trapped_Args *args);
++ extern u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args);
++
++/* NODE wrapper functions */
++ extern u32 NODEWRAP_Allocate(union Trapped_Args *args);
++ extern u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args);
++ extern u32 NODEWRAP_ChangePriority(union Trapped_Args *args);
++ extern u32 NODEWRAP_Connect(union Trapped_Args *args);
++ extern u32 NODEWRAP_Create(union Trapped_Args *args);
++ extern u32 NODEWRAP_Delete(union Trapped_Args *args);
++ extern u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetAttr(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetMessage(union Trapped_Args *args);
++ extern u32 NODEWRAP_Pause(union Trapped_Args *args);
++ extern u32 NODEWRAP_PutMessage(union Trapped_Args *args);
++ extern u32 NODEWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 NODEWRAP_Run(union Trapped_Args *args);
++ extern u32 NODEWRAP_Terminate(union Trapped_Args *args);
++ extern u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args);
++
++/* STRM wrapper functions */
++ extern u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args);
++ extern u32 STRMWRAP_Close(union Trapped_Args *args);
++ extern u32 STRMWRAP_FreeBuffer(union Trapped_Args *args);
++ extern u32 STRMWRAP_GetEventHandle(union Trapped_Args *args);
++ extern u32 STRMWRAP_GetInfo(union Trapped_Args *args);
++ extern u32 STRMWRAP_Idle(union Trapped_Args *args);
++ extern u32 STRMWRAP_Issue(union Trapped_Args *args);
++ extern u32 STRMWRAP_Open(union Trapped_Args *args);
++ extern u32 STRMWRAP_Reclaim(union Trapped_Args *args);
++ extern u32 STRMWRAP_RegisterNotify(union Trapped_Args *args);
++ extern u32 STRMWRAP_Select(union Trapped_Args *args);
++
++ extern u32 CMMWRAP_CallocBuf(union Trapped_Args *args);
++ extern u32 CMMWRAP_FreeBuf(union Trapped_Args *args);
++ extern u32 CMMWRAP_GetHandle(union Trapped_Args *args);
++ extern u32 CMMWRAP_GetInfo(union Trapped_Args *args);
++
++#endif /* _WCD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/brddefs.h b/arch/arm/plat-omap/include/dspbridge/brddefs.h
+new file mode 100644
+index 0000000..c62388c
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/brddefs.h
+@@ -0,0 +1,54 @@
++/*
++ * brddefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== brddefs.h ========
++ * Description:
++ * Global BRD constants and types, shared between WSX, WCD, and WMD.
++ *
++ *! Revision History:
++ *! ================
++ *! 31-Jan-2000 rr: Comment Exec changed to Monitor
++ *! 22-Jul-1999 jeh Added BRD_LOADED state.
++ *! 26-Mar-1997 gp: Added BRD_SYNCINIT state.
++ *! 11-Dec-1996 cr: Added BRD_LASTSTATE definition.
++ *! 11-Jul-1996 gp: Added missing u32 callback argument to BRD_CALLBACK.
++ *! 10-Jun-1996 gp: Created from board.h and brd.h.
++ */
++
++#ifndef BRDDEFS_
++#define BRDDEFS_
++
++/* platform status values */
++#define BRD_STOPPED 0x0 /* No Monitor Loaded, Not running. */
++#define BRD_IDLE 0x1 /* Monitor Loaded, but suspended. */
++#define BRD_RUNNING 0x2 /* Monitor loaded, and executing. */
++#define BRD_UNKNOWN 0x3 /* Board state is indeterminate. */
++#define BRD_SYNCINIT 0x4
++#define BRD_LOADED 0x5
++#define BRD_LASTSTATE BRD_LOADED /* Set to highest legal board state. */
++#define BRD_SLEEP_TRANSITION 0x6 /* Sleep transition in progress */
++#define BRD_HIBERNATION 0x7 /* MPU initiated hibernation */
++#define BRD_RETENTION 0x8 /* Retention mode */
++#define BRD_DSP_HIBERNATION 0x9 /* DSP initiated hibernation */
++#define BRD_ERROR 0xA /* Board state is Error */
++ typedef u32 BRD_STATUS;
++
++/* BRD Object */
++ struct BRD_OBJECT;
++
++#endif /* BRDDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cfg.h b/arch/arm/plat-omap/include/dspbridge/cfg.h
+new file mode 100644
+index 0000000..68db842
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cfg.h
+@@ -0,0 +1,339 @@
++/*
++ * cfg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cfg.h ========
++ * Purpose:
++ * PM Configuration module.
++ *
++ * Private Functions:
++ * CFG_Exit
++ * CFG_GetAutoStart
++ * CFG_GetCDVersion
++ * CFG_GetDevObject
++ * CFG_GetDSPResources
++ * CFG_GetExecFile
++ * CFG_GetHostResources
++ * CFG_GetObject
++ * CFG_GetPerfValue
++ * CFG_GetWMDFileName
++ * CFG_GetZLFile
++ * CFG_Init
++ * CFG_SetDevObject
++ * CFG_SetObject
++ *
++ *! Revision History:
++ *! =================
++ *! 26-Feb-2003 kc Removed unused CFG fxns.
++ *! 28-Aug-2001 jeh Added CFG_GetLoaderName.
++ *! 26-Jul-2000 rr: Added CFG_GetDCDName to retrieve the DCD Dll name.
++ *! 13-Jul-2000 rr: Added CFG_GetObject & CFG_SetObject.
++ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! CFG_GetWinBRIDGEDir/Directory,CFG_GetSearchPath removed.
++ *! 15-Jan-1998 cr: Code review cleanup.
++ *! 16-Aug-1997 cr: Added explicit cdecl identifiers.
++ *! 12-Dec-1996 gp: Moved CFG_FindInSearchPath to CSP module.
++ *! 13-Sep-1996 gp: Added CFG_GetBoardName().
++ *! 22-Jul-1996 gp: Added CFG_GetTraceStr, to retrieve an initial GT trace.
++ *! 26-Jun-1996 cr: Added CFG_FindInSearchPath.
++ *! 25-Jun-1996 cr: Added CFG_GetWinSPOXDir.
++ *! 17-Jun-1996 cr: Added CFG_GetDevNode.
++ *! 11-Jun-1996 cr: Cleaned up for code review.
++ *! 07-Jun-1996 cr: Added CFG_GetExecFile and CFG_GetZLFileName functions.
++ *! 04-Jun-1996 gp: Added AutoStart regkey and accessor function. Placed
++ *! OUT parameters in accessor function param. lists at end.
++ *! 29-May-1996 gp: Moved DEV_HDEVNODE to here and renamed CFG_HDEVNODE.
++ *! 22-May-1996 cr: Added GetHostResources, GetDSPResources, and
++ *! GetWMDFileName services.
++ *! 18-May-1996 gp: Created.
++ */
++
++#ifndef CFG_
++#define CFG_
++#include <dspbridge/host_os.h>
++#include <dspbridge/cfgdefs.h>
++
++/*
++ * ======== CFG_Exit ========
++ * Purpose:
++ * Discontinue usage of the CFG module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CFG_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in CFG_Init(void) are freed.
++ */
++ extern void CFG_Exit(void);
++
++/*
++ * ======== CFG_GetAutoStart ========
++ * Purpose:
++ * Retreive the autostart mask, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * pdwAutoStart: Ptr to location for 32 bit autostart mask.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: Unable to retreive resource.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwAutoStart contains autostart mask for this devnode.
++ */
++ extern DSP_STATUS CFG_GetAutoStart(IN struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwAutoStart);
++
++/*
++ * ======== CFG_GetCDVersion ========
++ * Purpose:
++ * Retrieves the version of the PM Class Driver.
++ * Parameters:
++ * pdwVersion: Ptr to u32 to contain version number upon return.
++ * Returns:
++ * DSP_SOK: Success. pdwVersion contains Class Driver version in
++ * the form: 0xAABBCCDD where AABB is Major version and
++ * CCDD is Minor.
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Success.
++ * else: *pdwVersion is NULL.
++ */
++ extern DSP_STATUS CFG_GetCDVersion(OUT u32 *pdwVersion);
++
++/*
++ * ======== CFG_GetDevObject ========
++ * Purpose:
++ * Retrieve the Device Object handle for a given devnode.
++ * Parameters:
++ * hDevNode: Platform's DevNode handle from which to retrieve value.
++ * pdwValue: Ptr to location to store the value.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_INVALIDPOINTER: phDevObject is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwValue is set to the retrieved u32.
++ * else: *pdwValue is set to 0L.
++ */
++ extern DSP_STATUS CFG_GetDevObject(IN struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwValue);
++
++/*
++ * ======== CFG_GetDSPResources ========
++ * Purpose:
++ * Get the DSP resources available to a given device.
++ * Parameters:
++ * hDevNode: Handle to the DEVNODE who's resources we are querying.
++ * pDSPResTable: Ptr to a location to store the DSP resource table.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The DSP Resource information is not
++ * available
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: pDSPResTable points to a filled table of resources allocated
++ * for the specified WMD.
++ */
++ extern DSP_STATUS CFG_GetDSPResources(IN struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_DSPRES *pDSPResTable);
++
++
++/*
++ * ======== CFG_GetExecFile ========
++ * Purpose:
++ * Retreive the default executable, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pstrExecFile: Ptr to character buf to hold ExecFile.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_INVALIDPOINTER: pstrExecFile is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied into pstrExecFile,
++ * and *pstrExecFile contains default executable for this
++ * devnode.
++ */
++ extern DSP_STATUS CFG_GetExecFile(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pstrExecFile);
++
++/*
++ * ======== CFG_GetHostResources ========
++ * Purpose:
++ * Get the Host PC allocated resources assigned to a given device.
++ * Parameters:
++ * hDevNode: Handle to the DEVNODE who's resources we are querying.
++ * pHostResTable: Ptr to a location to store the host resource table.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDPOINTER: pHostResTable is invalid.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The resource is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: pHostResTable points to a filled table of resources
++ * allocated for the specified WMD.
++ *
++ */
++ extern DSP_STATUS CFG_GetHostResources(IN struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_HOSTRES *pHostResTable);
++
++/*
++ * ======== CFG_GetObject ========
++ * Purpose:
++ * Retrieve the Driver Object handle From the Registry
++ * Parameters:
++ * pdwValue: Ptr to location to store the value.
++ * dwType Type of Object to Get
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: *pdwValue is set to the retrieved u32(non-Zero).
++ * else: *pdwValue is set to 0L.
++ */
++ extern DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType);
++
++/*
++ * ======== CFG_GetPerfValue ========
++ * Purpose:
++ * Retrieve a flag indicating whether PERF should log statistics for the
++ * PM class driver.
++ * Parameters:
++ * pfEnablePerf: Location to store flag. 0 indicates the key was
++ * not found, or had a zero value. A nonzero value
++ * means the key was found and had a nonzero value.
++ * Returns:
++ * Requires:
++ * pfEnablePerf != NULL;
++ * Ensures:
++ */
++ extern void CFG_GetPerfValue(OUT bool *pfEnablePerf);
++
++/*
++ * ======== CFG_GetWMDFileName ========
++ * Purpose:
++ * Get the mini-driver file name for a given device.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pWMDFileName: Ptr to a character buffer to hold the WMD filename.
++ * Returns:
++ * DSP_SOK: On success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: The filename is not available.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied
++ * into pWMDFileName.
++ *
++ */
++ extern DSP_STATUS CFG_GetWMDFileName(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pWMDFileName);
++
++/*
++ * ======== CFG_GetZLFile ========
++ * Purpose:
++ * Retreive the ZLFile, if any, for this board.
++ * Parameters:
++ * hDevNode: Handle to the DevNode who's WMD we are querying.
++ * cBufSize: Size of buffer.
++ * pstrZLFileName: Ptr to character buf to hold ZLFileName.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDPOINTER: pstrZLFileName is invalid.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * CFG_E_RESOURCENOTAVAIL: couldn't find the ZLFileName.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: Not more than cBufSize bytes were copied into
++ * pstrZLFileName, and *pstrZLFileName contains ZLFileName
++ * for this devnode.
++ */
++ extern DSP_STATUS CFG_GetZLFile(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 cBufSize,
++ OUT char *pstrZLFileName);
++
++/*
++ * ======== CFG_Init ========
++ * Purpose:
++ * Initialize the CFG module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CFG functions.
++ */
++ extern bool CFG_Init(void);
++
++/*
++ * ======== CFG_SetDevObject ========
++ * Purpose:
++ * Store the Device Object handle for a given devnode.
++ * Parameters:
++ * hDevNode: Platform's DevNode handle we are storing value with.
++ * dwValue: Arbitrary value to store.
++ * Returns:
++ * DSP_SOK: Success.
++ * CFG_E_INVALIDHDEVNODE: hDevNode is invalid.
++ * DSP_EFAIL: Internal Error.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: The Private u32 was successfully set.
++ */
++ extern DSP_STATUS CFG_SetDevObject(IN struct CFG_DEVNODE *hDevNode,
++ IN u32 dwValue);
++
++/*
++ * ======== CFG_SetDrvObject ========
++ * Purpose:
++ * Store the Driver Object handle.
++ * Parameters:
++ * dwValue: Arbitrary value to store.
++ * dwType Type of Object to Store
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal Error.
++ * Requires:
++ * CFG initialized.
++ * Ensures:
++ * DSP_SOK: The Private u32 was successfully set.
++ */
++ extern DSP_STATUS CFG_SetObject(IN u32 dwValue, IN u32 dwType);
++
++#endif /* CFG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cfgdefs.h b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+new file mode 100644
+index 0000000..4f78d82
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cfgdefs.h
+@@ -0,0 +1,126 @@
++/*
++ * cfgdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== cfgdefs.h ========
++ * Purpose:
++ * Global CFG constants and types, shared between class and mini driver.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 kc Removed wIOPort* in CFG_HOSTRES.
++ *! 06-Sep-2000 jeh Added channel info to CFG_HOSTRES.
++ *! 09-May-2000 rr: CFG_HOSTRES now support multiple windows for PCI support.
++ *! 31-Jan-2000 rr: Comments changed after code review.
++ *! 06-Jan-2000 rr: Bus Type included in CFG_HOSTRES.
++ *! 12-Nov-1999 rr: CFG_HOSTRES member names changed.
++ *! 25-Oct-1999 rr: Modified the CFG_HOSTRES Structure
++ *! PCMCIA ISR Register/Unregister fxn removed..
++ *! New flag PCCARD introduced during compile time.
++ *! 10-Sep-1999 ww: Added PCMCIA ISR Register/Unregister fxn.
++ *! 01-Sep-1999 ag: Removed NT/95 specific fields in CFG_HOSTRES
++ *! 27-Oct-1997 cr: Updated CFG_HOSTRES struct to support 1+ IRQs per board.
++ *! 17-Sep-1997 gp: Tacked some NT config info to end of CFG_HOSTRES structure.
++ *! 12-Dec-1996 cr: Cleaned up after code review.
++ *! 14-Nov-1996 gp: Renamed from wsxcfg.h
++ *! 19-Jun-1996 cr: Created.
++ */
++
++#ifndef CFGDEFS_
++#define CFGDEFS_
++
++/* Maximum length of module search path. */
++#define CFG_MAXSEARCHPATHLEN 255
++
++/* Maximum length of general paths. */
++#define CFG_MAXPATH 255
++
++/* Host Resources: */
++#define CFG_MAXMEMREGISTERS 9
++#define CFG_MAXIOPORTS 20
++#define CFG_MAXIRQS 7
++#define CFG_MAXDMACHANNELS 7
++
++/* IRQ flag */
++#define CFG_IRQSHARED 0x01 /* IRQ can be shared */
++
++/* DSP Resources: */
++#define CFG_DSPMAXMEMTYPES 10
++#define CFG_DEFAULT_NUM_WINDOWS 1 /* We support only one window. */
++
++/* A platform-related device handle: */
++ struct CFG_DEVNODE;
++
++/*
++ * Host resource structure.
++ */
++ struct CFG_HOSTRES {
++ u32 wNumMemWindows; /* Set to default */
++ /* This is the base.memory */
++ u32 dwMemBase[CFG_MAXMEMREGISTERS]; /* SHM virtual address */
++ u32 dwMemLength[CFG_MAXMEMREGISTERS]; /* Length of the Base */
++ u32 dwMemPhys[CFG_MAXMEMREGISTERS]; /* SHM Physical address */
++ u8 bIRQRegisters; /* IRQ Number */
++ u8 bIRQAttrib; /* IRQ Attribute */
++ u32 dwOffsetForMonitor; /* The Shared memory starts from
++ * dwMemBase + this offset */
++ u32 dwBusType; /* Bus type for this device */
++ u32 dwProgBase; /* DSP ProgBase */
++ u32 dwProgLength; /* DSP ProgBase Length */
++ u32 dwRegBase; /* DSP memory mapped register base */
++ u32 dwRegLength; /* DSP Register Base Length */
++ u32 ClientHandle; /* Client Handle */
++ u32 SocketHandle; /* Socket and Function Pair */
++ u32 CardInfo; /* This will be used as a context data in
++ * in the CardRequestIRQ */
++ /*
++ * Info needed by NODE for allocating channels to communicate with RMS:
++ * dwChnlOffset: Offset of RMS channels. Lower channels are
++ * reserved.
++ * dwChnlBufSize: Size of channel buffer to send to RMS
++ * dwNumChnls: Total number of channels (including reserved).
++ */
++ u32 dwChnlOffset;
++ u32 dwChnlBufSize;
++ u32 dwNumChnls;
++ u32 dwPrmBase;
++ u32 dwCmBase;
++ u32 dwPerBase;
++ u32 dwPerPmBase;
++ u32 dwCorePmBase;
++ u32 dwWdTimerDspBase;
++ u32 dwMboxBase;
++ u32 dwDmmuBase;
++ u32 dwDipiBase;
++ u32 dwSysCtrlBase;
++ } ;
++
++ struct CFG_DSPMEMDESC {
++ u32 uMemType; /* Type of memory. */
++ u32 ulMin; /* Minimum amount of memory of this type. */
++ u32 ulMax; /* Maximum amount of memory of this type. */
++ } ;
++
++ struct CFG_DSPRES {
++ u32 uChipType; /* DSP chip type. */
++ u32 uWordSize; /* Number of bytes in a word */
++ u32 cChips; /* Number of chips. */
++ u32 cMemTypes; /* Types of memory. */
++ struct CFG_DSPMEMDESC aMemDesc[CFG_DSPMAXMEMTYPES];
++ /* DSP Memory types */
++ } ;
++
++#endif /* CFGDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnl.h b/arch/arm/plat-omap/include/dspbridge/chnl.h
+new file mode 100644
+index 0000000..f39e3f4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnl.h
+@@ -0,0 +1,170 @@
++/*
++ * chnl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl.h ========
++ * Description:
++ * WCD channel interface: multiplexes data streams through the single
++ * physical link managed by a mini-driver.
++ *
++ * Public Functions:
++ * CHNL_AddIOReq
++ * CHNL_AllocBuffer
++ * CHNL_CancelIO
++ * CHNL_Close
++ * CHNL_CloseOrphans
++ * CHNL_Create
++ * CHNL_Destroy
++ * CHNL_Exit
++ * CHNL_FlushIO
++ * CHNL_FreeBuffer
++ * CHNL_GetEventHandle
++ * CHNL_GetHandle
++ * CHNL_GetIOCompletion
++ * CHNL_GetId
++ * CHNL_GetMgr
++ * CHNL_GetMode
++ * CHNL_GetPosition
++ * CHNL_GetProcessHandle
++ * CHNL_Init
++ * CHNL_Open
++ *
++ * Notes:
++ * See DSP API chnl.h for more details.
++ *
++ *! Revision History:
++ *! ================
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 24-Oct-1996 gp: Move CloseOrphans into here from dspsys.
++ *! 09-Sep-1996 gp: Added CHNL_GetProcessID() and CHNL_GetHandle().
++ *! 10-Jul-1996 gp: Created.
++ */
++
++#ifndef CHNL_
++#define CHNL_
++
++#include <dspbridge/chnlpriv.h>
++
++/*
++ * ======== CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * CHNL_Init(void) called.
++ * No thread must be blocked on this channel's I/O completion event.
++ * Ensures:
++ * DSP_SOK: The I/O completion event for this channel is freed.
++ * hChnl is no longer valid.
++ */
++ extern DSP_STATUS CHNL_Close(struct CHNL_OBJECT *hChnl);
++
++
++/*
++ * ======== CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given board.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Channel manager attributes.
++ * pMgrAttrs->cChannels: Max channels
++ * pMgrAttrs->bIRQ: Channel's I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: hDevObject is invalid.
++ * DSP_EINVALIDARG: cChannels is 0.
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug channel ISR for configured IRQ.
++ * CHNL_E_MAXCHANNELS: This manager cannot handle this many channels.
++ * CHNL_E_INVALIDIRQ: Invalid IRQ number. Must be 0 <= bIRQ <= 15.
++ * CHNL_E_INVALIDWORDSIZE: Invalid DSP word size. Must be > 0.
++ * CHNL_E_INVALIDMEMBASE: Invalid base address for DSP communications.
++ * CHNL_E_MGREXISTS: Channel manager already exists for this device.
++ * Requires:
++ * CHNL_Init(void) called.
++ * phChnlMgr != NULL.
++ * pMgrAttrs != NULL.
++ * Ensures:
++ * DSP_SOK: Subsequent calls to CHNL_Create() for the same
++ * board without an intervening call to
++ * CHNL_Destroy() will fail.
++ */
++ extern DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ * Parameters:
++ * hChnlMgr: Channel manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr was invalid.
++ * Requires:
++ * CHNL_Init(void) called.
++ * Ensures:
++ * DSP_SOK: Cancels I/O on each open channel.
++ * Closes each open channel.
++ * CHNL_Create may subsequently be called for the
++ * same board.
++ */
++ extern DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
++
++/*
++ * ======== CHNL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CHNL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CHNL_Init(void) previously called.
++ * Ensures:
++ * Resources, if any acquired in CHNL_Init(void), are freed when the last
++ * client of CHNL calls CHNL_Exit(void).
++ */
++ extern void CHNL_Exit(void);
++
++
++/*
++ * ======== CHNL_Init ========
++ * Purpose:
++ * Initialize the CHNL module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occurred.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CHNL functions.
++ */
++ extern bool CHNL_Init(void);
++
++
++
++#endif /* CHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnl_sm.h b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+new file mode 100644
+index 0000000..789b9bd
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnl_sm.h
+@@ -0,0 +1,168 @@
++/*
++ * chnl_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl_sm.h ========
++ * Description:
++ * Prototypes for channel lower edge functions for a WinBRIDGE mini driver
++ * implementing data transfer via shared memory.
++ *
++ * Public Functions:
++ * CHNLSM_DisableInterrupt;
++ * CHNLSM_EnableInterrupt;
++ * CHNLSM_ISR;
++ * CHNLSM_Read;
++ * CHNLSM_UpdateSHMLength;
++ * CHNLSM_Write;
++ *
++ * Notes:
++ * These lower edge functions must be implemented by the WMD writer.
++ * Currently, CHNLSM_Read() and CHNLSM_Write() are not called, but must
++ * be defined to link.
++ *
++ */
++
++#ifndef CHNLSM_
++#define CHNLSM_
++
++#include <dspbridge/wmd.h>
++
++/*
++ * ======== CHNLSM_DisableInterrupt ========
++ * Purpose:
++ * Disable interrupts from the DSP board to the PC.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT*
++ hDevContext);
++
++/*
++ * ======== CHNLSM_EnableInterrupt ========
++ * Purpose:
++ * Enable interrupts from the DSP board to the PC.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT*
++ hDevContext);
++
++/*
++ * ======== CHNLSM_InterruptDSP2 ========
++ * Purpose:
++ * Set interrupt value & send an interrupt to the DSP processor(s).
++ * This is typicaly used when mailbox interrupt mechanisms allow data
++ * to be associated with interrupt such as for OMAP's CMD/DATA regs.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * wMbVal: Value associated with interrupt(e.g. mailbox value).
++ * Returns:
++ * DSP_SOK: Interrupt sent;
++ * else: Unable to send interrupt.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT*
++ hDevContext, u16 wMbVal);
++
++/*
++ * ======== CHNLSM_ISR ========
++ * Purpose:
++ * Mini-driver's ISR, called by WCD when the board interrupts the host.
++ * Parameters:
++ * hDevContext: Handle to the mini-driver defined device info.
++ * pfSchedDPC: Set to TRUE to schedule a deferred procedure call
++ * to advance the channel protocol. The channel class
++ * library will call the WMD's CHNLSM_DPC routine during
++ * its own DPC, before dispatching I/O.
++ * The channel class library should ignore *pfSchedDPC when
++ * CHNLSM_ISR returns FALSE.
++ * pwMBRegVal: Value of mailbox register.
++ * Returns:
++ * TRUE if this interrupt is was generated by the DSP board.
++ * FALSE otherwise.
++ * Requires:
++ * Interrupts to the host processor are disabled on entry.
++ * Must only call functions which are in page locked memory.
++ * Must only call asynchronous OS services.
++ * The EOI for this interrupt has already been sent to the PIC.
++ * Ensures:
++ * If the interrupt is *not* shared, this routine must return TRUE.
++ */
++ extern bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT bool *pfSchedDPC,
++ OUT u16 *pwIntrVal);
++
++/*
++ * ======== CHNLSM_Read ========
++ * Purpose:
++ * Read data from DSP board memory into a Host buffer.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Destination).
++ * dwDSPAddr: Address on DSP board (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_Read(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes);
++
++/*
++ * ======== CHNLSM_UpdateSHMLength ========
++ * Purpose:
++ * Allow the minidriver a chance to override the SHM length as reported
++ * to the mini driver (chnl_sm.lib) by Windows Plug and Play.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pSHMLength: Pointer to size of SHM window (in DSP words).
++ * Returns:
++ * TRUE if pSHMLength updated; FALSE otherwise.
++ * Requires:
++ * pSHMLength != NULL.
++ * Ensures:
++ * No more than sizeof(u32) bytes written to *pSHMLength
++ */
++ extern bool CHNLSM_UpdateSHMLength(struct WMD_DEV_CONTEXT *hDevContext,
++ IN OUT u32 *pSHMLength);
++
++/*
++ * ======== CHNLSM_Write ========
++ * Purpose:
++ * Write data from a Host buffer to DSP board memory.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Source).
++ * dwDSPAddr: Address on DSP board (Destination).
++ * ulNumBytes: Number of bytes to transfer.
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CHNLSM_Write(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes);
++
++#endif /* CHNLSM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnldefs.h b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
+new file mode 100644
+index 0000000..9f59229
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnldefs.h
+@@ -0,0 +1,92 @@
++/*
++ * chnldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnldefs.h ========
++ * Purpose:
++ * System-wide channel objects and constants.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Jan-2002 ag Added cBufSize to IOC.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 02-Dec-1999 ag: Added new chnl attribute pstrEventName.
++ *! 12-Nov-1999 kc: Enabled hEvent attribute for tests.
++ *! 01-Nov-1999 ag: hEvent attribute not supported(yet).
++ *! 16-Jan-1997 gp: Moved private stuff into chnlpriv.h
++ *! 14-Jan-1997 gp: Updated based on code review feedback:
++ *! Removed CHNL_MODENOWAIT, CHNL_MODEDIRECT,
++ *! 03-Jan-1997 gp: Added channel class library types.
++ *! 14-Dec-1996 gp: Moved uChnlId field from CHNL_ATTRS to CHNL_Open().
++ *! 10-Dec-1996 gp: Added CHNL_IsTimedOut() macro.
++ *! 14-Nov-1996 gp: Renamed from wsxchnl.h.
++ *! 09-Sep-1996 gp: Added hReserved2 field to CHNL_ATTRS. Updated CHNL_INFO.
++ *! 10-Jul-1996 gp: Created from channel.h.
++ */
++
++#ifndef CHNLDEFS_
++#define CHNLDEFS_
++
++/* Channel id option. */
++#define CHNL_PICKFREE (~0UL) /* Let manager pick a free channel. */
++
++/* Channel manager limits: */
++#define CHNL_INITIOREQS 4 /* Default # of I/O requests. */
++
++/* Channel modes */
++#define CHNL_MODETODSP 0x0000 /* Data streaming to the DSP. */
++#define CHNL_MODEFROMDSP 0x0001 /* Data streaming from the DSP. */
++
++/* GetIOCompletion flags */
++#define CHNL_IOCINFINITE 0xffffffff /* Wait forever for IO completion. */
++#define CHNL_IOCNOWAIT 0x0 /* Dequeue an IOC, if available. */
++
++/* IO Completion Record status: */
++#define CHNL_IOCSTATCOMPLETE 0x0000 /* IO Completed. */
++#define CHNL_IOCSTATCANCEL 0x0002 /* IO was cancelled */
++#define CHNL_IOCSTATTIMEOUT 0x0008 /* Wait for IOC timed out. */
++#define CHNL_IOCSTATEOS 0x8000 /* End Of Stream reached. */
++
++/* Macros for checking I/O Completion status: */
++#define CHNL_IsEOS(ioc) (ioc.status & CHNL_IOCSTATEOS)
++#define CHNL_IsIOComplete(ioc) (!(ioc.status & ~CHNL_IOCSTATEOS))
++#define CHNL_IsIOCancelled(ioc) (ioc.status & CHNL_IOCSTATCANCEL)
++#define CHNL_IsTimedOut(ioc) (ioc.status & CHNL_IOCSTATTIMEOUT)
++
++/* CHNL types: */
++ typedef u32 CHNL_MODE; /* Channel transfer mode. */
++
++/* Channel attributes: */
++ struct CHNL_ATTRS {
++ u32 uIOReqs; /* Max # of preallocated I/O requests. */
++ HANDLE hEvent; /* User supplied auto-reset event object. */
++ char *pstrEventName; /* Ptr to name of user event object. */
++ HANDLE hReserved1; /* Reserved for future use. */
++ u32 hReserved2; /* Reserved for future use. */
++
++ };
++
++/* I/O completion record: */
++ struct CHNL_IOC {
++ void *pBuf; /* Buffer to be filled/emptied. */
++ u32 cBytes; /* Bytes transferred. */
++ u32 cBufSize; /* Actual buffer size in bytes */
++ u32 status; /* Status of IO completion. */
++ u32 dwArg; /* User argument associated with pBuf. */
++ } ;
++
++#endif /* CHNLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/chnlpriv.h b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+new file mode 100644
+index 0000000..fdcda24
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/chnlpriv.h
+@@ -0,0 +1,136 @@
++/*
++ * chnlpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnlpriv.h ========
++ * Description:
++ * Private channel header shared between DSPSYS, WCD and WMD modules.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Jan-2002 ag Added cChannels(total # of chnls) to CHNL_MGRINFO struct.
++ *! Added private CHNL_[PCPY][ZCPY][DDMA].
++ *! 17-Nov-2000 jeh Removed IRQ, shared memory from CHNL_MGRATTRS, since these
++ *! now belong to IO_ATTRS.
++ *! 21-Jan-2000 ag: Code review comments added.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 11-Dec-1999 ag: Added CHNL_MAXLOCKPAGES for CHNL_PrepareBuffer().
++ *! 04-Dec-1999 ag: Added CHNL_MAXEVTNAMELEN for i/o compl named event support.
++ *! 01-Nov-1999 ag: CHNL_MAXCHANNELS set to 16 for 16-bit DSPs.
++ *! 27-Oct-1997 cr: Expanded CHNL_MAXIRQ from 0x0f to 0xff.
++ *! 16-Jan-1997 gp: Moved symbols into here from chnldefs.h.
++ *! 03-Jan-1997 gp: Added CHNL_MAXIRQ define.
++ *! 09-Dec-1996 gp: Removed CHNL_STATEIDLE.
++ *! 15-Jul-1996 gp: Created.
++ */
++
++#ifndef CHNLPRIV_
++#define CHNLPRIV_
++
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/devdefs.h>
++#include <dspbridge/sync.h>
++
++/* CHNL Object validation signatures: */
++#define CHNL_MGRSIGNATURE 0x52474D43 /* "CMGR" (in reverse). */
++#define CHNL_SIGNATURE 0x4C4E4843 /* "CHNL" (in reverse). */
++
++/* Channel manager limits: */
++#define CHNL_MAXCHANNELS 32 /* Max channels available per transport */
++
++
++/*
++ * Trans port channel Id definitions:(must match dsp-side).
++ *
++ * For CHNL_MAXCHANNELS = 16:
++ *
++ * ChnlIds:
++ * 0-15 (PCPY) - transport 0)
++ * 16-31 (DDMA) - transport 1)
++ * 32-47 (ZCPY) - transport 2)
++ */
++#define CHNL_PCPY 0 /* Proc-copy transport 0 */
++
++#define CHNL_MAXIRQ 0xff /* Arbitrarily large number. */
++
++/* The following modes are private: */
++#define CHNL_MODEUSEREVENT 0x1000 /* User provided the channel event. */
++#define CHNL_MODEMASK 0x1001
++
++/* Higher level channel states: */
++#define CHNL_STATEREADY 0x0000 /* Channel ready for I/O. */
++#define CHNL_STATECANCEL 0x0001 /* I/O was cancelled. */
++#define CHNL_STATEEOS 0x0002 /* End Of Stream reached. */
++
++/* Determine if user supplied an event for this channel: */
++#define CHNL_IsUserEvent(mode) (mode & CHNL_MODEUSEREVENT)
++
++/* Macros for checking mode: */
++#define CHNL_IsInput(mode) (mode & CHNL_MODEFROMDSP)
++#define CHNL_IsOutput(mode) (!CHNL_IsInput(mode))
++
++/* Types of channel class libraries: */
++#define CHNL_TYPESM 1 /* Shared memory driver. */
++#define CHNL_TYPEBM 2 /* Bus Mastering driver. */
++
++/* Max string length of channel I/O completion event name - change if needed */
++#define CHNL_MAXEVTNAMELEN 32
++
++/* Max memory pages lockable in CHNL_PrepareBuffer() - change if needed */
++#define CHNL_MAXLOCKPAGES 64
++
++/* Channel info. */
++ struct CHNL_INFO {
++ struct CHNL_MGR *hChnlMgr; /* Owning channel manager. */
++ u32 dwID; /* Channel ID. */
++ HANDLE hEvent; /* Channel I/O completion event. */
++ /*Abstraction of I/O completion event.*/
++ struct SYNC_OBJECT *hSyncEvent;
++ u32 dwMode; /* Channel mode. */
++ u32 dwState; /* Current channel state. */
++ u32 cPosition; /* Total bytes transferred. */
++ u32 cIOCs; /* Number of IOCs in queue. */
++ u32 cIOReqs; /* Number of IO Requests in queue. */
++ u32 hProcess; /* Process owning this channel. */
++ /*
++ * Name of channel I/O completion event. Not required in Linux
++ */
++ char szEventName[CHNL_MAXEVTNAMELEN + 1];
++ } ;
++
++/* Channel manager info: */
++ struct CHNL_MGRINFO {
++ u32 dwType; /* Type of channel class library. */
++ /* Channel handle, given the channel id. */
++ struct CHNL_OBJECT *hChnl;
++ u32 cOpenChannels; /* Number of open channels. */
++ u32 cChannels; /* total # of chnls supported */
++ } ;
++
++/* Channel Manager Attrs: */
++ struct CHNL_MGRATTRS {
++ /* Max number of channels this manager can use. */
++ u32 cChannels;
++ u32 uWordSize; /* DSP Word size. */
++ } ;
++
++#endif /* CHNLPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/clk.h b/arch/arm/plat-omap/include/dspbridge/clk.h
+new file mode 100644
+index 0000000..4a23dab
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/clk.h
+@@ -0,0 +1,155 @@
++/*
++ * clk.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== clk.h ========
++ * Purpose: Provides Clock functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 08-May-2007 rg: Moved all clock functions from sync module.
++ */
++
++#ifndef _CLK_H
++#define _CLK_H
++
++ /* Generic TIMER object: */
++ struct TIMER_OBJECT;
++ enum SERVICES_ClkId {
++ SERVICESCLK_iva2_ck = 0,
++ SERVICESCLK_mailbox_ick,
++ SERVICESCLK_gpt5_fck,
++ SERVICESCLK_gpt5_ick,
++ SERVICESCLK_gpt6_fck,
++ SERVICESCLK_gpt6_ick,
++ SERVICESCLK_gpt7_fck,
++ SERVICESCLK_gpt7_ick,
++ SERVICESCLK_gpt8_fck,
++ SERVICESCLK_gpt8_ick,
++ SERVICESCLK_wdt3_fck,
++ SERVICESCLK_wdt3_ick,
++ SERVICESCLK_mcbsp1_fck,
++ SERVICESCLK_mcbsp1_ick,
++ SERVICESCLK_mcbsp2_fck,
++ SERVICESCLK_mcbsp2_ick,
++ SERVICESCLK_mcbsp3_fck,
++ SERVICESCLK_mcbsp3_ick,
++ SERVICESCLK_mcbsp4_fck,
++ SERVICESCLK_mcbsp4_ick,
++ SERVICESCLK_mcbsp5_fck,
++ SERVICESCLK_mcbsp5_ick,
++ SERVICESCLK_ssi_fck,
++ SERVICESCLK_ssi_ick,
++ SERVICESCLK_sys_32k_ck,
++ SERVICESCLK_sys_ck,
++ SERVICESCLK_NOT_DEFINED
++ } ;
++
++/*
++ * ======== CLK_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CLK initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void CLK_Exit(void);
++
++/*
++ * ======== CLK_Init ========
++ * Purpose:
++ * Initializes private state of CLK module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * CLK initialized.
++ */
++ extern bool CLK_Init(void);
++
++
++/*
++ * ======== CLK_Enable ========
++ * Purpose:
++ * Enables the clock requested.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while enabling the clock.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id);
++
++/*
++ * ======== CLK_Disable ========
++ * Purpose:
++ * Disables the clock requested.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while disabling the clock.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id);
++
++/*
++ * ======== CLK_GetRate ========
++ * Purpose:
++ * Get the clock rate of requested clock.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while Getting the clock rate.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id,
++ u32 *speedMhz);
++/*
++ * ======== CLK_Set_32KHz ========
++ * Purpose:
++ * Set the requested clock to 32KHz.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Error occured while setting the clock parent to 32KHz.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id);
++ extern void SSI_Clk_Prepare(bool FLAG);
++
++/*
++ * ======== CLK_Get_RefCnt ========
++ * Purpose:
++ * get the reference count for the clock.
++ * Parameters:
++ * Returns:
++ * s32: Reference Count for the clock.
++ * DSP_EFAIL: Error occured while getting the reference count of a clock.
++ * Requires:
++ * Ensures:
++ */
++ extern s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id);
++
++#endif /* _SYNC_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cmm.h b/arch/arm/plat-omap/include/dspbridge/cmm.h
+new file mode 100644
+index 0000000..0df8b83
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cmm.h
+@@ -0,0 +1,420 @@
++/*
++ * cmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== cmm.h ========
++ * Purpose:
++ * The Communication Memory Management(CMM) module provides shared memory
++ * management services for DSP/BIOS Bridge data streaming and messaging.
++ * Multiple shared memory segments can be registered with CMM. Memory is
++ * coelesced back to the appropriate pool when a buffer is freed.
++ *
++ * The CMM_Xlator[xxx] functions are used for node messaging and data
++ * streaming address translation to perform zero-copy inter-processor
++ * data transfer(GPP<->DSP). A "translator" object is created for a node or
++ * stream object that contains per thread virtual address information. This
++ * translator info is used at runtime to perform SM address translation
++ * to/from the DSP address space.
++ *
++ *
++ * Public Functions:
++ * CMM_CallocBuf
++ * CMM_Create
++ * CMM_Destroy
++ * CMM_Exit
++ * CMM_FreeBuf
++ * CMM_GetHandle
++ * CMM_GetInfo
++ * CMM_Init
++ * CMM_RegisterGPPSMSeg
++ * CMM_UnRegisterGPPSMSeg
++ * CMM_XlatorAllocBuf (Note #1 below)
++ * CMM_XlatorCreate "
++ * CMM_XlatorDelete "
++ * CMM_XlatorFreeBuf "
++ * CMM_XlatorTranslate "
++ *
++ *
++ * Notes:
++ * #1: Used by Node and Stream modules for SM address translation.
++ *
++ *! Revision History:
++ *! ================
++ *! 30-Jan-2002 ag Removed unused CMM_Alloc[Free]Desc & CMM_XlatorRegisterPa.
++ *! Renamed CMM_AllocBuf() to CMM_CallocBuf().
++ *! 29-Aug-2001 ag: Added dsp virt base and size to CMM_RegisterGPPSMSeg().
++ *! 12-Aug-2001 ag: Added CMM_UnRegisterGPP[DSP}SMSeg[s]().
++ *! 05-Dec-2000 ag: Added param to CMM_XlatorDelete() to force buf cleanup.
++ *! 30-Oct-2000 ag: Added conversion factor to CMM_RegisterDSP[GPP]SMSeg().
++ *! 12-Oct-2000 ag: Added CMM_Xlator[xxx] functions.
++ *! 10-Aug-2000 ag: Created.
++ *!
++ */
++
++#ifndef CMM_
++#define CMM_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/cmmdefs.h>
++#include <dspbridge/host_os.h>
++
++/*
++ * ======== CMM_CallocBuf ========
++ * Purpose:
++ * Allocate memory buffers that can be used for data streaming or
++ * messaging.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * uSize: Number of bytes to allocate.
++ * pAttr: Attributes of memory to allocate.
++ * ppBufVA: Address of where to place VA.
++ * Returns:
++ * Pointer to a zero'd block of SM memory;
++ * NULL if memory couldn't be allocated,
++ * or if cBytes == 0,
++ * Requires:
++ * Valid hCmmMgr.
++ * CMM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested.
++ *
++ */
++ extern void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr,
++ u32 uSize, struct CMM_ATTRS *pAttrs,
++ OUT void **ppBufVA);
++
++/*
++ * ======== CMM_Create ========
++ * Purpose:
++ * Create a communication memory manager object.
++ * Parameters:
++ * phCmmMgr: Location to store a communication manager handle on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Comm mem manager attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: Failed to initialize critical sect sync object.
++ *
++ * Requires:
++ * CMM_Init(void) called.
++ * phCmmMgr != NULL.
++ * pMgrAttrs->ulMinBlockSize >= 4 bytes.
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CMM_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== CMM_Destroy ========
++ * Purpose:
++ * Destroy the communication memory manager object.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * bForce: Force deallocation of all cmm memory immediately if set TRUE.
++ * If FALSE, and outstanding allocations will return DSP_EFAIL
++ * status.
++ * Returns:
++ * DSP_SOK: CMM object & resources deleted.
++ * DSP_EFAIL: Unable to free CMM object due to outstanding allocation.
++ * DSP_EHANDLE: Unable to free CMM due to bad handle.
++ * Requires:
++ * CMM is initialized.
++ * hCmmMgr != NULL.
++ * Ensures:
++ * Memory resources used by Cmm Mgr are freed.
++ */
++ extern DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce);
++
++/*
++ * ======== CMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module. Cleanup CMM module if CMM cRef reaches zero.
++ * Parameters:
++ * n/a
++ * Returns:
++ * n/a
++ * Requires:
++ * CMM is initialized.
++ * Ensures:
++ */
++ extern void CMM_Exit(void);
++
++/*
++ * ======== CMM_FreeBuf ========
++ * Purpose:
++ * Free the given buffer.
++ * Parameters:
++ * hCmmMgr: Cmm Mgr handle.
++ * pBuf: Pointer to memory allocated by CMM_CallocBuf().
++ * ulSegId: SM segment Id used in CMM_Calloc() attrs.
++ * Set to 0 to use default segment.
++ * Returns:
++ * DSP_SOK
++ * DSP_EFAIL
++ * Requires:
++ * CMM initialized.
++ * pBufPA != NULL
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr,
++ void *pBufPA, u32 ulSegId);
++
++/*
++ * ======== CMM_GetHandle ========
++ * Purpose:
++ * Return the handle to the cmm mgr for the given device obj.
++ * Parameters:
++ * hProcessor: Handle to a Processor.
++ * phCmmMgr: Location to store the shared memory mgr handle on output.
++ *
++ * Returns:
++ * DSP_SOK: Cmm Mgr opaque handle returned.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * phCmmMgr != NULL
++ * hDevObject != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct CMM_OBJECT **phCmmMgr);
++
++/*
++ * ======== CMM_GetInfo ========
++ * Purpose:
++ * Return the current SM and VM utilization information.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * pCmmInfo: Location to store the Cmm information on output.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * DSP_EINVALIDARG Invalid input argument.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
++ OUT struct CMM_INFO *pCmmInfo);
++
++/*
++ * ======== CMM_Init ========
++ * Purpose:
++ * Initializes private state of CMM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * CMM initialized.
++ */
++ extern bool CMM_Init(void);
++
++/*
++ * ======== CMM_RegisterGPPSMSeg ========
++ * Purpose:
++ * Register a block of SM with the CMM.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * lpGPPBasePA: GPP Base Physical address.
++ * ulSize: Size in GPP bytes.
++ * dwDSPAddrOffset GPP PA to DSP PA Offset.
++ * cFactor: Add offset if CMM_ADDTODSPPA, sub if CMM_SUBFROMDSPPA.
++ * dwDSPBase: DSP virtual base byte address.
++ * ulDSPSize: Size of DSP segment in bytes.
++ * pulSegId: Address to store segment Id.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hCmmMgr handle.
++ * DSP_EINVALIDARG: Invalid input argument.
++ * DSP_EFAIL: Unable to register.
++ * - On success *pulSegId is a valid SM segment ID.
++ * Requires:
++ * ulSize > 0
++ * pulSegId != NULL
++ * dwGPPBasePA != 0
++ * cFactor = CMM_ADDTODSPPA || cFactor = CMM_SUBFROMDSPPA
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
++ unsigned int dwGPPBasePA,
++ u32 ulSize,
++ u32 dwDSPAddrOffset,
++ enum CMM_CNVTTYPE cFactor,
++ unsigned int dwDSPBase,
++ u32 ulDSPSize,
++ u32 *pulSegId,
++ u32 dwGPPBaseBA);
++
++/*
++ * ======== CMM_UnRegisterGPPSMSeg ========
++ * Purpose:
++ * Unregister the given memory segment that was previously registered
++ * by CMM_RegisterGPPSMSeg.
++ * Parameters:
++ * hCmmMgr: Handle to a Cmm Mgr.
++ * ulSegId Segment identifier returned by CMM_RegisterGPPSMSeg.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * DSP_EINVALIDARG: Invalid ulSegId.
++ * DSP_EFAIL: Unable to unregister for unknown reason.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr,
++ u32 ulSegId);
++
++/*
++ * ======== CMM_XlatorAllocBuf ========
++ * Purpose:
++ * Allocate the specified SM buffer and create a local memory descriptor.
++ * Place on the descriptor on the translator's HaQ (Host Alloc'd Queue).
++ * Parameters:
++ * hXlator: Handle to a Xlator object.
++ * pVaBuf: Virtual address ptr(client context)
++ * uPaSize: Size of SM memory to allocate.
++ * Returns:
++ * Ptr to valid physical address(Pa) of uPaSize bytes, NULL if failed.
++ * Requires:
++ * pVaBuf != 0.
++ * uPaSize != 0.
++ * Ensures:
++ *
++ */
++ extern void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator,
++ void *pVaBuf, u32 uPaSize);
++
++/*
++ * ======== CMM_XlatorCreate ========
++ * Purpose:
++ * Create a translator(xlator) object used for process specific Va<->Pa
++ * address translation. Node messaging and streams use this to perform
++ * inter-processor(GPP<->DSP) zero-copy data transfer.
++ * Parameters:
++ * phXlator: Address to place handle to a new Xlator handle.
++ * hCmmMgr: Handle to Cmm Mgr associated with this translator.
++ * pXlatorAttrs: Translator attributes used for the client NODE or STREAM.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Bad input Attrs.
++ * DSP_EMEMORY: Insufficient memory(local) for requested resources.
++ * Requires:
++ * phXlator != NULL
++ * hCmmMgr != NULL
++ * pXlatorAttrs != NULL
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
++ struct CMM_OBJECT *hCmmMgr,
++ struct CMM_XLATORATTRS *pXlatorAttrs);
++
++/*
++ * ======== CMM_XlatorDelete ========
++ * Purpose:
++ * Delete translator resources
++ * Parameters:
++ * hXlator: handle to translator.
++ * bForce: bForce = TRUE will free XLators SM buffers/dscriptrs.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * DSP_EFAIL: Unable to free translator resources.
++ * Requires:
++ * cRefs > 0
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator,
++ bool bForce);
++
++/*
++ * ======== CMM_XlatorFreeBuf ========
++ * Purpose:
++ * Free SM buffer and descriptor.
++ * Does not free client process VM.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pBufVa Virtual address of PA to free.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * Requires:
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator,
++ void *pBufVa);
++
++/*
++ * ======== CMM_XlatorInfo ========
++ * Purpose:
++ * Set/Get process specific "translator" address info.
++ * This is used to perform fast virtaul address translation
++ * for shared memory buffers between the GPP and DSP.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pAddr: Virtual base address of segment.
++ * ulSize: Size in bytes.
++ * uSegId: Segment identifier of SM segment(s)
++ * bSetInfo Set xlator fields if TRUE, else return base addr
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Bad translator handle.
++ * Requires:
++ * (cRefs > 0)
++ * (pAddr != NULL)
++ * (ulSize > 0)
++ * Ensures:
++ *
++ */
++ extern DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator,
++ IN OUT u8 **pAddr,
++ u32 ulSize, u32 uSegId,
++ bool bSetInfo);
++
++/*
++ * ======== CMM_XlatorTranslate ========
++ * Purpose:
++ * Perform address translation VA<->PA for the specified stream or
++ * message shared memory buffer.
++ * Parameters:
++ * hXlator: handle to translator.
++ * pAddr address of buffer to translate.
++ * xType Type of address xlation. CMM_PA2VA or CMM_VA2PA.
++ * Returns:
++ * Valid address on success, else NULL.
++ * Requires:
++ * cRefs > 0
++ * pAddr != NULL
++ * xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA)
++ * Ensures:
++ *
++ */
++ extern void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator,
++ void *pAddr, enum CMM_XLATETYPE xType);
++
++#endif /* CMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cmmdefs.h b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+new file mode 100644
+index 0000000..a779377
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cmmdefs.h
+@@ -0,0 +1,135 @@
++/*
++ * cmmdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cmmdefs.h ========
++ * Purpose:
++ * Global MEM constants and types.
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Nov-2001 ag CMM_KERNMAPTYPE added for dsp<->device process addr map'n.
++ *! This allows addr conversion from drvr process <-> DSP addr.
++ *! 29-Aug-2001 ag Added CMM_ALLSEGMENTS.
++ *! 08-Dec-2000 ag Added bus address conversion type CMM_POMAPEMIF2DSPBUS.
++ *! 05-Dec-2000 ag Added default CMM_DEFLTCONVFACTOR & CMM_DEFLTDSPADDROFFSET.
++ *! 29-Oct-2000 ag Added converstion factor for GPP DSP Pa translation.
++ *! 15-Oct-2000 ag Added address translator attributes and defaults.
++ *! 12-Jul-2000 ag Created.
++ */
++
++#ifndef CMMDEFS_
++#define CMMDEFS_
++
++#include <dspbridge/list.h>
++
++/* Cmm attributes used in CMM_Create() */
++ struct CMM_MGRATTRS {
++ /* Minimum SM allocation; default 32 bytes. */
++ u32 ulMinBlockSize;
++ } ;
++
++/* Attributes for CMM_AllocBuf() & CMM_AllocDesc() */
++ struct CMM_ATTRS {
++ u32 ulSegId; /* 1,2... are SM segments. 0 is not. */
++ u32 ulAlignment; /* 0,1,2,4....ulMinBlockSize */
++ } ;
++
++/*
++ * DSPPa to GPPPa Conversion Factor.
++ *
++ * For typical platforms:
++ * converted Address = PaDSP + ( cFactor * addressToConvert).
++ */
++ enum CMM_CNVTTYPE {
++ CMM_SUBFROMDSPPA = -1,
++ /* PreOMAP is special case: not simple offset */
++ CMM_POMAPEMIF2DSPBUS = 0,
++ CMM_ADDTODSPPA = 1
++ } ;
++
++#define CMM_DEFLTDSPADDROFFSET 0
++#define CMM_DEFLTCONVFACTOR CMM_POMAPEMIF2DSPBUS /* PreOMAP DSPBUS<->EMIF */
++#define CMM_ALLSEGMENTS 0xFFFFFF /* All SegIds */
++#define CMM_MAXGPPSEGS 1 /* Maximum # of SM segs */
++
++/*
++ * SMSEGs are SM segments the DSP allocates from.
++ *
++ * This info is used by the GPP to xlate DSP allocated PAs.
++ */
++
++ struct CMM_SEGINFO {
++ u32 dwSegBasePa; /* Start Phys address of SM segment */
++ /* Total size in bytes of segment: DSP+GPP */
++ u32 ulTotalSegSize;
++ u32 dwGPPBasePA; /* Start Phys addr of Gpp SM seg */
++ u32 ulGPPSize; /* Size of Gpp SM seg in bytes */
++ u32 dwDSPBaseVA; /* DSP virt base byte address */
++ u32 ulDSPSize; /* DSP seg size in bytes */
++ /* # of current GPP allocations from this segment */
++ u32 ulInUseCnt;
++ u32 dwSegBaseVa; /* Start Virt address of SM seg */
++
++ } ;
++
++/* CMM useful information */
++ struct CMM_INFO {
++ /* # of SM segments registered with this Cmm. */
++ u32 ulNumGPPSMSegs;
++ /* Total # of allocations outstanding for CMM */
++ u32 ulTotalInUseCnt;
++ /* Min SM block size allocation from CMM_Create() */
++ u32 ulMinBlockSize;
++ /* Info per registered SM segment. */
++ struct CMM_SEGINFO segInfo[CMM_MAXGPPSEGS];
++ } ;
++
++/* XlatorCreate attributes */
++ struct CMM_XLATORATTRS {
++ u32 ulSegId; /* segment Id used for SM allocations */
++ u32 dwDSPBufs; /* # of DSP-side bufs */
++ u32 dwDSPBufSize; /* size of DSP-side bufs in GPP bytes */
++ /* Vm base address alloc'd in client process context */
++ void *pVmBase;
++ /* dwVmSize must be >= (dwMaxNumBufs * dwMaxSize) */
++ u32 dwVmSize;
++ } ;
++
++/*
++ * Cmm translation types. Use to map SM addresses to process context.
++ */
++ enum CMM_XLATETYPE {
++ CMM_VA2PA = 0, /* Virtual to GPP physical address xlation */
++ CMM_PA2VA = 1, /* GPP Physical to virtual */
++ CMM_VA2DSPPA = 2, /* Va to DSP Pa */
++ CMM_PA2DSPPA = 3, /* GPP Pa to DSP Pa */
++ CMM_DSPPA2PA = 4, /* DSP Pa to GPP Pa */
++ } ;
++
++/*
++ * Used to "map" between device process virt addr and dsp addr.
++ */
++ enum CMM_KERNMAPTYPE {
++ CMM_KERNVA2DSP = 0, /* Device process context to dsp address. */
++ CMM_DSP2KERNVA = 1, /* Dsp address to device process context. */
++ } ;
++
++ struct CMM_OBJECT;
++ struct CMM_XLATOROBJECT;
++
++#endif /* CMMDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/cod.h b/arch/arm/plat-omap/include/dspbridge/cod.h
+new file mode 100644
+index 0000000..a8a12c6
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/cod.h
+@@ -0,0 +1,433 @@
++/*
++ * cod.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cod.h ========
++ * Description:
++ * Code management module for DSPs. This module provides an interface
++ * interface for loading both static and dynamic code objects onto DSP
++ * systems.
++ *
++ * Public Functions:
++ * COD_Close
++ * COD_Create
++ * COD_Delete
++ * COD_Exit
++ * COD_GetBaseLib
++ * COD_GetBaseName
++ * COD_GetLoader
++ * COD_GetSection
++ * COD_GetSymValue
++ * COD_Init
++ * COD_LoadBase
++ * COD_Open
++ * COD_OpenBase
++ * COD_ReadSection
++ * COD_UnloadSection
++ *
++ * Note:
++ * Currently, only static loading is supported.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map: Changed DBL to DBLL
++ *! 07-Aug-2002 jeh: Added COD_GetBaseName().
++ *! 17-Jul-2002 jeh: Added COD_Open(), COD_Close().
++ *! 15-Mar-2002 jeh: Added DBL_Flags param to COD_OpenBase().
++ *! 19-Oct-2001 jeh: Added COD_GetBaseLib, COD_GetLoader, (left in
++ *! COD_LoadSection(), COD_UnloadSection(), since they
++ *! may be needed for BridgeLite).
++ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
++ *! 11-Jan-2001 jeh: Added COD_OpenBase.
++ *! 29-Sep-2000 kc: Added size param to COD_ReadSection for input buffer
++ *! validation.
++ *! 02-Aug-2000 kc: Added COD_ReadSection.
++ *! 04-Sep-1997 gp: Added CDECL identifier to COD_WRITEFXN (for NT)..
++ *! 18-Aug-1997 cr: Added explicit CDECL identifier.
++ *! 28-Oct-1996 gp: Added COD_GetSection.
++ *! 30-Jul-1996 gp: Added envp[] argument to COD_LoadBase().
++ *! 12-Jun-1996 gp: Moved OUT param first in _Create(). Updated _Create()
++ *! call to take a ZLFileName. Moved COD_ processor types
++ *! to CFG.
++ *! 29-May-1996 gp: Changed WCD_STATUS to DSP_STATUS. Removed include's.
++ *! 07-May-1996 mg: Created.
++ *
++ */
++
++#ifndef COD_
++#define COD_
++
++#include <dspbridge/dblldefs.h>
++
++#define COD_MAXPATHLENGTH 255
++#define COD_TRACEBEG "SYS_PUTCBEG"
++#define COD_TRACEEND "SYS_PUTCEND"
++#define COD_TRACESECT "trace"
++#define COD_TRACEBEGOLD "PUTCBEG"
++#define COD_TRACEENDOLD "PUTCEND"
++
++#define COD_NOLOAD DBLL_NOLOAD
++#define COD_SYMB DBLL_SYMB
++
++/* Flags passed to COD_Open */
++ typedef DBLL_Flags COD_FLAGS;
++
++/* COD code manager handle */
++ struct COD_MANAGER;
++
++/* COD library handle */
++ struct COD_LIBRARYOBJ;
++
++/* COD attributes */
++ struct COD_ATTRS {
++ u32 ulReserved;
++ } ;
++
++/*
++ * Function prototypes for writing memory to a DSP system, allocating
++ * and freeing DSP memory.
++ */
++ typedef u32(*COD_WRITEFXN) (void *pPrivRef, u32 ulDspAddr,
++ void *pBuf, u32 ulNumBytes,
++ u32 nMemSpace);
++
++
++/*
++ * ======== COD_Close ========
++ * Purpose:
++ * Close a library opened with COD_Open().
++ * Parameters:
++ * lib - Library handle returned by COD_Open().
++ * Returns:
++ * None.
++ * Requires:
++ * COD module initialized.
++ * valid lib.
++ * Ensures:
++ *
++ */
++ extern void COD_Close(struct COD_LIBRARYOBJ *lib);
++
++/*
++ * ======== COD_Create ========
++ * Purpose:
++ * Create an object to manage code on a DSP system. This object can be
++ * used to load an initial program image with arguments that can later
++ * be expanded with dynamically loaded object files.
++ * Symbol table information is managed by this object and can be retrieved
++ * using the COD_GetSymValue() function.
++ * Parameters:
++ * phManager: created manager object
++ * pstrZLFile: ZL DLL filename, of length < COD_MAXPATHLENGTH.
++ * attrs: attributes to be used by this object. A NULL value
++ * will cause default attrs to be used.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_NOZLFUNCTIONS: Could not initialize ZL functions.
++ * COD_E_ZLCREATEFAILED: ZL_Create failed.
++ * DSP_ENOTIMPL: attrs was not NULL. We don't yet support
++ * non default values of attrs.
++ * Requires:
++ * COD module initialized.
++ * pstrZLFile != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS COD_Create(OUT struct COD_MANAGER **phManager,
++ char *pstrZLFile,
++ IN OPTIONAL CONST struct COD_ATTRS *attrs);
++
++/*
++ * ======== COD_Delete ========
++ * Purpose:
++ * Delete a code manager object.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * Returns:
++ * None.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * Ensures:
++ */
++ extern void COD_Delete(struct COD_MANAGER *hManager);
++
++/*
++ * ======== COD_Exit ========
++ * Purpose:
++ * Discontinue usage of the COD module.
++ * Parameters:
++ * None.
++ * Returns:
++ * None.
++ * Requires:
++ * COD initialized.
++ * Ensures:
++ * Resources acquired in COD_Init(void) are freed.
++ */
++ extern void COD_Exit(void);
++
++/*
++ * ======== COD_GetBaseLib ========
++ * Purpose:
++ * Get handle to the base image DBL library.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * plib: location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * plib != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
++ struct DBLL_LibraryObj **plib);
++
++/*
++ * ======== COD_GetBaseName ========
++ * Purpose:
++ * Get the name of the base image DBL library.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * pszName: location to store library name on output.
++ * uSize: size of name buffer.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Buffer too small.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pszName != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager,
++ char *pszName, u32 uSize);
++
++/*
++ * ======== COD_GetEntry ========
++ * Purpose:
++ * Retrieve the entry point of a loaded DSP program image
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * pulEntry: pointer to location for entry point
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pulEntry != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager,
++ u32 *pulEntry);
++
++/*
++ * ======== COD_GetLoader ========
++ * Purpose:
++ * Get handle to the DBL loader.
++ * Parameters:
++ * hManager: handle of manager to be deleted
++ * phLoader: location to store loader handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * phLoader != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
++ struct DBLL_TarObj **phLoader);
++
++/*
++ * ======== COD_GetSection ========
++ * Purpose:
++ * Retrieve the starting address and length of a section in the COFF file
++ * given the section name.
++ * Parameters:
++ * lib Library handle returned from COD_Open().
++ * pstrSect: name of the section, with or without leading "."
++ * puAddr: Location to store address.
++ * puLen: Location to store length.
++ * Returns:
++ * DSP_SOK: Success
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pstrSect != NULL;
++ * puAddr != NULL;
++ * puLen != NULL;
++ * Ensures:
++ * DSP_SOK: *puAddr and *puLen contain the address and length of the
++ * section.
++ * else: *puAddr == 0 and *puLen == 0;
++ *
++ */
++ extern DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib,
++ IN char *pstrSect,
++ OUT u32 *puAddr,
++ OUT u32 *puLen);
++
++/*
++ * ======== COD_GetSymValue ========
++ * Purpose:
++ * Retrieve the value for the specified symbol. The symbol is first
++ * searched for literally and then, if not found, searched for as a
++ * C symbol.
++ * Parameters:
++ * lib: library handle returned from COD_Open().
++ * pstrSymbol: name of the symbol
++ * value: value of the symbol
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * COD module initialized.
++ * Valid hManager.
++ * pstrSym != NULL.
++ * pulValue != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hManager,
++ IN char *pstrSym,
++ OUT u32 *pulValue);
++
++/*
++ * ======== COD_Init ========
++ * Purpose:
++ * Initialize the COD module's private state.
++ * Parameters:
++ * None.
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public COD functions.
++ */
++ extern bool COD_Init(void);
++
++/*
++ * ======== COD_LoadBase ========
++ * Purpose:
++ * Load the initial program image, optionally with command-line arguments,
++ * on the DSP system managed by the supplied handle. The program to be
++ * loaded must be the first element of the args array and must be a fully
++ * qualified pathname.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * nArgc: number of arguments in the args array
++ * args: array of strings for arguments to DSP program
++ * writeFxn: board-specific function to write data to DSP system
++ * pArb: arbitrary pointer to be passed as first arg to writeFxn
++ * envp: array of environment strings for DSP exec.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * COD_E_LOADFAILED: Failed to load code onto target.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * nArgc > 0.
++ * aArgs != NULL.
++ * aArgs[0] != NULL.
++ * pfnWrite != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_LoadBase(struct COD_MANAGER *hManager,
++ u32 nArgc, char *aArgs[],
++ COD_WRITEFXN pfnWrite, void *pArb,
++ char *envp[]);
++
++
++/*
++ * ======== COD_Open ========
++ * Purpose:
++ * Open a library for reading sections. Does not load or set the base.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * pszCoffPath: Coff file to open.
++ * flags: COD_NOLOAD (don't load symbols) or COD_SYMB (load
++ * symbols).
++ * pLib: Handle returned that can be used in calls to COD_Close
++ * and COD_GetSection.
++ * Returns:
++ * S_OK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * flags == COD_NOLOAD || flags == COD_SYMB.
++ * pszCoffPath != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS COD_Open(struct COD_MANAGER *hMgr,
++ IN char *pszCoffPath,
++ COD_FLAGS flags,
++ OUT struct COD_LIBRARYOBJ **pLib);
++
++/*
++ * ======== COD_OpenBase ========
++ * Purpose:
++ * Open base image for reading sections. Does not load the base.
++ * Parameters:
++ * hMgr: manager to load the code with
++ * pszCoffPath: Coff file to open.
++ * flags: Specifies whether to load symbols.
++ * Returns:
++ * DSP_SOK: Success.
++ * COD_E_OPENFAILED: Failed to open target code.
++ * Requires:
++ * COD module initialized.
++ * hMgr is valid.
++ * pszCoffPath != NULL.
++ * Ensures:
++ */
++extern DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ DBLL_Flags flags);
++
++/*
++ * ======== COD_ReadSection ========
++ * Purpose:
++ * Retrieve the content of a code section given the section name.
++ * Parameters:
++ * hManager - manager in which to search for the symbol
++ * pstrSect - name of the section, with or without leading "."
++ * pstrContent - buffer to store content of the section.
++ * Returns:
++ * DSP_SOK: on success, error code on failure
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_READFAILED: Failed to read content of code section.
++ * Requires:
++ * COD module initialized.
++ * valid hManager.
++ * pstrSect != NULL;
++ * pstrContent != NULL;
++ * Ensures:
++ * DSP_SOK: *pstrContent stores the content of the named section.
++ */
++ extern DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib,
++ IN char *pstrSect,
++ OUT char *pstrContent,
++ IN u32 cContentSize);
++
++
++
++#endif /* COD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/csl.h b/arch/arm/plat-omap/include/dspbridge/csl.h
+new file mode 100644
+index 0000000..b90d6ff
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/csl.h
+@@ -0,0 +1,135 @@
++/*
++ * csl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== csl.h ========
++ * Purpose:
++ * Platform independent C Standard library functions.
++ *
++ * Public Functions:
++ * CSL_AnsiToWchar
++ * CSL_ByteSwap
++ * CSL_Exit
++ * CSL_Init
++ * CSL_NumToAscii
++ * CSL_Strtok
++ * CSL_Strtokr
++ * CSL_WcharToAnsi
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
++ *! 21-Sep-2001 jeh: Added CSL_Strncmp.
++ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
++ *! 19-Nov-2000 kc: Added CSL_ByteSwap().
++ *! 09-Nov-2000 kc: Added CSL_Strncat.
++ *! 29-Oct-1999 kc: Added CSL_Wstrlen().
++ *! 20-Sep-1999 ag: Added CSL_Wchar2Ansi().
++ *! 19-Jan-1998 cr: Code review cleanup (mostly documentation fixes).
++ *! 29-Dec-1997 cr: Changed CSL_lowercase to CSL_Uppercase, added
++ *! CSL_AnsiToWchar.
++ *! 30-Sep-1997 cr: Added explicit cdecl descriptors to fxn definitions.
++ *! 25-Jun-1997 cr: Added CSL_strcmp.
++ *! 12-Jun-1996 gp: Created.
++ */
++
++#ifndef CSL_
++#define CSL_
++
++#include <dspbridge/host_os.h>
++
++/*
++ * ======== CSL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CSL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * CSL initialized.
++ * Ensures:
++ * Resources acquired in CSL_Init(void) are freed.
++ */
++ extern void CSL_Exit(void);
++
++/*
++ * ======== CSL_Init ========
++ * Purpose:
++ * Initialize the CSL module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CSL functions.
++ */
++ extern bool CSL_Init(void);
++
++/*
++ * ======== CSL_NumToAscii ========
++ * Purpose:
++ * Convert a 1 or 2 digit number to a 2 digit string.
++ * Parameters:
++ * pstrNumber: Buffer to store converted string.
++ * dwNum: Number to convert.
++ * Returns:
++ * Requires:
++ * pstrNumber must be able to hold at least three characters.
++ * Ensures:
++ * pstrNumber will be null terminated.
++ */
++ extern void CSL_NumToAscii(OUT char *pstrNumber, IN u32 dwNum);
++
++
++/*
++ * ======== CSL_Strtok ========
++ * Purpose:
++ * Tokenize a NULL terminated string
++ * Parameters:
++ * ptstrSrc: pointer to string.
++ * szSeparators: pointer to a string of seperators
++ * Returns:
++ * char *
++ * Requires:
++ * CSL initialized.
++ * ptstrSrc is a valid string pointer.
++ * szSeparators is a valid string pointer.
++ * Ensures:
++ */
++ extern char *CSL_Strtok(IN char *ptstrSrc,
++ IN CONST char *szSeparators);
++
++/*
++ * ======== CSL_Strtokr ========
++ * Purpose:
++ * Re-entrant version of strtok.
++ * Parameters:
++ * pstrSrc: Pointer to string. May be NULL on subsequent calls.
++ * szSeparators: Pointer to a string of seperators
++ * ppstrCur: Location to store start of string for next call to
++ * to CSL_Strtokr.
++ * Returns:
++ * char * (the token)
++ * Requires:
++ * CSL initialized.
++ * szSeparators != NULL
++ * ppstrCur != NULL
++ * Ensures:
++ */
++ extern char *CSL_Strtokr(IN char *pstrSrc,
++ IN CONST char *szSeparators,
++ OUT char **ppstrCur);
++
++#endif /* CSL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbc.h b/arch/arm/plat-omap/include/dspbridge/dbc.h
+new file mode 100644
+index 0000000..0e6a67d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbc.h
+@@ -0,0 +1,66 @@
++/*
++ * dbc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbc.h ========
++ * Purpose:
++ * "Design by Contract" programming macros.
++ *
++ * Public Functions:
++ * DBC_Assert
++ * DBC_Require
++ * DBC_Ensure
++ *
++ * Notes:
++ * Requires that the GT->ERROR function has been defaulted to a valid
++ * error handler for the given execution environment.
++ *
++ * Does not require that GT_init() be called.
++ *
++ *! Revision History:
++ *! ================
++ *! 11-Aug-2000 ag: Removed include <dspbridge/std.h>
++ *! 22-Apr-1996 gp: Created.
++ */
++
++#ifndef DBC_
++#define DBC_
++
++#ifndef GT_TRACE
++#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
++#endif
++
++/* Assertion Macros: */
++#if GT_TRACE
++
++#include <dspbridge/gt.h>
++
++#define DBC_Assert(exp) \
++ if (!(exp)) \
++ printk("%s, line %d: Assertion (" #exp ") failed.\n", \
++ __FILE__, __LINE__)
++#define DBC_Require DBC_Assert /* Function Precondition. */
++#define DBC_Ensure DBC_Assert /* Function Postcondition. */
++
++#else
++
++#define DBC_Assert(exp)
++#define DBC_Require(exp)
++#define DBC_Ensure(exp)
++
++#endif /* DEBUG */
++
++#endif /* DBC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcd.h b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
+new file mode 100644
+index 0000000..fbc3870
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdcd.h
+@@ -0,0 +1,388 @@
++/*
++ * dbdcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbdcd.h ========
++ * Description:
++ * Defines the DSP/BIOS Bridge Configuration Database (DCD) API.
++ *
++ *! Revision History
++ *! ================
++ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
++ *! 24-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
++ *! DCD implementation.
++ *! 05-Aug-2002 jeh Added DCD_GetObjects().
++ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
++ *! 22-Apr-2002 jeh Added DCD_GetLibraryName().
++ *! 03-Apr-2001 sg Changed error names to have DCD_E* format.
++ *! 13-Feb-2001 kc Name changed from dcdbs.h to dbdcd.h.
++ *! 12-Dec-2000 kc Added DCD_AutoUnregister.
++ *! 09-Nov-2000 kc Updated usage of DCD_EnumerateObject.
++ *! 30-Oct-2000 kc Added DCD_AutoRegister. Updated error DCD error codes.
++ *! 29-Sep-2000 kc Incorporated code review comments. See
++ *! /src/reviews/dcd_review.txt.
++ *! 26-Jul-2000 kc Created.
++ *!
++ */
++
++#ifndef DBDCD_
++#define DBDCD_
++
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/host_os.h>
++#include <dspbridge/nldrdefs.h>
++
++/*
++ * ======== DCD_AutoRegister ========
++ * Purpose:
++ * This function automatically registers DCD objects specified in a
++ * special COFF section called ".dcd_register"
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing DCD
++ * objects to be registered.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto registration.
++ */
++ extern DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath);
++
++/*
++ * ======== DCD_AutoUnregister ========
++ * Purpose:
++ * This function automatically unregisters DCD objects specified in a
++ * special COFF section called ".dcd_register"
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing
++ * DCD objects to be unregistered.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find auto-registration section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto unregistration.
++ */
++ extern DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath);
++
++/*
++ * ======== DCD_CreateManager ========
++ * Purpose:
++ * This function creates a DCD module manager.
++ * Parameters:
++ * pszZlDllName: Pointer to a DLL name string.
++ * phDcdMgr: A pointer to a DCD manager handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory for DCD manager handle.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * pszZlDllName is non-NULL.
++ * phDcdMgr is non-NULL.
++ * Ensures:
++ * A DCD manager handle is created.
++ */
++ extern DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
++ OUT struct DCD_MANAGER **phDcdMgr);
++
++/*
++ * ======== DCD_DestroyManager ========
++ * Purpose:
++ * This function destroys a DCD module manager.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid DCD manager handle.
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr);
++
++/*
++ * ======== DCD_EnumerateObject ========
++ * Purpose:
++ * This function enumerates currently visible DSP/BIOS Bridge objects
++ * and returns the UUID and type of each enumerated object.
++ * Parameters:
++ * cIndex: The object enumeration index.
++ * objType: Type of object to enumerate.
++ * pUuid: Pointer to a DSP_UUID object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to enumerate through the DCD database.
++ * DSP_SENUMCOMPLETE: Enumeration completed. This is not an error code.
++ * Requires:
++ * DCD initialized.
++ * pUuid is a valid pointer.
++ * Ensures:
++ * Details:
++ * This function can be used in conjunction with DCD_GetObjectDef to
++ * retrieve object properties.
++ */
++ extern DSP_STATUS DCD_EnumerateObject(IN s32 cIndex,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DSP_UUID *pUuid);
++
++/*
++ * ======== DCD_Exit ========
++ * Purpose:
++ * This function cleans up the DCD module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ */
++ extern void DCD_Exit(void);
++
++/*
++ * ======== DCD_GetDepLibs ========
++ * Purpose:
++ * Given the uuid of a library and size of array of uuids, this function
++ * fills the array with the uuids of all dependent libraries of the input
++ * library.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID for a library.
++ * numLibs: Size of uuid array (number of library uuids).
++ * pDepLibUuids: Array of dependent library uuids to be filled in.
++ * pPersistentDepLibs: Array indicating if corresponding lib is persistent.
++ * phase: phase to obtain correct input library
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EDCDREADSECT: Failure to read section containing library info.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pUuid != NULL
++ * pDepLibUuids != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ u16 numLibs,
++ OUT struct DSP_UUID *pDepLibUuids,
++ OUT bool *pPersistentDepLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_GetNumDepLibs ========
++ * Purpose:
++ * Given the uuid of a library, determine its number of dependent
++ * libraries.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID for a library.
++ * pNumLibs: Size of uuid array (number of library uuids).
++ * pNumPersLibs: number of persistent dependent library.
++ * phase: Phase to obtain correct input library
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EDCDREADSECT: Failure to read section containing library info.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pUuid != NULL
++ * pNumLibs != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ OUT u16 *pNumLibs,
++ OUT u16 *pNumPersLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_GetLibraryName ========
++ * Purpose:
++ * This function returns the name of a (dynamic) library for a given
++ * UUID.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID that represents a unique DSP/BIOS
++ * Bridge object.
++ * pstrLibName: Buffer to hold library name.
++ * pdwSize: Contains buffer size. Set to string size on output.
++ * phase: Which phase to load
++ * fPhaseSplit: Are phases in multiple libraries
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * DCD initialized.
++ * Valid hDcdMgr.
++ * pstrLibName != NULL.
++ * pUuid != NULL
++ * pdwSize != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT char *pstrLibName,
++ IN OUT u32 *pdwSize,
++ IN enum NLDR_PHASE phase,
++ OUT bool *fPhaseSplit);
++
++/*
++ * ======== DCD_GetObjectDef ========
++ * Purpose:
++ * This function returns the properties/attributes of a DSP/BIOS Bridge
++ * object.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pUuid: Pointer to a DSP_UUID that represents a unique
++ * DSP/BIOS Bridge object.
++ * objType: The type of DSP/BIOS Bridge object to be
++ * referenced (node, processor, etc).
++ * pObjDef: Pointer to an object definition structure. A
++ * union of various possible DCD object types.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDPARSESECT: Unable to parse content of object code section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDGETSECT: Unable to access object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EFAIL: General failure.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle.
++ * Requires:
++ * DCD initialized.
++ * pObjUuid is non-NULL.
++ * pObjDef is non-NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pObjUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DCD_GENERICOBJ *pObjDef);
++
++/*
++ * ======== DCD_GetObjects ========
++ * Purpose:
++ * This function finds all DCD objects specified in a special
++ * COFF section called ".dcd_register", and for each object,
++ * call a "register" function. The "register" function may perform
++ * various actions, such as 1) register nodes in the node database, 2)
++ * unregister nodes from the node database, and 3) add overlay nodes.
++ * Parameters:
++ * hDcdMgr: A DCD manager handle.
++ * pszCoffPath: Pointer to name of COFF file containing DCD
++ * objects.
++ * registerFxn: Callback fxn to be applied on each located
++ * DCD object.
++ * handle: Handle to pass to callback.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EDCDNOAUTOREGISTER: Unable to find .dcd_register section.
++ * DSP_EDCDREADSECT: Unable to read object code section.
++ * DSP_EDCDLOADBASE: Unable to load code base.
++ * DSP_EHANDLE: Invalid DCD_HMANAGER handle..
++ * Requires:
++ * DCD initialized.
++ * Ensures:
++ * Note:
++ * Due to the DCD database construction, it is essential for a DCD-enabled
++ * COFF file to contain the right COFF sections, especially
++ * ".dcd_register", which is used for auto registration.
++ */
++ extern DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath,
++ DCD_REGISTERFXN registerFxn,
++ void *handle);
++
++/*
++ * ======== DCD_Init ========
++ * Purpose:
++ * This function initializes DCD.
++ * Parameters:
++ * Returns:
++ * FALSE: Initialization failed.
++ * TRUE: Initialization succeeded.
++ * Requires:
++ * Ensures:
++ * DCD initialized.
++ */
++ extern bool DCD_Init(void);
++
++/*
++ * ======== DCD_RegisterObject ========
++ * Purpose:
++ * This function registers a DSP/BIOS Bridge object in the DCD database.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID that identifies a DSP/BIOS
++ * Bridge object.
++ * objType: Type of object.
++ * pszPathName: Path to the object's COFF file.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to register object.
++ * Requires:
++ * DCD initialized.
++ * pUuid and szPathName are non-NULL values.
++ * objType is a valid type value.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN char *pszPathName);
++
++/*
++ * ======== DCD_UnregisterObject ========
++ * Purpose:
++ * This function de-registers a valid DSP/BIOS Bridge object from the DCD
++ * database.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID that identifies a DSP/BIOS Bridge
++ * object.
++ * objType: Type of object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to de-register the specified object.
++ * Requires:
++ * DCD initialized.
++ * pUuid is a non-NULL value.
++ * objType is a valid type value.
++ * Ensures:
++ */
++ extern DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType);
++
++#endif /* _DBDCD_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdcddef.h b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+new file mode 100644
+index 0000000..91b1c45
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdcddef.h
+@@ -0,0 +1,94 @@
++/*
++ * dbdcddef.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbdcddef.h ========
++ * Description:
++ * DCD (DSP/BIOS Bridge Configuration Database) constants and types.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Dec-2003 map Moved and renamed DCD_OBJTYPE to DSP_DCDOBJTYPE in dbdefs.h
++ *! 05-Dec-2002 map Added DCD_CREATELIBTYPE, DCD_EXECUTELIBTYPE,
++ * DCD_DELETELIBTYPE
++ *! 24-Feb-2003 kc Updated REG entry names to DspBridge.
++ *! 22-Nov-2002 gp Cleaned up comments, formatting.
++ *! 05-Aug-2002 jeh Added DCD_REGISTERFXN.
++ *! 19-Apr-2002 jeh Added DCD_LIBRARYTYPE to DCD_OBJTYPE, dynamic load
++ *! properties to DCD_NODEPROPS.
++ *! 29-Jul-2001 ag Added extended procObj.
++ *! 13-Feb-2001 kc: Named changed from dcdbsdef.h dbdcddef.h.
++ *! 12-Dec-2000 jeh Added DAIS iAlg name to DCD_NODEPROPS.
++ *! 30-Oct-2000 kc: Added #defines for DCD_AutoRegister function.
++ *! 05-Sep-2000 jeh Added DCD_NODEPROPS.
++ *! 12-Aug-2000 kc: Incoroporated the use of types defined in <dspdefs.h>.
++ *! 29-Jul-2000 kc: Created.
++ */
++
++#ifndef DBDCDDEF_
++#define DBDCDDEF_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/mgrpriv.h> /* for MGR_PROCESSOREXTINFO */
++
++/*
++ * The following defines are critical elements for the DCD module:
++ *
++ * - DCD_REGKEY enables DCD functions to locate registered DCD objects.
++ * - DCD_REGISTER_SECTION identifies the COFF section where the UUID of
++ * registered DCD objects are stored.
++ */
++#define DCD_REGKEY "Software\\TexasInstruments\\DspBridge\\DCD"
++#define DCD_REGISTER_SECTION ".dcd_register"
++
++/* DCD Manager Object */
++ struct DCD_MANAGER;
++
++/* DCD Node Properties */
++ struct DCD_NODEPROPS {
++ struct DSP_NDBPROPS ndbProps;
++ u32 uMsgSegid;
++ u32 uMsgNotifyType;
++ char *pstrCreatePhaseFxn;
++ char *pstrDeletePhaseFxn;
++ char *pstrExecutePhaseFxn;
++ char *pstrIAlgName;
++
++ /* Dynamic load properties */
++ u16 usLoadType; /* Static, dynamic, overlay */
++ u32 ulDataMemSegMask; /* Data memory requirements */
++ u32 ulCodeMemSegMask; /* Code memory requirements */
++ } ;
++
++/* DCD Generic Object Type */
++ struct DCD_GENERICOBJ {
++ union dcdObjUnion {
++ struct DCD_NODEPROPS nodeObj; /* node object. */
++ /* processor object. */
++ struct DSP_PROCESSORINFO procObj;
++ /* extended proc object (private) */
++ struct MGR_PROCESSOREXTINFO extProcObj;
++ } objData;
++ } ;
++
++/* DCD Internal Callback Type */
++ typedef DSP_STATUS(*DCD_REGISTERFXN) (IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN void *handle);
++
++#endif /* DBDCDDEF_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbdefs.h b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+new file mode 100644
+index 0000000..9782693
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+@@ -0,0 +1,580 @@
++/*
++ * dbdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbdefs.h ========
++ * Description:
++ * Global definitions and constants for DSP/BIOS Bridge.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added MAPATTR & ELEM_SIZE for Dynamic Memory Mapping feature
++ *! 09-Feb-2004 vp Added processor ID numbers for DSP and IVA
++ *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE. Updated IsValid*Event macros.
++ *! 22-Nov-2002 gp Cleaned up comments, formatting.
++ *! Removed unused DSP_ENUMLASTNODE define.
++ *! 13-Feb-2002 jeh Added uSysStackSize to DSP_NDBPROPS.
++ *! 23-Jan-2002 ag Added #define DSP_SHMSEG0.
++ *! 12-Dec-2001 ag Added DSP_ESTRMMODE error code.
++ *! 04-Dec-2001 jeh Added DSP_ENOTCONNECTED error code.
++ *! 10-Dec-2001 kc: Modified macros and definitions to disable DSP_POSTMESSAGE.
++ *! 01-Nov-2001 jeh Added DSP_EOVERLAYMEMORY.
++ *! 18-Oct-2001 ag Added DSP_STRMMODE type.
++ *! Added DSP_ENOTSHAREDMEM.
++ *! 21-Sep-2001 ag Added additional error codes.
++ *! 07-Jun-2001 sg Made DSPStream_AllocateBuffer fxn name plural.
++ *! 11-May-2001 jeh Changed DSP_NODE_MIN_PRIORITY from 0 to 1. Removed hNode
++ *! from DSP_NODEINFO.
++ *! 02-Apr-2001 sg Added missing error codes, rearranged codes, switched to
++ *! hex offsets, renamed some codes to match API spec.
++ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 05-Dec-2000 ag: Added DSP_RMSxxx user available message command codes.
++ *! 09-Nov-2000 rr: Added DSP_PROCEESORRESTART define; Removed DSP_PBUFFER.
++ *! Added DSP_DCD_ENOAUTOREGISTER, DSP_EUSER1-16, DSP_ESTRMFUL
++ *! Removed DSP_EDONE. Macros's modified.
++ *! 23-Oct-2000 jeh Replaced DSP_STREAMSTATECHANGE with DSP_STREAMDONE.
++ *! 09-Oct-2000 jeh Updated to version 0.9 DSP Bridge API spec.
++ *! 29-Sep-2000 kc Added error codes for DCD and REG to simplify use of
++ *! these codes within the RM module.
++ *! 27-Sep-2000 jeh Added segid, alignment, uNumBufs to DSP_STREAMATTRIN.
++ *! 29-Aug-2000 jeh Added DSP_NODETYPE enum, changed DSP_EALREADYATTACHED to
++ *! DSP_EALREADYCONNECTED. Changed scStreamConnection[1]
++ *! to scStreamConnection[16] in DSP_NODEINFO structure.
++ *! Added DSP_NOTIFICATION, DSP_STRMATTR. PSTRING changed
++ *! back to TCHAR * and moved to dbtype.h.
++ *! 11-Aug-2000 rr: Macros to check valid events and notify masks added.
++ *! 09-Aug-2000 rr: Changed PSTRING to *s8
++ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
++ *! 20-Jul-2000 rr: Updated to version 0.8
++ *! 17-Jul-2000 rr: New PROC states added to the DSP_PROCSTATE.
++ *! 27-Jun-2000 rr: Created from dspapi.h
++ */
++
++#ifndef DBDEFS_
++#define DBDEFS_
++
++#include <linux/types.h>
++
++#include <dspbridge/dbtype.h> /* GPP side type definitions */
++#include <dspbridge/std.h> /* DSP/BIOS type definitions */
++#include <dspbridge/rms_sh.h> /* Types shared between GPP and DSP */
++
++#define PG_SIZE_4K 4096
++#define PG_MASK(pg_size) (~((pg_size)-1))
++#define PG_ALIGN_LOW(addr, pg_size) ((addr) & PG_MASK(pg_size))
++#define PG_ALIGN_HIGH(addr, pg_size) (((addr)+(pg_size)-1) & PG_MASK(pg_size))
++
++/* API return value and calling convention */
++#define DBAPI DSP_STATUS
++
++/* Infinite time value for the uTimeout parameter to DSPStream_Select() */
++#define DSP_FOREVER (-1)
++
++/* Maximum length of node name, used in DSP_NDBPROPS */
++#define DSP_MAXNAMELEN 32
++
++/* uNotifyType values for the RegisterNotify() functions. */
++#define DSP_SIGNALEVENT 0x00000001
++
++/* Types of events for processors */
++#define DSP_PROCESSORSTATECHANGE 0x00000001
++#define DSP_PROCESSORATTACH 0x00000002
++#define DSP_PROCESSORDETACH 0x00000004
++#define DSP_PROCESSORRESTART 0x00000008
++
++/* DSP exception events (DSP/BIOS and DSP MMU fault) */
++#define DSP_MMUFAULT 0x00000010
++#define DSP_SYSERROR 0x00000020
++#define DSP_EXCEPTIONABORT 0x00000300
++
++/* IVA exception events (IVA MMU fault) */
++#define IVA_MMUFAULT 0x00000040
++/* Types of events for nodes */
++#define DSP_NODESTATECHANGE 0x00000100
++#define DSP_NODEMESSAGEREADY 0x00000200
++
++/* Types of events for streams */
++#define DSP_STREAMDONE 0x00001000
++#define DSP_STREAMIOCOMPLETION 0x00002000
++
++/* Handle definition representing the GPP node in DSPNode_Connect() calls */
++#define DSP_HGPPNODE 0xFFFFFFFF
++
++/* Node directions used in DSPNode_Connect() */
++#define DSP_TONODE 1
++#define DSP_FROMNODE 2
++
++/* Define Node Minimum and Maximum Priorities */
++#define DSP_NODE_MIN_PRIORITY 1
++#define DSP_NODE_MAX_PRIORITY 15
++
++/* Pre-Defined Message Command Codes available to user: */
++#define DSP_RMSUSERCODESTART RMS_USER /* Start of RMS user cmd codes */
++/* end of user codes */
++#define DSP_RMSUSERCODEEND (RMS_USER + RMS_MAXUSERCODES);
++#define DSP_RMSBUFDESC RMS_BUFDESC /* MSG contains SM buffer description */
++
++/* Shared memory identifier for MEM segment named "SHMSEG0" */
++#define DSP_SHMSEG0 (u32)(-1)
++
++/* Processor ID numbers */
++#define DSP_UNIT 0
++#define IVA_UNIT 1
++
++#define DSPWORD unsigned char
++#define DSPWORDSIZE sizeof(DSPWORD)
++
++/* Success & Failure macros */
++#define DSP_SUCCEEDED(Status) likely((s32)(Status) >= 0)
++#define DSP_FAILED(Status) unlikely((s32)(Status) < 0)
++
++/* Power control enumerations */
++#define PROC_PWRCONTROL 0x8070
++
++#define PROC_PWRMGT_ENABLE (PROC_PWRCONTROL + 0x3)
++#define PROC_PWRMGT_DISABLE (PROC_PWRCONTROL + 0x4)
++
++/* Bridge Code Version */
++#define BRIDGE_VERSION_CODE 333
++
++#define MAX_PROFILES 16
++
++/* Types defined for 'Bridge API */
++ typedef u32 DSP_STATUS; /* API return code type */
++
++ typedef HANDLE DSP_HNODE; /* Handle to a DSP Node object */
++ typedef HANDLE DSP_HPROCESSOR; /* Handle to a Processor object */
++ typedef HANDLE DSP_HSTREAM; /* Handle to a Stream object */
++
++ typedef u32 DSP_PROCFAMILY; /* Processor family */
++ typedef u32 DSP_PROCTYPE; /* Processor type (w/in family) */
++ typedef u32 DSP_RTOSTYPE; /* Type of DSP RTOS */
++
++/* Handy Macros */
++#define IsValidProcEvent(x) (((x) == 0) || (((x) & (DSP_PROCESSORSTATECHANGE | \
++ DSP_PROCESSORATTACH | \
++ DSP_PROCESSORDETACH | \
++ DSP_PROCESSORRESTART | \
++ DSP_NODESTATECHANGE | \
++ DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION | \
++ DSP_MMUFAULT | \
++ DSP_SYSERROR)) && \
++ !((x) & ~(DSP_PROCESSORSTATECHANGE | \
++ DSP_PROCESSORATTACH | \
++ DSP_PROCESSORDETACH | \
++ DSP_PROCESSORRESTART | \
++ DSP_NODESTATECHANGE | \
++ DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION | \
++ DSP_MMUFAULT | \
++ DSP_SYSERROR))))
++
++#define IsValidNodeEvent(x) (((x) == 0) || (((x) & (DSP_NODESTATECHANGE | \
++ DSP_NODEMESSAGEREADY)) && \
++ !((x) & ~(DSP_NODESTATECHANGE | \
++ DSP_NODEMESSAGEREADY))))
++
++#define IsValidStrmEvent(x) (((x) == 0) || (((x) & (DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION)) && \
++ !((x) & ~(DSP_STREAMDONE | \
++ DSP_STREAMIOCOMPLETION))))
++
++#define IsValidNotifyMask(x) ((x) & DSP_SIGNALEVENT)
++
++/* The Node UUID structure */
++ struct DSP_UUID {
++ u32 ulData1;
++ u16 usData2;
++ u16 usData3;
++ u8 ucData4;
++ u8 ucData5;
++ u8 ucData6[6];
++ };
++
++/* DCD types */
++ enum DSP_DCDOBJTYPE {
++ DSP_DCDNODETYPE,
++ DSP_DCDPROCESSORTYPE,
++ DSP_DCDLIBRARYTYPE,
++ DSP_DCDCREATELIBTYPE,
++ DSP_DCDEXECUTELIBTYPE,
++ DSP_DCDDELETELIBTYPE
++ } ;
++
++/* Processor states */
++ enum DSP_PROCSTATE {
++ PROC_STOPPED,
++ PROC_LOADED,
++ PROC_RUNNING,
++ PROC_ERROR
++ } ;
++
++/*
++ * Node types: Message node, task node, xDAIS socket node, and
++ * device node. _NODE_GPP is used when defining a stream connection
++ * between a task or socket node and the GPP.
++ *
++ */
++ enum NODE_TYPE {
++ NODE_DEVICE,
++ NODE_TASK,
++ NODE_DAISSOCKET,
++ NODE_MESSAGE,
++ NODE_GPP
++ } ;
++
++/*
++ * ======== NODE_STATE ========
++ * Internal node states.
++ */
++ enum NODE_STATE {
++ NODE_ALLOCATED,
++ NODE_CREATED,
++ NODE_RUNNING,
++ NODE_PAUSED,
++ NODE_DONE,
++ NODE_CREATING,
++ NODE_STARTING,
++ NODE_PAUSING,
++ NODE_TERMINATING,
++ NODE_DELETING,
++ } ;
++
++/* Stream states */
++ enum DSP_STREAMSTATE {
++ STREAM_IDLE,
++ STREAM_READY,
++ STREAM_PENDING,
++ STREAM_DONE
++ } ;
++
++/* Stream connect types */
++ enum DSP_CONNECTTYPE {
++ CONNECTTYPE_NODEOUTPUT,
++ CONNECTTYPE_GPPOUTPUT,
++ CONNECTTYPE_NODEINPUT,
++ CONNECTTYPE_GPPINPUT
++ } ;
++
++/* Stream mode types */
++ enum DSP_STRMMODE {
++ STRMMODE_PROCCOPY, /* Processor(s) copy stream data payloads */
++ STRMMODE_ZEROCOPY, /* Strm buffer ptrs swapped no data copied */
++ STRMMODE_LDMA, /* Local DMA : OMAP's System-DMA device */
++ STRMMODE_RDMA /* Remote DMA: OMAP's DSP-DMA device */
++ } ;
++
++/* Resource Types */
++ enum DSP_RESOURCEINFOTYPE {
++ DSP_RESOURCE_DYNDARAM = 0,
++ DSP_RESOURCE_DYNSARAM,
++ DSP_RESOURCE_DYNEXTERNAL,
++ DSP_RESOURCE_DYNSRAM,
++ DSP_RESOURCE_PROCLOAD
++ } ;
++
++/* Memory Segment Types */
++ enum DSP_MEMTYPE {
++ DSP_DYNDARAM = 0,
++ DSP_DYNSARAM,
++ DSP_DYNEXTERNAL,
++ DSP_DYNSRAM
++ } ;
++
++/* Memory Flush Types */
++ enum DSP_FLUSHTYPE {
++ PROC_INVALIDATE_MEM = 0,
++ PROC_WRITEBACK_MEM,
++ PROC_WRITEBACK_INVALIDATE_MEM,
++ } ;
++
++/* Memory Segment Status Values */
++ struct DSP_MEMSTAT {
++ u32 ulSize;
++ u32 ulTotalFreeSize;
++ u32 ulLenMaxFreeBlock;
++ u32 ulNumFreeBlocks;
++ u32 ulNumAllocBlocks;
++ } ;
++
++/* Processor Load information Values */
++ struct DSP_PROCLOADSTAT {
++ u32 uCurrLoad;
++ u32 uPredictedLoad;
++ u32 uCurrDspFreq;
++ u32 uPredictedFreq;
++ } ;
++
++/* Attributes for STRM connections between nodes */
++ struct DSP_STRMATTR {
++ u32 uSegid; /* Memory segment on DSP to allocate buffers */
++ u32 uBufsize; /* Buffer size (DSP words) */
++ u32 uNumBufs; /* Number of buffers */
++ u32 uAlignment; /* Buffer alignment */
++ u32 uTimeout; /* Timeout for blocking STRM calls */
++ enum DSP_STRMMODE lMode; /* mode of stream when opened */
++ /* DMA chnl id if DSP_STRMMODE is LDMA or RDMA */
++ u32 uDMAChnlId;
++ u32 uDMAPriority; /* DMA channel priority 0=lowest, >0=high */
++ } ;
++
++/* The DSP_CBDATA structure */
++ struct DSP_CBDATA {
++ u32 cbData;
++ u8 cData[1];
++ } ;
++
++/* The DSP_MSG structure */
++ struct DSP_MSG {
++ u32 dwCmd;
++ u32 dwArg1;
++ u32 dwArg2;
++ } ;
++
++/* The DSP_RESOURCEREQMTS structure for node's resource requirements */
++ struct DSP_RESOURCEREQMTS {
++ u32 cbStruct;
++ u32 uStaticDataSize;
++ u32 uGlobalDataSize;
++ u32 uProgramMemSize;
++ u32 uWCExecutionTime;
++ u32 uWCPeriod;
++ u32 uWCDeadline;
++ u32 uAvgExectionTime;
++ u32 uMinimumPeriod;
++ } ;
++
++/*
++ * The DSP_STREAMCONNECT structure describes a stream connection
++ * between two nodes, or between a node and the GPP
++ */
++ struct DSP_STREAMCONNECT {
++ u32 cbStruct;
++ enum DSP_CONNECTTYPE lType;
++ u32 uThisNodeStreamIndex;
++ DSP_HNODE hConnectedNode;
++ struct DSP_UUID uiConnectedNodeID;
++ u32 uConnectedNodeStreamIndex;
++ } ;
++
++ struct DSP_NODEPROFS {
++ u32 ulHeapSize;
++ } ;
++
++/* The DSP_NDBPROPS structure reports the attributes of a node */
++ struct DSP_NDBPROPS {
++ u32 cbStruct;
++ struct DSP_UUID uiNodeID;
++ char acName[DSP_MAXNAMELEN];
++ enum NODE_TYPE uNodeType;
++ u32 bCacheOnGPP;
++ struct DSP_RESOURCEREQMTS dspResourceReqmts;
++ s32 iPriority;
++ u32 uStackSize;
++ u32 uSysStackSize;
++ u32 uStackSeg;
++ u32 uMessageDepth;
++ u32 uNumInputStreams;
++ u32 uNumOutputStreams;
++ u32 uTimeout;
++ u32 uCountProfiles; /* Number of supported profiles */
++ /* Array of profiles */
++ struct DSP_NODEPROFS aProfiles[MAX_PROFILES];
++ u32 uStackSegName; /* Stack Segment Name */
++ } ;
++
++ /* The DSP_NODEATTRIN structure describes the attributes of a
++ * node client */
++ struct DSP_NODEATTRIN {
++ u32 cbStruct;
++ s32 iPriority;
++ u32 uTimeout;
++ u32 uProfileID;
++ /* Reserved, for Bridge Internal use only */
++ u32 uHeapSize;
++ void *pGPPVirtAddr; /* Reserved, for Bridge Internal use only */
++ } ;
++
++ /* The DSP_NODEINFO structure is used to retrieve information
++ * about a node */
++ struct DSP_NODEINFO {
++ u32 cbStruct;
++ struct DSP_NDBPROPS nbNodeDatabaseProps;
++ u32 uExecutionPriority;
++ enum NODE_STATE nsExecutionState;
++ DSP_HNODE hDeviceOwner;
++ u32 uNumberStreams;
++ struct DSP_STREAMCONNECT scStreamConnection[16];
++ u32 uNodeEnv;
++ } ;
++
++ /* The DSP_NODEATTR structure describes the attributes of a node */
++ struct DSP_NODEATTR {
++ u32 cbStruct;
++ struct DSP_NODEATTRIN inNodeAttrIn;
++ u32 uInputs;
++ u32 uOutputs;
++ struct DSP_NODEINFO iNodeInfo;
++ } ;
++
++/*
++ * Notification type: either the name of an opened event, or an event or
++ * window handle.
++ */
++ struct DSP_NOTIFICATION {
++ char *psName;
++ HANDLE handle;
++ } ;
++
++/* The DSP_PROCESSORATTRIN structure describes the attributes of a processor */
++ struct DSP_PROCESSORATTRIN{
++ u32 cbStruct;
++ u32 uTimeout;
++ } ;
++
++ enum chipTypes {
++ DSPTYPE_55 = 6,
++ IVA_ARM7 = 0x97,
++ DSPTYPE_64 = 0x99
++ };
++
++/*
++ * The DSP_PROCESSORINFO structure describes basic capabilities of a
++ * DSP processor
++ */
++ struct DSP_PROCESSORINFO {
++ u32 cbStruct;
++ DSP_PROCFAMILY uProcessorFamily;
++ DSP_PROCTYPE uProcessorType;
++ u32 uClockRate;
++ u32 ulInternalMemSize;
++ u32 ulExternalMemSize;
++ u32 uProcessorID;
++ DSP_RTOSTYPE tyRunningRTOS;
++ s32 nNodeMinPriority;
++ s32 nNodeMaxPriority;
++ } ;
++
++/* Error information of last DSP exception signalled to the GPP */
++ struct DSP_ERRORINFO {
++ u32 dwErrMask;
++ u32 dwVal1;
++ u32 dwVal2;
++ u32 dwVal3;
++ } ;
++
++/* The DSP_PROCESSORSTATE structure describes the state of a DSP processor */
++ struct DSP_PROCESSORSTATE {
++ u32 cbStruct;
++ enum DSP_PROCSTATE iState;
++ struct DSP_ERRORINFO errInfo;
++ } ;
++
++/*
++ * The DSP_RESOURCEINFO structure is used to retrieve information about a
++ * processor's resources
++ */
++ struct DSP_RESOURCEINFO {
++ u32 cbStruct;
++ enum DSP_RESOURCEINFOTYPE uResourceType;
++ union {
++ u32 ulResource;
++ struct DSP_MEMSTAT memStat;
++ struct DSP_PROCLOADSTAT procLoadStat;
++ } result;
++ } ;
++
++/*
++ * The DSP_STREAMATTRIN structure describes the attributes of a stream,
++ * including segment and alignment of data buffers allocated with
++ * DSPStream_AllocateBuffers(), if applicable
++ */
++ struct DSP_STREAMATTRIN {
++ u32 cbStruct;
++ u32 uTimeout;
++ u32 uSegment;
++ u32 uAlignment;
++ u32 uNumBufs;
++ enum DSP_STRMMODE lMode;
++ u32 uDMAChnlId;
++ u32 uDMAPriority;
++ } ;
++
++/* The DSP_BUFFERATTR structure describes the attributes of a data buffer */
++ struct DSP_BUFFERATTR {
++ u32 cbStruct;
++ u32 uSegment;
++ u32 uAlignment;
++ } ;
++
++/*
++ * The DSP_STREAMINFO structure is used to retrieve information
++ * about a stream.
++ */
++ struct DSP_STREAMINFO {
++ u32 cbStruct;
++ u32 uNumberBufsAllowed;
++ u32 uNumberBufsInStream;
++ u32 ulNumberBytes;
++ HANDLE hSyncObjectHandle;
++ enum DSP_STREAMSTATE ssStreamState;
++ } ;
++
++/* DMM MAP attributes
++It is a bit mask with each bit value indicating a specific attribute
++bit 0 - GPP address type (user virtual=0, physical=1)
++bit 1 - MMU Endianism (Big Endian=1, Little Endian=0)
++bit 2 - MMU mixed page attribute (Mixed/ CPUES=1, TLBES =0)
++bit 3 - MMU element size = 8bit (valid only for non mixed page entries)
++bit 4 - MMU element size = 16bit (valid only for non mixed page entries)
++bit 5 - MMU element size = 32bit (valid only for non mixed page entries)
++bit 6 - MMU element size = 64bit (valid only for non mixed page entries)
++*/
++
++/* Types of mapping attributes */
++
++/* MPU address is virtual and needs to be translated to physical addr */
++#define DSP_MAPVIRTUALADDR 0x00000000
++#define DSP_MAPPHYSICALADDR 0x00000001
++
++/* Mapped data is big endian */
++#define DSP_MAPBIGENDIAN 0x00000002
++#define DSP_MAPLITTLEENDIAN 0x00000000
++
++/* Element size is based on DSP r/w access size */
++#define DSP_MAPMIXEDELEMSIZE 0x00000004
++
++/*
++ * Element size for MMU mapping (8, 16, 32, or 64 bit)
++ * Ignored if DSP_MAPMIXEDELEMSIZE enabled
++ */
++#define DSP_MAPELEMSIZE8 0x00000008
++#define DSP_MAPELEMSIZE16 0x00000010
++#define DSP_MAPELEMSIZE32 0x00000020
++#define DSP_MAPELEMSIZE64 0x00000040
++
++#define DSP_MAPVMALLOCADDR 0x00000080
++
++#define DSP_MAPDONOTLOCK 0x00000100
++
++
++#define GEM_CACHE_LINE_SIZE 128
++#define GEM_L1P_PREFETCH_SIZE 128
++
++#endif /* DBDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbg.h b/arch/arm/plat-omap/include/dspbridge/dbg.h
+new file mode 100644
+index 0000000..7f44ff9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbg.h
+@@ -0,0 +1,110 @@
++/*
++ * dbg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbg.h ========
++ * Purpose:
++ * Provide debugging services for 'Bridge Mini Drivers.
++ *
++ * Public Functions:
++ * DBG_Exit
++ * DBG_Init
++ * DBG_Printf
++ * DBG_Trace
++ *
++ * Notes:
++ * WMD's must not call DBG_Init or DBG_Exit.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Feb-2000 rr: DBG Levels redefined.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Oct-1997 cr: Added DBG_Printf service.
++ *! 29-May-1996 gp: Removed WCD_ prefix.
++ *! 15-May-1996 gp: Created.
++ */
++
++#ifndef DBG_
++#define DBG_
++#include <dspbridge/host_os.h>
++#include <linux/types.h>
++
++/* Levels of trace debug messages: */
++#define DBG_ENTER (u8)(0x01) /* Function entry point. */
++#define DBG_LEVEL1 (u8)(0x02) /* Display debugging state/varibles */
++#define DBG_LEVEL2 (u8)(0x04) /* Display debugging state/varibles */
++#define DBG_LEVEL3 (u8)(0x08) /* Display debugging state/varibles */
++#define DBG_LEVEL4 (u8)(0x10) /* Display debugging state/varibles */
++#define DBG_LEVEL5 (u8)(0x20) /* Module Init, Exit */
++#define DBG_LEVEL6 (u8)(0x40) /* Warn SERVICES Failures */
++#define DBG_LEVEL7 (u8)(0x80) /* Warn Critical Errors */
++
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++
++/*
++ * ======== DBG_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DBG initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void DBG_Exit(void);
++
++/*
++ * ======== DBG_Init ========
++ * Purpose:
++ * Initializes private state of DBG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ */
++ extern bool DBG_Init(void);
++
++/*
++ * ======== DBG_Trace ========
++ * Purpose:
++ * Output a trace message to the debugger, if the given trace level
++ * is unmasked.
++ * Parameters:
++ * bLevel: Trace level.
++ * pstrFormat: sprintf-style format string.
++ * ...: Arguments for format string.
++ * Returns:
++ * DSP_SOK: Success, or trace level masked.
++ * DSP_EFAIL: On Error.
++ * Requires:
++ * DBG initialized.
++ * Ensures:
++ * Debug message is printed to debugger output window, if trace level
++ * is unmasked.
++ */
++ extern DSP_STATUS DBG_Trace(IN u8 bLevel, IN char *pstrFormat, ...);
++#else
++
++#define DBG_Exit(void)
++#define DBG_Init(void) true
++#define DBG_Trace(bLevel, pstrFormat, args...)
++
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
++
++#endif /* DBG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbl.h b/arch/arm/plat-omap/include/dspbridge/dbl.h
+new file mode 100644
+index 0000000..19847f9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbl.h
+@@ -0,0 +1,354 @@
++/*
++ * dbl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbl.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 19-Mar-2002 jeh Pass DBL_Symbol pointer to DBL_getAddr, DBL_getCAddr
++ *! to accomodate dynamic loader library.
++ *! 20-Nov-2001 jeh Removed DBL_loadArgs().
++ *! 24-Sep-2001 jeh Code review changes.
++ *! 07-Sep-2001 jeh Added DBL_LoadSect(), DBL_UnloadSect().
++ *! 05-Jun-2001 jeh Created based on zl.h.
++ */
++
++#ifndef DBL_
++#define DBL_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dbldefs.h>
++
++/*
++ * ======== DBL_close ========
++ * Close library opened with DBL_open.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++ extern void DBL_close(struct DBL_LibraryObj *lib);
++
++/*
++ * ======== DBL_create ========
++ * Create a target object by specifying the alloc, free, and write
++ * functions for the target.
++ * Parameters:
++ * pTarget - Location to store target handle on output.
++ * pAttrs - Attributes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * DBL initialized.
++ * pAttrs != NULL.
++ * pTarget != NULL;
++ * Ensures:
++ * Success: *pTarget != NULL.
++ * Failure: *pTarget == NULL.
++ */
++ extern DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_delete ========
++ * Delete target object and free resources for any loaded libraries.
++ * Parameters:
++ * target - Handle returned from DBL_Create().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * Ensures:
++ */
++ extern void DBL_delete(struct DBL_TargetObj *target);
++
++/*
++ * ======== DBL_exit ========
++ * Discontinue use of DBL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * cRefs > 0.
++ * Ensures:
++ * cRefs >= 0.
++ */
++ extern void DBL_exit(void);
++
++/*
++ * ======== DBL_getAddr ========
++ * Get address of name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym);
++
++/*
++ * ======== DBL_getAttrs ========
++ * Retrieve the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBL_Create().
++ * pAttrs - Location to store attributes on output.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++ extern void DBL_getAttrs(struct DBL_TargetObj *target,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_getCAddr ========
++ * Get address of "C" name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym);
++
++/*
++ * ======== DBL_getEntry ========
++ * Get program entry point.
++ *
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * pEntry - Location to store entry address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++ extern bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry);
++
++/*
++ * ======== DBL_getSect ========
++ * Get address and size of a named section.
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * name - Name of section.
++ * pAddr - Location to store section address on output.
++ * pSize - Location to store section size on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL;
++ * pSize != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name,
++ u32 *pAddr, u32 *pSize);
++
++/*
++ * ======== DBL_init ========
++ * Initialize DBL module.
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * cRefs >= 0.
++ * Ensures:
++ * Success: cRefs > 0.
++ * Failure: cRefs >= 0.
++ */
++ extern bool DBL_init(void);
++
++/*
++ * ======== DBL_load ========
++ * Add symbols/code/data defined in file to that already present on
++ * the target.
++ *
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * flags - Specifies whether loading code, data, and/or symbols.
++ * attrs - May contain write, alloc, and free functions.
++ * pulEntry - Location to store program entry on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFREAD: File read failed.
++ * DSP_EFWRITE: Write to target failed.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
++ struct DBL_Attrs *attrs, u32 *pEntry);
++
++/*
++ * ======== DBL_loadSect ========
++ * Load a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains write function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * DSP_EFWRITE: Write function failed.
++ * Requires:
++ * Valid lib.
++ * sectName != NULL.
++ * attrs != NULL.
++ * attrs->write != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib,
++ char *sectName,
++ struct DBL_Attrs *attrs);
++
++/*
++ * ======== DBL_open ========
++ * DBL_open() returns a library handle that can be used to load/unload
++ * the symbols/code/data via DBL_load()/DBL_unload().
++ * Parameters:
++ * target - Handle returned from DBL_create().
++ * file - Name of file to open.
++ * flags - Specifies whether to load symbols now.
++ * pLib - Location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFOPEN: File open failure.
++ * DSP_EFREAD: File read failure.
++ * DSP_ECORRUPTFILE: Unable to determine target type.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * file != NULL.
++ * pLib != NULL.
++ * struct DBL_Attrs fopen function non-NULL.
++ * Ensures:
++ * Success: Valid *pLib.
++ * Failure: *pLib == NULL.
++ */
++ extern DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file,
++ DBL_Flags flags,
++ struct DBL_LibraryObj **pLib);
++
++/*
++ * ======== DBL_readSect ========
++ * Read COFF section into a character buffer.
++ * Parameters:
++ * lib - Library handle returned from DBL_open().
++ * name - Name of section.
++ * pBuf - Buffer to write section contents into.
++ * size - Buffer size
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section does not exists.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pBuf != NULL.
++ * size != 0.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name,
++ char *pBuf, u32 size);
++
++/*
++ * ======== DBL_setAttrs ========
++ * Set the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBL_create().
++ * pAttrs - New attributes.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++ extern void DBL_setAttrs(struct DBL_TargetObj *target,
++ struct DBL_Attrs *pAttrs);
++
++/*
++ * ======== DBL_unload ========
++ * Remove the symbols/code/data corresponding to the library lib.
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++ extern void DBL_unload(struct DBL_LibraryObj *lib,
++ struct DBL_Attrs *attrs);
++
++/*
++ * ======== DBL_unloadSect ========
++ * Unload a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * sectName != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib,
++ char *sectName,
++ struct DBL_Attrs *attrs);
++
++#endif /* DBL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbldefs.h b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
+new file mode 100644
+index 0000000..79b9e54
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbldefs.h
+@@ -0,0 +1,155 @@
++/*
++ * dbldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbldefs.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 19-Mar-2002 jeh Added DBL_Fxns type (to make it easier to switch
++ *! between different loaders).
++ *! 28-Sep-2001 jeh Created from zl.h.
++ */
++#ifndef DBLDEFS_
++#define DBLDEFS_
++
++/*
++ * Bit masks for DBL_Flags.
++ */
++#define DBL_NOLOAD 0x0 /* Don't load symbols, code, or data */
++#define DBL_SYMB 0x1 /* load symbols */
++#define DBL_CODE 0x2 /* load code */
++#define DBL_DATA 0x4 /* load data */
++#define DBL_DYNAMIC 0x8 /* dynamic load */
++#define DBL_BSS 0x20 /* Unitialized section */
++
++#define DBL_MAXPATHLENGTH 255
++
++
++
++/*
++ * ======== DBL_Flags ========
++ * Specifies whether to load code, data, or symbols
++ */
++typedef s32 DBL_Flags;
++
++/*
++ * ======== DBL_SectInfo ========
++ * For collecting info on overlay sections
++ */
++struct DBL_SectInfo {
++ const char *name; /* name of section */
++ u32 runAddr; /* run address of section */
++ u32 loadAddr; /* load address of section */
++ u32 size; /* size of section (target MAUs) */
++ DBL_Flags type; /* Code, data, or BSS */
++} ;
++
++/*
++ * ======== DBL_Symbol ========
++ * (Needed for dynamic load library)
++ */
++struct DBL_Symbol {
++ u32 value;
++};
++
++/*
++ * ======== DBL_AllocFxn ========
++ * Allocate memory function. Allocate or reserve (if reserved == TRUE)
++ * "size" bytes of memory from segment "space" and return the address in
++ * *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
++ * success, or an error code on failure.
++ */
++typedef s32(*DBL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
++ u32 *dspAddr, s32 segId, s32 req, bool reserved);
++
++
++
++/*
++ * ======== DBL_FreeFxn ========
++ * Free memory function. Free, or unreserve (if reserved == TRUE) "size"
++ * bytes of memory from segment "space"
++ */
++typedef bool(*DBL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
++ bool reserved);
++
++/*
++ * ======== DBL_LogWriteFxn ========
++ * Function to call when writing data from a section, to log the info.
++ * Can be NULL if no logging is required.
++ */
++typedef DSP_STATUS(*DBL_LogWriteFxn) (void *handle, struct DBL_SectInfo *sect,
++ u32 addr, u32 nBytes);
++
++
++/*
++ * ======== DBL_SymLookup ========
++ * Symbol lookup function - Find the symbol name and return its value.
++ *
++ * Parameters:
++ * handle - Opaque handle
++ * pArg - Opaque argument.
++ * name - Name of symbol to lookup.
++ * sym - Location to store address of symbol structure.
++ *
++ * Returns:
++ * TRUE: Success (symbol was found).
++ * FALSE: Failed to find symbol.
++ */
++typedef bool(*DBL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
++ const char *name, struct DBL_Symbol **sym);
++
++
++/*
++ * ======== DBL_WriteFxn ========
++ * Write memory function. Write "n" HOST bytes of memory to segment "mtype"
++ * starting at address "dspAddr" from the buffer "buf". The buffer is
++ * formatted as an array of words appropriate for the DSP.
++ */
++typedef s32(*DBL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
++ u32 n, s32 mtype);
++
++/*
++ * ======== DBL_Attrs ========
++ */
++struct DBL_Attrs {
++ DBL_AllocFxn alloc;
++ DBL_FreeFxn free;
++ void *rmmHandle; /* Handle to pass to alloc, free functions */
++ DBL_WriteFxn write;
++ void *wHandle; /* Handle to pass to write, cinit function */
++
++ DBL_LogWriteFxn logWrite;
++ void *logWriteHandle;
++
++ /* Symbol matching function and handle to pass to it */
++ DBL_SymLookup symLookup;
++ void *symHandle;
++ void *symArg;
++
++ /*
++ * These file manipulation functions should be compatible with the
++ * "C" run time library functions of the same name.
++ */
++ s32(*fread) (void *, size_t, size_t, void *);
++ s32(*fseek) (void *, long, int);
++ s32(*ftell) (void *);
++ s32(*fclose) (void *);
++ void *(*fopen) (const char *, const char *);
++} ;
++
++#endif /* DBLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbll.h b/arch/arm/plat-omap/include/dspbridge/dbll.h
+new file mode 100644
+index 0000000..c3aa212
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbll.h
+@@ -0,0 +1,70 @@
++/*
++ * dbll.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbll.h ========
++ * DSP/BIOS Bridge Dynamic load library module interface. Function header
++ * comments are in the file dblldefs.h.
++ *
++ *! Revision History
++ *! ================
++ *! 31-Jul-2002 jeh Removed function comments (now in dblldefs.h).
++ *! 17-Apr-2002 jeh Created based on zl.h.
++ */
++
++#ifndef DBLL_
++#define DBLL_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dblldefs.h>
++
++ extern void DBLL_close(struct DBLL_LibraryObj *lib);
++ extern DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget,
++ struct DBLL_Attrs *pAttrs);
++ extern void DBLL_delete(struct DBLL_TarObj *target);
++ extern void DBLL_exit(void);
++ extern bool DBLL_getAddr(struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++ extern void DBLL_getAttrs(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *pAttrs);
++ extern bool DBLL_getCAddr(struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++ extern DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name,
++ u32 *pAddr, u32 *pSize);
++ extern bool DBLL_init(void);
++ extern DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib,
++ DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *pEntry);
++ extern DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *lib,
++ char *sectName,
++ struct DBLL_Attrs *attrs);
++ extern DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file,
++ DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib);
++ extern DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib,
++ char *name,
++ char *pBuf, u32 size);
++ extern void DBLL_setAttrs(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *pAttrs);
++ extern void DBLL_unload(struct DBLL_LibraryObj *lib,
++ struct DBLL_Attrs *attrs);
++ extern DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib,
++ char *sectName,
++ struct DBLL_Attrs *attrs);
++
++#endif /* DBLL_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dblldefs.h b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
+new file mode 100644
+index 0000000..2361ce8
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dblldefs.h
+@@ -0,0 +1,509 @@
++/*
++ * dblldefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dblldefs.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map Consolidated DBL into DBLL name
++ *! 19-Mar-2002 jeh Added DBL_Fxns type (to make it easier to switch
++ *! between different loaders).
++ *! 28-Sep-2001 jeh Created from zl.h.
++ */
++#ifndef DBLLDEFS_
++#define DBLLDEFS_
++
++/*
++ * Bit masks for DBL_Flags.
++ */
++#define DBLL_NOLOAD 0x0 /* Don't load symbols, code, or data */
++#define DBLL_SYMB 0x1 /* load symbols */
++#define DBLL_CODE 0x2 /* load code */
++#define DBLL_DATA 0x4 /* load data */
++#define DBLL_DYNAMIC 0x8 /* dynamic load */
++#define DBLL_BSS 0x20 /* Unitialized section */
++
++#define DBLL_MAXPATHLENGTH 255
++
++
++/*
++ * ======== DBLL_Target ========
++ *
++ */
++struct DBLL_TarObj;
++
++/*
++ * ======== DBLL_Flags ========
++ * Specifies whether to load code, data, or symbols
++ */
++typedef s32 DBLL_Flags;
++
++/*
++ * ======== DBLL_Library ========
++ *
++ */
++struct DBLL_LibraryObj;
++
++/*
++ * ======== DBLL_SectInfo ========
++ * For collecting info on overlay sections
++ */
++struct DBLL_SectInfo {
++ const char *name; /* name of section */
++ u32 runAddr; /* run address of section */
++ u32 loadAddr; /* load address of section */
++ u32 size; /* size of section (target MAUs) */
++ DBLL_Flags type; /* Code, data, or BSS */
++} ;
++
++/*
++ * ======== DBLL_Symbol ========
++ * (Needed for dynamic load library)
++ */
++struct DBLL_Symbol {
++ u32 value;
++};
++
++/*
++ * ======== DBLL_AllocFxn ========
++ * Allocate memory function. Allocate or reserve (if reserved == TRUE)
++ * "size" bytes of memory from segment "space" and return the address in
++ * *dspAddr (or starting at *dspAddr if reserve == TRUE). Returns 0 on
++ * success, or an error code on failure.
++ */
++typedef s32(*DBLL_AllocFxn) (void *hdl, s32 space, u32 size, u32 align,
++ u32 *dspAddr, s32 segId, s32 req,
++ bool reserved);
++
++/*
++ * ======== DBLL_CloseFxn ========
++ */
++typedef s32(*DBLL_FCloseFxn) (void *);
++
++/*
++ * ======== DBLL_FreeFxn ========
++ * Free memory function. Free, or unreserve (if reserved == TRUE) "size"
++ * bytes of memory from segment "space"
++ */
++typedef bool(*DBLL_FreeFxn) (void *hdl, u32 addr, s32 space, u32 size,
++ bool reserved);
++
++/*
++ * ======== DBLL_FOpenFxn ========
++ */
++typedef void *(*DBLL_FOpenFxn) (const char *, const char *);
++
++/*
++ * ======== DBLL_LogWriteFxn ========
++ * Function to call when writing data from a section, to log the info.
++ * Can be NULL if no logging is required.
++ */
++typedef DSP_STATUS(*DBLL_LogWriteFxn)(void *handle, struct DBLL_SectInfo *sect,
++ u32 addr, u32 nBytes);
++
++/*
++ * ======== DBLL_ReadFxn ========
++ */
++typedef s32(*DBLL_ReadFxn) (void *, size_t, size_t, void *);
++
++/*
++ * ======== DBLL_SeekFxn ========
++ */
++typedef s32(*DBLL_SeekFxn) (void *, long, int);
++
++/*
++ * ======== DBLL_SymLookup ========
++ * Symbol lookup function - Find the symbol name and return its value.
++ *
++ * Parameters:
++ * handle - Opaque handle
++ * pArg - Opaque argument.
++ * name - Name of symbol to lookup.
++ * sym - Location to store address of symbol structure.
++ *
++ * Returns:
++ * TRUE: Success (symbol was found).
++ * FALSE: Failed to find symbol.
++ */
++typedef bool(*DBLL_SymLookup) (void *handle, void *pArg, void *rmmHandle,
++ const char *name, struct DBLL_Symbol **sym);
++
++/*
++ * ======== DBLL_TellFxn ========
++ */
++typedef s32(*DBLL_TellFxn) (void *);
++
++/*
++ * ======== DBLL_WriteFxn ========
++ * Write memory function. Write "n" HOST bytes of memory to segment "mtype"
++ * starting at address "dspAddr" from the buffer "buf". The buffer is
++ * formatted as an array of words appropriate for the DSP.
++ */
++typedef s32(*DBLL_WriteFxn) (void *hdl, u32 dspAddr, void *buf,
++ u32 n, s32 mtype);
++
++/*
++ * ======== DBLL_Attrs ========
++ */
++struct DBLL_Attrs {
++ DBLL_AllocFxn alloc;
++ DBLL_FreeFxn free;
++ void *rmmHandle; /* Handle to pass to alloc, free functions */
++ DBLL_WriteFxn write;
++ void *wHandle; /* Handle to pass to write, cinit function */
++ bool baseImage;
++ DBLL_LogWriteFxn logWrite;
++ void *logWriteHandle;
++
++ /* Symbol matching function and handle to pass to it */
++ DBLL_SymLookup symLookup;
++ void *symHandle;
++ void *symArg;
++
++ /*
++ * These file manipulation functions should be compatible with the
++ * "C" run time library functions of the same name.
++ */
++ s32(*fread) (void *, size_t, size_t, void *);
++ s32(*fseek) (void *, long, int);
++ s32(*ftell) (void *);
++ s32(*fclose) (void *);
++ void *(*fopen) (const char *, const char *);
++} ;
++
++/*
++ * ======== DBLL_close ========
++ * Close library opened with DBLL_open.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++typedef void(*DBLL_CloseFxn) (struct DBLL_LibraryObj *library);
++
++/*
++ * ======== DBLL_create ========
++ * Create a target object, specifying the alloc, free, and write functions.
++ * Parameters:
++ * pTarget - Location to store target handle on output.
++ * pAttrs - Attributes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * DBL initialized.
++ * pAttrs != NULL.
++ * pTarget != NULL;
++ * Ensures:
++ * Success: *pTarget != NULL.
++ * Failure: *pTarget == NULL.
++ */
++typedef DSP_STATUS(*DBLL_CreateFxn)(struct DBLL_TarObj **pTarget,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_delete ========
++ * Delete target object and free resources for any loaded libraries.
++ * Parameters:
++ * target - Handle returned from DBLL_Create().
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * Ensures:
++ */
++typedef void(*DBLL_DeleteFxn) (struct DBLL_TarObj *target);
++
++/*
++ * ======== DBLL_exit ========
++ * Discontinue use of DBL module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * cRefs > 0.
++ * Ensures:
++ * cRefs >= 0.
++ */
++typedef void(*DBLL_ExitFxn) (void);
++
++/*
++ * ======== DBLL_getAddr ========
++ * Get address of name in the specified library.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid library.
++ * name != NULL.
++ * ppSym != NULL.
++ * Ensures:
++ */
++typedef bool(*DBLL_GetAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++
++/*
++ * ======== DBLL_getAttrs ========
++ * Retrieve the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBLL_Create().
++ * pAttrs - Location to store attributes on output.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++typedef void(*DBLL_GetAttrsFxn) (struct DBLL_TarObj *target,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_getCAddr ========
++ * Get address of "C" name on the specified library.
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * name - Name of symbol
++ * ppSym - Location to store symbol address on output.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Symbol not found.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * name != NULL.
++ * ppSym != NULL.
++ * Ensures:
++ */
++typedef bool(*DBLL_GetCAddrFxn) (struct DBLL_LibraryObj *lib, char *name,
++ struct DBLL_Symbol **ppSym);
++
++/*
++ * ======== DBLL_getSect ========
++ * Get address and size of a named section.
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * name - Name of section.
++ * pAddr - Location to store section address on output.
++ * pSize - Location to store section size on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pAddr != NULL;
++ * pSize != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_GetSectFxn) (struct DBLL_LibraryObj *lib, char *name,
++ u32 *addr, u32 *size);
++
++/*
++ * ======== DBLL_init ========
++ * Initialize DBL module.
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * cRefs >= 0.
++ * Ensures:
++ * Success: cRefs > 0.
++ * Failure: cRefs >= 0.
++ */
++typedef bool(*DBLL_InitFxn) (void);
++
++/*
++ * ======== DBLL_load ========
++ * Load library onto the target.
++ *
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * flags - Load code, data and/or symbols.
++ * attrs - May contain alloc, free, and write function.
++ * pulEntry - Location to store program entry on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFREAD: File read failed.
++ * DSP_EFWRITE: Write to target failed.
++ * DSP_EDYNLOAD: Failure in dynamic loader library.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * pEntry != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_LoadFxn) (struct DBLL_LibraryObj *lib,
++ DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *entry);
++
++/*
++ * ======== DBLL_loadSect ========
++ * Load a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains write function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Section not found.
++ * DSP_EFWRITE: Write function failed.
++ * DSP_ENOTIMPL: Function not implemented.
++ * Requires:
++ * Valid lib.
++ * sectName != NULL.
++ * attrs != NULL.
++ * attrs->write != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_LoadSectFxn) (struct DBLL_LibraryObj *lib,
++ char *pszSectName,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_open ========
++ * DBLL_open() returns a library handle that can be used to load/unload
++ * the symbols/code/data via DBLL_load()/DBLL_unload().
++ * Parameters:
++ * target - Handle returned from DBLL_create().
++ * file - Name of file to open.
++ * flags - If flags & DBLL_SYMB, load symbols.
++ * pLib - Location to store library handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFOPEN: File open failure.
++ * DSP_EFREAD: File read failure.
++ * DSP_ECORRUPTFILE: Unable to determine target type.
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * file != NULL.
++ * pLib != NULL.
++ * DBLL_Attrs fopen function non-NULL.
++ * Ensures:
++ * Success: Valid *pLib.
++ * Failure: *pLib == NULL.
++ */
++typedef DSP_STATUS(*DBLL_OpenFxn) (struct DBLL_TarObj *target, char *file,
++ DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib);
++
++/*
++ * ======== DBLL_readSect ========
++ * Read COFF section into a character buffer.
++ * Parameters:
++ * lib - Library handle returned from DBLL_open().
++ * name - Name of section.
++ * pBuf - Buffer to write section contents into.
++ * size - Buffer size
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section does not exists.
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * name != NULL.
++ * pBuf != NULL.
++ * size != 0.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_ReadSectFxn) (struct DBLL_LibraryObj *lib, char *name,
++ char *content, u32 uContentSize);
++
++/*
++ * ======== DBLL_setAttrs ========
++ * Set the attributes of the target.
++ * Parameters:
++ * target - Handle returned from DBLL_create().
++ * pAttrs - New attributes.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid target.
++ * pAttrs != NULL.
++ * Ensures:
++ */
++typedef void(*DBLL_SetAttrsFxn)(struct DBLL_TarObj *target,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_unload ========
++ * Unload library loaded with DBLL_load().
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * Ensures:
++ */
++typedef void(*DBLL_UnloadFxn) (struct DBLL_LibraryObj *library,
++ struct DBLL_Attrs *attrs);
++
++/*
++ * ======== DBLL_unloadSect ========
++ * Unload a named section from an library (for overlay support).
++ * Parameters:
++ * lib - Handle returned from DBLL_open().
++ * sectName - Name of section to load.
++ * attrs - Contains free() function and handle to pass to it.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ENOSECT: Named section not found.
++ * DSP_ENOTIMPL
++ * Requires:
++ * DBL initialized.
++ * Valid lib.
++ * sectName != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*DBLL_UnloadSectFxn) (struct DBLL_LibraryObj *lib,
++ char *pszSectName,
++ struct DBLL_Attrs *attrs);
++
++struct DBLL_Fxns {
++ DBLL_CloseFxn closeFxn;
++ DBLL_CreateFxn createFxn;
++ DBLL_DeleteFxn deleteFxn;
++ DBLL_ExitFxn exitFxn;
++ DBLL_GetAttrsFxn getAttrsFxn;
++ DBLL_GetAddrFxn getAddrFxn;
++ DBLL_GetCAddrFxn getCAddrFxn;
++ DBLL_GetSectFxn getSectFxn;
++ DBLL_InitFxn initFxn;
++ DBLL_LoadFxn loadFxn;
++ DBLL_LoadSectFxn loadSectFxn;
++ DBLL_OpenFxn openFxn;
++ DBLL_ReadSectFxn readSectFxn;
++ DBLL_SetAttrsFxn setAttrsFxn;
++ DBLL_UnloadFxn unloadFxn;
++ DBLL_UnloadSectFxn unloadSectFxn;
++} ;
++
++#endif /* DBLDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbof.h b/arch/arm/plat-omap/include/dspbridge/dbof.h
+new file mode 100644
+index 0000000..54f4250
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbof.h
+@@ -0,0 +1,117 @@
++/*
++ * dbof.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbof.h ========
++ * Description:
++ * Defines and typedefs for DSP/BIOS Bridge Object File Format (DBOF).
++ *
++ *! Revision History
++ *! ================
++ *! 12-Jul-2002 jeh Added defines for DBOF_SectHdr page.
++ *! 12-Oct-2001 jeh Converted to std.h format.
++ *! 07-Sep-2001 jeh Added overlay support.
++ *! 06-Jul-2001 jeh Created.
++ */
++
++#ifndef DBOF_
++#define DBOF_
++
++/* Enough to hold DCD section names: 32 digit ID + underscores */
++#define DBOF_DCDSECTNAMELEN 40
++
++/* Values for DBOF_SectHdr page field. */
++#define DBOF_PROGRAM 0
++#define DBOF_DATA 1
++#define DBOF_CINIT 2
++
++/*
++ * ======== DBOF_FileHdr ========
++ */
++ struct DBOF_FileHdr {
++ u32 magic; /* COFF magic number */
++ u32 entry; /* Program entry point */
++ u16 numSymbols; /* Number of bridge symbols */
++ u16 numDCDSects; /* Number of DCD sections */
++ u16 numSects; /* Number of sections to load */
++ u16 numOvlySects; /* Number of overlay sections */
++ u32 symOffset; /* Offset in file to symbols */
++ u32 dcdSectOffset; /* Offset to DCD sections */
++ u32 loadSectOffset; /* Offset to loadable sections */
++ u32 ovlySectOffset; /* Offset to overlay data */
++ u16 version; /* DBOF version number */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++/*
++ * ======== DBOF_DCDSectHdr ========
++ */
++ struct DBOF_DCDSectHdr {
++ u32 size; /* Sect size (target MAUs) */
++ char name[DBOF_DCDSECTNAMELEN]; /* DCD section name */
++ } ;
++
++/*
++ * ======== DBOF_OvlySectHdr ========
++ */
++ struct DBOF_OvlySectHdr {
++ u16 nameLen; /* Length of section name */
++ u16 numCreateSects; /* # of sects loaded for create phase */
++ u16 numDeleteSects; /* # of sects loaded for delete phase */
++ u16 numExecuteSects; /* # of sects loaded for execute phase */
++
++ /*
++ * Number of sections where load/unload phase is not specified.
++ * These sections will be loaded when create phase sects are
++ * loaded, and unloaded when the delete phase is unloaded.
++ */
++ u16 numOtherSects;
++ u16 resvd; /* Reserved for future use */
++ };
++
++/*
++ * ======== DBOF_OvlySectData ========
++ */
++ struct DBOF_OvlySectData {
++ u32 loadAddr; /* Section load address */
++ u32 runAddr; /* Section run address */
++ u32 size; /* Section size (target MAUs) */
++ u16 page; /* Memory page number */
++ u16 resvd; /* Reserved */
++ } ;
++
++/*
++ * ======== DBOF_SectHdr ========
++ */
++ struct DBOF_SectHdr {
++ u32 addr; /* Section address */
++ u32 size; /* Section size (target MAUs) */
++ u16 page; /* Page number */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++/*
++ * ======== DBOF_SymbolHdr ========
++ */
++ struct DBOF_SymbolHdr {
++ u32 value; /* Symbol value */
++ u16 nameLen; /* Length of symbol name */
++ u16 resvd; /* Reserved for future use */
++ } ;
++
++#endif /* DBOF_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbreg.h b/arch/arm/plat-omap/include/dspbridge/dbreg.h
+new file mode 100644
+index 0000000..d311b88
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbreg.h
+@@ -0,0 +1,113 @@
++/*
++ * dbreg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbreg.h ========
++ * Purpose:
++ * Registry keys for use in Linux. This is the clearinghouse for
++ * registry definitions, hopefully eliminating overlapping between
++ * modules.
++ *
++ *! Revision History:
++ *! ================
++ *! 10-Apr-2003 vp: Added macro for subkey TCWORDSWAP.
++ *! 21-Mar-2003 sb: Added macro for subkey SHMSize
++ *! 27-Aug-2001 jeh Added WSXREG_LOADERFILENAME.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 29-Nov-2000 rr: Added WSXREG_DSPTYPE_55 as 6.
++ *! 06-Sep-2000 jeh: Added WSXREG_CHNLOFFSET, WSXREG_NUMCHNLS,
++ *! WSXREG_CHNLBUFSIZE.
++ *! 26-Aug-2000 rr: MEMBASE expanded to 9 entries.
++ *! 26-Jul-2000 rr: Added WSXREG_DCDNAME for the DCD Dll name. It will
++ *! live under WSXREG_WINSPOXCONFIG.
++ *! 17-Jul-2000 rr: REG_MGR_OBJECT and REG_DRV_OBJECT defined. They
++ *! are stored in the Registrty under WSXREG_WINSPOXCONFIG
++ *! when they are created in DSP_Init. WSXREG_DEVOBJECT
++ *! and WSXREG_MGROBJECT defined.
++ *! 11-Dec-1999 ag: Renamed Isa to IsaBus due to conflict with ceddk.h.
++ *! 12-Nov-1999 rr: New Registry Defnitions.
++ *! 15-Oct-1999 rr: New entry for DevObject created. WSXREG_DEVOBJECT
++ *! under WSXREG_DDSPDRIVERPATH
++ *! 10-Nov-1997 cr: Added WSXREG_INFPATH, WSXREG_WINDEVICEPATH,
++ *! WSXREG_WINCURVERSION
++ *! 21-Oct-1997 cr: Added WSXREG_BUSTYPE.
++ *! 08-Sep-1997 cr: Added WSXREG_SERVICES, WSXREG_SERVICENAME and
++ *! WSXREG_CLASSINDEX.
++ *! 30-Aug-1997 cr: Added WSXREG_SOFTWAREPATHNT & WSXREG_WBCLASSGUID.
++ *! 24-Mar-1997 gp: Added MAXCHIPINFOSUBKEY def.
++ *! 18-Feb-1997 cr: Changed Version1.1 -> Version1.0
++ *! 12-Feb-1997 cr: Changed WinSPOX -> WinBRIDGE.
++ *! 11-Dec-1996 gp: Added Perf key name in WinSPOX Config.
++ *! 22-Jul-1996 gp: Added Trace key name.
++ *! 30-May-1996 cr: Created.
++ */
++
++#ifndef DBREG_
++#define DBREG_ 1 /* Defined as "1" so InstallShield programs compile. */
++
++#define REG_MGR_OBJECT 1
++#define REG_DRV_OBJECT 2
++/* general registry definitions */
++#define MAXREGPATHLENGTH 255 /* Max registry path length. Also the
++ max registry value length. */
++#define DSPTYPE_55 6 /* This is the DSP Chip type for 55 */
++#define DSPTYPE_64 0x99
++#define IVA_ARM7 0x97 /* This is the DSP Chip type for IVA/ARM7 */
++
++#define DSPPROCTYPE_C55 5510
++#define DSPPROCTYPE_C64 6410
++#define IVAPROCTYPE_ARM7 470
++/* registry */
++#define DEVNODESTRING "DevNode" /* u32 devnode */
++#define CONFIG "Software\\TexasInstruments\\DirectDSP\\Config"
++#define DRVOBJECT "DrvObject"
++#define MGROBJECT "MgrObject"
++#define CLASS "Device" /* device class */
++#define TRACE "Trace" /* GT Trace settings. */
++#define PERFR "Perf" /* Enable perf bool. */
++#define ROOT "Root" /* root dir */
++
++/* MiniDriver related definitions */
++/* The following definitions are under "Drivers\\DirectDSP\\Device\\XXX "
++ * Where XXX is the device or board name */
++
++#define WMDFILENAME "MiniDriver" /* WMD entry name */
++#define CHIPTYPE "ChipType" /* Chip type */
++#define CHIPNUM "NumChips" /* Number of chips */
++#define NUMPROCS "NumOfProcessors" /* Number of processors */
++#define DEFEXEC "DefaultExecutable" /* Default executable */
++#define AUTOSTART "AutoStart" /* Statically load flag */
++#define IVAAUTOSTART "IvaAutoStart" /* Statically load flag */
++#define BOARDNAME "BoardName" /* Name of the Board */
++#define UNITNUMBER "UnitNumber" /* Unit # of the Board */
++#define BUSTYPE "BusType" /* Bus type board is on */
++#define BUSNUMBER "BusNumber" /* Bus number board is on */
++#define CURRENTCONFIG "CurrentConfig" /* Current resources */
++#define PCIVENDEVID "VendorDeviceId" /* The board's id */
++#define INFPATH "InfPath" /* wmd's inf filename */
++#define DEVOBJECT "DevObject"
++#define ZLFILENAME "ZLFileName" /* Name of ZL file */
++#define WORDSIZE "WordSize" /* NumBytes in DSP Word */
++#define SHMSIZE "SHMSize" /* Size of SHM reservd on MPU */
++#define IVAEXTMEMSIZE "IVAEXTMEMSize" /* IVA External Memeory size */
++#define TCWORDSWAP "TCWordSwap" /* Traffic Contoller Word Swap */
++#define DSPRESOURCES "DspTMSResources" /* C55 DSP resurces on OMAP */
++#define IVA1RESOURCES "ARM7IvaResources" /* ARM7 IVA resurces on OMAP */
++#define PHYSMEMPOOLBASE "PhysicalMemBase" /* Physical mem passed to driver */
++#define PHYSMEMPOOLSIZE "PhysicalMemSize" /* Physical mem passed to driver */
++
++#endif /* DBREG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dbtype.h b/arch/arm/plat-omap/include/dspbridge/dbtype.h
+new file mode 100644
+index 0000000..b4953a0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dbtype.h
+@@ -0,0 +1,103 @@
++/*
++ * dbtype.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbtype.h ========
++ * Description:
++ * This header defines data types for DSP/BIOS Bridge APIs and device
++ * driver modules. It also defines the Hungarian
++ * prefix to use for each base type.
++ *
++ *
++ *! Revision History:
++ *! =================
++ *! 23-Nov-2002 gp: Purpose -> Description in file header.
++ *! 13-Feb-2001 kc: Name changed from ddsptype.h dbtype.h.
++ *! 09-Oct-2000 jeh Added CHARACTER.
++ *! 11-Aug-2000 ag: Added 'typedef void void'.
++ *! 08-Apr-2000 ww: Cloned.
++ */
++
++#ifndef DBTYPE_
++#define DBTYPE_
++
++/*============================================================================*/
++/* Argument specification syntax */
++/*============================================================================*/
++
++#ifndef IN
++#define IN /* Following parameter is for input. */
++#endif
++
++#ifndef OUT
++#define OUT /* Following parameter is for output. */
++#endif
++
++#ifndef OPTIONAL
++#define OPTIONAL /* Function may optionally use previous parameter. */
++#endif
++
++#ifndef CONST
++#define CONST const
++#endif
++
++/*============================================================================*/
++/* Boolean constants */
++/*============================================================================*/
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++/*============================================================================*/
++/* NULL (Definition is language specific) */
++/*============================================================================*/
++
++#ifndef NULL
++#define NULL ((void *)0) /* Null pointer. */
++#endif
++
++/*============================================================================*/
++/* NULL character (normally used for string termination) */
++/*============================================================================*/
++
++#ifndef NULL_CHAR
++#define NULL_CHAR '\0' /* Null character. */
++#endif
++
++/*============================================================================*/
++/* Basic Type definitions (with Prefixes for Hungarian notation) */
++/*============================================================================*/
++
++#ifndef OMAPBRIDGE_TYPES
++#define OMAPBRIDGE_TYPES
++typedef volatile unsigned short REG_UWORD16;
++#endif
++
++typedef void *HANDLE; /* h */
++
++#define TEXT(x) x
++
++#define DLLIMPORT
++#define DLLEXPORT
++
++/* Define DSPAPIDLL correctly in dspapi.h */
++#define _DSPSYSDLL32_
++
++#endif /* DBTYPE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dehdefs.h b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
+new file mode 100644
+index 0000000..06e5582
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dehdefs.h
+@@ -0,0 +1,42 @@
++/*
++ * dehdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dehdefs.h ========
++ * Purpose:
++ * Definition for mini-driver module DEH.
++ *
++ *! Revision History:
++ *! ================
++ *! 17-Dec-2001 ag: added #include <dspbridge/mbx_sh.h> for shared mailbox codes.
++ *! 10-Dec-2001 kc: added DEH error base value and error max value.
++ *! 11-Sep-2001 kc: created.
++ */
++
++#ifndef DEHDEFS_
++#define DEHDEFS_
++
++#include <dspbridge/mbx_sh.h> /* shared mailbox codes */
++
++/* DEH object manager */
++ struct DEH_MGR;
++
++/* Magic code used to determine if DSP signaled exception. */
++#define DEH_BASE MBX_DEH_BASE
++#define DEH_USERS_BASE MBX_DEH_USERS_BASE
++#define DEH_LIMIT MBX_DEH_LIMIT
++
++#endif /* _DEHDEFS_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dev.h b/arch/arm/plat-omap/include/dspbridge/dev.h
+new file mode 100644
+index 0000000..5f468c9
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dev.h
+@@ -0,0 +1,785 @@
++/*
++ * dev.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dev.h ========
++ * Description:
++ * 'Bridge Mini-driver device operations.
++ *
++ * Public Functions:
++ * DEV_BrdWriteFxn
++ * DEV_CreateDevice
++ * DEV_Create2
++ * DEV_Destroy2
++ * DEV_DestroyDevice
++ * DEV_GetChnlMgr
++ * DEV_GetCmmMgr
++ * DEV_GetCodMgr
++ * DEV_GetDehMgr
++ * DEV_GetDevNode
++ * DEV_GetDSPWordSize
++ * DEV_GetFirst
++ * DEV_GetIntfFxns
++ * DEV_GetIOMgr
++ * DEV_GetMsgMgr
++ * DEV_GetNext
++ * DEV_GetNodeManager
++ * DEV_GetSymbol
++ * DEV_GetWMDContext
++ * DEV_Exit
++ * DEV_Init
++ * DEV_InsertProcObject
++ * DEV_IsLocked
++ * DEV_NotifyClient
++ * DEV_RegisterNotify
++ * DEV_ReleaseCodMgr
++ * DEV_RemoveDevice
++ * DEV_RemoveProcObject
++ * DEV_SetChnlMgr
++ * DEV_SetMsgMgr
++ * DEV_SetLockOwner
++ * DEV_StartDevice
++ *
++ *! Revision History:
++ *! ================
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature - Dev_GetDmmMgr
++ *! 09-Feb-2004 vp Added functions required for IVA
++ *! 25-Feb-2003 swa PMGR Code Review changes incorporated
++ *! 05-Nov-2001 kc: Added DEV_GetDehMgr.
++ *! 05-Dec-2000 jeh Added DEV_SetMsgMgr.
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 17-Nov-2000 jeh Added DEV_GetMsgMgr.
++ *! 05-Oct-2000 rr: DEV_Create2 & DEV_Destroy2 Added.
++ *! 02-Oct-2000 rr: Added DEV_GetNodeManager.
++ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr() for shared memory management.
++ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
++ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
++ *! 05-Nov-1999 kc: Updated function prototypes.
++ *! 08-Oct-1997 cr: Added explicit CDECL function identifiers.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 22-Oct-1996 gp: Added DEV_CleanupProcessState().
++ *! 29-May-1996 gp: Changed DEV_HDEVNODE --> CFG_HDEVNODE.
++ *! 18-May-1996 gp: Created.
++ */
++
++#ifndef DEV_
++#define DEV_
++
++/* ----------------------------------- Module Dependent Headers */
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/cod.h>
++#include <dspbridge/dehdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/dispdefs.h>
++#include <dspbridge/wmd.h>
++#include <dspbridge/dmm.h>
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/devdefs.h>
++
++
++/*
++ * ======== DEV_BrdWriteFxn ========
++ * Purpose:
++ * Exported function to be used as the COD write function. This function
++ * is passed a handle to a DEV_hObject by ZL in pArb, then calls the
++ * device's WMD_BRD_Write() function.
++ * Parameters:
++ * pArb: Handle to a Device Object.
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * Number of bytes written. Returns 0 if the DEV_hObject passed in via
++ * pArb is invalid.
++ * Requires:
++ * DEV Initialized.
++ * pHostBuf != NULL
++ * Ensures:
++ */
++ extern u32 DEV_BrdWriteFxn(void *pArb,
++ u32 ulDspAddr,
++ void *pHostBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== DEV_CreateDevice ========
++ * Purpose:
++ * Called by the operating system to load the 'Bridge Mini Driver for a
++ * 'Bridge device.
++ * Parameters:
++ * phDevObject: Ptr to location to receive the device object handle.
++ * pstrWMDFileName: Name of WMD PE DLL file to load. If the absolute
++ * path is not provided, the file is loaded through
++ * 'Bridge's module search path.
++ * pHostConfig: Host configuration information, to be passed down
++ * to the WMD when WMD_DEV_Create() is called.
++ * pDspConfig: DSP resources, to be passed down to the WMD when
++ * WMD_DEV_Create() is called.
++ * hDevNode: Platform (Windows) specific device node.
++ * Returns:
++ * DSP_SOK: Module is loaded, device object has been created
++ * DSP_EMEMORY: Insufficient memory to create needed resources.
++ * DEV_E_NEWWMD: The WMD was compiled for a newer version of WCD.
++ * DEV_E_NULLWMDINTF: WMD passed back a NULL Fxn Interface Struct Ptr
++ * DEV_E_NOCODMODULE: No ZL file name was specified in the registry
++ * for this hDevNode.
++ * LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
++ * LDR_E_NOMEMORY: PELDR is out of resources.
++ * DSP_EFAIL: Unable to find WMD entry point function.
++ * COD_E_NOZLFUNCTIONS: One or more ZL functions exports not found.
++ * COD_E_ZLCREATEFAILED: Unable to load ZL DLL.
++ * Requires:
++ * DEV Initialized.
++ * phDevObject != NULL.
++ * pstrWMDFileName != NULL.
++ * pHostConfig != NULL.
++ * pDspConfig != NULL.
++ * Ensures:
++ * DSP_SOK: *phDevObject will contain handle to the new device object.
++ * Otherwise, does not create the device object, ensures the WMD module is
++ * unloaded, and sets *phDevObject to NULL.
++ */
++ extern DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT
++ **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES
++ *pHostConfig,
++ IN CONST struct CFG_DSPRES
++ *pDspConfig,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_CreateIVADevice ========
++ * Purpose:
++ * Called by the operating system to load the 'Bridge Mini Driver for IVA.
++ * Parameters:
++ * phDevObject: Ptr to location to receive the device object handle.
++ * pstrWMDFileName: Name of WMD PE DLL file to load. If the absolute
++ * path is not provided, the file is loaded through
++ * 'Bridge's module search path.
++ * pHostConfig: Host configuration information, to be passed down
++ * to the WMD when WMD_DEV_Create() is called.
++ * pDspConfig: DSP resources, to be passed down to the WMD when
++ * WMD_DEV_Create() is called.
++ * hDevNode: Platform (Windows) specific device node.
++ * Returns:
++ * DSP_SOK: Module is loaded, device object has been created
++ * DSP_EMEMORY: Insufficient memory to create needed resources.
++ * DEV_E_NEWWMD: The WMD was compiled for a newer version of WCD.
++ * DEV_E_NULLWMDINTF: WMD passed back a NULL Fxn Interface Struct Ptr
++ * DEV_E_NOCODMODULE: No ZL file name was specified in the registry
++ * for this hDevNode.
++ * LDR_E_FILEUNABLETOOPEN: Unable to open the specified WMD.
++ * LDR_E_NOMEMORY: PELDR is out of resources.
++ * DSP_EFAIL: Unable to find WMD entry point function.
++ * COD_E_NOZLFUNCTIONS: One or more ZL functions exports not found.
++ * COD_E_ZLCREATEFAILED: Unable to load ZL DLL.
++ * Requires:
++ * DEV Initialized.
++ * phDevObject != NULL.
++ * pstrWMDFileName != NULL.
++ * pHostConfig != NULL.
++ * pDspConfig != NULL.
++ * Ensures:
++ * DSP_SOK: *phDevObject will contain handle to the new device object.
++ * Otherwise, does not create the device object, ensures the WMD module is
++ * unloaded, and sets *phDevObject to NULL.
++ */
++ extern DSP_STATUS DEV_CreateIVADevice(OUT struct DEV_OBJECT
++ **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES *pHostConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_Create2 ========
++ * Purpose:
++ * After successful loading of the image from WCD_InitComplete2
++ * (PROC Auto_Start) or PROC_Load this fxn is called. This creates
++ * the Node Manager and updates the DEV Object.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Successful Creation of Node Manager
++ * DSP_EFAIL: Some Error Occurred.
++ * Requires:
++ * DEV Initialized
++ * Valid hDevObject
++ * Ensures:
++ * DSP_SOK and hDevObject->hNodeMgr != NULL
++ * else hDevObject->hNodeMgr == NULL
++ */
++ extern DSP_STATUS DEV_Create2(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_Destroy2 ========
++ * Purpose:
++ * Destroys the Node manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Successful Creation of Node Manager
++ * DSP_EFAIL: Some Error Occurred.
++ * Requires:
++ * DEV Initialized
++ * Valid hDevObject
++ * Ensures:
++ * DSP_SOK and hDevObject->hNodeMgr == NULL
++ * else DSP_EFAIL.
++ */
++ extern DSP_STATUS DEV_Destroy2(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_DestroyDevice ========
++ * Purpose:
++ * Destroys the channel manager for this device, if any, calls
++ * WMD_DEV_Destroy(), and then attempts to unload the WMD module.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * DSP_EFAIL: The WMD failed it's WMD_DEV_Destroy() function.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ======== DEV_GetChnlMgr ========
++ * Purpose:
++ * Retrieve the handle to the channel manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CHNL_MGR **phMgr);
++
++/*
++ * ======== DEV_GetCmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the shared memory manager created for this
++ * device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CMM_OBJECT **phMgr);
++
++/*
++ * ======== DEV_GetDmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the dynamic memory manager created for this
++ * device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to a channel manager object,
++ * or NULL.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DMM_OBJECT **phMgr);
++
++/*
++ * ======== DEV_GetCodMgr ========
++ * Purpose:
++ * Retrieve the COD manager create for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phCodMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phCodMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phCodMgr contains a handle to a COD manager object.
++ * else: *phCodMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct COD_MANAGER **phCodMgr);
++
++/*
++ * ======== DEV_GetDehMgr ========
++ * Purpose:
++ * Retrieve the DEH manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * *phDehMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDehMgr != NULL.
++ * DEH Initialized.
++ * Ensures:
++ * DSP_SOK: *phDehMgr contains a handle to a DEH manager object.
++ * else: *phDehMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DEH_MGR **phDehMgr);
++
++/*
++ * ======== DEV_GetDevNode ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * phDevNode: Ptr to location to get the device node handle.
++ * Returns:
++ * DSP_SOK: In Win95, returns a DEVNODE in *hDevNode; In NT, ???
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDevNode != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phDevNode contains a platform specific device ID;
++ * else: *phDevNode is NULL.
++ */
++ extern DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
++ OUT struct CFG_DEVNODE **phDevNode);
++
++/*
++ * ======== DEV_GetDevType ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * phDevNode: Ptr to location to get the device node handle.
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phDevNode != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phDevNode contains a platform specific device ID;
++ * else: *phDevNode is NULL.
++ */
++ extern DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject,
++ u32 *devType);
++
++/*
++ * ======== DEV_GetFirst ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DEV.
++ * Parameters:
++ * Returns:
++ * NULL if there are no device objects stored; else
++ * a valid DEV_HOBJECT.
++ * Requires:
++ * No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
++ * internal device object list) may occur between calls to DEV_GetFirst
++ * and DEV_GetNext.
++ * Ensures:
++ * The DEV_HOBJECT returned is valid.
++ * A subsequent call to DEV_GetNext will return the next device object in
++ * the list.
++ */
++ extern struct DEV_OBJECT *DEV_GetFirst(void);
++
++/*
++ * ======== DEV_GetIntfFxns ========
++ * Purpose:
++ * Retrieve the WMD interface function structure for the loaded WMD.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *ppIntfFxns: Ptr to location to store fxn interface.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * ppIntfFxns != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *ppIntfFxns contains a pointer to the WMD interface;
++ * else: *ppIntfFxns is NULL.
++ */
++ extern DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DRV_INTERFACE **ppIntfFxns);
++
++/*
++ * ======== DEV_GetIOMgr ========
++ * Purpose:
++ * Retrieve the handle to the IO manager created for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * *phMgr: Ptr to location to store handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phMgr != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phMgr contains a handle to an IO manager object.
++ * else: *phMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct IO_MGR **phMgr);
++
++/*
++ * ======== DEV_GetNext ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DEV, after having previously called
++ * DEV_GetFirst() and zero or more DEV_GetNext
++ * Parameters:
++ * hDevObject: Handle to the device object returned from a previous
++ * call to DEV_GetFirst() or DEV_GetNext().
++ * Returns:
++ * NULL if there are no further device objects on the list or hDevObject
++ * was invalid;
++ * else the next valid DEV_HOBJECT in the list.
++ * Requires:
++ * No calls to DEV_CreateDevice or DEV_DestroyDevice (which my modify the
++ * internal device object list) may occur between calls to DEV_GetFirst
++ * and DEV_GetNext.
++ * Ensures:
++ * The DEV_HOBJECT returned is valid.
++ * A subsequent call to DEV_GetNext will return the next device object in
++ * the list.
++ */
++ extern struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ========= DEV_GetMsgMgr ========
++ * Purpose:
++ * Retrieve the MSG Manager Handle from the DevObject.
++ * Parameters:
++ * hDevObject: Handle to the Dev Object
++ * phMsgMgr: Location where MSG Manager handle will be returned.
++ * Returns:
++ * Requires:
++ * DEV Initialized.
++ * Valid hDevObject.
++ * phNodeMgr != NULL.
++ * Ensures:
++ */
++ extern void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct MSG_MGR **phMsgMgr);
++
++/*
++ * ========= DEV_GetNodeManager ========
++ * Purpose:
++ * Retrieve the Node Manager Handle from the DevObject. It is an
++ * accessor function
++ * Parameters:
++ * hDevObject: Handle to the Dev Object
++ * phNodeMgr: Location where Handle to the Node Manager will be
++ * returned..
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EHANDLE: Invalid Dev Object handle.
++ * Requires:
++ * DEV Initialized.
++ * phNodeMgr is not null
++ * Ensures:
++ * DSP_SOK: *phNodeMgr contains a handle to a Node manager object.
++ * else: *phNodeMgr is NULL.
++ */
++ extern DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT
++ *hDevObject,
++ OUT struct NODE_MGR **phNodeMgr);
++
++/*
++ * ======== DEV_GetSymbol ========
++ * Purpose:
++ * Get the value of a symbol in the currently loaded program.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * pstrSym: Name of symbol to look up.
++ * pulValue: Ptr to symbol value.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * COD_E_NOSYMBOLSLOADED: Symbols have not been loaded onto the board.
++ * COD_E_SYMBOLNOTFOUND: The symbol could not be found.
++ * Requires:
++ * pstrSym != NULL.
++ * pulValue != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *pulValue contains the symbol value;
++ */
++ extern DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
++ IN CONST char *pstrSym,
++ OUT u32 *pulValue);
++
++/*
++ * ======== DEV_GetWMDContext ========
++ * Purpose:
++ * Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice()
++ * *phWmdContext: Ptr to location to store context handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * phWmdContext != NULL.
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: *phWmdContext contains context handle;
++ * else: *phWmdContext is NULL;
++ */
++ extern DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DEV_CONTEXT **phWmdContext);
++
++/*
++ * ======== DEV_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DEV is initialized.
++ * Ensures:
++ * When reference count == 0, DEV's private resources are freed.
++ */
++ extern void DEV_Exit(void);
++
++/*
++ * ======== DEV_Init ========
++ * Purpose:
++ * Initialize DEV's private state, keeping a reference count on each call.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public DEV functions.
++ */
++ extern bool DEV_Init(void);
++
++/*
++ * ======== DEV_IsLocked ========
++ * Purpose:
++ * Predicate function to determine if the device has been
++ * locked by a client for exclusive access.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * DSP_SOK: TRUE: device has been locked.
++ * DSP_SFALSE: FALSE: device not locked.
++ * DSP_EHANDLE: hDevObject was invalid.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_IsLocked(IN struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DEV_InsertProcObject ========
++ * Purpose:
++ * Inserts the Processor Object into the List of PROC Objects
++ * kept in the DEV Object
++ * Parameters:
++ * hProcObject: Handle to the Proc Object
++ * hDevObject Handle to the Dev Object
++ * bAttachedNew Specifies if there are already processors attached
++ * Returns:
++ * DSP_SOK: Successfully inserted into the list
++ * Requires:
++ * hProcObject is not NULL
++ * hDevObject is a valid handle to the DEV.
++ * DEV Initialized.
++ * List(of Proc object in Dev) Exists.
++ * Ensures:
++ * DSP_SOK & the PROC Object is inserted and the list is not empty
++ * Details:
++ * If the List of Proc Object is empty bAttachedNew is TRUE, it indicated
++ * this is the first Processor attaching.
++ * If it is False, there are already processors attached.
++ */
++ extern DSP_STATUS DEV_InsertProcObject(IN struct DEV_OBJECT
++ *hDevObject,
++ IN u32 hProcObject,
++ OUT bool *
++ pbAlreadyAttached);
++
++/*
++ * ======== DEV_RemoveProcObject ========
++ * Purpose:
++ * Search for and remove a Proc object from the given list maintained
++ * by the DEV
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject: Ptr to Dev Object where the list is.
++ * pbAlreadyAttached: Ptr to return the bool
++ * Returns:
++ * DSP_SOK: If successful.
++ * DSP_EFAIL Failure to Remove the PROC Object from the list
++ * Requires:
++ * DevObject is Valid
++ * hProcObject != 0
++ * pDevObject->procList != NULL
++ * !LST_IsEmpty(pDevObject->procList)
++ * pbAlreadyAttached !=NULL
++ * Ensures:
++ * Details:
++ * List will be deleted when the DEV is destroyed.
++ *
++ */
++ extern DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT
++ *hDevObject,
++ u32 hProcObject);
++
++/*
++ * ======== DEV_NotifyClients ========
++ * Purpose:
++ * Notify all clients of this device of a change in device status.
++ * Clients may include multiple users of BRD, as well as CHNL.
++ * This function is asychronous, and may be called by a timer event
++ * set up by a watchdog timer.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * ulStatus: A status word, most likely a BRD_STATUS.
++ * Returns:
++ * DSP_SOK: All registered clients were asynchronously notified.
++ * DSP_EINVALIDARG: Invalid hDevObject.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ * DSP_SOK: Notifications are queued by the operating system to be
++ * delivered to clients. This function does not ensure that
++ * the notifications will ever be delivered.
++ */
++ extern DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject,
++ u32 ulStatus);
++
++
++
++/*
++ * ======== DEV_RemoveDevice ========
++ * Purpose:
++ * Destroys the Device Object created by DEV_StartDevice.
++ * Parameters:
++ * hDevNode: Device node as it is know to OS.
++ * Returns:
++ * DSP_SOK: If success;
++ * <error code> Otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== DEV_SetChnlMgr ========
++ * Purpose:
++ * Set the channel manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * hMgr: Handle to a channel manager, or NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject,
++ struct CHNL_MGR *hMgr);
++
++/*
++ * ======== DEV_SetMsgMgr ========
++ * Purpose:
++ * Set the Message manager for this device.
++ * Parameters:
++ * hDevObject: Handle to device object created with DEV_CreateDevice().
++ * hMgr: Handle to a message manager, or NULL.
++ * Returns:
++ * Requires:
++ * DEV Initialized.
++ * Ensures:
++ */
++ extern void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject,
++ struct MSG_MGR *hMgr);
++
++/*
++ * ======== DEV_StartDevice ========
++ * Purpose:
++ * Initializes the new device with the WinBRIDGE environment. This
++ * involves querying CM for allocated resources, querying the registry
++ * for necessary dsp resources (requested in the INF file), and using
++ * this information to create a WinBRIDGE device object.
++ * Parameters:
++ * hDevNode: Device node as it is know to OS.
++ * Returns:
++ * DSP_SOK: If success;
++ * <error code> Otherwise.
++ * Requires:
++ * DEV initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode);
++
++#endif /* DEV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/devdefs.h b/arch/arm/plat-omap/include/dspbridge/devdefs.h
+new file mode 100644
+index 0000000..e9ff725
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/devdefs.h
+@@ -0,0 +1,35 @@
++/*
++ * devdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== devdefs.h ========
++ * Purpose:
++ * Definition of common include typedef between wmd.h and dev.h. Required
++ * to break circular dependency between WMD and DEV include files.
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Nov-1996 gp: Renamed from dev1.h.
++ *! 30-May-1996 gp: Broke out from dev.h
++ */
++
++#ifndef DEVDEFS_
++#define DEVDEFS_
++
++/* WCD Device Object */
++ struct DEV_OBJECT;
++
++#endif /* DEVDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/disp.h b/arch/arm/plat-omap/include/dspbridge/disp.h
+new file mode 100644
+index 0000000..e116734
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/disp.h
+@@ -0,0 +1,236 @@
++/*
++ * disp.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== disp.h ========
++ *
++ * Description:
++ * DSP/BIOS Bridge Node Dispatcher.
++ *
++ * Public Functions:
++ * DISP_Create
++ * DISP_Delete
++ * DISP_Exit
++ * DISP_Init
++ * DISP_NodeChangePriority
++ * DISP_NodeCreate
++ * DISP_NodeDelete
++ * DISP_NodeRun
++ *
++ *! Revision History:
++ *! =================
++ *! 28-Jan-2003 map Removed DISP_DoCinit().
++ *! 15-May-2002 jeh Added DISP_DoCinit().
++ *! 24-Apr-2002 jeh Added DISP_MemWrite().
++ *! 07-Sep-2001 jeh Added DISP_MemCopy().
++ *! 10-May-2001 jeh Code review cleanup.
++ *! 08-Aug-2000 jeh Removed DISP_NodeTerminate since it no longer uses RMS.
++ *! 17-Jul-2000 jeh Updates to function headers.
++ *! 19-Jun-2000 jeh Created.
++ */
++
++#ifndef DISP_
++#define DISP_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/dispdefs.h>
++
++/*
++ * ======== DISP_Create ========
++ * Create a NODE Dispatcher object. This object handles the creation,
++ * deletion, and execution of nodes on the DSP target, through communication
++ * with the Resource Manager Server running on the target. Each NODE
++ * Manager object should have exactly one NODE Dispatcher.
++ *
++ * Parameters:
++ * phDispObject: Location to store node dispatcher object on output.
++ * hDevObject: Device for this processor.
++ * pDispAttrs: Node dispatcher attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: Unable to create dispatcher.
++ * Requires:
++ * DISP_Init(void) called.
++ * pDispAttrs != NULL.
++ * hDevObject != NULL.
++ * phDispObject != NULL.
++ * Ensures:
++ * DSP_SOK: IsValid(*phDispObject).
++ * error: *phDispObject == NULL.
++ */
++ extern DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DISP_ATTRS *pDispAttrs);
++
++/*
++ * ======== DISP_Delete ========
++ * Delete the NODE Dispatcher.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * Returns:
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * Ensures:
++ * hDispObject is invalid.
++ */
++ extern void DISP_Delete(struct DISP_OBJECT *hDispObject);
++
++/*
++ * ======== DISP_Exit ========
++ * Discontinue usage of DISP module.
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DISP_Init(void) previously called.
++ * Ensures:
++ * Any resources acquired in DISP_Init(void) will be freed when last DISP
++ * client calls DISP_Exit(void).
++ */
++ extern void DISP_Exit(void);
++
++/*
++ * ======== DISP_Init ========
++ * Initialize the DISP module.
++ *
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool DISP_Init(void);
++
++/*
++ * ======== DISP_NodeChangePriority ========
++ * Change the priority of a node currently running on the target.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node currently
++ * allocated or running on the DSP.
++ * ulFxnAddress: Address of RMS function for changing priority.
++ * nodeEnv: Address of node's environment structure.
++ * nPriority: New priority level to set node's priority to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT
++ *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ NODE_ENV nodeEnv,
++ s32 nPriority);
++
++/*
++ * ======== DISP_NodeCreate ========
++ * Create a node on the DSP by remotely calling the node's create function.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node handle obtained from NODE_Allocate().
++ * ulFxnAddr: Address or RMS create node function.
++ * ulCreateFxn: Address of node's create function.
++ * pArgs: Arguments to pass to RMS node create function.
++ * pNodeEnv: Location to store node environment pointer on
++ * output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETASK: Unable to create the node's task or process on the DSP.
++ * DSP_ESTREAM: Stream creation failure on the DSP.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EUSER: A user-defined failure occurred.
++ * DSP_EFAIL: A failure occurred, unable to create node.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * pArgs != NULL.
++ * hNode != NULL.
++ * pNodeEnv != NULL.
++ * NODE_GetType(hNode) != NODE_DEVICE.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulCreateFxn,
++ IN CONST struct NODE_CREATEARGS
++ *pArgs,
++ OUT NODE_ENV *pNodeEnv);
++
++/*
++ * ======== DISP_NodeDelete ========
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node currently
++ * loaded on the DSP.
++ * ulFxnAddr: Address or RMS delete node function.
++ * ulDeleteFxn: Address of node's delete function.
++ * nodeEnv: Address of node's environment structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulDeleteFxn, NODE_ENV nodeEnv);
++
++/*
++ * ======== DISP_NodeRun ========
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via DISP_NodePause()) on the DSP.
++ *
++ * Parameters:
++ * hDispObject: Node Dispatcher object.
++ * hNode: Node object representing a node to be executed
++ * on the DSP.
++ * ulFxnAddr: Address or RMS node execute function.
++ * ulExecuteFxn: Address of node's execute function.
++ * nodeEnv: Address of node's environment structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * Requires:
++ * DISP_Init(void) called.
++ * Valid hDispObject.
++ * hNode != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDispObject,
++ struct NODE_OBJECT *hNode,
++ u32 ulFxnAddr,
++ u32 ulExecuteFxn, NODE_ENV nodeEnv);
++
++#endif /* DISP_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dispdefs.h b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
+new file mode 100644
+index 0000000..401ad4f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dispdefs.h
+@@ -0,0 +1,45 @@
++/*
++ * dispdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dispdefs.h ========
++ * Description:
++ * Global DISP constants and types, shared by PROCESSOR, NODE, and DISP.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Aug-2000 jeh Added fields to DISP_ATTRS.
++ *! 06-Jul-2000 jeh Created.
++ */
++
++#ifndef DISPDEFS_
++#define DISPDEFS_
++
++ struct DISP_OBJECT;
++
++/* Node Dispatcher attributes */
++ struct DISP_ATTRS {
++ u32 ulChnlOffset; /* Offset of channel ids reserved for RMS */
++ /* Size of buffer for sending data to RMS */
++ u32 ulChnlBufSize;
++ DSP_PROCFAMILY procFamily; /* eg, 5000 */
++ DSP_PROCTYPE procType; /* eg, 5510 */
++ HANDLE hReserved1; /* Reserved for future use. */
++ u32 hReserved2; /* Reserved for future use. */
++ } ;
++
++#endif /* DISPDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dmm.h b/arch/arm/plat-omap/include/dspbridge/dmm.h
+new file mode 100644
+index 0000000..ef37668
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dmm.h
+@@ -0,0 +1,85 @@
++/*
++ * dmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dmm.h ========
++ * Purpose:
++ * The Dynamic Memory Mapping(DMM) module manages the DSP Virtual address
++ * space that can be directly mapped to any MPU buffer or memory region
++ *
++ * Public Functions:
++ *
++ *! Revision History:
++ *! ================
++ *! 20-Feb-2004 sb: Created.
++ *!
++ */
++
++#ifndef DMM_
++#define DMM_
++
++#include <dspbridge/dbdefs.h>
++
++ struct DMM_OBJECT;
++
++/* DMM attributes used in DMM_Create() */
++ struct DMM_MGRATTRS {
++ u32 reserved;
++ } ;
++
++#define DMMPOOLSIZE 0x4000000
++
++/*
++ * ======== DMM_GetHandle ========
++ * Purpose:
++ * Return the dynamic memory manager object for this device.
++ * This is typically called from the client process.
++ */
++
++ extern DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct DMM_OBJECT **phDmmMgr);
++
++ extern DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 size,
++ u32 *pRsvAddr);
++
++ extern DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 rsvAddr);
++
++ extern DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr,
++ u32 size);
++
++ extern DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr,
++ u32 addr,
++ u32 *pSize);
++
++ extern DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr);
++
++ extern DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr);
++
++ extern DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DMM_MGRATTRS *pMgrAttrs);
++
++ extern bool DMM_Init(void);
++
++ extern void DMM_Exit(void);
++
++ extern DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr,
++ u32 addr, u32 size);
++ extern u32 *DMM_GetPhysicalAddrTable(void);
++#endif /* DMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dpc.h b/arch/arm/plat-omap/include/dspbridge/dpc.h
+new file mode 100644
+index 0000000..8c20506
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dpc.h
+@@ -0,0 +1,167 @@
++/*
++ * dpc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dpc.h ========
++ * Purpose:
++ * Deferred Procedure Call(DPC) Services.
++ *
++ * Public Functions:
++ * DPC_Cancel
++ * DPC_Create
++ * DPC_Destroy
++ * DPC_Exit
++ * DPC_Init
++ * DPC_Schedule
++ *
++ *! Revision History:
++ *! ================
++ *! 31-Jan-2000 rr: DPC_Destroy ensures Suceess and DPC Object is NULL.
++ *! 21-Jan-2000 ag: Updated comments per code review.
++ *! 06-Jan-2000 ag: Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 14-Jan-1998 gp: Added DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 18-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 28-Jul-1996 gp: Created.
++ */
++
++#ifndef DPC_
++#define DPC_
++
++ struct DPC_OBJECT;
++
++/*
++ * ======== DPC_PROC ========
++ * Purpose:
++ * Deferred processing routine. Typically scheduled from an ISR to
++ * complete I/O processing.
++ * Parameters:
++ * pRefData: Ptr to user data: passed in via ISR_ScheduleDPC.
++ * Returns:
++ * Requires:
++ * The DPC should not block, or otherwise acquire resources.
++ * Interrupts to the processor are enabled.
++ * DPC_PROC executes in a critical section.
++ * Ensures:
++ * This DPC will not be reenterred on the same thread.
++ * However, the DPC may take hardware interrupts during execution.
++ * Interrupts to the processor are enabled.
++ */
++ typedef void(*DPC_PROC) (void *pRefData);
++
++/*
++ * ======== DPC_Cancel ========
++ * Purpose:
++ * Cancel a DPC previously scheduled by DPC_Schedule.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: Scheduled DPC, if any, is cancelled.
++ * DSP_SFALSE: No DPC is currently scheduled for execution.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * Ensures:
++ * If the DPC has already executed, is executing, or was not yet
++ * scheduled, this function will have no effect.
++ */
++ extern DSP_STATUS DPC_Cancel(IN struct DPC_OBJECT *hDPC);
++
++/*
++ * ======== DPC_Create ========
++ * Purpose:
++ * Create a DPC object, allowing a client's own DPC procedure to be
++ * scheduled for a call with client reference data.
++ * Parameters:
++ * phDPC: Pointer to location to store DPC object.
++ * pfnDPC: Client's DPC procedure.
++ * pRefData: Pointer to user-defined reference data.
++ * Returns:
++ * DSP_SOK: DPC object created.
++ * DSP_EPOINTER: phDPC == NULL or pfnDPC == NULL.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * Must not be called at interrupt time.
++ * Ensures:
++ * DSP_SOK: DPC object is created;
++ * else: *phDPC is set to NULL.
++ */
++ extern DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC,
++ IN DPC_PROC pfnDPC,
++ IN void *pRefData);
++
++/*
++ * ======== DPC_Destroy ========
++ * Purpose:
++ * Cancel the last scheduled DPC, and deallocate a DPC object previously
++ * allocated with DPC_Create().Frees the Object only if the thread and
++ * the events are terminated successfuly.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * All DPC's scheduled for the DPC object must have completed their
++ * processing.
++ * Ensures:
++ * (SUCCESS && hDPC is NULL) or DSP_EFAILED status
++ */
++ extern DSP_STATUS DPC_Destroy(IN struct DPC_OBJECT *hDPC);
++
++/*
++ * ======== DPC_Exit ========
++ * Purpose:
++ * Discontinue usage of the DPC module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * DPC_Init(void) was previously called.
++ * Ensures:
++ * Resources acquired in DPC_Init(void) are freed.
++ */
++ extern void DPC_Exit(void);
++
++/*
++ * ======== DPC_Init ========
++ * Purpose:
++ * Initialize the DPC module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public DPC functions.
++ */
++ extern bool DPC_Init(void);
++
++/*
++ * ======== DPC_Schedule ========
++ * Purpose:
++ * Schedule a deferred procedure call to be executed at a later time.
++ * Latency and order of DPC execution is platform specific.
++ * Parameters:
++ * hDPC: A DPC object handle created in DPC_Create().
++ * Returns:
++ * DSP_SOK: An event is scheduled for deferred processing.
++ * DSP_EHANDLE: Invalid hDPC.
++ * Requires:
++ * See requirements for DPC_PROC.
++ * Ensures:
++ * DSP_SOK: The DPC will not be called before this function returns.
++ */
++ extern DSP_STATUS DPC_Schedule(IN struct DPC_OBJECT *hDPC);
++
++#endif /* DPC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/drv.h b/arch/arm/plat-omap/include/dspbridge/drv.h
+new file mode 100644
+index 0000000..c468461
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/drv.h
+@@ -0,0 +1,449 @@
++/*
++ * drv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv.h ========
++ * Purpose:
++ * DRV Resource allocation module. Driver Object gets Created
++ * at the time of Loading. It holds the List of Device Objects
++ * in the Syste,
++ *
++ * Public Functions:
++ * DRV_Create
++ * DRV_Destroy
++ * DRV_Exit
++ * DRV_GetDevObject
++ * DRV_GetDevExtension
++ * DRV_GetFirstDevObject
++ * DRV_GetNextDevObject
++ * DRV_GetNextDevExtension
++ * DRV_Init
++ * DRV_InsertDevObject
++ * DRV_RemoveDevObject
++ * DRV_RequestResources
++ * DRV_ReleaseResources
++ *
++ *! Revision History
++ *! ================
++ *! 10-Feb-2004 vp: Added OMAP24xx specific definitions.
++ *! 14-Aug-2000 rr: Cleaned up.
++ *! 27-Jul-2000 rr: DRV_RequestResources split into two(Request and Release)
++ *! Device extension created to hold the DevNodeString.
++ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
++ *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
++ *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
++ *! 12-Nov-1999 rr: New Flag defines for DRV_ASSIGN and DRV_RELEASE
++ *! 25-Oct-1999 rr: Resource Structure removed.
++ *! 15-Oct-1999 rr: New Resource structure created.
++ *! 05-Oct-1999 rr: Added DRV_RequestResources
++ *! Removed fxn'sDRV_RegisterMiniDriver(),
++ *! DRV_UnRegisterMiniDriver()
++ *! Removed Structures DSP_DRIVER & DRV_EXTENSION.
++ *!
++ *! 24-Sep-1999 rr: Added DRV_EXTENSION and DSP_DRIVER structures.
++ *!
++ */
++
++#ifndef DRV_
++#define DRV_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/drvdefs.h>
++
++#define DRV_ASSIGN 1
++#define DRV_RELEASE 0
++
++/* Provide the DSP Internal memory windows that can be accessed from L3 address
++ * space */
++
++#define OMAP_GEM_BASE 0x107F8000
++#define OMAP_DSP_SIZE 0x00720000
++
++/* MEM1 is L2 RAM + L2 Cache space */
++#define OMAP_DSP_MEM1_BASE 0x5C7F8000
++#define OMAP_DSP_MEM1_SIZE 0x18000
++#define OMAP_DSP_GEM1_BASE 0x107F8000
++
++
++/* MEM2 is L1P RAM/CACHE space */
++#define OMAP_DSP_MEM2_BASE 0x5CE00000
++#define OMAP_DSP_MEM2_SIZE 0x8000
++#define OMAP_DSP_GEM2_BASE 0x10E00000
++
++/* MEM3 is L1D RAM/CACHE space */
++#define OMAP_DSP_MEM3_BASE 0x5CF04000
++#define OMAP_DSP_MEM3_SIZE 0x14000
++#define OMAP_DSP_GEM3_BASE 0x10F04000
++
++
++#define OMAP_IVA2_PRM_BASE 0x48306000
++#define OMAP_IVA2_PRM_SIZE 0x1000
++
++#define OMAP_IVA2_CM_BASE 0x48004000
++#define OMAP_IVA2_CM_SIZE 0x1000
++
++#define OMAP_PER_CM_BASE 0x48005000
++#define OMAP_PER_CM_SIZE 0x1000
++
++#define OMAP_PER_PRM_BASE 0x48307000
++#define OMAP_PER_PRM_SIZE 0x1000
++
++#define OMAP_CORE_PRM_BASE 0x48306A00
++#define OMAP_CORE_PRM_SIZE 0x1000
++
++#define OMAP_SYSC_BASE 0x48002000
++#define OMAP_SYSC_SIZE 0x1000
++
++#define OMAP_MBOX_BASE 0x48094000
++#define OMAP_MBOX_SIZE 0x1000
++
++#define OMAP_DMMU_BASE 0x5D000000
++#define OMAP_DMMU_SIZE 0x1000
++
++#define OMAP_PRCM_VDD1_DOMAIN 1
++#define OMAP_PRCM_VDD2_DOMAIN 2
++
++#ifndef RES_CLEANUP_DISABLE
++
++/* GPP PROCESS CLEANUP Data structures */
++
++/* New structure (member of process context) abstracts NODE resource info */
++struct NODE_RES_OBJECT {
++ DSP_HNODE hNode;
++ s32 nodeAllocated; /* Node status */
++ s32 heapAllocated; /* Heap status */
++ s32 streamsAllocated; /* Streams status */
++ struct NODE_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts DMM resource info */
++struct DMM_RES_OBJECT {
++ s32 dmmAllocated; /* DMM status */
++ u32 ulMpuAddr;
++ u32 ulDSPAddr;
++ u32 ulDSPResAddr;
++ u32 dmmSize;
++ HANDLE hProcessor;
++ struct DMM_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts DMM resource info */
++struct DSPHEAP_RES_OBJECT {
++ s32 heapAllocated; /* DMM status */
++ u32 ulMpuAddr;
++ u32 ulDSPAddr;
++ u32 ulDSPResAddr;
++ u32 heapSize;
++ HANDLE hProcessor;
++ struct DSPHEAP_RES_OBJECT *next;
++} ;
++
++/* New structure (member of process context) abstracts stream resource info */
++struct STRM_RES_OBJECT {
++ s32 streamAllocated; /* Stream status */
++ DSP_HSTREAM hStream;
++ u32 uNumBufs;
++ u32 uDir;
++ struct STRM_RES_OBJECT *next;
++} ;
++
++/* Overall Bridge process resource usage state */
++enum GPP_PROC_RES_STATE {
++ PROC_RES_ALLOCATED,
++ PROC_RES_FREED
++} ;
++
++/* Process Context */
++struct PROCESS_CONTEXT{
++ /* Process State */
++ enum GPP_PROC_RES_STATE resState;
++
++ /* Process ID (Same as UNIX process ID) */
++ u32 pid;
++
++ /* Pointer to next process context
++ * (To maintain a linked list of process contexts) */
++ struct PROCESS_CONTEXT *next;
++
++ /* Processor info to which the process is related */
++ DSP_HPROCESSOR hProcessor;
++
++ /* DSP Node resources */
++ struct NODE_RES_OBJECT *pNodeList;
++
++ /* DMM resources */
++ struct DMM_RES_OBJECT *pDMMList;
++
++ /* DSP Heap resources */
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPList;
++
++ /* Stream resources */
++ struct STRM_RES_OBJECT *pSTRMList;
++} ;
++#endif
++
++/*
++ * ======== DRV_Create ========
++ * Purpose:
++ * Creates the Driver Object. This is done during the driver loading.
++ * There is only one Driver Object in the DSP/BIOS Bridge.
++ * Parameters:
++ * phDrvObject: Location to store created DRV Object handle.
++ * Returns:
++ * DSP_SOK: Sucess
++ * DSP_EMEMORY: Failed in Memory allocation
++ * DSP_EFAIL: General Failure
++ * Requires:
++ * DRV Initialized (cRefs > 0 )
++ * phDrvObject != NULL.
++ * Ensures:
++ * DSP_SOK: - *phDrvObject is a valid DRV interface to the device.
++ * - List of DevObject Created and Initialized.
++ * - List of DevNode String created and intialized.
++ * - Registry is updated with the DRV Object.
++ * !DSP_SOK: DRV Object not created
++ * Details:
++ * There is one Driver Object for the Driver representing
++ * the driver itself. It contains the list of device
++ * Objects and the list of Device Extensions in the system.
++ * Also it can hold other neccessary
++ * information in its storage area.
++ */
++ extern DSP_STATUS DRV_Create(struct DRV_OBJECT **phDrvObject);
++
++/*
++ * ======== DRV_Destroy ========
++ * Purpose:
++ * destroys the Dev Object list, DrvExt list
++ * and destroy the DRV object
++ * Called upon driver unLoading.or unsuccesful loading of the driver.
++ * Parameters:
++ * hDrvObject: Handle to Driver object .
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to destroy DRV Object
++ * Requires:
++ * DRV Initialized (cRegs > 0 )
++ * hDrvObject is not NULL and a valid DRV handle .
++ * List of DevObject is Empty.
++ * List of DrvExt is Empty
++ * Ensures:
++ * DSP_SOK: - DRV Object destroyed and hDrvObject is not a valid
++ * DRV handle.
++ * - Registry is updated with "0" as the DRV Object.
++ */
++ extern DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDrvObject);
++
++/*
++ * ======== DRV_Exit ========
++ * Purpose:
++ * Exit the DRV module, freeing any modules initialized in DRV_Init.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * Ensures:
++ */
++ extern void DRV_Exit(void);
++
++/*
++ * ======== DRV_GetFirstDevObject ========
++ * Purpose:
++ * Returns the Ptr to the FirstDev Object in the List
++ * Parameters:
++ * Requires:
++ * DRV Initialized
++ * Returns:
++ * dwDevObject: Ptr to the First Dev Object as a u32
++ * 0 if it fails to retrieve the First Dev Object
++ * Ensures:
++ */
++ extern u32 DRV_GetFirstDevObject(void);
++
++/*
++ * ======== DRV_GetFirstDevExtension ========
++ * Purpose:
++ * Returns the Ptr to the First Device Extension in the List
++ * Parameters:
++ * Requires:
++ * DRV Initialized
++ * Returns:
++ * dwDevExtension: Ptr to the First Device Extension as a u32
++ * 0: Failed to Get the Device Extension
++ * Ensures:
++ */
++ extern u32 DRV_GetFirstDevExtension(void);
++
++/*
++ * ======== DRV_GetDevObject ========
++ * Purpose:
++ * Given a index, returns a handle to DevObject from the list
++ * Parameters:
++ * hDrvObject: Handle to the Manager
++ * phDevObject: Location to store the Dev Handle
++ * Requires:
++ * DRV Initialized
++ * uIndex >= 0
++ * hDrvObject is not NULL and Valid DRV Object
++ * phDevObject is not NULL
++ * Device Object List not Empty
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EFAIL: Failed to Get the Dev Object
++ * Ensures:
++ * DSP_SOK: *phDevObject != NULL
++ * DSP_EFAIL: *phDevObject = NULL
++ */
++ extern DSP_STATUS DRV_GetDevObject(u32 uIndex,
++ struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT **phDevObject);
++
++/*
++ * ======== DRV_GetNextDevObject ========
++ * Purpose:
++ * Returns the Ptr to the Next Device Object from the the List
++ * Parameters:
++ * hDevObject: Handle to the Device Object
++ * Requires:
++ * DRV Initialized
++ * hDevObject != 0
++ * Returns:
++ * dwDevObject: Ptr to the Next Dev Object as a u32
++ * 0: If it fail to get the next Dev Object.
++ * Ensures:
++ */
++ extern u32 DRV_GetNextDevObject(u32 hDevObject);
++
++/*
++ * ======== DRV_GetNextDevExtension ========
++ * Purpose:
++ * Returns the Ptr to the Next Device Extension from the the List
++ * Parameters:
++ * hDevExtension: Handle to the Device Extension
++ * Requires:
++ * DRV Initialized
++ * hDevExtension != 0.
++ * Returns:
++ * dwDevExtension: Ptr to the Next Dev Extension
++ * 0: If it fail to Get the next Dev Extension
++ * Ensures:
++ */
++ extern u32 DRV_GetNextDevExtension(u32 hDevExtension);
++
++/*
++ * ======== DRV_Init ========
++ * Purpose:
++ * Initialize the DRV module.
++ * Parameters:
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS DRV_Init(void);
++
++/*
++ * ======== DRV_InsertDevObject ========
++ * Purpose:
++ * Insert a DeviceObject into the list of Driver object.
++ * Parameters:
++ * hDrvObject: Handle to DrvObject
++ * hDevObject: Handle to DeviceObject to insert.
++ * Returns:
++ * DSP_SOK: If successful.
++ * DSP_EFAIL: General Failure:
++ * Requires:
++ * hDrvObject != NULL and Valid DRV Handle.
++ * hDevObject != NULL.
++ * Ensures:
++ * DSP_SOK: Device Object is inserted and the List is not empty.
++ */
++ extern DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DRV_RemoveDevObject ========
++ * Purpose:
++ * Search for and remove a Device object from the given list of Device Obj
++ * objects.
++ * Parameters:
++ * hDrvObject: Handle to DrvObject
++ * hDevObject: Handle to DevObject to Remove
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to find pDevObject.
++ * Requires:
++ * hDrvObject != NULL and a Valid DRV Handle.
++ * hDevObject != NULL.
++ * List exists and is not empty.
++ * Ensures:
++ * List either does not exist (NULL), or is not empty if it does exist.
++*/
++ extern DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== DRV_RequestResources ========
++ * Purpose:
++ * Assigns the Resources or Releases them.
++ * Parameters:
++ * dwContext: Path to the driver Registry Key.
++ * pDevNodeString: Ptr to DevNode String stored in the Device Ext.
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * The Resources are assigned based on Bus type.
++ * The hardware is initialized. Resource information is
++ * gathered from the Registry(ISA, PCMCIA)or scanned(PCI)
++ * Resource structure is stored in the registry which will be
++ * later used by the CFG module.
++ */
++ extern DSP_STATUS DRV_RequestResources(IN u32 dwContext,
++ OUT u32 *pDevNodeString);
++
++/*
++ * ======== DRV_ReleaseResources ========
++ * Purpose:
++ * Assigns the Resources or Releases them.
++ * Parameters:
++ * dwContext: Path to the driver Registry Key.
++ * hDrvObject: Handle to the Driver Object.
++ * Returns:
++ * TRUE if success; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * The Resources are released based on Bus type.
++ * Resource structure is deleted from the registry
++ */
++ extern DSP_STATUS DRV_ReleaseResources(IN u32 dwContext,
++ struct DRV_OBJECT *hDrvObject);
++
++/*
++ * ======== DRV_ProcFreeDMMRes ========
++ * Purpose:
++ * Actual DMM De-Allocation.
++ * Parameters:
++ * hPCtxt: Path to the driver Registry Key.
++ * Returns:
++ * DSP_SOK if success;
++ */
++
++
++ extern DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt);
++
++#endif /* DRV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/drvdefs.h b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
+new file mode 100644
+index 0000000..ed86010
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/drvdefs.h
+@@ -0,0 +1,34 @@
++/*
++ * drvdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drvdefs.h ========
++ * Purpose:
++ * Definition of common include typedef between wmd.h and drv.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 17-Jul-2000 rr: Created
++ */
++
++#ifndef DRVDEFS_
++#define DRVDEFS_
++
++/* WCD Driver Object */
++ struct DRV_OBJECT;
++
++#endif /* DRVDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/dspdrv.h b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
+new file mode 100644
+index 0000000..f500ffb
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dspdrv.h
+@@ -0,0 +1,106 @@
++/*
++ * dspdrv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dspdrv.h ========
++ * Purpose:
++ * This is the Stream Interface for the DDSP Class driver.
++ * All Device operations are performed via DeviceIOControl.
++ * Read, Seek and Write not used.
++ *
++ * Public Functions
++ * DSP_Close
++ * DSP_Deinit
++ * DSP_Init
++ * DSP_IOControl
++ * DSP_Open
++ * DSP_PowerUp
++ * DSP_PowerDown
++ *
++ *! Revision History
++ *! ================
++ *! 28-Jan-2000 rr: Type void changed to Void.
++ *! 02-Dec-1999 rr: MAX_DEV define moved from wcdce.c file.Code cleaned up.
++ *! 12-Nov-1999 rr: "#include<wncnxerr.h> removed.
++ *! 05-Oct-1999 rr Renamed the file name to wcdce.h Removed Bus Specific
++ *! code and #defines to PCCARD.h.
++ *! 24-Sep-1999 rr Changed the DSP_COMMON_WINDOW_SIZE to 0x4000(16k) for the
++ *! Memory windows.
++ *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet driver.
++ *!
++ */
++
++#if !defined __DSPDRV_h__
++#define __DSPDRV_h__
++
++#define MAX_DEV 10 /* Max support of 10 devices */
++
++/*
++ * ======== DSP_Close ========
++ * Purpose:
++ * Called when the client application/driver unloads the DDSP DLL. Upon
++ * unloading, the DDSP DLL will call CloseFile().
++ * Parameters:
++ * dwDeviceContext: Handle returned by XXX_Open used to identify
++ * the open context of the device
++ * Returns:
++ * TRUE indicates the device is successfully closed. FALSE indicates
++ * otherwise.
++ * Requires:
++ * dwOpenContext!= NULL.
++ * Ensures:The Application instance owned objects are cleaned up.
++ */
++extern bool DSP_Close(u32 dwDeviceContext);
++
++/*
++ * ======== DSP_Deinit ========
++ * Purpose:
++ * This function is called by Device Manager to de-initialize a device.
++ * This function is not called by applications.
++ * Parameters:
++ * dwDeviceContext:Handle to the device context. The XXX_Init function
++ * creates and returns this identifier.
++ * Returns:
++ * TRUE indicates the device successfully de-initialized. Otherwise it
++ * returns FALSE.
++ * Requires:
++ * dwDeviceContext!= NULL. For a built in device this should never
++ * get called.
++ * Ensures:
++ */
++extern bool DSP_Deinit(u32 dwDeviceContext);
++
++/*
++ * ======== DSP_Init ========
++ * Purpose:
++ * This function is called by Device Manager to initialize a device.
++ * This function is not called by applications
++ * Parameters:
++ * dwContext: Specifies a pointer to a string containing the registry
++ * path to the active key for the stream interface driver.
++ * HKEY_LOCAL_MACHINE\Drivers\Active
++ * Returns:
++ * Returns a handle to the device context created. This is the our actual
++ * Device Object representing the DSP Device instance.
++ * Requires:
++ * Ensures:
++ * Succeeded: device context > 0
++ * Failed: device Context = 0
++ */
++extern u32 DSP_Init(OUT u32 *initStatus);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+new file mode 100644
+index 0000000..ea5f77f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/dynamic_loader.h
+@@ -0,0 +1,505 @@
++/*
++ * dynamic_loader.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _DYNAMIC_LOADER_H_
++#define _DYNAMIC_LOADER_H_
++#include <linux/kernel.h>
++#include <linux/types.h>
++
++/*
++ * Dynamic Loader
++ *
++ * The function of the dynamic loader is to load a "module" containing
++ * instructions for a "target" processor into that processor. In the process
++ * it assigns memory for the module, resolves symbol references made by the
++ * module, and remembers symbols defined by the module.
++ *
++ * The dynamic loader is parameterized for a particular system by 4 classes
++ * that supply the module and system specific functions it requires
++ */
++ /* The read functions for the module image to be loaded */
++ struct Dynamic_Loader_Stream;
++
++ /* This class defines "host" symbol and support functions */
++ struct Dynamic_Loader_Sym;
++
++ /* This class defines the allocator for "target" memory */
++ struct Dynamic_Loader_Allocate;
++
++ /* This class defines the copy-into-target-memory functions */
++ struct Dynamic_Loader_Initialize;
++
++/*
++ * Option flags to modify the behavior of module loading
++ */
++#define DLOAD_INITBSS 0x1 /* initialize BSS sections to zero */
++#define DLOAD_BIGEND 0x2 /* require big-endian load module */
++#define DLOAD_LITTLE 0x4 /* require little-endian load module */
++
++ typedef void *DLOAD_mhandle; /* module handle for loaded modules */
++
++/*****************************************************************************
++ * Procedure Dynamic_Load_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization, or NULL for symbol read only
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references resolved
++ * as necessary, and the resulting executable bits are placed into target memory
++ * using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle, and zero is
++ * returned. On error, the number of errors detected is returned. Individual
++ * errors are reported during the load process using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Load_Module(
++ /* the source for the module image*/
++ struct Dynamic_Loader_Stream *module,
++ /* host support for symbols and storage*/
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator*/
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer*/
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, /* option flags*/
++ /* the returned module handle*/
++ DLOAD_mhandle *mhandle
++ );
++
++/*****************************************************************************
++ * Procedure Dynamic_Open_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization, or NULL for symbol read only
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references resolved
++ * as necessary, and the resulting executable bits are placed into target memory
++ * using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle, and zero is
++ * returned. On error, the number of errors detected is returned. Individual
++ * errors are reported during the load process using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Open_Module(
++ /* the source for the module image */
++ struct Dynamic_Loader_Stream *module,
++ /* host support for symbols and storage */
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator */
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer */
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, /* option flags */
++ /* the returned module handle */
++ DLOAD_mhandle *mhandle
++ );
++
++/*****************************************************************************
++ * Procedure Dynamic_Unload_Module
++ *
++ * Parameters:
++ * mhandle A module handle from Dynamic_Load_Module
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ *
++ * Effect:
++ * The module specified by mhandle is unloaded. Unloading causes all
++ * target memory to be deallocated, all symbols defined by the module to
++ * be purged, and any host-side storage used by the dynamic loader for
++ * this module to be released.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report().
++ *****************************************************************************/
++ extern int Dynamic_Unload_Module(DLOAD_mhandle mhandle, /* the module
++ * handle*/
++ /* host support for symbols and
++ * storage */
++ struct Dynamic_Loader_Sym *syms,
++ /* the target memory allocator*/
++ struct Dynamic_Loader_Allocate *alloc,
++ /* the target memory initializer*/
++ struct Dynamic_Loader_Initialize *init
++ );
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader for input of the module image
++ *****************************************************************************
++ *****************************************************************************/
++ struct Dynamic_Loader_Stream {
++/* public: */
++ /*************************************************************************
++ * read_buffer
++ *
++ * PARAMETERS :
++ * buffer Pointer to the buffer to fill
++ * bufsiz Amount of data desired in sizeof() units
++ *
++ * EFFECT :
++ * Reads the specified amount of data from the module input stream
++ * into the specified buffer. Returns the amount of data read in sizeof()
++ * units (which if less than the specification, represents an error).
++ *
++ * NOTES:
++ * In release 1 increments the file position by the number of bytes read
++ *
++ *************************************************************************/
++ int (*read_buffer) (struct Dynamic_Loader_Stream *thisptr,
++ void *buffer, unsigned bufsiz);
++
++ /*************************************************************************
++ * set_file_posn (release 1 only)
++ *
++ * PARAMETERS :
++ * posn Desired file position relative to start of file in sizeof() units.
++ *
++ * EFFECT :
++ * Adjusts the internal state of the stream object so that the next
++ * read_buffer call will begin to read at the specified offset from
++ * the beginning of the input module. Returns 0 for success, non-zero
++ * for failure.
++ *
++ *************************************************************************/
++ int (*set_file_posn) (struct Dynamic_Loader_Stream *thisptr,
++ /* to be eliminated in release 2*/
++ unsigned int posn);
++
++ };
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader for symbol table support and
++ * miscellaneous host-side functions
++ *****************************************************************************
++ *****************************************************************************/
++
++ typedef u32 LDR_ADDR;
++
++/*
++ * the structure of a symbol known to the dynamic loader
++ */
++ struct dynload_symbol {
++ LDR_ADDR value;
++ } ;
++
++ struct Dynamic_Loader_Sym {
++/* public: */
++ /*************************************************************************
++ * Find_Matching_Symbol
++ *
++ * PARAMETERS :
++ * name The name of the desired symbol
++ *
++ * EFFECT :
++ * Locates a symbol matching the name specified. A pointer to the
++ * symbol is returned if it exists; 0 is returned if no such symbol is
++ * found.
++ *
++ *************************************************************************/
++ struct dynload_symbol *(*Find_Matching_Symbol)
++ (struct Dynamic_Loader_Sym *
++ thisptr,
++ const char *name);
++
++ /*************************************************************************
++ * Add_To_Symbol_Table
++ *
++ * PARAMETERS :
++ * nname Pointer to the name of the new symbol
++ * moduleid An opaque module id assigned by the dynamic loader
++ *
++ * EFFECT :
++ * The new symbol is added to the table. A pointer to the symbol is
++ * returned, or NULL is returned for failure.
++ *
++ * NOTES:
++ * It is permissible for this function to return NULL; the effect is that
++ * the named symbol will not be available to resolve references in
++ * subsequent loads. Returning NULL will not cause the current load
++ * to fail.
++ *************************************************************************/
++ struct dynload_symbol *(*Add_To_Symbol_Table)
++ (struct Dynamic_Loader_Sym *
++ thisptr,
++ const char *nname,
++ unsigned moduleid);
++
++ /*************************************************************************
++ * Purge_Symbol_Table
++ *
++ * PARAMETERS :
++ * moduleid An opaque module id assigned by the dynamic loader
++ *
++ * EFFECT :
++ * Each symbol in the symbol table whose moduleid matches the argument
++ * is removed from the table.
++ *************************************************************************/
++ void (*Purge_Symbol_Table) (struct Dynamic_Loader_Sym *thisptr,
++ unsigned moduleid);
++
++ /*************************************************************************
++ * Allocate
++ *
++ * PARAMETERS :
++ * memsiz size of desired memory in sizeof() units
++ *
++ * EFFECT :
++ * Returns a pointer to some "host" memory for use by the dynamic
++ * loader, or NULL for failure.
++ * This function is serves as a replaceable form of "malloc" to
++ * allow the user to configure the memory usage of the dynamic loader.
++ *************************************************************************/
++ void *(*Allocate) (struct Dynamic_Loader_Sym *thisptr,
++ unsigned memsiz);
++
++ /*************************************************************************
++ * Deallocate
++ *
++ * PARAMETERS :
++ * memptr pointer to previously allocated memory
++ *
++ * EFFECT :
++ * Releases the previously allocated "host" memory.
++ *************************************************************************/
++ void (*Deallocate) (struct Dynamic_Loader_Sym *thisptr,
++ void *memptr);
++
++ /*************************************************************************
++ * Error_Report
++ *
++ * PARAMETERS :
++ * errstr pointer to an error string
++ * args additional arguments
++ *
++ * EFFECT :
++ * This function provides an error reporting interface for the dynamic
++ * loader. The error string and arguments are designed as for the
++ * library function vprintf.
++ *************************************************************************/
++ void (*Error_Report) (struct Dynamic_Loader_Sym *thisptr,
++ const char *errstr, va_list args);
++
++ }; /* class Dynamic_Loader_Sym */
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader to allocate and deallocate target memory.
++ *****************************************************************************
++ *****************************************************************************/
++
++ struct LDR_SECTION_INFO {
++ /* Name of the memory section assigned at build time */
++ const char *name;
++ LDR_ADDR run_addr; /* execution address of the section */
++ LDR_ADDR load_addr; /* load address of the section */
++ LDR_ADDR size; /* size of the section in addressable units */
++#ifndef _BIG_ENDIAN
++ u16 page; /* memory page or view */
++ u16 type; /* one of the section types below */
++#else
++ u16 type; /* one of the section types below */
++ u16 page; /* memory page or view */
++#endif
++ /* a context field for use by Dynamic_Loader_Allocate;
++ * ignored but maintained by the dynamic loader */
++ u32 context;
++ } ;
++
++/* use this macro to extract type of section from LDR_SECTION_INFO.type field */
++#define DLOAD_SECTION_TYPE(typeinfo) (typeinfo & 0xF)
++
++/* type of section to be allocated */
++#define DLOAD_TEXT 0
++#define DLOAD_DATA 1
++#define DLOAD_BSS 2
++ /* internal use only, run-time cinit will be of type DLOAD_DATA */
++#define DLOAD_CINIT 3
++
++ struct Dynamic_Loader_Allocate {
++/* public: */
++
++ /*************************************************************************
++ * Function allocate
++ *
++ * Parameters:
++ * info A pointer to an information block for the section
++ * align The alignment of the storage in target AUs
++ *
++ * Effect:
++ * Allocates target memory for the specified section and fills in the
++ * load_addr and run_addr fields of the section info structure. Returns TRUE
++ * for success, FALSE for failure.
++ *
++ * Notes:
++ * Frequently load_addr and run_addr are the same, but if they are not
++ * load_addr is used with Dynamic_Loader_Initialize, and run_addr is
++ * used for almost all relocations. This function should always initialize
++ * both fields.
++ *************************************************************************/
++ int (*Allocate) (struct Dynamic_Loader_Allocate *thisptr,
++ struct LDR_SECTION_INFO *info, unsigned align);
++
++ /*************************************************************************
++ * Function deallocate
++ *
++ * Parameters:
++ * info A pointer to an information block for the section
++ *
++ * Effect:
++ * Releases the target memory previously allocated.
++ *
++ * Notes:
++ * The content of the info->name field is undefined on call to this function.
++ *************************************************************************/
++ void (*Deallocate) (struct Dynamic_Loader_Allocate *thisptr,
++ struct LDR_SECTION_INFO *info);
++
++ }; /* class Dynamic_Loader_Allocate */
++
++/*****************************************************************************
++ *****************************************************************************
++ * A class used by the dynamic loader to load data into a target. This class
++ * provides the interface-specific functions needed to load data.
++ *****************************************************************************
++ *****************************************************************************/
++
++ struct Dynamic_Loader_Initialize {
++/* public: */
++ /*************************************************************************
++ * Function connect
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Connect to the initialization interface. Returns TRUE for success,
++ * FALSE for failure.
++ *
++ * Notes:
++ * This function is called prior to use of any other functions in
++ * this interface.
++ *************************************************************************/
++ int (*connect) (struct Dynamic_Loader_Initialize *thisptr);
++
++ /*************************************************************************
++ * Function readmem
++ *
++ * Parameters:
++ * bufr Pointer to a word-aligned buffer for the result
++ * locn Target address of first data element
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be read in sizeof() units
++ *
++ * Effect:
++ * Fills the specified buffer with data from the target. Returns TRUE for
++ * success, FALSE for failure.
++ *************************************************************************/
++ int (*readmem) (struct Dynamic_Loader_Initialize *thisptr,
++ void *bufr,
++ LDR_ADDR locn,
++ struct LDR_SECTION_INFO *info,
++ unsigned bytsiz);
++
++ /*************************************************************************
++ * Function writemem
++ *
++ * Parameters:
++ * bufr Pointer to a word-aligned buffer of data
++ * locn Target address of first data element to be written
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be written in sizeof() units
++ *
++ * Effect:
++ * Writes the specified buffer to the target. Returns TRUE for success,
++ * FALSE for failure.
++ *************************************************************************/
++ int (*writemem) (struct Dynamic_Loader_Initialize *thisptr,
++ void *bufr,
++ LDR_ADDR locn,
++ struct LDR_SECTION_INFO *info,
++ unsigned bytsiz);
++
++ /*************************************************************************
++ * Function fillmem
++ *
++ * Parameters:
++ * locn Target address of first data element to be written
++ * info Section info for the section in which the address resides
++ * bytsiz Size of the data to be written in sizeof() units
++ * val Value to be written in each byte
++ * Effect:
++ * Fills the specified area of target memory. Returns TRUE for success,
++ * FALSE for failure.
++ *************************************************************************/
++ int (*fillmem) (struct Dynamic_Loader_Initialize *thisptr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info,
++ unsigned bytsiz, unsigned val);
++
++ /*************************************************************************
++ * Function execute
++ *
++ * Parameters:
++ * start Starting address
++ *
++ * Effect:
++ * The target code at the specified starting address is executed.
++ *
++ * Notes:
++ * This function is called at the end of the dynamic load process
++ * if the input module has specified a starting address.
++ *************************************************************************/
++ int (*execute) (struct Dynamic_Loader_Initialize *thisptr,
++ LDR_ADDR start);
++
++ /*************************************************************************
++ * Function release
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Releases the connection to the load interface.
++ *
++ * Notes:
++ * This function is called at the end of the dynamic load process.
++ *************************************************************************/
++ void (*release) (struct Dynamic_Loader_Initialize *thisptr);
++
++ }; /* class Dynamic_Loader_Initialize */
++
++#endif /* _DYNAMIC_LOADER_H_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/errbase.h b/arch/arm/plat-omap/include/dspbridge/errbase.h
+new file mode 100644
+index 0000000..f04c005
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/errbase.h
+@@ -0,0 +1,509 @@
++/*
++ * errbase.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== errbase.h ========
++ * Description:
++ * Central repository for DSP/BIOS Bridge error and status code.
++ *
++ * Error codes are of the form:
++ * [<MODULE>]_E<ERRORCODE>
++ *
++ * Success codes are of the form:
++ * [<MODULE>]_S<SUCCESSCODE>
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Jan-2003 map Added DSP_SALREADYLOADED for persistent library checking
++ *! 23-Nov-2002 gp: Minor comment cleanup.
++ *! 13-May-2002 sg Added DSP_SALREADYASLEEP and DSP_SALREADYWAKE.
++ *! 18-Feb-2002 mk: Added DSP_EOVERLAYMEMORY, EFWRITE, ENOSECT.
++ *! 31-Jan-2002 mk: Added definitions of DSP_STRUE and DSP_SFALSE.
++ *! 29-Jan-2002 mk: Added definition of CFG_E_INSUFFICIENTBUFSIZE.
++ *! 24-Oct-2001 sp: Consolidated all the error codes into this file.
++ *! 24-Jul-2001 mk: Type-casted all definitions of WSX_STATUS types for
++ *! removal of compile warnings.
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 18-Aug-1999 rr: Ported From WSX.
++ *! 29-May-1996 gp: Removed WCD_ and WMD_ error ranges. Redefined format of
++ *! error codes.
++ *! 10-May-1996 gp: Created.
++ */
++
++#ifndef ERRBASE_
++#define ERRBASE_
++
++/* Base of generic errors and component errors */
++#define DSP_SBASE (DSP_STATUS)0x00008000
++#define DSP_EBASE (DSP_STATUS)0x80008000
++
++#define DSP_COMP_EBASE (DSP_STATUS)0x80040200
++#define DSP_COMP_ELAST (DSP_STATUS)0x80047fff
++
++/* SUCCESS Codes */
++
++/* Generic success code */
++#define DSP_SOK (DSP_SBASE + 0)
++
++/* GPP is already attached to this DSP processor */
++#define DSP_SALREADYATTACHED (DSP_SBASE + 1)
++
++/* This is the last object available for enumeration. */
++#define DSP_SENUMCOMPLETE (DSP_SBASE + 2)
++
++/* The DSP is already asleep. */
++#define DSP_SALREADYASLEEP (DSP_SBASE + 3)
++
++/* The DSP is already awake. */
++#define DSP_SALREADYAWAKE (DSP_SBASE + 4)
++
++/* TRUE */
++#define DSP_STRUE (DSP_SBASE + 5)
++
++/* FALSE */
++#define DSP_SFALSE (DSP_SBASE + 6)
++
++/* A library contains no dependent library references */
++#define DSP_SNODEPENDENTLIBS (DSP_SBASE + 7)
++
++/* A persistent library is already loaded by the dynamic loader */
++#define DSP_SALREADYLOADED (DSP_SBASE + 8)
++
++/* Some error occured, but it is OK to continue */
++#define DSP_OKTO_CONTINUE (DSP_SBASE + 9)
++
++/* FAILURE Codes */
++
++/* The caller does not have access privileges to call this function */
++#define DSP_EACCESSDENIED (DSP_EBASE + 0)
++
++/* The Specified Connection already exists */
++#define DSP_EALREADYCONNECTED (DSP_EBASE + 1)
++
++/* The GPP must be detached from the DSP before this function is called */
++#define DSP_EATTACHED (DSP_EBASE + 2)
++
++/* During enumeration a change in the number or properties of the objects
++ * has occurred. */
++#define DSP_ECHANGEDURINGENUM (DSP_EBASE + 3)
++
++/* An error occurred while parsing the DSP executable file */
++#define DSP_ECORRUPTFILE (DSP_EBASE + 4)
++
++/* A failure occurred during a delete operation */
++#define DSP_EDELETE (DSP_EBASE + 5)
++
++/* The specified direction is invalid */
++#define DSP_EDIRECTION (DSP_EBASE + 6)
++
++/* A stream has been issued the maximum number of buffers allowed in the
++ * stream at once ; buffers must be reclaimed from the stream before any
++ * more can be issued. */
++#define DSP_ESTREAMFULL (DSP_EBASE + 7)
++
++/* A general failure occurred */
++#define DSP_EFAIL (DSP_EBASE + 8)
++
++/* The specified executable file could not be found. */
++#define DSP_EFILE (DSP_EBASE + 9)
++
++/* The specified handle is invalid. */
++#define DSP_EHANDLE (DSP_EBASE + 0xa)
++
++/* An invalid argument was specified. */
++#define DSP_EINVALIDARG (DSP_EBASE + 0xb)
++
++/* A memory allocation failure occurred. */
++#define DSP_EMEMORY (DSP_EBASE + 0xc)
++
++/* The requested operation is invalid for this node type. */
++#define DSP_ENODETYPE (DSP_EBASE + 0xd)
++
++/* No error text was found for the specified error code. */
++#define DSP_ENOERRTEXT (DSP_EBASE + 0xe)
++
++/* No more connections can be made for this node. */
++#define DSP_ENOMORECONNECTIONS (DSP_EBASE + 0xf)
++
++/* The indicated operation is not supported. */
++#define DSP_ENOTIMPL (DSP_EBASE + 0x10)
++
++/* I/O is currently pending. */
++#define DSP_EPENDING (DSP_EBASE + 0x11)
++
++/* An invalid pointer was specified. */
++#define DSP_EPOINTER (DSP_EBASE + 0x12)
++
++/* A parameter is specified outside its valid range. */
++#define DSP_ERANGE (DSP_EBASE + 0x13)
++
++/* An invalid size parameter was specified. */
++#define DSP_ESIZE (DSP_EBASE + 0x14)
++
++/* A stream creation failure occurred on the DSP. */
++#define DSP_ESTREAM (DSP_EBASE + 0x15)
++
++/* A task creation failure occurred on the DSP. */
++#define DSP_ETASK (DSP_EBASE + 0x16)
++
++/* A timeout occurred before the requested operation could complete. */
++
++#define DSP_ETIMEOUT (DSP_EBASE + 0x17)
++
++/* A data truncation occurred, e.g., when requesting a descriptive error
++ * string, not enough space was allocated for the complete error message. */
++
++#define DSP_ETRUNCATED (DSP_EBASE + 0x18)
++
++/* A parameter is invalid. */
++#define DSP_EVALUE (DSP_EBASE + 0x1a)
++
++/* The state of the specified object is incorrect for the requested
++ * operation. */
++#define DSP_EWRONGSTATE (DSP_EBASE + 0x1b)
++
++/* Symbol not found in the COFF file. DSPNode_Create will return this if
++ * the iAlg function table for an xDAIS socket is not found in the COFF file.
++ * In this case, force the symbol to be linked into the COFF file.
++ * DSPNode_Create, DSPNode_Execute, and DSPNode_Delete will return this if
++ * the create, execute, or delete phase function, respectively, could not be
++ * found in the COFF file. */
++#define DSP_ESYMBOL (DSP_EBASE + 0x1c)
++
++/* UUID not found in registry. */
++#define DSP_EUUID (DSP_EBASE + 0x1d)
++
++/* Unable to read content of DCD data section ; this is typically caused by
++ * improperly configured nodes. */
++#define DSP_EDCDREADSECT (DSP_EBASE + 0x1e)
++
++/* Unable to decode DCD data section content ; this is typically caused by
++ * changes to DSP/BIOS Bridge data structures. */
++#define DSP_EDCDPARSESECT (DSP_EBASE + 0x1f)
++
++/* Unable to get pointer to DCD data section ; this is typically caused by
++ * improperly configured UUIDs. */
++#define DSP_EDCDGETSECT (DSP_EBASE + 0x20)
++
++/* Unable to load file containing DCD data section ; this is typically
++ * caused by a missing COFF file. */
++#define DSP_EDCDLOADBASE (DSP_EBASE + 0x21)
++
++/* The specified COFF file does not contain a valid node registration
++ * section. */
++#define DSP_EDCDNOAUTOREGISTER (DSP_EBASE + 0x22)
++
++/* A requested resource is not available. */
++#define DSP_ERESOURCE (DSP_EBASE + 0x28)
++
++/* A critical error has occurred, and the DSP is being re-started. */
++#define DSP_ERESTART (DSP_EBASE + 0x29)
++
++/* A DSP memory free operation failed. */
++#define DSP_EFREE (DSP_EBASE + 0x2a)
++
++/* A DSP I/O free operation failed. */
++#define DSP_EIOFREE (DSP_EBASE + 0x2b)
++
++/* Multiple instances are not allowed. */
++#define DSP_EMULINST (DSP_EBASE + 0x2c)
++
++/* A specified entity was not found. */
++#define DSP_ENOTFOUND (DSP_EBASE + 0x2d)
++
++/* A DSP I/O resource is not available. */
++#define DSP_EOUTOFIO (DSP_EBASE + 0x2e)
++
++/* A shared memory buffer contained in a message or stream could not be
++ * mapped to the GPP client process's virtual space. */
++#define DSP_ETRANSLATE (DSP_EBASE + 0x2f)
++
++/* File or section load write function failed to write to DSP */
++#define DSP_EFWRITE (DSP_EBASE + 0x31)
++
++/* Unable to find a named section in DSP executable */
++#define DSP_ENOSECT (DSP_EBASE + 0x32)
++
++/* Unable to open file */
++#define DSP_EFOPEN (DSP_EBASE + 0x33)
++
++/* Unable to read file */
++#define DSP_EFREAD (DSP_EBASE + 0x34)
++
++/* A non-existent memory segment identifier was specified */
++#define DSP_EOVERLAYMEMORY (DSP_EBASE + 0x37)
++
++/* Invalid segment ID */
++#define DSP_EBADSEGID (DSP_EBASE + 0x38)
++
++/* Invalid alignment */
++#define DSP_EALIGNMENT (DSP_EBASE + 0x39)
++
++/* Invalid stream mode */
++#define DSP_ESTRMMODE (DSP_EBASE + 0x3a)
++
++/* Nodes not connected */
++#define DSP_ENOTCONNECTED (DSP_EBASE + 0x3b)
++
++/* Not shared memory */
++#define DSP_ENOTSHAREDMEM (DSP_EBASE + 0x3c)
++
++/* Error occurred in a dynamic loader library function */
++#define DSP_EDYNLOAD (DSP_EBASE + 0x3d)
++
++/* Device in 'sleep/suspend' mode due to DPM */
++#define DSP_EDPMSUSPEND (DSP_EBASE + 0x3e)
++
++/* A node-specific error has occurred. */
++#define DSP_EUSER1 (DSP_EBASE + 0x40)
++#define DSP_EUSER2 (DSP_EBASE + 0x41)
++#define DSP_EUSER3 (DSP_EBASE + 0x42)
++#define DSP_EUSER4 (DSP_EBASE + 0x43)
++#define DSP_EUSER5 (DSP_EBASE + 0x44)
++#define DSP_EUSER6 (DSP_EBASE + 0x45)
++#define DSP_EUSER7 (DSP_EBASE + 0x46)
++#define DSP_EUSER8 (DSP_EBASE + 0x47)
++#define DSP_EUSER9 (DSP_EBASE + 0x48)
++#define DSP_EUSER10 (DSP_EBASE + 0x49)
++#define DSP_EUSER11 (DSP_EBASE + 0x4a)
++#define DSP_EUSER12 (DSP_EBASE + 0x4b)
++#define DSP_EUSER13 (DSP_EBASE + 0x4c)
++#define DSP_EUSER14 (DSP_EBASE + 0x4d)
++#define DSP_EUSER15 (DSP_EBASE + 0x4e)
++#define DSP_EUSER16 (DSP_EBASE + 0x4f)
++
++/* FAILURE Codes : DEV */
++#define DEV_EBASE (DSP_COMP_EBASE + 0x000)
++
++/* The mini-driver expected a newer version of the class driver. */
++#define DEV_E_NEWWMD (DEV_EBASE + 0x00)
++
++/* WMD_DRV_Entry function returned a NULL function interface table. */
++#define DEV_E_NULLWMDINTF (DEV_EBASE + 0x01)
++
++/* FAILURE Codes : LDR */
++#define LDR_EBASE (DSP_COMP_EBASE + 0x100)
++
++/* Insufficient memory to export class driver services. */
++#define LDR_E_NOMEMORY (LDR_EBASE + 0x00)
++
++/* Unable to find WMD file in system directory. */
++#define LDR_E_FILEUNABLETOOPEN (LDR_EBASE + 0x01)
++
++/* FAILURE Codes : CFG */
++#define CFG_EBASE (DSP_COMP_EBASE + 0x200)
++
++/* Invalid pointer passed into a configuration module function */
++#define CFG_E_INVALIDPOINTER (CFG_EBASE + 0x00)
++
++/* Invalid device node handle passed into a configuration module function. */
++#define CFG_E_INVALIDHDEVNODE (CFG_EBASE + 0x01)
++
++/* Unable to retrieve resource information from the registry. */
++#define CFG_E_RESOURCENOTAVAIL (CFG_EBASE + 0x02)
++
++/* Unable to find board name key in registry. */
++#define CFG_E_INVALIDBOARDNAME (CFG_EBASE + 0x03)
++
++/* Unable to find a device node in registry with given unit number. */
++#define CFG_E_INVALIDUNITNUM (CFG_EBASE + 0x04)
++
++/* Insufficient buffer size */
++#define CFG_E_INSUFFICIENTBUFSIZE (CFG_EBASE + 0x05)
++
++/* FAILURE Codes : BRD */
++#define BRD_EBASE (DSP_COMP_EBASE + 0x300)
++
++/* Board client does not have sufficient access rights for this operation. */
++#define BRD_E_ACCESSDENIED (BRD_EBASE + 0x00)
++
++/* Unable to find trace buffer symbols in the DSP executable COFF file. */
++#define BRD_E_NOTRACEBUFFER (BRD_EBASE + 0x01)
++
++/* Attempted to auto-start board, but no default DSP executable configured. */
++#define BRD_E_NOEXEC (BRD_EBASE + 0x02)
++
++/* The operation failed because it was started from a wrong state */
++#define BRD_E_WRONGSTATE (BRD_EBASE + 0x03)
++
++/* FAILURE Codes : COD */
++#define COD_EBASE (DSP_COMP_EBASE + 0x400)
++
++/* No symbol table is loaded for this board. */
++#define COD_E_NOSYMBOLSLOADED (COD_EBASE + 0x00)
++
++/* Symbol not found in for this board. */
++#define COD_E_SYMBOLNOTFOUND (COD_EBASE + 0x01)
++
++/* ZL DLL module is not exporting the correct function interface. */
++#define COD_E_NOZLFUNCTIONS (COD_EBASE + 0x02)
++
++/* Unable to initialize the ZL COFF parsing module. */
++#define COD_E_ZLCREATEFAILED (COD_EBASE + 0x03)
++
++/* Unable to open DSP executable COFF file. */
++#define COD_E_OPENFAILED (COD_EBASE + 0x04)
++
++/* Unable to parse DSP executable COFF file. */
++#define COD_E_LOADFAILED (COD_EBASE + 0x05)
++
++/* Unable to read DSP executable COFF file. */
++#define COD_E_READFAILED (COD_EBASE + 0x06)
++
++/* FAILURE Codes : CHNL */
++#define CHNL_EBASE (DSP_COMP_EBASE + 0x500)
++
++/* Attempt to created channel manager with too many channels. */
++#define CHNL_E_MAXCHANNELS (CHNL_EBASE + 0x00)
++
++/* No channel manager exists for this mini-driver. */
++#define CHNL_E_NOMGR (CHNL_EBASE + 0x01)
++
++/* No free channels are available. */
++#define CHNL_E_OUTOFSTREAMS (CHNL_EBASE + 0x02)
++
++/* Channel ID is out of range. */
++#define CHNL_E_BADCHANID (CHNL_EBASE + 0x03)
++
++/* Channel is already in use. */
++#define CHNL_E_CHANBUSY (CHNL_EBASE + 0x04)
++
++/* Invalid channel mode argument. */
++#define CHNL_E_BADMODE (CHNL_EBASE + 0x05)
++
++/* dwTimeOut parameter was CHNL_IOCNOWAIT, yet no I/O completions were
++ * queued. */
++#define CHNL_E_NOIOC (CHNL_EBASE + 0x06)
++
++/* I/O has been cancelled on this channel. */
++#define CHNL_E_CANCELLED (CHNL_EBASE + 0x07)
++
++/* End of stream was already requested on this output channel. */
++#define CHNL_E_EOS (CHNL_EBASE + 0x09)
++
++/* Unable to create the channel event object. */
++#define CHNL_E_CREATEEVENT (CHNL_EBASE + 0x0A)
++
++/* Board name and unit number do not identify a valid board name. */
++#define CHNL_E_BRDID (CHNL_EBASE + 0x0B)
++
++/* Invalid IRQ configured for this WMD for this system. */
++#define CHNL_E_INVALIDIRQ (CHNL_EBASE + 0x0C)
++
++/* DSP word size of zero configured for this device. */
++#define CHNL_E_INVALIDWORDSIZE (CHNL_EBASE + 0x0D)
++
++/* A zero length memory base was specified for a shared memory class driver. */
++#define CHNL_E_INVALIDMEMBASE (CHNL_EBASE + 0x0E)
++
++/* Memory map is not configured, or unable to map physical to linear
++ * address. */
++#define CHNL_E_NOMEMMAP (CHNL_EBASE + 0x0F)
++
++/* Attempted to create a channel manager when one already exists. */
++#define CHNL_E_MGREXISTS (CHNL_EBASE + 0x10)
++
++/* Unable to plug channel ISR for configured IRQ. */
++#define CHNL_E_ISR (CHNL_EBASE + 0x11)
++
++/* No free I/O request packets are available. */
++#define CHNL_E_NOIORPS (CHNL_EBASE + 0x12)
++
++/* Buffer size is larger than the size of physical channel. */
++#define CHNL_E_BUFSIZE (CHNL_EBASE + 0x13)
++
++/* User cannot mark end of stream on an input channel. */
++#define CHNL_E_NOEOS (CHNL_EBASE + 0x14)
++
++/* Wait for flush operation on an output channel timed out. */
++#define CHNL_E_WAITTIMEOUT (CHNL_EBASE + 0x15)
++
++/* User supplied hEvent must be specified with pstrEventName attribute */
++#define CHNL_E_BADUSEREVENT (CHNL_EBASE + 0x16)
++
++/* Illegal user event name specified */
++#define CHNL_E_USEREVENTNAME (CHNL_EBASE + 0x17)
++
++/* Unable to prepare buffer specified */
++#define CHNL_E_PREPFAILED (CHNL_EBASE + 0x18)
++
++/* Unable to Unprepare buffer specified */
++#define CHNL_E_UNPREPFAILED (CHNL_EBASE + 0x19)
++
++/* FAILURE Codes : SYNC */
++#define SYNC_EBASE (DSP_COMP_EBASE + 0x600)
++
++/* Wait on a kernel event failed. */
++#define SYNC_E_FAIL (SYNC_EBASE + 0x00)
++
++/* Timeout expired while waiting for event to be signalled. */
++#define SYNC_E_TIMEOUT (SYNC_EBASE + 0x01)
++
++/* FAILURE Codes : WMD */
++#define WMD_EBASE (DSP_COMP_EBASE + 0x700)
++
++/* A test of hardware assumptions or integrity failed. */
++#define WMD_E_HARDWARE (WMD_EBASE + 0x00)
++
++/* One or more configuration parameters violated WMD hardware assumptions. */
++#define WMD_E_BADCONFIG (WMD_EBASE + 0x01)
++
++/* Timeout occurred waiting for a response from the hardware. */
++#define WMD_E_TIMEOUT (WMD_EBASE + 0x02)
++
++/* FAILURE Codes : REG */
++#define REG_EBASE (DSP_COMP_EBASE + 0x800)
++
++/* Invalid subkey parameter. */
++#define REG_E_INVALIDSUBKEY (REG_EBASE + 0x00)
++
++/* Invalid entry parameter. */
++#define REG_E_INVALIDENTRY (REG_EBASE + 0x01)
++
++/* No more registry values. */
++#define REG_E_NOMOREITEMS (REG_EBASE + 0x02)
++
++/* Insufficient space to hold data in registry value. */
++#define REG_E_MOREDATA (REG_EBASE + 0x03)
++
++/* FAILURE Codes : KFILE */
++#define KFILE_EBASE (DSP_COMP_EBASE + 0x900)
++
++/* Invalid file handle. */
++#define E_KFILE_INVALIDHANDLE (KFILE_EBASE + 0x01)
++
++/* Bad file name. */
++#define E_KFILE_BADFILENAME (KFILE_EBASE + 0x02)
++
++/* Invalid file mode. */
++#define E_KFILE_INVALIDMODE (KFILE_EBASE + 0x03)
++
++/* No resources available. */
++#define E_KFILE_NORESOURCES (KFILE_EBASE + 0x04)
++
++/* Invalid file buffer . */
++#define E_KFILE_INVALIDBUFFER (KFILE_EBASE + 0x05)
++
++/* Bad origin argument. */
++#define E_KFILE_BADORIGINFLAG (KFILE_EBASE + 0x06)
++
++/* Invalid file offset value. */
++#define E_KFILE_INVALIDOFFSET (KFILE_EBASE + 0x07)
++
++/* General KFILE error condition */
++#define E_KFILE_ERROR (KFILE_EBASE + 0x08)
++
++#endif /* ERRBASE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gb.h b/arch/arm/plat-omap/include/dspbridge/gb.h
+new file mode 100644
+index 0000000..f147751
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gb.h
+@@ -0,0 +1,85 @@
++/*
++ * gb.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== gb.h ========
++ * Generic bitmap manager.
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GB_
++#define GB_
++
++#define GB_NOBITS (~0)
++#include <dspbridge/host_os.h>
++typedef s32 GB_BitNum;
++struct GB_TMap;
++
++/*
++ * ======== GB_clear ========
++ * Clear the bit in position bitn in the bitmap map. Bit positions are
++ * zero based.
++ */
++
++extern void GB_clear(struct GB_TMap *map, GB_BitNum bitn);
++
++/*
++ * ======== GB_create ========
++ * Create a bit map with len bits. Initially all bits are cleared.
++ */
++
++extern struct GB_TMap *GB_create(GB_BitNum len);
++
++/*
++ * ======== GB_delete ========
++ * Delete previously created bit map
++ */
++
++extern void GB_delete(struct GB_TMap *map);
++
++/*
++ * ======== GB_findandset ========
++ * Finds a clear bit, sets it, and returns the position
++ */
++
++extern GB_BitNum GB_findandset(struct GB_TMap *map);
++
++/*
++ * ======== GB_minclear ========
++ * GB_minclear returns the minimum clear bit position. If no bit is
++ * clear, GB_minclear returns -1.
++ */
++extern GB_BitNum GB_minclear(struct GB_TMap *map);
++
++/*
++ * ======== GB_set ========
++ * Set the bit in position bitn in the bitmap map. Bit positions are
++ * zero based.
++ */
++
++extern void GB_set(struct GB_TMap *map, GB_BitNum bitn);
++
++/*
++ * ======== GB_test ========
++ * Returns TRUE if the bit in position bitn is set in map; otherwise
++ * GB_test returns FALSE. Bit positions are zero based.
++ */
++
++extern bool GB_test(struct GB_TMap *map, GB_BitNum bitn);
++
++#endif /*GB_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/getsection.h b/arch/arm/plat-omap/include/dspbridge/getsection.h
+new file mode 100644
+index 0000000..33ff50d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/getsection.h
+@@ -0,0 +1,118 @@
++/*
++ * getsection.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _GETSECTION_H_
++#define _GETSECTION_H_
++
++
++#include "dynamic_loader.h"
++
++/*
++ * Get Section Information
++ *
++ * This file provides an API add-on to the dynamic loader that allows the user
++ * to query section information and extract section data from dynamic load
++ * modules.
++ *
++ * NOTE:
++ * Functions in this API assume that the supplied Dynamic_Loader_Stream object
++ * supports the set_file_posn method.
++ */
++
++ /* opaque handle for module information */
++ typedef void *DLOAD_module_info;
++
++/*
++ * Procedure DLOAD_module_open
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side malloc/free and error reporting functions.
++ * Other methods are unused.
++ *
++ * Effect:
++ * Reads header information from a dynamic loader module using the specified
++ * stream object, and returns a handle for the module information. This
++ * handle may be used in subsequent query calls to obtain information
++ * contained in the module.
++ *
++ * Returns:
++ * NULL if an error is encountered, otherwise a module handle for use
++ * in subsequent operations.
++ */
++ extern DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream
++ *module,
++ struct Dynamic_Loader_Sym
++ *syms);
++
++/*
++ * Procedure DLOAD_GetSectionInfo
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionName Pointer to the string name of the section desired
++ * sectionInfo Address of a section info structure pointer to be initialized
++ *
++ * Effect:
++ * Finds the specified section in the module information, and fills in
++ * the provided LDR_SECTION_INFO structure.
++ *
++ * Returns:
++ * TRUE for success, FALSE for section not found
++ */
++ extern int DLOAD_GetSectionInfo(DLOAD_module_info minfo,
++ const char *sectionName,
++ const struct LDR_SECTION_INFO
++ ** const sectionInfo);
++
++/*
++ * Procedure DLOAD_GetSection
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionInfo Pointer to a section info structure for the desired section
++ * sectionData Buffer to contain the section initialized data
++ *
++ * Effect:
++ * Copies the initialized data for the specified section into the
++ * supplied buffer.
++ *
++ * Returns:
++ * TRUE for success, FALSE for section not found
++ */
++ extern int DLOAD_GetSection(DLOAD_module_info minfo,
++ const struct LDR_SECTION_INFO *sectionInfo,
++ void *sectionData);
++
++/*
++ * Procedure DLOAD_module_close
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Releases any storage associated with the module handle. On return,
++ * the module handle is invalid.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report(), where syms was
++ * an argument to DLOAD_module_open
++ */
++ extern void DLOAD_module_close(DLOAD_module_info minfo);
++
++#endif /* _GETSECTION_H_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gh.h b/arch/arm/plat-omap/include/dspbridge/gh.h
+new file mode 100644
+index 0000000..089a042
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gh.h
+@@ -0,0 +1,37 @@
++/*
++ * gh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gh.h ========
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GH_
++#define GH_
++#include <dspbridge/host_os.h>
++
++extern struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
++ u16(*hash) (void *, u16), bool(*match) (void *, void *),
++ void(*delete) (void *));
++extern void GH_delete(struct GH_THashTab *hashTab);
++extern void GH_exit(void);
++extern void *GH_find(struct GH_THashTab *hashTab, void *key);
++extern void GH_init(void);
++extern void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value);
++#endif /* GH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gs.h b/arch/arm/plat-omap/include/dspbridge/gs.h
+new file mode 100644
+index 0000000..fd5ef27
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gs.h
+@@ -0,0 +1,64 @@
++/*
++ * gs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== gs.h ========
++ * Memory allocation/release wrappers. This module allows clients to
++ * avoid OS spacific issues related to memory allocation. It also provides
++ * simple diagnostic capabilities to assist in the detection of memory
++ * leaks.
++ *! Revision History
++ *! ================
++ */
++
++#ifndef GS_
++#define GS_
++
++/*
++ * ======== GS_alloc ========
++ * Alloc size bytes of space. Returns pointer to space
++ * allocated, otherwise NULL.
++ */
++extern void *GS_alloc(u32 size);
++
++/*
++ * ======== GS_exit ========
++ * Module exit. Do not change to "#define GS_init()"; in
++ * some environments this operation must actually do some work!
++ */
++extern void GS_exit(void);
++
++/*
++ * ======== GS_free ========
++ * Free space allocated by GS_alloc() or GS_calloc().
++ */
++extern void GS_free(void *ptr);
++
++/*
++ * ======== GS_frees ========
++ * Free space allocated by GS_alloc() or GS_calloc() and assert that
++ * the size of the allocation is size bytes.
++ */
++extern void GS_frees(void *ptr, u32 size);
++
++/*
++ * ======== GS_init ========
++ * Module initialization. Do not change to "#define GS_init()"; in
++ * some environments this operation must actually do some work!
++ */
++extern void GS_init(void);
++
++#endif /*GS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/gt.h b/arch/arm/plat-omap/include/dspbridge/gt.h
+new file mode 100644
+index 0000000..456c866
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/gt.h
+@@ -0,0 +1,315 @@
++/*
++ * gt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gt.h ========
++ * Purpose:
++ * There are two definitions that affect which portions of trace
++ * are acutally compiled into the client: GT_TRACE and GT_ASSERT. If
++ * GT_TRACE is set to 0 then all trace statements (except for assertions)
++ * will be compiled out of the client. If GT_ASSERT is set to 0 then
++ * assertions will be compiled out of the client. GT_ASSERT can not be
++ * set to 0 unless GT_TRACE is also set to 0 (i.e. GT_TRACE == 1 implies
++ * GT_ASSERT == 1).
++ *
++ *! Revision History
++ *! ================
++ *! 02-Feb-2000 rr: Renamed this file to gtce.h. GT CLASS and trace definitions
++ *! are WinCE Specific.
++ *! 03-Jan-1997 ge Replaced "GT_" prefix to GT_Config structure members
++ *! to eliminate preprocessor confusion with other macros.
++ */
++#include <linux/types.h>
++#ifndef GT_
++#define GT_
++
++#ifndef GT_TRACE
++#define GT_TRACE 0 /* 0 = "trace compiled out"; 1 = "trace active" */
++#endif
++
++#include <dspbridge/host_os.h>
++
++#if !defined(GT_ASSERT) || GT_TRACE
++#define GT_ASSERT 1
++#endif
++
++struct GT_Config {
++ Fxn PRINTFXN;
++ Fxn PIDFXN;
++ Fxn TIDFXN;
++ Fxn ERRORFXN;
++};
++
++extern struct GT_Config *GT;
++
++struct GT_Mask {
++ char *modName;
++ u8 *flags;
++} ;
++
++/*
++ * New GT Class defenitions.
++ *
++ * The following are the explanations and how it could be used in the code
++ *
++ * - GT_ENTER On Entry to Functions
++ *
++ * - GT_1CLASS Display level of debugging status- Object/Automatic
++ * variables
++ * - GT_2CLASS ---- do ----
++ *
++ * - GT_3CLASS ---- do ---- + It can be used(recommended) for debug
++ * status in the ISR, IST
++ * - GT_4CLASS ---- do ----
++ *
++ * - GT_5CLASS Display entry for module init/exit functions
++ *
++ * - GT_6CLASS Warn whenever SERVICES function fails
++ *
++ * - GT_7CLASS Warn failure of Critical failures
++ *
++ */
++
++#define GT_ENTER ((u8)0x01)
++#define GT_1CLASS ((u8)0x02)
++#define GT_2CLASS ((u8)0x04)
++#define GT_3CLASS ((u8)0x08)
++#define GT_4CLASS ((u8)0x10)
++#define GT_5CLASS ((u8)0x20)
++#define GT_6CLASS ((u8)0x40)
++#define GT_7CLASS ((u8)0x80)
++
++#ifdef _LINT_
++
++/* LINTLIBRARY */
++
++/*
++ * ======== GT_assert ========
++ */
++/* ARGSUSED */
++void GT_assert(struct GT_Mask mask, s32 expr)
++{
++}
++
++/*
++ * ======== GT_config ========
++ */
++/* ARGSUSED */
++void GT_config(struct GT_Config config)
++{
++}
++
++/*
++ * ======== GT_create ========
++ */
++/* ARGSUSED */
++void GT_create(struct GT_Mask *mask, char *modName)
++{
++}
++
++/*
++ * ======== GT_curLine ========
++ * Purpose:
++ * Returns the current source code line number. Is useful for performing
++ * branch testing using trace. For example,
++ *
++ * GT_1trace(curTrace, GT_1CLASS,
++ * "in module XX_mod, executing line %u\n", GT_curLine());
++ */
++/* ARGSUSED */
++u16 GT_curLine(void)
++{
++ return (u16)NULL;
++}
++
++/*
++ * ======== GT_exit ========
++ */
++/* ARGSUSED */
++void GT_exit(void)
++{
++}
++
++/*
++ * ======== GT_init ========
++ */
++/* ARGSUSED */
++void GT_init(void)
++{
++}
++
++/*
++ * ======== GT_query ========
++ */
++/* ARGSUSED */
++bool GT_query(struct GT_Mask mask, u8 class)
++{
++ return false;
++}
++
++/*
++ * ======== GT_set ========
++ * sets trace mask according to settings
++ */
++
++/* ARGSUSED */
++void GT_set(char *settings)
++{
++}
++
++/*
++ * ======== GT_setprintf ========
++ * sets printf function
++ */
++
++/* ARGSUSED */
++void GT_setprintf(Fxn fxn)
++{
++}
++
++/* ARGSUSED */
++void GT_0trace(struct GT_Mask mask, u8 class, char *format)
++{
++}
++
++/* ARGSUSED */
++void GT_1trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_2trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_3trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_4trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_5trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++/* ARGSUSED */
++void GT_6trace(struct GT_Mask mask, u8 class, char *format, ...)
++{
++}
++
++#else
++
++#define GT_BOUND 26 /* 26 letters in alphabet */
++
++extern void _GT_create(struct GT_Mask *mask, char *modName);
++
++#define GT_exit()
++
++extern void GT_init(void);
++extern void _GT_set(char *str);
++extern s32 _GT_trace(struct GT_Mask *mask, char *format, ...);
++
++#if GT_ASSERT == 0
++
++#define GT_assert(mask, expr)
++#define GT_config(config)
++#define GT_configInit(config)
++#define GT_seterror(fxn)
++
++#else
++
++extern struct GT_Config _GT_params;
++
++#define GT_assert(mask, expr) \
++ (!(expr) ? \
++ printk("assertion violation: %s, line %d\n", \
++ __FILE__, __LINE__), NULL : NULL)
++
++#define GT_config(config) (_GT_params = *(config))
++#define GT_configInit(config) (*(config) = _GT_params)
++#define GT_seterror(fxn) (_GT_params.ERRORFXN = (Fxn)(fxn))
++
++#endif
++
++#if GT_TRACE == 0
++
++#define GT_curLine() ((u16)__LINE__)
++#define GT_create(mask, modName)
++#define GT_exit()
++#define GT_init()
++#define GT_set(settings)
++#define GT_setprintf(fxn)
++
++#define GT_query(mask, class) false
++
++#define GT_0trace(mask, class, format)
++#define GT_1trace(mask, class, format, arg1)
++#define GT_2trace(mask, class, format, arg1, arg2)
++#define GT_3trace(mask, class, format, arg1, arg2, arg3)
++#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4)
++#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5)
++#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6)
++
++#else /* GT_TRACE == 1 */
++
++
++#define GT_create(mask, modName) _GT_create((mask), (modName))
++#define GT_curLine() ((u16)__LINE__)
++#define GT_set(settings) _GT_set(settings)
++#define GT_setprintf(fxn) (_GT_params.PRINTFXN = (Fxn)(fxn))
++
++#define GT_query(mask, class) ((*(mask).flags & (class)))
++
++#define GT_0trace(mask, class, format) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format)) : 0)
++
++#define GT_1trace(mask, class, format, arg1) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1)) : 0)
++
++#define GT_2trace(mask, class, format, arg1, arg2) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2)) : 0)
++
++#define GT_3trace(mask, class, format, arg1, arg2, arg3) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3)) : 0)
++
++#define GT_4trace(mask, class, format, arg1, arg2, arg3, arg4) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4)) : 0)
++
++#define GT_5trace(mask, class, format, arg1, arg2, arg3, arg4, arg5) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5)) : 0)
++
++#define GT_6trace(mask, class, format, arg1, arg2, arg3, arg4, arg5, arg6) \
++ ((*(mask).flags & (class)) ? \
++ _GT_trace(&(mask), (format), (arg1), (arg2), (arg3), (arg4), (arg5), \
++ (arg6)) : 0)
++
++#endif /* GT_TRACE */
++
++#endif /* _LINT_ */
++
++#endif /* GTCE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/host_os.h b/arch/arm/plat-omap/include/dspbridge/host_os.h
+new file mode 100644
+index 0000000..f539bd0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/host_os.h
+@@ -0,0 +1,96 @@
++/*
++ * host_os.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== windows.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 08-Mar-2004 sb Added cacheflush.h to support Dynamic Memory Mapping feature
++ *! 16-Feb-2004 sb Added headers required for consistent_alloc
++ */
++
++#ifndef _HOST_OS_H_
++#define _HOST_OS_H_
++
++#include <linux/autoconf.h>
++#include <asm/system.h>
++#include <asm/atomic.h>
++#include <linux/semaphore.h>
++#include <linux/uaccess.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <linux/syscalls.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/string.h>
++#include <linux/stddef.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/ctype.h>
++#include <linux/mm.h>
++#include <linux/device.h>
++#include <linux/vmalloc.h>
++#include <linux/ioport.h>
++#include <linux/platform_device.h>
++#include <dspbridge/dbtype.h>
++#include <mach/clock.h>
++#include <linux/clk.h>
++#include <linux/pagemap.h>
++#include <asm/cacheflush.h>
++#include <linux/dma-mapping.h>
++
++/* ----------------------------------- Macros */
++
++#define SEEK_SET 0 /* Seek from beginning of file. */
++#define SEEK_CUR 1 /* Seek from current position. */
++#define SEEK_END 2 /* Seek from end of file. */
++
++/* TODO -- Remove, once BP defines them */
++#define INT_MAIL_MPU_IRQ 26
++#define INT_DSP_MMU_IRQ 28
++
++struct dspbridge_platform_data {
++ void (*dsp_set_min_opp)(u8 opp_id);
++ u8 (*dsp_get_opp)(void);
++ void (*cpu_set_freq)(unsigned long f);
++ unsigned long (*cpu_get_freq)(void);
++ unsigned long mpu_speed[6];
++
++ u32 phys_mempool_base;
++ u32 phys_mempool_size;
++};
++
++#define PRCM_VDD1 1
++
++extern struct platform_device *omap_dspbridge_dev;
++
++#if defined(CONFIG_MPU_BRIDGE) || defined(CONFIG_MPU_BRIDGE_MODULE)
++extern void dspbridge_reserve_sdram(void);
++#else
++static inline void dspbridge_reserve_sdram(void) {}
++#endif
++
++extern unsigned long dspbridge_get_mempool_base(void);
++#endif
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/io.h b/arch/arm/plat-omap/include/dspbridge/io.h
+new file mode 100644
+index 0000000..6dc63f2
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/io.h
+@@ -0,0 +1,132 @@
++/*
++ * io.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io.h ========
++ * Description:
++ * The io module manages IO between CHNL and MSG.
++ *
++ * Public Functions:
++ * IO_Create
++ * IO_Destroy
++ * IO_Exit
++ * IO_Init
++ * IO_OnLoaded
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Nov-2000 jeh Created.
++ */
++
++#ifndef IO_
++#define IO_
++
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/iodefs.h>
++
++/*
++ * ======== IO_Create ========
++ * Purpose:
++ * Create an IO manager object, responsible for managing IO between
++ * CHNL and MSG.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on
++ * output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: IO manager attributes.
++ * pMgrAttrs->bIRQ: I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug channel ISR for configured IRQ.
++ * CHNL_E_INVALIDIRQ: Invalid IRQ number. Must be 0 <= bIRQ <= 15.
++ * CHNL_E_INVALIDWORDSIZE: Invalid DSP word size. Must be > 0.
++ * CHNL_E_INVALIDMEMBASE: Invalid base address for DSP communications.
++ * Requires:
++ * IO_Init(void) called.
++ * phIOMgr != NULL.
++ * pMgrAttrs != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++/*
++ * ======== IO_Destroy ========
++ * Purpose:
++ * Destroy the IO manager.
++ * Parameters:
++ * hIOMgr: IOmanager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hIOMgr was invalid.
++ * Requires:
++ * IO_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr);
++
++/*
++ * ======== IO_Exit ========
++ * Purpose:
++ * Discontinue usage of the IO module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * IO_Init(void) previously called.
++ * Ensures:
++ * Resources, if any acquired in IO_Init(void), are freed when the last
++ * client of IO calls IO_Exit(void).
++ */
++ extern void IO_Exit(void);
++
++/*
++ * ======== IO_Init ========
++ * Purpose:
++ * Initialize the IO module's private state.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occurred.
++ * Requires:
++ * Ensures:
++ * A requirement for each of the other public CHNL functions.
++ */
++ extern bool IO_Init(void);
++
++/*
++ * ======== IO_OnLoaded ========
++ * Purpose:
++ * Called when a program is loaded so IO manager can update its
++ * internal state.
++ * Parameters:
++ * hIOMgr: IOmanager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hIOMgr was invalid.
++ * Requires:
++ * IO_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS IO_OnLoaded(struct IO_MGR *hIOMgr);
++
++#endif /* CHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/io_sm.h b/arch/arm/plat-omap/include/dspbridge/io_sm.h
+new file mode 100644
+index 0000000..3dcbf74
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/io_sm.h
+@@ -0,0 +1,335 @@
++/*
++ * io_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io_sm.h ========
++ * Description:
++ * IO dispatcher for a shared memory channel driver.
++ * Also, includes macros to simulate SHM via port io calls.
++ *
++ * Public Functions:
++ * IO_Dispatch
++ * IO_DPC
++ * IO_ISR
++ * IO_RequestChnl
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 01-Mar-2004 vp: Added IVA releated functions.
++ *! 23-Apr-2003 sb: Fixed mailbox deadlock
++ *! 06-Feb-2003 kc Added IO_DDMAClearChnlDesc and IO_DDZCClearChnlDesc.
++ *! 21-Dec-2001 ag Removed unused param in IO_DDMAInitChnlDesc().
++ * Updated comments. Removed #ifdef CHNL_NOIPCINTR.
++ *! 05-Nov-2001 kc Updated IO_CALLISR macro.
++ *! 01-May-2001 jeh Removed IO_RequestMsg.
++ *! 29-Mar-2001 ag Added #ifdef CHNL_NOIPCINTR.
++ *! 04-Dec-2000 jeh Added IO_RequestMsg.
++ *! 26-Oct-2000 jeh Added IO_GetLong, IO_SetLong, IO_ReadValueLong, and
++ *! IO_WriteValueLong, for passing arg in SHM structure.
++ *! 20-Jan-2000 ag: Updated header comments per code review.
++ *! 05-Jan-2000 ag: Text format clean-up.
++ *! 02-Nov-1999 ag: Updated header descriptions.
++ *! 25-May-1999 jg: Removed assumption of 4 bytes / word.
++ *! 12-Aug-1996 gp: Created.
++ */
++
++#ifndef IOSM_
++#define IOSM_
++
++#include <dspbridge/_chnl_sm.h>
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/iodefs.h>
++
++#define IO_INPUT 0
++#define IO_OUTPUT 1
++#define IO_SERVICE 2
++#define IO_MAXSERVICE IO_SERVICE
++
++#define IO_MGRSIGNATURE 0x494f4D43 /* "IOGR" */
++
++#define DSPFieldAddr(type, field, base, wordsize) \
++ ((((s32)&(((type *)0)->field)) / wordsize) + (u32)base)
++
++/* Access can be different SM access word size (e.g. 16/32 bit words) */
++#define IO_SetValue(pContext, type, base, field, value) (base->field = value)
++#define IO_GetValue(pContext, type, base, field) (base->field)
++#define IO_OrValue(pContext, type, base, field, value) (base->field |= value)
++#define IO_AndValue(pContext, type, base, field, value) (base->field &= value)
++#define IO_SetLong(pContext, type, base, field, value) (base->field = value)
++#define IO_GetLong(pContext, type, base, field) (base->field)
++
++#define IO_DisableInterrupt(h) CHNLSM_DisableInterrupt(h)
++#define IO_EnableInterrupt(h) CHNLSM_EnableInterrupt(h)
++#define IO_CALLISR(h, pFlag, pwMBRegVal) CHNLSM_ISR(h, pFlag, pwMBRegVal)
++
++/*
++ * ======== IO_CancelChnl ========
++ * Purpose:
++ * Cancel IO on a given channel.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * ulChnl: Index of channel to cancel IO on.
++ * Returns:
++ * Requires:
++ * Valid hIOMgr.
++ * Ensures:
++ */
++ extern void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl);
++
++/*
++ * ======== IO_DPC ========
++ * Purpose:
++ * Deferred procedure call for shared memory channel driver ISR. Carries
++ * out the dispatch of I/O.
++ * Parameters:
++ * pRefData: Pointer to reference data registered via a call to
++ * DPC_Create().
++ * Returns:
++ * Requires:
++ * Must not block.
++ * Must not acquire resources.
++ * All data touched must be locked in memory if running in kernel mode.
++ * Ensures:
++ * Non-preemptible (but interruptible).
++ */
++ extern void IO_DPC(IN OUT void *pRefData);
++
++/*
++ * ======== IO_ISR ========
++ * Purpose:
++ * Main interrupt handler for the shared memory WMD channel manager.
++ * Calls the WMD's CHNLSM_ISR to determine if this interrupt is ours, then
++ * schedules a DPC to dispatch I/O..
++ * Parameters:
++ * pRefData: Pointer to the channel manager object for this board.
++ * Set in an initial call to ISR_Install().
++ * Returns:
++ * TRUE if interrupt handled; FALSE otherwise.
++ * Requires:
++ * Must be in locked memory if executing in kernel mode.
++ * Must only call functions which are in locked memory if Kernel mode.
++ * Must only call asynchronous services.
++ * Interrupts are disabled and EOI for this interrupt has been sent.
++ * Ensures:
++ */
++ irqreturn_t IO_ISR(int irq, IN void *pRefData);
++/*
++ * ======== IO_RequestChnl ========
++ * Purpose:
++ * Request I/O from the DSP. Sets flags in shared memory, then interrupts
++ * the DSP.
++ * Parameters:
++ * hIOMgr: IO manager handle.
++ * pChnl: Ptr to the channel requesting I/O.
++ * iMode: Mode of channel: {IO_INPUT | IO_OUTPUT}.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * Ensures:
++ */
++ extern void IO_RequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ u32 iMode, OUT u16 *pwMbVal);
++
++/*
++ * ======== IO_Schedule ========
++ * Purpose:
++ * Schedule DPC for IO.
++ * Parameters:
++ * pIOMgr: Ptr to a I/O manager.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * Ensures:
++ */
++ extern void IO_Schedule(struct IO_MGR *hIOMgr);
++
++/*
++ * DSP-DMA IO functions
++ */
++
++/*
++ * ======== IO_DDMAInitChnlDesc ========
++ * Purpose:
++ * Initialize DSP DMA channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uDDMAChnlId: DDMA channel identifier.
++ * uNumDesc: Number of buffer descriptors(equals # of IOReqs &
++ * Chirps)
++ * pDsp: Dsp address;
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXDDMACHNLS
++ * uNumDesc > 0
++ * pVa != NULL
++ * pDspPa != NULL
++ *
++ * Ensures:
++ */
++ extern void IO_DDMAInitChnlDesc(struct IO_MGR *hIOMgr, u32 uDDMAChnlId,
++ u32 uNumDesc, void *pDsp);
++
++/*
++ * ======== IO_DDMAClearChnlDesc ========
++ * Purpose:
++ * Clear DSP DMA channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uDDMAChnlId: DDMA channel identifier.
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXDDMACHNLS
++ * Ensures:
++ */
++ extern void IO_DDMAClearChnlDesc(struct IO_MGR *hIOMgr,
++ u32 uDDMAChnlId);
++
++/*
++ * ======== IO_DDMARequestChnl ========
++ * Purpose:
++ * Request channel DSP-DMA from the DSP. Sets up SM descriptors and
++ * control fields in shared memory.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * pChnl: Ptr to channel object
++ * pChirp: Ptr to channel i/o request packet.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * pChnl->cIOReqs > 0
++ * pChirp != NULL
++ * Ensures:
++ */
++ extern void IO_DDMARequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp,
++ OUT u16 *pwMbVal);
++
++/*
++ * Zero-copy IO functions
++ */
++
++/*
++ * ======== IO_DDZCInitChnlDesc ========
++ * Purpose:
++ * Initialize ZCPY channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uZId: zero-copy channel identifier.
++ * Returns:
++ * Requires:
++ * uDDMAChnlId < DDMA_MAXZCPYCHNLS
++ * hIOMgr != Null
++ * Ensures:
++ */
++ extern void IO_DDZCInitChnlDesc(struct IO_MGR *hIOMgr, u32 uZId);
++
++/*
++ * ======== IO_DDZCClearChnlDesc ========
++ * Purpose:
++ * Clear DSP ZC channel descriptor.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * uChnlId: ZC channel identifier.
++ * Returns:
++ * Requires:
++ * hIOMgr is valid
++ * uChnlId < DDMA_MAXZCPYCHNLS
++ * Ensures:
++ */
++ extern void IO_DDZCClearChnlDesc(struct IO_MGR *hIOMgr, u32 uChnlId);
++
++/*
++ * ======== IO_DDZCRequestChnl ========
++ * Purpose:
++ * Request zero-copy channel transfer. Sets up SM descriptors and
++ * control fields in shared memory.
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * pChnl: Ptr to channel object
++ * pChirp: Ptr to channel i/o request packet.
++ * Returns:
++ * Requires:
++ * pChnl != NULL
++ * pChnl->cIOReqs > 0
++ * pChirp != NULL
++ * Ensures:
++ */
++ extern void IO_DDZCRequestChnl(struct IO_MGR *hIOMgr,
++ struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp,
++ OUT u16 *pwMbVal);
++
++/*
++ * ======== IO_SHMsetting ========
++ * Purpose:
++ * Sets the shared memory setting
++ * Parameters:
++ * hIOMgr: Handle to a I/O manager.
++ * desc: Shared memory type
++ * pArgs: Ptr to SHM setting
++ * Returns:
++ * Requires:
++ * hIOMgr != NULL
++ * pArgs != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr,
++ IN enum SHM_DESCTYPE desc,
++ IN void *pArgs);
++
++/*
++ * Misc functions for the CHNL_IO shared memory library:
++ */
++
++/* Maximum channel bufsize that can be used. */
++ extern u32 IO_BufSize(struct IO_MGR *hIOMgr);
++
++ extern u32 IO_ReadValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr);
++
++ extern void IO_WriteValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern u32 IO_ReadValueLong(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr);
++
++ extern void IO_WriteValueLong(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_OrSetValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_AndSetValue(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr, u32 dwValue);
++
++ extern void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal);
++
++ extern void IO_SM_init(void);
++
++/*
++ * ========PrintDspTraceBuffer ========
++ * Print DSP tracebuffer.
++ */
++ extern DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT
++ *hWmdContext);
++
++#endif /* IOSM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/iodefs.h b/arch/arm/plat-omap/include/dspbridge/iodefs.h
+new file mode 100644
+index 0000000..f45890a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/iodefs.h
+@@ -0,0 +1,45 @@
++/*
++ * iodefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== iodefs.h ========
++ * Description:
++ * System-wide channel objects and constants.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Nov-2000 jeh Created.
++ */
++
++#ifndef IODEFS_
++#define IODEFS_
++
++#define IO_MAXIRQ 0xff /* Arbitrarily large number. */
++
++/* IO Objects: */
++ struct IO_MGR;
++
++/* IO manager attributes: */
++ struct IO_ATTRS {
++ u8 bIRQ; /* Channel's I/O IRQ number. */
++ bool fShared; /* TRUE if the IRQ is shareable. */
++ u32 uWordSize; /* DSP Word size. */
++ u32 dwSMBase; /* Physical base address of shared memory. */
++ u32 uSMLength; /* Size (in bytes) of shared memory. */
++ } ;
++
++#endif /* IODEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/kfile.h b/arch/arm/plat-omap/include/dspbridge/kfile.h
+new file mode 100644
+index 0000000..23c89b0
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/kfile.h
+@@ -0,0 +1,216 @@
++/*
++ * kfile.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== kfile.h ========
++ * Purpose:
++ * Provide file I/O management capabilities.
++ *
++ * Public Functions:
++ * KFILE_Close
++ * KFILE_Exit
++ * KFILE_Init
++ * KFILE_Open
++ * KFILE_Read
++ * KFILE_Seek
++ * KFILE_Tell
++ * KFILE_Write
++ *
++ * Notes:
++ * The KFILE module is not like most of the other DSP/BIOS Bridge modules
++ * in that it doesn't return WSX_STATUS type values. Rather, it's
++ * prototypes are meant to match the stdio file prototypes
++ * (ie, fopen, fclose, etc.).
++ *
++ *! Revision History
++ *! ================
++ *! 29-Oct-1999 kc: Clean up for code review.
++ *! 07-Jan-1998 cr: Clean up for code review.
++ *! 15-Aug-1997 cr: Added E_KFILE_ERROR for general error condition.
++ *! 04-Aug-1997 cr: Added explicit CDECL descriptions.
++ *! 11-Nov-1996 cr: Implemented changes based on code review.
++ *! 05-Nov-1996 cr: Cleaned up for code review.
++ *! 29-May-1996 gp: Added requirement that size != 0 in _Write() and _Read().
++ *! 28-May-1996 mg: Changed return values for Read/Write.
++ *! 14-Dec-1995 cr: Created.
++ */
++
++#ifndef KFILE_
++#define KFILE_
++
++/*
++ * Constants for KFILE_Seek. Note that these MUST be the same definitions as
++ * those defined for fseek.
++ */
++#define KFILE_SEEK_SET 0x00 /* seek from beginning of file */
++#define KFILE_SEEK_CUR 0x01 /* seek from current position */
++#define KFILE_SEEK_END 0x02 /* seek from end of file */
++
++ struct KFILE_FileObj;
++
++/*
++ * ======== KFILE_Close ========
++ * Purpose:
++ * This function closes a file's stream.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad handle.
++ * 0: success.
++ * E_KFILE_ERROR: unable to close specified handle.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Close(IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void KFILE_Exit(void);
++
++/*
++ * ======== KFILE_Init ========
++ * Purpose:
++ * Initializes private state of KFILE module.
++ * Parameters:
++ * Returns:
++ * TRUE if success, else FALSE.
++ * Requires:
++ * Ensures:
++ * KFILE initialized.
++ */
++ extern bool KFILE_Init(void);
++
++/*
++ * ======== KFILE_Open ========
++ * Purpose:
++ * Opens a file for use.
++ * Parameters:
++ * pszFileName: Full path to name of the file to open.
++ * pszMode: String containing open status. Only the first
++ * character of the string is examined, for either
++ * "r" (read) or "w" (write) mode.
++ * Returns:
++ * A valid file handle if success, else NULL.
++ * Requires:
++ * - KFILE initialized.
++ * - pszMode != NULL.
++ * - pszFileName != NULL.
++ * Ensures:
++ */
++ extern struct KFILE_FileObj *KFILE_Open(IN CONST char *filename,
++ IN CONST char *mode);
++
++/*
++ * ======== KFILE_Read ========
++ * Purpose:
++ * This function reads a specified number of bytes into a buffer.
++ * Parameters:
++ * pBuffer: Array to which the file data is copied.
++ * cSize: Number of characters in each object.
++ * cCount: Number of objects to read in.
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * E_KFILE_ERROR: general failure.
++ * > 0: success; # of objects read from file.
++ * Requires:
++ * KFILE initialized.
++ * pBuffer is a valid pointer.
++ * Ensures:
++ */
++ extern s32 KFILE_Read(OUT void __user*buffer,
++ IN s32 size, IN s32 count,
++ IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Seek ========
++ * Purpose:
++ * This function sets the file position indicator. NOTE: we don't
++ * support seeking beyond the boundaries of a file.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * offset: Number of bytes from the origin to move.
++ * origin: File reference point, one of the following values:
++ * KFILE_SEEK_SET: Seek from beginning of file.
++ * KFILE_SEEK_CUR: Seek from current position.
++ * KFILE_SEEK_END: Seek from end of file.
++ * Returns:
++ * 0: success.
++ * E_KFILE_INVALIDHANDLE: bad handle.
++ * E_KFILE_BADORIGIN: invalid origin paramater.
++ * E_KFILE_ERROR: general failure.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Seek(IN struct KFILE_FileObj *hFile,
++ IN s32 offset, IN s32 origin);
++
++/*
++ * ======== KFILE_Tell ========
++ * Purpose:
++ * This function reports the current value of the position indicator.
++ * Parameters:
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Return value:
++ * > 0: success; returns # of bytes the position indicator is from
++ * beginning of file.
++ * E_KFILE_ERROR: general failure.
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * Requires:
++ * KFILE initialized.
++ * Ensures:
++ */
++ extern s32 KFILE_Tell(IN struct KFILE_FileObj *hFile);
++
++/*
++ * ======== KFILE_Write ========
++ * Purpose:
++ * This function writes a number of objects to the stream.
++ * Parameters:
++ * pBuffer: Array from which the file data is written.
++ * cSize: Number of characters in each object.
++ * cCount: Number of objects to write out.
++ * hFile: Handle of the file stream returned by KFILE_Open.
++ * Returns:
++ * E_KFILE_INVALIDHANDLE: bad file handle.
++ * E_KFILE_ERROR: general failure.
++ * > 0: success; # of objects written to file.
++ * Requires:
++ * KFILE initialized.
++ * pBuffer != NULL.
++ * Postcondition:
++ * The file position indicator is advanced by the number of
++ * characters written.
++ */
++ extern s32 KFILE_Write(OUT void *buffer,
++ IN s32 size,
++ IN s32 count,
++ IN struct KFILE_FileObj *hFile);
++
++#endif /* KFILE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/ldr.h b/arch/arm/plat-omap/include/dspbridge/ldr.h
+new file mode 100644
+index 0000000..7e13c93
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/ldr.h
+@@ -0,0 +1,51 @@
++/*
++ * ldr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ldr.h ========
++ * Purpose:
++ * Provide module loading services and symbol export services.
++ *
++ * Public Functions:
++ * LDR_Exit
++ * LDR_FreeModule
++ * LDR_GetProcAddress
++ * LDR_Init
++ * LDR_LoadModule
++ *
++ * Notes:
++ * This service is meant to be used by modules of the DSP/BIOS Bridge
++ * class driver.
++ *
++ *! Revision History:
++ *! ================
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 12-Nov-1999 kc: Removed declaration of unused loader object.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 12-Jan-1998 cr: Cleaned up for code review.
++ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 11-Nov-1996 cr: Cleaned up for code review.
++ *! 16-May-1996 gp: Created.
++ */
++
++#ifndef LDR_
++#define LDR_
++
++/* Loader objects: */
++ struct LDR_MODULE;
++
++#endif /* LDR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/list.h b/arch/arm/plat-omap/include/dspbridge/list.h
+new file mode 100644
+index 0000000..2e3f995
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/list.h
+@@ -0,0 +1,296 @@
++/*
++ * list.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== list.h ========
++ * Purpose:
++ * Declarations of list management control structures and definitions
++ * of inline list management functions.
++ *
++ * Public Functions:
++ * LST_Create
++ * LST_Delete
++ * LST_Exit
++ * LST_First
++ * LST_GetHead
++ * LST_InitElem
++ * LST_Init
++ * LST_InsertBefore
++ * LST_IsEmpty
++ * LST_Next
++ * LST_PutTail
++ * LST_RemoveElem
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 10-Aug-2000 ag: Added LST_InsertBefore().
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 16-Aug-1997 cr: added explicit identifiers.
++ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v.1.1; renamed identifiers.
++ *! 21-Oct-1994 dh4: Cleaned / commented for code review.
++ *! 08-Jun-1994 dh4: Converted to SPM (added extern "C").
++ */
++
++#ifndef LIST_
++#define LIST_
++
++#include <dspbridge/host_os.h>
++
++#define LST_IsEmpty(l) (((l)->head.next == &(l)->head))
++
++ struct LST_ELEM {
++ struct LST_ELEM *next;
++ struct LST_ELEM *prev;
++ struct LST_ELEM *self;
++ } ;
++
++ struct LST_LIST {
++ struct LST_ELEM head;
++ } ;
++
++/*
++ * ======== LST_Create ========
++ * Purpose:
++ * Allocates and initializes a circular list.
++ * Details:
++ * Uses portable MEM_Calloc() function to allocate a list containing
++ * a single element and initializes that element to indicate that it
++ * is the "end of the list" (i.e., the list is empty).
++ * An empty list is indicated by the "next" pointer in the element
++ * at the head of the list pointing to the head of the list, itself.
++ * Parameters:
++ * Returns:
++ * Pointer to beginning of created list (success)
++ * NULL --> Allocation failed
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * The created list contains a single element. This element is the
++ * "empty" element, because its "next" and "prev" pointers point at
++ * the same location (the element itself).
++ */
++ extern struct LST_LIST *LST_Create(void);
++
++/*
++ * ======== LST_Delete ========
++ * Purpose:
++ * Removes a list by freeing its control structure's memory space.
++ * Details:
++ * Uses portable MEM_Free() function to deallocate the memory
++ * block pointed at by the input parameter.
++ * Parameters:
++ * pList: Pointer to list control structure of list to be deleted
++ * Returns:
++ * Void
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ * Notes:
++ * Must ONLY be used for empty lists, because it does not walk the
++ * chain of list elements. Calling this function on a non-empty list
++ * will cause a memory leak.
++ */
++ extern void LST_Delete(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void LST_Exit(void);
++
++/*
++ * ======== LST_First ========
++ * Purpose:
++ * Returns a pointer to the first element of the list, or NULL if the list
++ * is empty.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * Returns:
++ * Pointer to first list element, or NULL.
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ */
++ extern struct LST_ELEM *LST_First(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_GetHead ========
++ * Purpose:
++ * Pops the head off the list and returns a pointer to it.
++ * Details:
++ * If the list is empty, returns NULL.
++ * Else, removes the element at the head of the list, making the next
++ * element the head of the list.
++ * The head is removed by making the tail element of the list point its
++ * "next" pointer at the next element after the head, and by making the
++ * "prev" pointer of the next element after the head point at the tail
++ * element. So the next element after the head becomes the new head of
++ * the list.
++ * Parameters:
++ * pList: Pointer to list control structure of list whose head
++ * element is to be removed
++ * Returns:
++ * Pointer to element that was at the head of the list (success)
++ * NULL No elements in list
++ * Requires:
++ * - head.self must be correctly set to &head.
++ * - LST initialized.
++ * - pList != NULL.
++ * Ensures:
++ * Notes:
++ * Because the tail of the list points forward (its "next" pointer) to
++ * the head of the list, and the head of the list points backward (its
++ * "prev" pointer) to the tail of the list, this list is circular.
++ */
++ extern struct LST_ELEM *LST_GetHead(IN struct LST_LIST *pList);
++
++/*
++ * ======== LST_Init ========
++ * Purpose:
++ * Initializes private state of LST module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE otherwise.
++ * Requires:
++ * Ensures:
++ * LST initialized.
++ */
++ extern bool LST_Init(void);
++
++/*
++ * ======== LST_InitElem ========
++ * Purpose:
++ * Initializes a list element to default (cleared) values
++ * Details:
++ * Parameters:
++ * pElem: Pointer to list element to be reset
++ * Returns:
++ * Requires:
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * This function must not be called to "reset" an element in the middle
++ * of a list chain -- that would break the chain.
++ *
++ */
++ extern void LST_InitElem(IN struct LST_ELEM *pListElem);
++
++/*
++ * ======== LST_InsertBefore ========
++ * Purpose:
++ * Insert the element before the existing element.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pElem: Pointer to element in list to insert.
++ * pElemExisting: Pointer to existing list element.
++ * Returns:
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pElem != NULL.
++ * - pElemExisting != NULL.
++ * Ensures:
++ */
++ extern void LST_InsertBefore(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pElem,
++ IN struct LST_ELEM *pElemExisting);
++
++/*
++ * ======== LST_Next ========
++ * Purpose:
++ * Returns a pointer to the next element of the list, or NULL if the next
++ * element is the head of the list or the list is empty.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pCurElem: Pointer to element in list to remove.
++ * Returns:
++ * Pointer to list element, or NULL.
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pCurElem != NULL.
++ * Ensures:
++ */
++ extern struct LST_ELEM *LST_Next(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pCurElem);
++
++/*
++ * ======== LST_PutTail ========
++ * Purpose:
++ * Adds the specified element to the tail of the list
++ * Details:
++ * Sets new element's "prev" pointer to the address previously held by
++ * the head element's prev pointer. This is the previous tail member of
++ * the list.
++ * Sets the new head's prev pointer to the address of the element.
++ * Sets next pointer of the previous tail member of the list to point to
++ * the new element (rather than the head, which it had been pointing at).
++ * Sets new element's next pointer to the address of the head element.
++ * Sets head's prev pointer to the address of the new element.
++ * Parameters:
++ * pList: Pointer to list control structure to which *pElem will be
++ * added
++ * pElem: Pointer to list element to be added
++ * Returns:
++ * Void
++ * Requires:
++ * *pElem and *pList must both exist.
++ * pElem->self = pElem before pElem is passed to this function.
++ * LST initialized.
++ * Ensures:
++ * Notes:
++ * Because the tail is always "just before" the head of the list (the
++ * tail's "next" pointer points at the head of the list, and the head's
++ * "prev" pointer points at the tail of the list), the list is circular.
++ * Warning: if pElem->self is not set beforehand, LST_GetHead() will
++ * return an erroneous pointer when it is called for this element.
++ */
++ extern void LST_PutTail(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pListElem);
++
++/*
++ * ======== LST_RemoveElem ========
++ * Purpose:
++ * Removes (unlinks) the given element from the list, if the list is not
++ * empty. Does not free the list element.
++ * Parameters:
++ * pList: Pointer to list control structure.
++ * pCurElem: Pointer to element in list to remove.
++ * Returns:
++ * Requires:
++ * - LST initialized.
++ * - pList != NULL.
++ * - pCurElem != NULL.
++ * Ensures:
++ */
++extern void LST_RemoveElem(IN struct LST_LIST *pList,
++ IN struct LST_ELEM *pCurElem);
++
++#endif /* LIST_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mbx_sh.h b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+new file mode 100644
+index 0000000..be0909e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mbx_sh.h
+@@ -0,0 +1,213 @@
++/*
++ * mbx_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mbx_sh.h ========
++ * Definitions for shared mailbox cmd/data values.(used on both
++ * the GPP and DSP sides).
++ *
++ * Bridge usage of OMAP mailbox 1 is determined by the "class" of the
++ * mailbox interrupt's cmd value received. The class value are defined
++ * as a bit (10 thru 15) being set.
++ *
++ * Note: Only 16 bits of each is used. Other 16 bit data reg available.
++ *
++ * 16 bit Mbx bit defns:
++ *
++ * A). Exception/Error handling (Module DEH) : class = 0.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|0|0|x|x|x|x|x|x|x|x|x|x|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ *
++ *
++ * B: DSP-DMA link driver channels (DDMA) : class = 1.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|0|1|b|b|b|b|b|c|c|c|c|c|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where b -> buffer index (32 DDMA buffers/chnl max)
++ * c -> channel Id (32 DDMA chnls max)
++ *
++ *
++ *
++ *
++ * C: Proc-copy link driver channels (PCPY) : class = 2.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|0|1|0|x|x|x|x|x|x|x|x|x|x|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ *
++ * D: Zero-copy link driver channels (DDZC) : class = 4.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|0|1|0|0|x|x|x|x|x|c|c|c|c|c|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where x -> not used
++ * c -> channel Id (32 ZCPY chnls max)
++ *
++ *
++ * E: Power management : class = 8.
++ *
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|1|0|0|0|x|x|x|x|x|c|c|c|c|c|
++
++ * 0010 00xx xxxc cccc
++ * 0010 00nn pppp qqqq
++ * nn:
++ * 00 = reserved
++ * 01 = pwr state change
++ * 10 = opp pre-change
++ * 11 = opp post-change
++ *
++ * if nn = pwr state change:
++ * pppp = don't care
++ * qqqq:
++ * 0010 = hibernate
++ * 0010 0001 0000 0010
++ * 0110 = retention
++ * 0010 0001 0000 0110
++ * others reserved
++ *
++ * if nn = opp pre-change:
++ * pppp = current opp
++ * qqqq = next opp
++ *
++ * if nn = opp post-change:
++ * pppp = prev opp
++ * qqqq = current opp
++ *
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where x -> not used
++ * c -> Power management command
++ *
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Sep-2002 mr Added DEH reset const
++ *! 24-Apr-2002 sg Added more PM commands.
++ *! 04-Mar-2002 gv Added MBX_PM_CLASS
++ *! 22-Jan-2002 ag Bug fix in MBX_SETZCPYVAL(x) macro.
++ *! 21-Dec-2001 ag Added bit masks defns.
++ *! 17-Dec-2001 ag: created.
++ */
++
++#ifndef _MBX_SH_H
++#define _MBX_SH_H
++
++#define MBX_CLASS_MSK 0xFC00 /* Class bits are 10 thru 15 */
++#define MBX_VALUE_MSK 0x03FF /* Value is 0 thru 9 */
++
++#define MBX_DEH_CLASS 0x0000 /* DEH owns Mbx INTR */
++#define MBX_DDMA_CLASS 0x0400 /* DSP-DMA link drvr chnls owns INTR */
++#define MBX_PCPY_CLASS 0x0800 /* PROC-COPY " */
++#define MBX_ZCPY_CLASS 0x1000 /* ZERO-COPY " */
++#define MBX_PM_CLASS 0x2000 /* Power Management */
++#define MBX_DBG_CLASS 0x4000 /* For debugging purpose */
++
++/*
++ * Exception Handler codes
++ * Magic code used to determine if DSP signaled exception.
++ */
++#define MBX_DEH_BASE 0x0
++#define MBX_DEH_USERS_BASE 0x100 /* 256 */
++#define MBX_DEH_LIMIT 0x3FF /* 1023 */
++#define MBX_DEH_RESET 0x101 /* DSP RESET (DEH) */
++#define MBX_DEH_EMMU 0X103 /*DSP MMU FAULT RECOVERY*/
++
++/*
++ * Link driver command/status codes.
++ */
++/* DSP-DMA */
++#define MBX_DDMA_NUMCHNLBITS 5 /* # chnl Id: # bits available */
++#define MBX_DDMA_CHNLSHIFT 0 /* # of bits to shift */
++#define MBX_DDMA_CHNLMSK 0x01F /* bits 0 thru 4 */
++
++#define MBX_DDMA_NUMBUFBITS 5 /* buffer index: # of bits avail */
++#define MBX_DDMA_BUFSHIFT (MBX_DDMA_NUMCHNLBITS + MBX_DDMA_CHNLSHIFT)
++#define MBX_DDMA_BUFMSK 0x3E0 /* bits 5 thru 9 */
++
++/* Zero-Copy */
++#define MBX_ZCPY_NUMCHNLBITS 5 /* # chnl Id: # bits available */
++#define MBX_ZCPY_CHNLSHIFT 0 /* # of bits to shift */
++#define MBX_ZCPY_CHNLMSK 0x01F /* bits 0 thru 4 */
++
++/* Power Management Commands */
++#define MBX_PM_DSPIDLE (MBX_PM_CLASS + 0x0)
++#define MBX_PM_DSPWAKEUP (MBX_PM_CLASS + 0x1)
++#define MBX_PM_EMERGENCYSLEEP (MBX_PM_CLASS + 0x2)
++#define MBX_PM_SLEEPUNTILRESTART (MBX_PM_CLASS + 0x3)
++#define MBX_PM_DSPGLOBALIDLE_OFF (MBX_PM_CLASS + 0x4)
++#define MBX_PM_DSPGLOBALIDLE_ON (MBX_PM_CLASS + 0x5)
++#define MBX_PM_SETPOINT_PRENOTIFY (MBX_PM_CLASS + 0x6)
++#define MBX_PM_SETPOINT_POSTNOTIFY (MBX_PM_CLASS + 0x7)
++#define MBX_PM_DSPRETN (MBX_PM_CLASS + 0x8)
++#define MBX_PM_DSPRETENTION (MBX_PM_CLASS + 0x8)
++#define MBX_PM_DSPHIBERNATE (MBX_PM_CLASS + 0x9)
++#define MBX_PM_HIBERNATE_EN (MBX_PM_CLASS + 0xA)
++#define MBX_PM_OPP_REQ (MBX_PM_CLASS + 0xB)
++#define MBX_PM_OPP_CHG (MBX_PM_CLASS + 0xC)
++
++#define MBX_PM_TYPE_MASK 0x0300
++#define MBX_PM_TYPE_PWR_CHNG 0x0100
++#define MBX_PM_TYPE_OPP_PRECHNG 0x0200
++#define MBX_PM_TYPE_OPP_POSTCHNG 0x0300
++#define MBX_PM_TYPE_OPP_MASK 0x0300
++#define MBX_PM_OPP_PRECHNG (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG)
++/* DSP to MPU */
++#define MBX_PM_OPP_CHNG(OPP) (MBX_PM_CLASS | MBX_PM_TYPE_OPP_PRECHNG | (OPP))
++#define MBX_PM_RET (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0006)
++#define MBX_PM_HIB (MBX_PM_CLASS | MBX_PM_TYPE_PWR_CHNG | 0x0002)
++#define MBX_PM_OPP_1 0
++#define MBX_PM_OPP_2 1
++#define MBX_PM_OPP_3 2
++#define MBX_PM_OPP_4 3
++#define MBX_OLDOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
++#define MBX_NEWOPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
++#define MBX_PREVOPP_EXTRACT(OPPMSG) ((0x00F0 & (OPPMSG)) >> 4)
++#define MBX_CUROPP_EXTRACT(OPPMSG) (0x000F & (OPPMSG))
++
++/* Bridge Debug Commands */
++#define MBX_DBG_SYSPRINTF (MBX_DBG_CLASS + 0x0)
++
++/*
++ * Useful macros
++ */
++/* DSP-DMA channel */
++#define MBX_SETDDMAVAL(x, y) (MBX_DDMA_CLASS | (x << MBX_DDMA_BUFSHIFT) | \
++ (y << MBX_DDMA_CHNLSHIFT))
++
++/* Zero-Copy channel */
++#define MBX_SETZCPYVAL(x) (MBX_ZCPY_CLASS | (x << MBX_ZCPY_CHNLSHIFT))
++
++#endif /* _MBX_SH_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mem.h b/arch/arm/plat-omap/include/dspbridge/mem.h
+new file mode 100644
+index 0000000..535ac3a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mem.h
+@@ -0,0 +1,340 @@
++/*
++ * mem.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mem.h ========
++ * Purpose:
++ * Memory management and address mapping services for the DSP/BIOS Bridge
++ * class driver and mini-driver.
++ *
++ * Public Functions:
++ * MEM_Alloc
++ * MEM_AllocObject
++ * MEM_AllocPhysMem
++ * MEM_Calloc
++ * MEM_Exit
++ * MEM_FlushCache
++ * MEM_Free
++ * MEM_FreeObject
++ * MEM_FreePhysMem
++ * MEM_GetNumPages
++ * MEM_Init
++ * MEM_IsValidHandle
++ * MEM_LinearAddress
++ * MEM_PageLock
++ * MEM_PageUnlock
++ * MEM_UnMapLinearAddress
++ * MEM_VirtualToPhysical
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
++ *! 01-Sep-2001 ag: Cleaned up notes for MEM_LinearAddress() does not
++ *! require phys address to be page aligned!
++ *! 02-Dec-1999 rr: stdwin.h included for retail build
++ *! 12-Nov-1999 kc: Added warning about use of MEM_LinearAddress.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 07-Jan-1998 gp: Added MEM_AllocUMB and MEM_UMBFree for User Mapped Buffers
++ *! used by WMD_CHNL.
++ *! 23-Dec-1997 cr: Code review cleanup, removed dead Ring 3 code.
++ *! 04-Aug-1997 cr: Added explicit CDECL identifiers.
++ *! 01-Nov-1996 gp: Updated based on code review.
++ *! 04-Sep-1996 gp: Added MEM_PageLock() and MEM_PageUnlock() services.
++ *! 14-Aug-1996 mg: Added MEM_GetPhysAddr() and MEM_GetNumPages()
++ *! 25-Jul-1996 gp: Added MEM_IsValidHandle() macro.
++ *! 10-May-1996 gp: Added MEM_Calloc().
++ *! 25-Apr-1996 gp: Added MEM_PhysicalAddress()
++ *! 17-Apr-1996 gp: Added MEM_Exit function; updated to latest naming standard.
++ *! 08-Apr-1996 gp: Created.
++ */
++
++#ifndef MEM_
++#define MEM_
++
++#include <dspbridge/host_os.h>
++#include <dspbridge/memdefs.h>
++
++/*
++ * ======== MEM_Alloc ========
++ * Purpose:
++ * Allocate memory from the paged or non-paged pools.
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * type: Type of memory to allocate; one of:
++ * MEM_PAGED: Allocate from pageable memory.
++ * MEM_NONPAGED: Allocate from page locked memory.
++ * Returns:
++ * Pointer to a block of memory;
++ * NULL if memory couldn't be allocated, if cBytes == 0, or if type is
++ * not one of MEM_PAGED or MEM_NONPAGED.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested.
++ */
++ extern void *MEM_Alloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
++
++/*
++ * ======== MEM_AllocObject ========
++ * Purpose:
++ * Allocate an object, and set it's signature.
++ * Parameters:
++ * pObj: Pointer to the new object.
++ * Obj: Type of the object to allocate.
++ * Signature: Magic field value. Must be non-zero.
++ * Returns:
++ * Requires:
++ * Same requirements as MEM_Calloc(); and
++ * The object structure has a dwSignature field. The compiler ensures
++ * this requirement.
++ * Ensures:
++ * A subsequent call to MEM_IsValidHandle() will succeed for this object.
++ */
++#define MEM_AllocObject(pObj, Obj, Signature) \
++{ \
++ pObj = MEM_Calloc(sizeof(Obj), MEM_NONPAGED); \
++ if (pObj) { \
++ pObj->dwSignature = Signature; \
++ } \
++}
++
++/* ======== MEM_AllocPhysMem ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * ulAlign: Alignment Mask.
++ * pPhysicalAddress: Physical address of allocated memory.
++ * Returns:
++ * Pointer to a block of memory;
++ * NULL if memory couldn't be allocated, or if cBytes == 0.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block of
++ * the size requested. Returned physical address refers to physical
++ * location of memory.
++ */
++ extern void *MEM_AllocPhysMem(IN u32 cBytes,
++ IN u32 ulAlign,
++ OUT u32 *pPhysicalAddress);
++
++/*
++ * ======== MEM_Calloc ========
++ * Purpose:
++ * Allocate zero-initialized memory from the paged or non-paged pools.
++ * Parameters:
++ * cBytes: Number of bytes to allocate.
++ * type: Type of memory to allocate; one of:
++ * MEM_PAGED: Allocate from pageable memory.
++ * MEM_NONPAGED: Allocate from page locked memory.
++ * Returns:
++ * Pointer to a block of zeroed memory;
++ * NULL if memory couldn't be allocated, if cBytes == 0, or if type is
++ * not one of MEM_PAGED or MEM_NONPAGED.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * The returned pointer, if not NULL, points to a valid memory block
++ * of the size requested.
++ */
++ extern void *MEM_Calloc(IN u32 cBytes, IN enum MEM_POOLATTRS type);
++
++/*
++ * ======== MEM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MEM is initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void MEM_Exit(void);
++
++/*
++ * ======== MEM_FlushCache ========
++ * Purpose:
++ * Performs system cache sync with discard
++ * Parameters:
++ * pMemBuf: Pointer to memory region to be flushed.
++ * pMemBuf: Size of the memory region to be flushed.
++ * Returns:
++ * Requires:
++ * MEM is initialized.
++ * Ensures:
++ * Cache is synchronized
++ */
++ extern void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType);
++
++/*
++ * ======== MEM_Free ========
++ * Purpose:
++ * Free the given block of system memory.
++ * Parameters:
++ * pMemBuf: Pointer to memory allocated by MEM_Calloc/Alloc().
++ * Returns:
++ * Requires:
++ * MEM initialized.
++ * pMemBuf is a valid memory address returned by MEM_Calloc/Alloc().
++ * Ensures:
++ * pMemBuf is no longer a valid pointer to memory.
++ */
++ extern void MEM_Free(IN void *pMemBuf);
++
++/*
++ * ======== MEM_FreePhysMem ========
++ * Purpose:
++ * Free the given block of physically contiguous memory.
++ * Parameters:
++ * pVirtualAddress: Pointer to virtual memory region allocated
++ * by MEM_AllocPhysMem().
++ * pPhysicalAddress: Pointer to physical memory region allocated
++ * by MEM_AllocPhysMem().
++ * cBytes: Size of the memory region allocated by MEM_AllocPhysMem().
++ * Returns:
++ * Requires:
++ * MEM initialized.
++ * pVirtualAddress is a valid memory address returned by
++ * MEM_AllocPhysMem()
++ * Ensures:
++ * pVirtualAddress is no longer a valid pointer to memory.
++ */
++ extern void MEM_FreePhysMem(void *pVirtualAddress,
++ u32 pPhysicalAddress, u32 cBytes);
++
++/*
++ * ======== MEM_FreeObject ========
++ * Purpose:
++ * Utility macro to invalidate an object's signature, and deallocate it.
++ * Parameters:
++ * pObj: Pointer to the object to free.
++ * Returns:
++ * Requires:
++ * Same requirements as MEM_Free().
++ * Ensures:
++ * A subsequent call to MEM_IsValidHandle() will fail for this object.
++ */
++#define MEM_FreeObject(pObj) \
++{ \
++ pObj->dwSignature = 0x00; \
++ MEM_Free(pObj); \
++}
++
++/*
++ * ======== MEM_GetNumPages ========
++ * Purpose:
++ * Calculate the number of pages corresponding to the supplied buffer.
++ * Parameters:
++ * pAddr: Linear (virtual) address of the buffer.
++ * cBytes: Number of bytes in the buffer.
++ * Returns:
++ * Number of pages.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * If cBytes > 0, number of pages returned > 0.
++ */
++ extern s32 MEM_GetNumPages(IN void *pAddr, IN u32 cBytes);
++
++/*
++ * ======== MEM_Init ========
++ * Purpose:
++ * Initializes private state of MEM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * MEM initialized.
++ */
++ extern bool MEM_Init(void);
++
++/*
++ * ======== MEM_IsValidHandle ========
++ * Purpose:
++ * Validate the object handle.
++ * Parameters:
++ * hObj: Handle to object created with MEM_AllocObject().
++ * Sig: Expected signature u32.
++ * Returns:
++ * TRUE if handle is valid; FALSE otherwise.
++ * Requires:
++ * The object structure has a dwSignature field. Ensured by compiler.
++ * Ensures:
++ */
++#define MEM_IsValidHandle(hObj, Sig) \
++ ((hObj != NULL) && (hObj->dwSignature == Sig))
++
++/*
++ * ======== MEM_LinearAddress ========
++ * Purpose:
++ * Get the linear address corresponding to the given physical address.
++ * Parameters:
++ * pPhysAddr: Physical address to be mapped.
++ * cBytes: Number of bytes in physical range to map.
++ * Returns:
++ * The corresponding linear address, or NULL if unsuccessful.
++ * Requires:
++ * MEM initialized.
++ * Ensures:
++ * Notes:
++ * If valid linear address is returned, be sure to call
++ * MEM_UnmapLinearAddress().
++ */
++#define MEM_LinearAddress(pPhyAddr, cBytes) pPhyAddr
++
++/*
++ * ======== MEM_UnmapLinearAddress ========
++ * Purpose:
++ * Unmap the linear address mapped in MEM_LinearAddress.
++ * Parameters:
++ * pBaseAddr: Ptr to mapped memory (as returned by MEM_LinearAddress()).
++ * Returns:
++ * Requires:
++ * - MEM initialized.
++ * - pBaseAddr is a valid linear address mapped in MEM_LinearAddress.
++ * Ensures:
++ * - pBaseAddr no longer points to a valid linear address.
++ */
++#define MEM_UnmapLinearAddress(pBaseAddr)
++
++/*
++ * ======== MEM_ExtPhysPoolInit ========
++ * Purpose:
++ * Uses the physical memory chunk passed for internal consitent memory
++ * allocations.
++ * physical address based on the page frame address.
++ * Parameters:
++ * poolPhysBase starting address of the physical memory pool.
++ * poolSize size of the physical memory pool.
++ * Returns:
++ * none.
++ * Requires:
++ * - MEM initialized.
++ * - valid physical address for the base and size > 0
++ */
++ extern void MEM_ExtPhysPoolInit(IN u32 poolPhysBase,
++ IN u32 poolSize);
++
++#endif /* MEM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/memdefs.h b/arch/arm/plat-omap/include/dspbridge/memdefs.h
+new file mode 100644
+index 0000000..a5bb259
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/memdefs.h
+@@ -0,0 +1,52 @@
++/*
++ * memdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== memdefs.h ========
++ * Purpose:
++ * Global MEM constants and types, shared between WSX, WCD, and WMD.
++ *
++ *! Revision History:
++ *! ================
++ *! 28-Aug-2001 ag: Added MEM_[SET][GET]VIRTUALSEGID.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 15-Nov-1996 gp: Renamed from wsxmem.h and moved to kwinos.
++ *! 21-Aug-1996 cr: Created from mem.h.
++ */
++
++#ifndef MEMDEFS_
++#define MEMDEFS_
++
++/* Memory Pool Attributes: */
++ enum MEM_POOLATTRS {
++ MEM_PAGED = 0,
++ MEM_NONPAGED = 1,
++ MEM_LARGEVIRTMEM = 2
++ } ;
++
++/*
++ * MEM_VIRTUALSEGID is used by Node & Strm to access virtual address space in
++ * the correct client process context.
++ */
++#define MEM_SETVIRTUALSEGID 0x10000000
++#define MEM_GETVIRTUALSEGID 0x20000000
++#define MEM_MASKVIRTUALSEGID (MEM_SETVIRTUALSEGID | MEM_GETVIRTUALSEGID)
++
++#define TO_VIRTUAL_UNCACHED(x) x
++#define INTREG_TO_VIRTUAL_UNCACHED(x) x
++
++#endif /* MEMDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mgr.h b/arch/arm/plat-omap/include/dspbridge/mgr.h
+new file mode 100644
+index 0000000..24c4472
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mgr.h
+@@ -0,0 +1,234 @@
++/*
++ * mgr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgr.h ========
++ * Description:
++ * This is the Class driver RM module interface.
++ *
++ * Public Functions:
++ * MGR_Create
++ * MGR_Destroy
++ * MGR_EnumNodeInfo
++ * MGR_EnumProcessorInfo
++ * MGR_Exit
++ * MGR_GetDCDHandle
++ * MGR_Init
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Oct-2002 kc: Removed legacy PERF definitions.
++ *! 11-Jul-2001 jeh Added CFG_HDEVNODE parameter to MGR_Create().
++ *! 22-Nov-2000 kc: Added MGR_GetPerfData for acquiring PERF stats.
++ *! 03-Nov-2000 rr: Added MGR_GetDCDHandle. Modified after code review.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 14-Aug-2000 rr: Cleaned up.
++ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
++ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types).
++ *! 20-Jun-2000 rr: Created.
++ */
++
++#ifndef MGR_
++#define MGR_
++
++#include <dspbridge/mgrpriv.h>
++
++#define MAX_EVENTS 32
++
++/*
++ * ======== MGR_WaitForBridgeEvents ========
++ * Purpose:
++ * Block on any Bridge event(s)
++ * Parameters:
++ * aNotifications : array of pointers to notification objects.
++ * uCount : number of elements in above array
++ * puIndex : index of signaled event object
++ * uTimeout : timeout interval in milliseocnds
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_ETIMEOUT : Wait timed out. *puIndex is undetermined.
++ * Details:
++ */
++
++ DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION
++ **aNotifications,
++ u32 uCount, OUT u32 *puIndex,
++ u32 uTimeout);
++
++/*
++ * ======== MGR_Create ========
++ * Purpose:
++ * Creates the Manager Object. This is done during the driver loading.
++ * There is only one Manager Object in the DSP/BIOS Bridge.
++ * Parameters:
++ * phMgrObject: Location to store created MGR Object handle.
++ * hDevNode: Device object as known to Windows system.
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EMEMORY: Failed to Create the Object
++ * DSP_EFAIL: General Failure
++ * Requires:
++ * MGR Initialized (cRefs > 0 )
++ * phMgrObject != NULL.
++ * Ensures:
++ * DSP_SOK: *phMgrObject is a valid MGR interface to the device.
++ * MGR Object stores the DCD Manager Handle.
++ * MGR Object stored in the Regsitry.
++ * !DSP_SOK: MGR Object not created
++ * Details:
++ * DCD Dll is loaded and MGR Object stores the handle of the DLL.
++ */
++ extern DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **hMgrObject,
++ struct CFG_DEVNODE *hDevNode);
++
++/*
++ * ======== MGR_Destroy ========
++ * Purpose:
++ * Destroys the MGR object. Called upon driver unloading.
++ * Parameters:
++ * hMgrObject: Handle to Manager object .
++ * Returns:
++ * DSP_SOK: Success.
++ * DCD Manager freed; MGR Object destroyed;
++ * MGR Object deleted from the Registry.
++ * DSP_EFAIL: Failed to destroy MGR Object
++ * Requires:
++ * MGR Initialized (cRefs > 0 )
++ * hMgrObject is a valid MGR handle .
++ * Ensures:
++ * DSP_SOK: MGR Object destroyed and hMgrObject is Invalid MGR
++ * Handle.
++ */
++ extern DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject);
++
++/*
++ * ======== MGR_EnumNodeInfo ========
++ * Purpose:
++ * Enumerate and get configuration information about nodes configured
++ * in the node database.
++ * Parameters:
++ * uNode: The node index (base 0).
++ * pNDBProps: Ptr to the DSP_NDBPROPS structure for output.
++ * uNDBPropsSize: Size of the DSP_NDBPROPS structure.
++ * puNumNodes: Location where the number of nodes configured
++ * in the database will be returned.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Parameter uNode is > than the number of nodes.
++ * configutred in the system
++ * DSP_ECHANGEDURINGENUM: During Enumeration there has been a change in
++ * the number of nodes configured or in the
++ * the properties of the enumerated nodes.
++ * DSP_EFAIL: Failed to querry the Node Data Base
++ * Requires:
++ * pNDBPROPS is not null
++ * uNDBPropsSize >= sizeof(DSP_NDBPROPS)
++ * puNumNodes is not null
++ * MGR Initialized (cRefs > 0 )
++ * Ensures:
++ * SUCCESS on successful retreival of data and *puNumNodes > 0 OR
++ * DSP_FAILED && *puNumNodes == 0.
++ * Details:
++ */
++ extern DSP_STATUS MGR_EnumNodeInfo(u32 uNode,
++ OUT struct DSP_NDBPROPS *pNDBProps,
++ u32 uNDBPropsSize,
++ OUT u32 *puNumNodes);
++
++/*
++ * ======== MGR_EnumProcessorInfo ========
++ * Purpose:
++ * Enumerate and get configuration information about available DSP
++ * processors
++ * Parameters:
++ * uProcessor: The processor index (zero-based).
++ * pProcessorInfo: Ptr to the DSP_PROCESSORINFO structure .
++ * uProcessorInfoSize: Size of DSP_PROCESSORINFO structure.
++ * puNumProcs: Location where the number of DSPs configured
++ * in the database will be returned
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EINVALIDARG: Parameter uProcessor is > than the number of
++ * DSP Processors in the system.
++ * DSP_EFAIL: Failed to querry the Node Data Base
++ * Requires:
++ * pProcessorInfo is not null
++ * puNumProcs is not null
++ * uProcessorInfoSize >= sizeof(DSP_PROCESSORINFO)
++ * MGR Initialized (cRefs > 0 )
++ * Ensures:
++ * SUCCESS on successful retreival of data and *puNumProcs > 0 OR
++ * DSP_FAILED && *puNumProcs == 0.
++ * Details:
++ */
++ extern DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
++ OUT struct DSP_PROCESSORINFO *
++ pProcessorInfo,
++ u32 uProcessorInfoSize,
++ OUT u32 *puNumProcs);
++/*
++ * ======== MGR_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MGR is initialized.
++ * Ensures:
++ * When reference count == 0, MGR's private resources are freed.
++ */
++ extern void MGR_Exit(void);
++
++/*
++ * ======== MGR_GetDCDHandle ========
++ * Purpose:
++ * Retrieves the MGR handle. Accessor Function
++ * Parameters:
++ * hMGRHandle: Handle to the Manager Object
++ * phDCDHandle: Ptr to receive the DCD Handle.
++ * Returns:
++ * DSP_SOK: Sucess
++ * DSP_EFAIL: Failure to get the Handle
++ * Requires:
++ * MGR is initialized.
++ * phDCDHandle != NULL
++ * Ensures:
++ * DSP_SOK and *phDCDHandle != NULL ||
++ * DSP_EFAIL and *phDCDHandle == NULL
++ */
++ extern DSP_STATUS MGR_GetDCDHandle(IN struct MGR_OBJECT
++ *hMGRHandle,
++ OUT u32 *phDCDHandle);
++
++/*
++ * ======== MGR_Init ========
++ * Purpose:
++ * Initialize MGR's private state, keeping a reference count on each
++ * call. Intializes the DCD.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public MGR functions.
++ */
++ extern bool MGR_Init(void);
++
++#endif /* MGR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/mgrpriv.h b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+new file mode 100644
+index 0000000..4a34086
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/mgrpriv.h
+@@ -0,0 +1,55 @@
++/*
++ * mgrpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgrpriv.h ========
++ * Description:
++ * Global MGR constants and types, shared by PROC, MGR, and WCD.
++ *
++ *! Revision History:
++ *! ================
++ *! 29-July-2001 ag: added MGR_PROCESSOREXTINFO.
++ *! 05-July-2000 rr: Created
++ */
++
++#ifndef MGRPRIV_
++#define MGRPRIV_
++
++/*
++ * OMAP1510 specific
++ */
++#define MGR_MAXTLBENTRIES 32
++
++/* RM MGR Object */
++ struct MGR_OBJECT;
++
++ struct MGR_TLBENTRY {
++ u32 ulDspVirt; /* DSP virtual address */
++ u32 ulGppPhys; /* GPP physical address */
++ } ;
++
++/*
++ * The DSP_PROCESSOREXTINFO structure describes additional extended
++ * capabilities of a DSP processor not exposed to user.
++ */
++ struct MGR_PROCESSOREXTINFO {
++ struct DSP_PROCESSORINFO tyBasic; /* user processor info */
++ /* private dsp mmu entries */
++ struct MGR_TLBENTRY tyTlb[MGR_MAXTLBENTRIES];
++ } ;
++
++#endif /* MGRPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/msg.h b/arch/arm/plat-omap/include/dspbridge/msg.h
+new file mode 100644
+index 0000000..f2872cc
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/msg.h
+@@ -0,0 +1,106 @@
++/*
++ * msg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg.h ========
++ * Description:
++ * DSP/BIOS Bridge MSG Module.
++ *
++ * Public Functions:
++ * MSG_Create
++ * MSG_Delete
++ * MSG_Exit
++ * MSG_Init
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 17-Nov-2000 jeh Removed MSG_Get, MSG_Put, MSG_CreateQueue,
++ *! MSG_DeleteQueue, and MSG_RegisterNotify, since these
++ *! are now part of mini-driver.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++#ifndef MSG_
++#define MSG_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * ======== MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object. The MSG manager must be created before
++ * the IO Manager.
++ * Parameters:
++ * phMsgMgr: Location to store MSG manager handle on output.
++ * hDevObject: The device object.
++ * msgCallback: Called whenever an RMS_EXIT message is received.
++ * Returns:
++ * Requires:
++ * MSG_Init(void) called.
++ * phMsgMgr != NULL.
++ * hDevObject != NULL.
++ * msgCallback != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++/*
++ * ======== MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in MSG_Create().
++ * Parameters:
++ * hMsgMgr: Handle returned from MSG_Create().
++ * Returns:
++ * Requires:
++ * MSG_Init(void) called.
++ * Valid hMsgMgr.
++ * Ensures:
++ */
++ extern void MSG_Delete(struct MSG_MGR *hMsgMgr);
++
++/*
++ * ======== MSG_Exit ========
++ * Purpose:
++ * Discontinue usage of MSG module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * MSG_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in MSG_Init(void) will be freed when last MSG
++ * client calls MSG_Exit(void).
++ */
++ extern void MSG_Exit(void);
++
++/*
++ * ======== MSG_Init ========
++ * Purpose:
++ * Initialize the MSG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool MSG_Init(void);
++
++#endif /* MSG_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/msgdefs.h b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
+new file mode 100644
+index 0000000..8ea4551
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/msgdefs.h
+@@ -0,0 +1,43 @@
++/*
++ * msgdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msgdefs.h ========
++ * Description:
++ * Global MSG constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 09-May-2001 jeh Removed MSG_TODSP, MSG_FROMDSP.
++ *! 17-Nov-2000 jeh Added MSGMGR_SIGNATURE.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++#ifndef MSGDEFS_
++#define MSGDEFS_
++
++#define MSGMGR_SIGNATURE 0x4d47534d /* "MGSM" */
++
++/* MSG Objects: */
++ struct MSG_MGR;
++ struct MSG_QUEUE;
++
++/* Function prototype for callback to be called on RMS_EXIT message received */
++ typedef void(*MSG_ONEXIT) (HANDLE h, s32 nStatus);
++
++#endif /* MSGDEFS_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/nldr.h b/arch/arm/plat-omap/include/dspbridge/nldr.h
+new file mode 100644
+index 0000000..0915846
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nldr.h
+@@ -0,0 +1,81 @@
++/*
++ * nldr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldr.h ========
++ *
++ * Description:
++ * DSP/BIOS Bridge dynamic loader interface. See the file dldrdefs.h
++ * for a description of these functions.
++ *
++ * Public Functions:
++ * NLDR_Allocate
++ * NLDR_Create
++ * NLDR_Delete
++ * NLDR_Exit
++ * NLDR_Free
++ * NLDR_GetFxnAddr
++ * NLDR_Init
++ * NLDR_Load
++ * NLDR_Unload
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 31-Jul-2002 jeh Removed function header comments.
++ *! 17-Apr-2002 jeh Created.
++ */
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/rmm.h>
++#include <dspbridge/nldrdefs.h>
++
++#ifndef NLDR_
++#define NLDR_
++
++ extern DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr,
++ void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS
++ *pNodeProps,
++ OUT struct NLDR_NODEOBJECT **phNldrNode,
++ IN bool *pfPhaseSplit);
++
++ extern DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS *pAttrs);
++
++ extern void NLDR_Delete(struct NLDR_OBJECT *hNldr);
++ extern void NLDR_Exit(void);
++ extern void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode);
++
++ extern DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode,
++ char *pstrFxn, u32 *pulAddr);
++
++ extern DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
++ OUT struct RMM_TargetObj
++ **phRmmMgr);
++
++ extern bool NLDR_Init(void);
++ extern DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++ extern DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++#endif /* NLDR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nldrdefs.h b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+new file mode 100644
+index 0000000..84b36a3
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nldrdefs.h
+@@ -0,0 +1,307 @@
++/*
++ * nldrdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldrdefs.h ========
++ * Description:
++ * Global Dynamic + static/overlay Node loader (NLDR) constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 07-Apr-2003 map Consolidated dldrdefs.h into nldrdefs.h
++ *! 05-Aug-2002 jeh Created.
++ */
++
++#ifndef NLDRDEFS_
++#define NLDRDEFS_
++
++#include <dspbridge/dbdcddef.h>
++#include <dspbridge/devdefs.h>
++
++#define NLDR_MAXPATHLENGTH 255
++/* NLDR Objects: */
++ struct NLDR_OBJECT;
++ struct NLDR_NODEOBJECT;
++
++/*
++ * ======== NLDR_LOADTYPE ========
++ * Load types for a node. Must match values in node.h55.
++ */
++ enum NLDR_LOADTYPE {
++ NLDR_STATICLOAD, /* Linked in base image, not overlay */
++ NLDR_DYNAMICLOAD, /* Dynamically loaded node */
++ NLDR_OVLYLOAD /* Linked in base image, overlay node */
++ } ;
++
++/*
++ * ======== NLDR_OVLYFXN ========
++ * Causes code or data to be copied from load address to run address. This
++ * is the "COD_WRITEFXN" that gets passed to the DBLL_Library and is used as
++ * the ZL write function.
++ *
++ * Parameters:
++ * pPrivRef: Handle to identify the node.
++ * ulDspRunAddr: Run address of code or data.
++ * ulDspLoadAddr: Load address of code or data.
++ * ulNumBytes: Number of (GPP) bytes to copy.
++ * nMemSpace: RMS_CODE or RMS_DATA.
++ * Returns:
++ * ulNumBytes: Success.
++ * 0: Failure.
++ * Requires:
++ * Ensures:
++ */
++ typedef u32(*NLDR_OVLYFXN) (void *pPrivRef, u32 ulDspRunAddr,
++ u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== NLDR_WRITEFXN ========
++ * Write memory function. Used for dynamic load writes.
++ * Parameters:
++ * pPrivRef: Handle to identify the node.
++ * ulDspAddr: Address of code or data.
++ * pBuf: Code or data to be written
++ * ulNumBytes: Number of (GPP) bytes to write.
++ * nMemSpace: DBLL_DATA or DBLL_CODE.
++ * Returns:
++ * ulNumBytes: Success.
++ * 0: Failure.
++ * Requires:
++ * Ensures:
++ */
++ typedef u32(*NLDR_WRITEFXN) (void *pPrivRef,
++ u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++/*
++ * ======== NLDR_ATTRS ========
++ * Attributes passed to NLDR_Create function.
++ */
++ struct NLDR_ATTRS {
++ NLDR_OVLYFXN pfnOvly;
++ NLDR_WRITEFXN pfnWrite;
++ u16 usDSPWordSize;
++ u16 usDSPMauSize;
++ } ;
++
++/*
++ * ======== NLDR_PHASE ========
++ * Indicates node create, delete, or execute phase function.
++ */
++ enum NLDR_PHASE {
++ NLDR_CREATE,
++ NLDR_DELETE,
++ NLDR_EXECUTE,
++ NLDR_NOPHASE
++ } ;
++
++/*
++ * Typedefs of loader functions imported from a DLL, or defined in a
++ * function table.
++ */
++
++/*
++ * ======== NLDR_Allocate ========
++ * Allocate resources to manage the loading of a node on the DSP.
++ *
++ * Parameters:
++ * hNldr: Handle of loader that will load the node.
++ * pPrivRef: Handle to identify the node.
++ * pNodeProps: Pointer to a DCD_NODEPROPS for the node.
++ * phNldrNode: Location to store node handle on output. This handle
++ * will be passed to NLDR_Load/NLDR_Unload.
++ * pfPhaseSplit: pointer to boolean variable referenced in node.c
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldr.
++ * pNodeProps != NULL.
++ * phNldrNode != NULL.
++ * Ensures:
++ * DSP_SOK: IsValidNode(*phNldrNode).
++ * error: *phNldrNode == NULL.
++ */
++ typedef DSP_STATUS(*NLDR_ALLOCATEFXN) (struct NLDR_OBJECT *hNldr,
++ void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS
++ *pNodeProps,
++ OUT struct NLDR_NODEOBJECT
++ **phNldrNode,
++ OUT bool *pfPhaseSplit);
++
++/*
++ * ======== NLDR_Create ========
++ * Create a loader object. This object handles the loading and unloading of
++ * create, delete, and execute phase functions of nodes on the DSP target.
++ *
++ * Parameters:
++ * phNldr: Location to store loader handle on output.
++ * hDevObject: Device for this processor.
++ * pAttrs: Loader attributes.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * Requires:
++ * NLDR_Init(void) called.
++ * phNldr != NULL.
++ * hDevObject != NULL.
++ * pAttrs != NULL.
++ * Ensures:
++ * DSP_SOK: Valid *phNldr.
++ * error: *phNldr == NULL.
++ */
++ typedef DSP_STATUS(*NLDR_CREATEFXN) (OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS
++ *pAttrs);
++
++/*
++ * ======== NLDR_Delete ========
++ * Delete the NLDR loader.
++ *
++ * Parameters:
++ * hNldr: Node manager object.
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldr.
++ * Ensures:
++ * hNldr invalid
++ */
++ typedef void(*NLDR_DELETEFXN) (struct NLDR_OBJECT *hNldr);
++
++/*
++ * ======== NLDR_Exit ========
++ * Discontinue usage of NLDR module.
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in NLDR_Init(void) will be freed when last NLDR
++ * client calls NLDR_Exit(void).
++ */
++ typedef void(*NLDR_EXITFXN) (void);
++
++/*
++ * ======== NLDR_Free ========
++ * Free resources allocated in NLDR_Allocate.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * Returns:
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef void(*NLDR_FREEFXN) (struct NLDR_NODEOBJECT *hNldrNode);
++
++/*
++ * ======== NLDR_GetFxnAddr ========
++ * Get address of create, delete, or execute phase function of a node on
++ * the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * pstrFxn: Name of function.
++ * pulAddr: Location to store function address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ESYMBOL: Address of function not found.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * pulAddr != NULL;
++ * pstrFxn != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_GETFXNADDRFXN) (struct NLDR_NODEOBJECT
++ *hNldrNode,
++ char *pstrFxn, u32 *pulAddr);
++
++/*
++ * ======== NLDR_Init ========
++ * Initialize the NLDR module.
++ *
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ typedef bool(*NLDR_INITFXN) (void);
++
++/*
++ * ======== NLDR_Load ========
++ * Load create, delete, or execute phase function of a node on the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * phase: Type of function to load (create, delete, or execute).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EOVERLAYMEMORY: Can't overlay phase because overlay memory
++ * is already in use.
++ * DSP_EDYNLOAD: Failure in dynamic loader library.
++ * DSP_EFWRITE: Failed to write phase's code or date to target.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_LOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++/*
++ * ======== NLDR_Unload ========
++ * Unload create, delete, or execute phase function of a node on the DSP.
++ *
++ * Parameters:
++ * hNldrNode: Handle returned from NLDR_Allocate().
++ * phase: Node function to unload (create, delete, or execute).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * Requires:
++ * NLDR_Init(void) called.
++ * Valid hNldrNode.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*NLDR_UNLOADFXN) (struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++
++/*
++ * ======== NLDR_FXNS ========
++ */
++ struct NLDR_FXNS {
++ NLDR_ALLOCATEFXN pfnAllocate;
++ NLDR_CREATEFXN pfnCreate;
++ NLDR_DELETEFXN pfnDelete;
++ NLDR_EXITFXN pfnExit;
++ NLDR_FREEFXN pfnFree;
++ NLDR_GETFXNADDRFXN pfnGetFxnAddr;
++ NLDR_INITFXN pfnInit;
++ NLDR_LOADFXN pfnLoad;
++ NLDR_UNLOADFXN pfnUnload;
++ } ;
++
++#endif /* NLDRDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/node.h b/arch/arm/plat-omap/include/dspbridge/node.h
+new file mode 100644
+index 0000000..d253962
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/node.h
+@@ -0,0 +1,619 @@
++/*
++ * node.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== node.h ========
++ * Description:
++ * DSP/BIOS Bridge Node Manager.
++ *
++ * Public Functions:
++ * NODE_Allocate
++ * NODE_AllocMsgBuf
++ * NODE_ChangePriority
++ * NODE_Connect
++ * NODE_Create
++ * NODE_CreateMgr
++ * NODE_Delete
++ * NODE_DeleteMgr
++ * NODE_EnumNodes
++ * NODE_Exit
++ * NODE_FreeMsgBuf
++ * NODE_GetAttr
++ * NODE_GetMessage
++ * NODE_GetProcessor
++ * NODE_Init
++ * NODE_OnExit
++ * NODE_Pause
++ * NODE_PutMessage
++ * NODE_RegisterNotify
++ * NODE_Run
++ * NODE_Terminate
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 23-Apr-2001 jeh Updated with code review changes.
++ *! 16-Jan-2001 jeh Added DSP_ESYMBOL, DSP_EUUID to return codes.
++ *! 17-Nov-2000 jeh Added NODE_OnExit().
++ *! 27-Oct-2000 jeh Added timeouts to NODE_GetMessage, NODE_PutMessage.
++ *! 12-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Removed
++ *! NODE_RegisterAllNodes().
++ *! 07-Sep-2000 jeh Changed type HANDLE in NODE_RegisterNotify to
++ *! DSP_HNOTIFICATION. Added DSP_STRMATTR param to
++ *! NODE_Connect(). Removed NODE_GetMessageStream().
++ *! 17-Jul-2000 jeh Updated function header descriptions.
++ *! 19-Jun-2000 jeh Created.
++ */
++
++#ifndef NODE_
++#define NODE_
++
++#include <dspbridge/procpriv.h>
++
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/dispdefs.h>
++#include <dspbridge/nldrdefs.h>
++
++/*
++ * ======== NODE_Allocate ========
++ * Purpose:
++ * Allocate GPP resources to manage a node on the DSP.
++ * Parameters:
++ * hProcessor: Handle of processor that is allocating the node.
++ * pNodeId: Pointer to a DSP_UUID for the node.
++ * pArgs: Optional arguments to be passed to the node.
++ * pAttrIn: Optional pointer to node attributes (priority,
++ * timeout...)
++ * phNode: Location to store node handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EUUID: Node UUID has not been registered.
++ * DSP_ESYMBOL: iAlg functions not found for a DAIS node.
++ * DSP_ERANGE: pAttrIn != NULL and pAttrIn->iPriority out of
++ * range.
++ * DSP_EFAIL: A failure occured, unable to allocate node.
++ * DSP_EWRONGSTATE: Proccessor is not in the running state.
++ * Requires:
++ * NODE_Init(void) called.
++ * hProcessor != NULL.
++ * pNodeId != NULL.
++ * phNode != NULL.
++ * Ensures:
++ * DSP_SOK: IsValidNode(*phNode).
++ * error: *phNode == NULL.
++ */
++ extern DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OPTIONAL IN CONST struct DSP_CBDATA
++ *pArgs,
++ OPTIONAL IN CONST struct DSP_NODEATTRIN
++ *pAttrIn,
++ OUT struct NODE_OBJECT **phNode);
++
++/*
++ * ======== NODE_AllocMsgBuf ========
++ * Purpose:
++ * Allocate and Prepare a buffer whose descriptor will be passed to a
++ * Node within a (DSP_MSG)message
++ * Parameters:
++ * hNode: The node handle.
++ * uSize: The size of the buffer to be allocated.
++ * pAttr: Pointer to a DSP_BUFFERATTR structure.
++ * pBuffer: Location to store the address of the allocated
++ * buffer on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid node handle.
++ * DSP_EMEMORY: Insufficent memory.
++ * DSP_EFAIL: General Failure.
++ * DSP_ESIZE: Invalid Size.
++ * Requires:
++ * NODE_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_AllocMsgBuf(struct NODE_OBJECT *hNode,
++ u32 uSize,
++ OPTIONAL struct DSP_BUFFERATTR
++ *pAttr,
++ OUT u8 **pBuffer);
++
++/*
++ * ======== NODE_ChangePriority ========
++ * Purpose:
++ * Change the priority of an allocated node.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate.
++ * nPriority: New priority level to set node's priority to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ERANGE: nPriority is out of range.
++ * DSP_ENODETYPE: The specified node is not a task node.
++ * DSP_EWRONGSTATE: Node is not in the NODE_ALLOCATED, NODE_PAUSED,
++ * or NODE_RUNNING state.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_ERESTART: A critical error has occurred and the DSP is
++ * being restarted.
++ * DSP_EFAIL: Unable to change node's runtime priority level.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ * DSP_SOK && (Node's current priority == nPriority)
++ */
++ extern DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode,
++ s32 nPriority);
++
++/*
++ * ======== NODE_CloseOrphans ========
++ * Purpose:
++ * Delete all nodes whose owning processor is being destroyed.
++ * Parameters:
++ * hNodeMgr: Node manager object.
++ * hProc: Handle to processor object being destroyed.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to delete all nodes belonging to hProc.
++ * Requires:
++ * Valid hNodeMgr.
++ * hProc != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_CloseOrphans(struct NODE_MGR *hNodeMgr,
++ struct PROC_OBJECT *hProc);
++
++/*
++ * ======== NODE_Connect ========
++ * Purpose:
++ * Connect two nodes on the DSP, or a node on the DSP to the GPP. In the
++ * case that the connnection is being made between a node on the DSP and
++ * the GPP, one of the node handles (either hNode1 or hNode2) must be
++ * the constant NODE_HGPPNODE.
++ * Parameters:
++ * hNode1: Handle of first node to connect to second node. If
++ * this is a connection from the GPP to hNode2, hNode1
++ * must be the constant NODE_HGPPNODE. Otherwise, hNode1
++ * must be a node handle returned from a successful call
++ * to Node_Allocate().
++ * hNode2: Handle of second node. Must be either NODE_HGPPNODE
++ * if this is a connection from DSP node to GPP, or a
++ * node handle returned from a successful call to
++ * NODE_Allocate().
++ * uStream1: Output stream index on first node, to be connected
++ * to second node's input stream. Value must range from
++ * 0 <= uStream1 < number of output streams.
++ * uStream2: Input stream index on second node. Value must range
++ * from 0 <= uStream2 < number of input streams.
++ * pAttrs: Stream attributes (NULL ==> use defaults).
++ * pConnParam: A pointer to a DSP_CBDATA structure that defines
++ * connection parameter for device nodes to pass to DSP
++ * side.
++ * If the value of this parameter is NULL, then this API
++ * behaves like DSPNode_Connect. This parameter will have
++ * length of the string and the null terminated string in
++ * DSP_CBDATA struct. This can be extended in future tp
++ * pass binary data.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode1 or hNode2.
++ * DSP_EMEMORY: Insufficient host memory.
++ * DSP_EVALUE: A stream index parameter is invalid.
++ * DSP_EALREADYCONNECTED: A connection already exists for one of the
++ * indices uStream1 or uStream2.
++ * DSP_EWRONGSTATE: Either hNode1 or hNode2 is not in the
++ * NODE_ALLOCATED state.
++ * DSP_ENOMORECONNECTIONS: No more connections available.
++ * DSP_EFAIL: Attempt to make an illegal connection (eg,
++ * Device node to device node, or device node to
++ * GPP), the two nodes are on different DSPs.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1,
++ u32 uStream1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream2,
++ OPTIONAL IN struct DSP_STRMATTR *pAttrs,
++ OPTIONAL IN struct DSP_CBDATA
++ *pConnParam);
++
++/*
++ * ======== NODE_Create ========
++ * Purpose:
++ * Create a node on the DSP by remotely calling the node's create
++ * function. If necessary, load code that contains the node's create
++ * function.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ESYMBOL: Create function not found in the COFF file.
++ * DSP_EWRONGSTATE: Node is not in the NODE_ALLOCATED state.
++ * DSP_EMEMORY: Memory allocation failure on the DSP.
++ * DSP_ETASK: Unable to create node's task or process on the DSP.
++ * DSP_ESTREAM: Stream creation failure on the DSP.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EUSER1-16: A user-defined failure occurred on the DSP.
++ * DSP_EFAIL: A failure occurred, unable to create node.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_CreateMgr ========
++ * Purpose:
++ * Create a NODE Manager object. This object handles the creation,
++ * deletion, and execution of nodes on the DSP target. The NODE Manager
++ * also maintains a pipe map of used and available node connections.
++ * Each DEV object should have exactly one NODE Manager object.
++ *
++ * Parameters:
++ * phNodeMgr: Location to store node manager handle on output.
++ * hDevObject: Device for this processor.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * NODE_Init(void) called.
++ * phNodeMgr != NULL.
++ * hDevObject != NULL.
++ * Ensures:
++ * DSP_SOK: Valide *phNodeMgr.
++ * error: *phNodeMgr == NULL.
++ */
++ extern DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== NODE_Delete ========
++ * Purpose:
++ * Delete resources allocated in NODE_Allocate(). If the node was
++ * created, delete the node on the DSP by remotely calling the node's
++ * delete function. Loads the node's delete function if necessary.
++ * GPP side resources are freed after node's delete function returns.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EDELETE: A deletion failure occurred.
++ * DSP_EUSER1-16: Node specific failure occurred on the DSP.
++ * DSP_EFAIL: A failure occurred in deleting the node.
++ * DSP_ESYMBOL: Delete function not found in the COFF file.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ * DSP_SOK: hNode is invalid.
++ */
++ extern DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_DeleteMgr ========
++ * Purpose:
++ * Delete the NODE Manager.
++ * Parameters:
++ * hNodeMgr: Node manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * Requires:
++ * NODE_Init(void) called.
++ * Valid hNodeMgr.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr);
++
++/*
++ * ======== NODE_EnumNodes ========
++ * Purpose:
++ * Enumerate the nodes currently allocated for the DSP.
++ * Parameters:
++ * hNodeMgr: Node manager returned from NODE_CreateMgr().
++ * aNodeTab: Array to copy node handles into.
++ * uNodeTabSize: Number of handles that can be written to aNodeTab.
++ * puNumNodes: Location where number of node handles written to
++ * aNodeTab will be written.
++ * puAllocated: Location to write total number of allocated nodes.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ESIZE: aNodeTab is too small to hold all node handles.
++ * Requires:
++ * Valid hNodeMgr.
++ * aNodeTab != NULL || uNodeTabSize == 0.
++ * puNumNodes != NULL.
++ * puAllocated != NULL.
++ * Ensures:
++ * - (DSP_ESIZE && *puNumNodes == 0)
++ * - || (DSP_SOK && *puNumNodes <= uNodeTabSize) &&
++ * (*puAllocated == *puNumNodes)
++ */
++ extern DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr,
++ IN DSP_HNODE *aNodeTab,
++ u32 uNodeTabSize,
++ OUT u32 *puNumNodes,
++ OUT u32 *puAllocated);
++
++/*
++ * ======== NODE_Exit ========
++ * Purpose:
++ * Discontinue usage of NODE module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NODE_Init(void) successfully called before.
++ * Ensures:
++ * Any resources acquired in NODE_Init(void) will be freed when last NODE
++ * client calls NODE_Exit(void).
++ */
++ extern void NODE_Exit(void);
++
++/*
++ * ======== NODE_FreeMsgBuf ========
++ * Purpose:
++ * Free a message buffer previously allocated with NODE_AllocMsgBuf.
++ * Parameters:
++ * hNode: The node handle.
++ * pBuffer: (Address) Buffer allocated by NODE_AllocMsgBuf.
++ * pAttr: Same buffer attributes passed to NODE_AllocMsgBuf.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid node handle.
++ * DSP_EFAIL: Failure to free the buffer.
++ * Requires:
++ * NODE_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode,
++ IN u8 *pBuffer,
++ OPTIONAL struct DSP_BUFFERATTR
++ *pAttr);
++
++/*
++ * ======== NODE_GetAttr ========
++ * Purpose:
++ * Copy the current attributes of the specified node into a DSP_NODEATTR
++ * structure.
++ * Parameters:
++ * hNode: Node object allocated from NODE_Allocate().
++ * pAttr: Pointer to DSP_NODEATTR structure to copy node's
++ * attributes.
++ * uAttrSize: Size of pAttr.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Requires:
++ * NODE_Init(void) called.
++ * pAttr != NULL.
++ * Ensures:
++ * DSP_SOK: *pAttrs contains the node's current attributes.
++ */
++ extern DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
++ OUT struct DSP_NODEATTR *pAttr,
++ u32 uAttrSize);
++
++/*
++ * ======== NODE_GetMessage ========
++ * Purpose:
++ * Retrieve a message from a node on the DSP. The node must be either a
++ * message node, task node, or XDAIS socket node.
++ * If a message is not available, this function will block until a
++ * message is available, or the node's timeout value is reached.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * pMessage: Pointer to DSP_MSG structure to copy the
++ * message into.
++ * uTimeout: Timeout in milliseconds to wait for message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Cannot retrieve messages from this type of node.
++ * DSP_ETIMEOUT: Timeout occurred and no message is available.
++ * DSP_EFAIL: Error occurred while trying to retrieve a message.
++ * Requires:
++ * NODE_Init(void) called.
++ * pMessage != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode,
++ OUT struct DSP_MSG *pMessage,
++ u32 uTimeout);
++
++/*
++ * ======== NODE_GetNldrObj ========
++ * Purpose:
++ * Retrieve the Nldr manager
++ * Parameters:
++ * hNodeMgr: Node Manager
++ * phNldrObj: Pointer to a Nldr manager handle
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
++ OUT struct NLDR_OBJECT **phNldrObj);
++
++/*
++ * ======== NODE_Init ========
++ * Purpose:
++ * Initialize the NODE module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool NODE_Init(void);
++
++/*
++ * ======== NODE_OnExit ========
++ * Purpose:
++ * Gets called when RMS_EXIT is received for a node. PROC needs to pass
++ * this function as a parameter to MSG_Create(). This function then gets
++ * called by the mini-driver when an exit message for a node is received.
++ * Parameters:
++ * hNode: Handle of the node that the exit message is for.
++ * nStatus: Return status of the node's execute phase.
++ * Returns:
++ * Ensures:
++ */
++ void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus);
++
++/*
++ * ======== NODE_Pause ========
++ * Purpose:
++ * Suspend execution of a node currently running on the DSP.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Node is not a task or socket node.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EWRONGSTSATE: Node is not in NODE_RUNNING state.
++ * DSP_EFAIL: Failed to pause node.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_PutMessage ========
++ * Purpose:
++ * Send a message to a message node, task node, or XDAIS socket node.
++ * This function will block until the message stream can accommodate
++ * the message, or a timeout occurs. The message will be copied, so Msg
++ * can be re-used immediately after return.
++ * Parameters:
++ * hNode: Node handle returned by NODE_Allocate().
++ * pMsg: Location of message to be sent to the node.
++ * uTimeout: Timeout in msecs to wait.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Messages can't be sent to this type of node.
++ * DSP_ETIMEOUT: Timeout occurred before message could be set.
++ * DSP_EWRONGSTATE: Node is in invalid state for sending messages.
++ * DSP_EFAIL: Unable to send message.
++ * Requires:
++ * NODE_Init(void) called.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== NODE_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this node.
++ * Parameters:
++ * hNode: Node handle returned by NODE_Allocate().
++ * uEventMask: Mask of types of events to be notified about.
++ * uNotifyType: Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EVALUE: uEventMask is invalid.
++ * DSP_ENOTIMPL: Notification type specified by uNotifyType is not
++ * supported.
++ * Requires:
++ * NODE_Init(void) called.
++ * hNotification != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== NODE_Run ========
++ * Purpose:
++ * Start execution of a node's execute phase, or resume execution of
++ * a node that has been suspended (via NODE_Pause()) on the DSP. Load
++ * the node's execute function if necessary.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: hNode doesn't represent a message, task or dais
++ * socket node.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_EWRONGSTSATE: Node is not in NODE_PAUSED or NODE_CREATED state.
++ * DSP_EFAIL: Unable to start or resume execution.
++ * DSP_ESYMBOL: Execute function not found in the COFF file.
++ * Requires:
++ * NODE_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_Terminate ========
++ * Purpose:
++ * Signal a node running on the DSP that it should exit its execute
++ * phase function.
++ * Parameters:
++ * hNode: Node object representing a node currently
++ * running on the DSP.
++ * pStatus: Location to store execute-phase function return
++ * value (DSP_EUSER1-16).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ETIMEOUT: A timeout occurred before the DSP responded.
++ * DSP_ENODETYPE: Type of node specified cannot be terminated.
++ * DSP_EWRONGSTATE: Operation not valid for the current node state.
++ * DSP_EFAIL: Unable to terminate the node.
++ * Requires:
++ * NODE_Init(void) called.
++ * pStatus != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode,
++ OUT DSP_STATUS *pStatus);
++
++
++
++/*
++ * ======== NODE_GetUUIDProps ========
++ * Purpose:
++ * Fetch Node properties given the UUID
++ * Parameters:
++ *
++ */
++ extern DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OUT struct DSP_NDBPROPS
++ *pNodeProps);
++
++#endif /* NODE_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nodedefs.h b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
+new file mode 100644
+index 0000000..cdc0c4b
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nodedefs.h
+@@ -0,0 +1,40 @@
++/*
++ * nodedefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nodedefs.h ========
++ * Description:
++ * Global NODE constants and types, shared by PROCESSOR, NODE, and DISP.
++ *
++ *! Revision History
++ *! ================
++ *! 23-Apr-2001 jeh Removed NODE_MGRATTRS.
++ *! 21-Sep-2000 jeh Removed NODE_TYPE enum.
++ *! 17-Jul-2000 jeh Changed order of node types to match rms_sh.h.
++ *! 20-Jun-2000 jeh Created.
++ */
++
++#ifndef NODEDEFS_
++#define NODEDEFS_
++
++#define NODE_SUSPENDEDPRI -1
++
++/* NODE Objects: */
++ struct NODE_MGR;
++ struct NODE_OBJECT;
++
++#endif /* NODEDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/nodepriv.h b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
+new file mode 100644
+index 0000000..d28b29b
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/nodepriv.h
+@@ -0,0 +1,202 @@
++/*
++ * nodepriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== nodepriv.h ========
++ * Description:
++ * Private node header shared by NODE and DISP.
++ *
++ * Public Functions:
++ * NODE_GetChannelId
++ * NODE_GetStrmMgr
++ * NODE_GetTimeout
++ * NODE_GetType
++ * NODE_GetLoadType
++ *
++ *! Revision History
++ *! ================
++ *! 19-Nov-2002 map Added NODE_GetLoadType
++ *! 13-Feb-2002 jeh Added uSysStackSize to NODE_TASKARGS.
++ *! 23-Apr-2001 jeh Removed unused typedefs, defines.
++ *! 10-Oct-2000 jeh Added alignment to NODE_STRMDEF.
++ *! 20-Jun-2000 jeh Created.
++ */
++
++#ifndef NODEPRIV_
++#define NODEPRIV_
++
++#include <dspbridge/strmdefs.h>
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nldrdefs.h>
++
++/* DSP address of node environment structure */
++ typedef u32 NODE_ENV;
++
++/*
++ * Node create structures
++ */
++
++/* Message node */
++ struct NODE_MSGARGS {
++ u32 uMaxMessages; /* Max # of simultaneous messages for node */
++ u32 uSegid; /* Segment for allocating message buffers */
++ u32 uNotifyType; /* Notify type (SEM_post, SWI_post, etc.) */
++ u32 uArgLength; /* Length in 32-bit words of arg data block */
++ u8 *pData; /* Argument data for node */
++ } ;
++
++ struct NODE_STRMDEF {
++ u32 uBufsize; /* Size of buffers for SIO stream */
++ u32 uNumBufs; /* max # of buffers in SIO stream at once */
++ u32 uSegid; /* Memory segment id to allocate buffers */
++ u32 uTimeout; /* Timeout for blocking SIO calls */
++ u32 uAlignment; /* Buffer alignment */
++ char *szDevice; /* Device name for stream */
++ } ;
++
++/* Task node */
++ struct NODE_TASKARGS {
++ struct NODE_MSGARGS msgArgs;
++ s32 nPriority;
++ u32 uStackSize;
++ u32 uSysStackSize;
++ u32 uStackSeg;
++ u32 uDSPHeapResAddr; /* DSP virtual heap address */
++ u32 uDSPHeapAddr; /* DSP virtual heap address */
++ u32 uHeapSize; /* Heap size */
++ u32 uGPPHeapAddr; /* GPP virtual heap address */
++ u32 uProfileID; /* Profile ID */
++ u32 uNumInputs;
++ u32 uNumOutputs;
++ u32 ulDaisArg; /* Address of iAlg object */
++ struct NODE_STRMDEF *strmInDef;
++ struct NODE_STRMDEF *strmOutDef;
++ } ;
++
++/*
++ * ======== NODE_CREATEARGS ========
++ */
++ struct NODE_CREATEARGS {
++ union {
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++ } asa;
++ } ;
++
++/*
++ * ======== NODE_GetChannelId ========
++ * Purpose:
++ * Get the channel index reserved for a stream connection between the
++ * host and a node. This index is reserved when NODE_Connect() is called
++ * to connect the node with the host. This index should be passed to
++ * the CHNL_Open function when the stream is actually opened.
++ * Parameters:
++ * hNode: Node object allocated from NODE_Allocate().
++ * uDir: Input (DSP_TONODE) or output (DSP_FROMNODE).
++ * uIndex: Stream index.
++ * pulId: Location to store channel index.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_ENODETYPE: Not a task or DAIS socket node.
++ * DSP_EVALUE: The node's stream corresponding to uIndex and uDir
++ * is not a stream to or from the host.
++ * Requires:
++ * NODE_Init(void) called.
++ * Valid uDir.
++ * pulId != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode,
++ u32 uDir,
++ u32 uIndex, OUT u32 *pulId);
++
++/*
++ * ======== NODE_GetStrmMgr ========
++ * Purpose:
++ * Get the STRM manager for a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate().
++ * phStrmMgr: Location to store STRM manager on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * Requires:
++ * phStrmMgr != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
++ struct STRM_MGR **phStrmMgr);
++
++/*
++ * ======== NODE_GetTimeout ========
++ * Purpose:
++ * Get the timeout value of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node's timeout value.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern u32 NODE_GetTimeout(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== NODE_GetType ========
++ * Purpose:
++ * Get the type (device, message, task, or XDAIS socket) of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node type: NODE_DEVICE, NODE_TASK, NODE_XDAIS, or NODE_GPP.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode);
++
++/*
++ * ======== GetNodeInfo ========
++ * Purpose:
++ * Get node information without holding semaphore.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node info: priority, device owner, no. of streams, execution state
++ * NDB properties.
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern void GetNodeInfo(struct NODE_OBJECT *hNode,
++ struct DSP_NODEINFO *pNodeInfo);
++
++/*
++ * ======== NODE_GetLoadType ========
++ * Purpose:
++ * Get the load type (dynamic, overlay, static) of a node.
++ * Parameters:
++ * hNode: Node allocated with NODE_Allocate(), or DSP_HGPPNODE.
++ * Returns:
++ * Node type: NLDR_DYNAMICLOAD, NLDR_OVLYLOAD, NLDR_STATICLOAD
++ * Requires:
++ * Valid hNode.
++ * Ensures:
++ */
++ extern enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode);
++
++#endif /* NODEPRIV_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/ntfy.h b/arch/arm/plat-omap/include/dspbridge/ntfy.h
+new file mode 100644
+index 0000000..5a0992a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/ntfy.h
+@@ -0,0 +1,146 @@
++/*
++ * ntfy.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ntfy.h ========
++ * Purpose:
++ * Manage lists of notification events.
++ *
++ * Public Functions:
++ * NTFY_Create
++ * NTFY_Delete
++ * NTFY_Exit
++ * NTFY_Init
++ * NTFY_Notify
++ * NTFY_Register
++ *
++ *! Revision History:
++ *! =================
++ *! 05-Nov-2001 kc: Updated NTFY_Register.
++ *! 07-Sep-2000 jeh Created.
++ */
++
++#ifndef NTFY_
++#define NTFY_
++
++ struct NTFY_OBJECT;
++
++/*
++ * ======== NTFY_Create ========
++ * Purpose:
++ * Create an empty list of notifications.
++ * Parameters:
++ * phNtfy: Location to store handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * Requires:
++ * NTFY_Init(void) called.
++ * phNtfy != NULL.
++ * Ensures:
++ * DSP_SUCCEEDED(status) <==> IsValid(*phNtfy).
++ */
++ extern DSP_STATUS NTFY_Create(OUT struct NTFY_OBJECT **phNtfy);
++
++/*
++ * ======== NTFY_Delete ========
++ * Purpose:
++ * Free resources allocated in NTFY_Create.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * Ensures:
++ */
++ extern void NTFY_Delete(IN struct NTFY_OBJECT *hNtfy);
++
++/*
++ * ======== NTFY_Exit ========
++ * Purpose:
++ * Discontinue usage of NTFY module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) successfully called before.
++ * Ensures:
++ */
++ extern void NTFY_Exit(void);
++
++/*
++ * ======== NTFY_Init ========
++ * Purpose:
++ * Initialize the NTFY module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Ensures:
++ */
++ extern bool NTFY_Init(void);
++
++/*
++ * ======== NTFY_Notify ========
++ * Purpose:
++ * Execute notify function (signal event or post message) for every
++ * element in the notification list that is to be notified about the
++ * event specified in uEventMask.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * uEventMask: The type of event that has occurred.
++ * Returns:
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * Ensures:
++ */
++ extern void NTFY_Notify(IN struct NTFY_OBJECT *hNtfy,
++ IN u32 uEventMask);
++
++/*
++ * ======== NTFY_Register ========
++ * Purpose:
++ * Add a notification element to the list. If the notification is already
++ * registered, and uEventMask != 0, the notification will get posted for
++ * events specified in the new event mask. If the notification is already
++ * registered and uEventMask == 0, the notification will be unregistered.
++ * Parameters:
++ * hNtfy: Handle returned from NTFY_Create().
++ * hNotification: Handle to a DSP_NOTIFICATION object.
++ * uEventMask: Events to be notified about.
++ * uNotifyType: Type of notification: DSP_SIGNALEVENT.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EVALUE: uEventMask is 0 and hNotification was not
++ * previously registered.
++ * DSP_EHANDLE: NULL hNotification, hNotification event name
++ * too long, or hNotification event name NULL.
++ * Requires:
++ * NTFY_Init(void) called.
++ * IsValid(hNtfy).
++ * hNotification != NULL.
++ * uNotifyType is DSP_SIGNALEVENT
++ * Ensures:
++ */
++ extern DSP_STATUS NTFY_Register(IN struct NTFY_OBJECT *hNtfy,
++ IN struct DSP_NOTIFICATION
++ *hNotification,
++ IN u32 uEventMask,
++ IN u32 uNotifyType);
++
++#endif /* NTFY_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/proc.h b/arch/arm/plat-omap/include/dspbridge/proc.h
+new file mode 100644
+index 0000000..486652e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/proc.h
+@@ -0,0 +1,648 @@
++/*
++ * proc.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== proc.h ========
++ * Description:
++ * This is the Class driver RM module interface.
++ *
++ * Public Functions:
++ * PROC_Attach
++ * PROC_Create
++ * PROC_Ctrl (OEM-function)
++ * PROC_Destroy
++ * PROC_Detach
++ * PROC_EnumNodes
++ * PROC_Exit
++ * PROC_FlushMemory
++ * PROC_GetDevObject (OEM-function)
++ * PROC_GetResourceInfo
++ * PROC_GetState
++ * PROC_GetProcessorId
++ * PROC_GetTrace (OEM-function)
++ * PROC_Init
++ * PROC_Load (OEM-function)
++ * PROC_Map
++ * PROC_NotifyAllclients
++ * PROC_NotifyClients (OEM-function)
++ * PROC_RegisterNotify
++ * PROC_ReserveMemory
++ * PROC_Start (OEM-function)
++ * PROC_UnMap
++ * PROC_UnReserveMemory
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs
++ *! 09-Feb-2003 vp: Added PROC_GetProcessorID function
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 28-Sep-2000 rr: Updated to Version 0.9.
++ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
++ *! 27-Jul-2000 rr: Updated to ver 0.8 of DSPAPI(types). GetTrace added.
++ *! 27-Jun-2000 rr: Created from dspapi.h
++ */
++
++#ifndef PROC_
++#define PROC_
++
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/devdefs.h>
++
++/*
++ * ======== PROC_Attach ========
++ * Purpose:
++ * Prepare for communication with a particular DSP processor, and return
++ * a handle to the processor object. The PROC Object gets created
++ * Parameters:
++ * uProcessor : The processor index (zero-based).
++ * hMgrObject : Handle to the Manager Object
++ * pAttrIn : Ptr to the DSP_PROCESSORATTRIN structure.
++ * A NULL value means use default values.
++ * phProcessor : Ptr to location to store processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EFAIL : General failure.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_SALREADYATTACHED: Success; Processor already attached.
++ * Requires:
++ * phProcessor != NULL.
++ * PROC Initialized.
++ * Ensures:
++ * DSP_EFAIL, and *phProcessor == NULL, OR
++ * Success and *phProcessor is a Valid Processor handle OR
++ * DSP_SALREADYATTACHED and *phProcessor is a Valid Processor.
++ * Details:
++ * When pAttrIn is NULL, the default timeout value is 10 seconds.
++ */
++ extern DSP_STATUS PROC_Attach(u32 uProcessor,
++ OPTIONAL CONST struct DSP_PROCESSORATTRIN
++ *pAttrIn,
++ OUT DSP_HPROCESSOR *phProcessor);
++
++/*
++ * ======== PROC_AutoStart =========
++ * Purpose:
++ * A Particular device gets loaded with the default image
++ * if the AutoStart flag is set.
++ * Parameters:
++ * hDevObject : Handle to the Device
++ * Returns:
++ * DSP_SOK : On Successful Loading
++ * DSP_EFILE : No DSP exec file found.
++ * DSP_EFAIL : General Failure
++ * Requires:
++ * hDevObject != NULL.
++ * hDevNode != NULL.
++ * PROC Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject);
++
++/*
++ * ======== PROC_Ctrl ========
++ * Purpose:
++ * Pass control information to the GPP device driver managing the DSP
++ * processor. This will be an OEM-only function, and not part of the
++ * 'Bridge application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * dwCmd : Private driver IOCTL cmd ID.
++ * pArgs : Ptr to an driver defined argument structure.
++ * Returns:
++ * DSP_SOK : SUCCESS
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ETIMEOUT: A Timeout Occured before the Control information
++ * could be sent.
++ * DSP_EACCESSDENIED: Client does not have the access rights required
++ * to call this function.
++ * DSP_ERESTART: A Critical error has occured and the DSP is being
++ * restarted.
++ * DSP_EFAIL : General Failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures
++ * Details:
++ * This function Calls WMD_BRD_Ioctl.
++ */
++ extern DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor,
++ u32 dwCmd, IN struct DSP_CBDATA *pArgs);
++
++/*
++ * ======== PROC_Detach ========
++ * Purpose:
++ * Close a DSP processor and de-allocate all (GPP) resources reserved
++ * for it. The Processor Object is deleted.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : InValid Handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * PROC Object is destroyed.
++ */
++ extern DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_EnumNodes ========
++ * Purpose:
++ * Enumerate the nodes currently allocated on a processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * aNodeTab : The first Location of an array allocated for node
++ * handles.
++ * uNodeTabSize: The number of (DSP_HNODE) handles that can be held
++ * to the memory the client has allocated for aNodeTab
++ * puNumNodes : Location where DSPProcessor_EnumNodes will return
++ * the number of valid handles written to aNodeTab
++ * puAllocated : Location where DSPProcessor_EnumNodes will return
++ * the number of nodes that are allocated on the DSP.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ESIZE : The amount of memory allocated for aNodeTab is
++ * insufficent. That is the number of nodes actually
++ * allocated on the DSP is greater than the value
++ * specified for uNodeTabSize.
++ * DSP_EFAIL : Unable to get Resource Information.
++ * Details:
++ * Requires
++ * puNumNodes is not NULL.
++ * puAllocated is not NULL.
++ * aNodeTab is not NULL.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor,
++ IN DSP_HNODE *aNodeTab,
++ IN u32 uNodeTabSize,
++ OUT u32 *puNumNodes,
++ OUT u32 *puAllocated);
++
++/*
++ * ======== PROC_GetResourceInfo ========
++ * Purpose:
++ * Enumerate the resources currently available on a processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * uResourceType: Type of resource .
++ * pResourceInfo: Ptr to the DSP_RESOURCEINFO structure.
++ * uResourceInfoSize: Size of the structure.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: The processor is not in the PROC_RUNNING state.
++ * DSP_ETIMEOUT: A timeout occured before the DSP responded to the
++ * querry.
++ * DSP_ERESTART: A Critical error has occured and the DSP is being
++ * restarted.
++ * DSP_EFAIL : Unable to get Resource Information
++ * Requires:
++ * pResourceInfo is not NULL.
++ * Parameter uResourceType is Valid.[TBD]
++ * uResourceInfoSize is >= sizeof DSP_RESOURCEINFO struct.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * This function currently returns
++ * DSP_ENOTIMPL, and does not write any data to the pResourceInfo struct.
++ */
++ extern DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor,
++ u32 uResourceType,
++ OUT struct DSP_RESOURCEINFO *
++ pResourceInfo,
++ u32 uResourceInfoSize);
++
++/*
++ * ======== PROC_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * PROC is initialized.
++ * Ensures:
++ * When reference count == 0, PROC's private resources are freed.
++ */
++ extern void PROC_Exit(void);
++
++/*
++ * ======== PROC_GetDevObject =========
++ * Purpose:
++ * Returns the DEV Hanlde for a given Processor handle
++ * Parameters:
++ * hProcessor : Processor Handle
++ * phDevObject : Location to store the DEV Handle.
++ * Returns:
++ * DSP_SOK : Success; *phDevObject has Dev handle
++ * DSP_EFAIL : Failure; *phDevObject is zero.
++ * Requires:
++ * phDevObject is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * DSP_SOK : *phDevObject is not NULL
++ * DSP_EFAIL : *phDevObject is NULL.
++ */
++ extern DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
++ struct DEV_OBJECT **phDevObject);
++
++/*
++ * ======== PROC_Init ========
++ * Purpose:
++ * Initialize PROC's private state, keeping a reference count on each
++ * call.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * TRUE: A requirement for the other public PROC functions.
++ */
++ extern bool PROC_Init(void);
++
++/*
++ * ======== PROC_GetState ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pProcStatus : Ptr to location to store the DSP_PROCESSORSTATE
++ * structure.
++ * uStateInfoSize: Size of DSP_PROCESSORSTATE.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while querying processor state.
++ * Requires:
++ * pProcStatus is not NULL
++ * uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
++ OUT struct DSP_PROCESSORSTATE
++ *pProcStatus,
++ u32 uStateInfoSize);
++
++/*
++ * ======== PROC_GetProcessorID ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * procID : Processor ID
++ *
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while querying processor state.
++ * Requires:
++ * pProcStatus is not NULL
++ * uStateInfoSize is >= than the size of DSP_PROCESSORSTATE structure.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProcessor,
++ u32 *procID);
++
++/*
++ * ======== PROC_GetTrace ========
++ * Purpose:
++ * Retrieve the trace buffer from the specified DSP processor.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pBuf : Ptr to buffer to hold trace output.
++ * uMaxSize : Maximum size of the output buffer.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure while retireving processor trace
++ * Buffer.
++ * Requires:
++ * pBuf is not NULL
++ * uMaxSize is > 0.
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf,
++ u32 uMaxSize);
++
++/*
++ * ======== PROC_Load ========
++ * Purpose:
++ * Reset a processor and load a new base program image.
++ * This will be an OEM-only function.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * iArgc : The number of Arguments(strings)in the aArgV[]
++ * aArgv : An Array of Arguments(Unicode Strings)
++ * aEnvp : An Array of Environment settings(Unicode Strings)
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EFILE : The DSP Execuetable was not found.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_ECORRUTFILE: Unable to Parse the DSP Execuetable
++ * DSP_EATTACHED: Abort because a GPP Client is attached to the
++ * specified Processor
++ * DSP_EACCESSDENIED: Client does not have the required access rights
++ * to reset and load the Processor
++ * DSP_EFAIL : Unable to Load the Processor
++ * Requires:
++ * aArgv is not NULL
++ * iArgc is > 0
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_LOADED
++ * or DSP_FAILED status.
++ * Details:
++ * Does not implement access rights to control which GPP application
++ * can load the processor.
++ */
++ extern DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor,
++ IN CONST s32 iArgc, IN CONST char **aArgv,
++ IN CONST char **aEnvp);
++
++/*
++ * ======== PROC_RegisterNotify ========
++ * Purpose:
++ * Register to be notified of specific processor events
++ * Parameters:
++ * hProcessor : The processor handle.
++ * uEventMask : Mask of types of events to be notified about.
++ * uNotifyType : Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle or hNotification.
++ * DSP_EVALUE : Parameter uEventMask is Invalid
++ * DSP_ENOTIMP : The notification type specified in uNotifyMask
++ * is not supported.
++ * DSP_EFAIL : Unable to register for notification.
++ * Requires:
++ * hNotification is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== PROC_NotifyClients ========
++ * Purpose:
++ * Notify the Processor Clients
++ * Parameters:
++ * hProc : The processor handle.
++ * uEvents : Event to be notified about.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : Failure to Set or Reset the Event
++ * Requires:
++ * uEvents is Supported or Valid type of Event
++ * hProc is a valid handle
++ * PROC Initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc,
++ u32 uEvents);
++
++/*
++ * ======== PROC_NotifyAllClients ========
++ * Purpose:
++ * Notify the Processor Clients
++ * Parameters:
++ * hProc : The processor handle.
++ * uEvents : Event to be notified about.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : Failure to Set or Reset the Event
++ * Requires:
++ * uEvents is Supported or Valid type of Event
++ * hProc is a valid handle
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * NODE And STRM would use this function to notify their clients
++ * about the state changes in NODE or STRM.
++ */
++ extern DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc,
++ u32 uEvents);
++
++/*
++ * ======== PROC_Start ========
++ * Purpose:
++ * Start a processor running.
++ * Processor must be in PROC_LOADED state.
++ * This will be an OEM-only function, and not part of the 'Bridge
++ * application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: Processor is not in PROC_LOADED state.
++ * DSP_EFAIL : Unable to start the processor.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_RUNNING or DSP_FAILED status.
++ * Details:
++ */
++ extern DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_Stop ========
++ * Purpose:
++ * Start a processor running.
++ * Processor must be in PROC_LOADED state.
++ * This will be an OEM-only function, and not part of the 'Bridge
++ * application developer's API.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EWRONGSTATE: Processor is not in PROC_LOADED state.
++ * DSP_EFAIL : Unable to start the processor.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Success and ProcState == PROC_RUNNING or DSP_FAILED status.
++ * Details:
++ */
++ extern DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor);
++
++/*
++ * ======== PROC_FlushMemory ========
++ * Purpose:
++ * Flushes a buffer from the MPU data cache.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Buffer start address
++ * ulSize : Buffer size
++ * ulFlags : Reserved.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * All the arguments are currently ignored.
++ */
++ extern DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize, u32 ulFlags);
++
++
++/*
++ * ======== PROC_InvalidateMemory ========
++ * Purpose:
++ * Invalidates a buffer from the MPU data cache.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Buffer start address
++ * ulSize : Buffer size
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * Requires:
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ * All the arguments are currently ignored.
++ */
++ extern DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize);
++
++/*
++ * ======== PROC_Map ========
++ * Purpose:
++ * Maps a MPU buffer to DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMpuAddr : Starting address of the memory region to map.
++ * ulSize : Size of the memory region to map.
++ * pReqAddr : Requested DSP start address. Offset-adjusted actual
++ * mapped address is in the last argument.
++ * ppMapAddr : Ptr to DSP side mapped u8 address.
++ * ulMapAttr : Optional endianness attributes, virt to phys flag.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_EMEMORY : MPU side memory allocation error.
++ * DSP_ENOTFOUND : Cannot find a reserved region starting with this
++ * : address.
++ * Requires:
++ * pMpuAddr is not NULL
++ * ulSize is not zero
++ * ppMapAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor,
++ void *pMpuAddr,
++ u32 ulSize,
++ void *pReqAddr,
++ void **ppMapAddr, u32 ulMapAttr);
++
++/*
++ * ======== PROC_ReserveMemory ========
++ * Purpose:
++ * Reserve a virtually contiguous region of DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * ulSize : Size of the address space to reserve.
++ * ppRsvAddr : Ptr to DSP side reserved u8 address.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_EMEMORY : Cannot reserve chunk of this size.
++ * Requires:
++ * ppRsvAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor,
++ u32 ulSize, void **ppRsvAddr);
++
++/*
++ * ======== PROC_UnMap ========
++ * Purpose:
++ * Removes a MPU buffer mapping from the DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pMapAddr : Starting address of the mapped memory region.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_ENOTFOUND : Cannot find a mapped region starting with this
++ * : address.
++ * Requires:
++ * pMapAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr);
++
++/*
++ * ======== PROC_UnReserveMemory ========
++ * Purpose:
++ * Frees a previously reserved region of DSP address space.
++ * Parameters:
++ * hProcessor : The processor handle.
++ * pRsvAddr : Ptr to DSP side reservedBYTE address.
++ * Returns:
++ * DSP_SOK : Success.
++ * DSP_EHANDLE : Invalid processor handle.
++ * DSP_EFAIL : General failure.
++ * DSP_ENOTFOUND : Cannot find a reserved region starting with this
++ * : address.
++ * Requires:
++ * pRsvAddr is not NULL
++ * PROC Initialized.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor,
++ void *pRsvAddr);
++
++#endif /* PROC_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/procpriv.h b/arch/arm/plat-omap/include/dspbridge/procpriv.h
+new file mode 100644
+index 0000000..21d4b3e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/procpriv.h
+@@ -0,0 +1,35 @@
++/*
++ * procpriv.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== procpriv.h ========
++ * Description:
++ * Global PROC constants and types, shared by PROC, MGR, and WCD.
++ *
++ *! Revision History:
++ *! ================
++ *! 05-July-2000 rr: Created
++ */
++
++#ifndef PROCPRIV_
++#define PROCPRIV_
++
++/* RM PROC Object */
++ struct PROC_OBJECT;
++
++#endif /* PROCPRIV_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/pwr.h b/arch/arm/plat-omap/include/dspbridge/pwr.h
+new file mode 100644
+index 0000000..a6645ca
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/pwr.h
+@@ -0,0 +1,129 @@
++/*
++ * pwr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== pwr.h ========
++ *
++ * Public Functions:
++ *
++ * PWR_SleepDSP
++ * PWR_WakeDSP
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 06-Jun-2002 sg Replaced dspdefs.h with includes of dbdefs.h and errbase.h.
++ *! 13-May-2002 sg Added DSP_SAREADYASLEEP and DSP_SALREADYAWAKE.
++ *! 09-May-2002 sg Updated, added timeouts.
++ *! 02-May-2002 sg Initial.
++ */
++
++#ifndef PWR_
++#define PWR_
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/pwr_sh.h>
++
++/*
++ * ======== PWR_SleepDSP ========
++ * Signal the DSP to go to sleep.
++ *
++ * Parameters:
++ * sleepCode: New sleep state for DSP. (Initially, valid codes
++ * are PWR_DEEPSLEEP or PWR_EMERGENCYDEEPSLEEP; both of
++ * these codes will simply put the DSP in deep sleep.)
++ *
++ * timeout: Maximum time (msec) that PWR should wait for
++ * confirmation that the DSP sleep state has been
++ * reached. If PWR should simply send the command to
++ * the DSP to go to sleep and then return (i.e.,
++ * asynchrounous sleep), the timeout should be
++ * specified as zero.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYASLEEP: Success, but the DSP was already asleep.
++ * DSP_EINVALIDARG: The specified sleepCode is not supported.
++ * DSP_ETIMEOUT: A timeout occured while waiting for DSP sleep
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send sleep command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode,
++ IN CONST u32 timeout);
++
++/*
++ * ======== PWR_WakeDSP ========
++ * Signal the DSP to wake from sleep.
++ *
++ * Parameters:
++ * timeout: Maximum time (msec) that PWR should wait for
++ * confirmation that the DSP is awake. If PWR should
++ * simply send a command to the DSP to wake and then
++ * return (i.e., asynchrounous wake), timeout should
++ * be specified as zero.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout);
++
++/*
++ * ======== PWR_PM_PreScale ========
++ * Prescale notification to DSP.
++ *
++ * Parameters:
++ * voltage_domain: The voltage domain for which notification is sent
++ * level: The level of voltage domain
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level);
++
++/*
++ * ======== PWR_PM_PostScale ========
++ * PostScale notification to DSP.
++ *
++ * Parameters:
++ * voltage_domain: The voltage domain for which notification is sent
++ * level: The level of voltage domain
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_SALREADYAWAKE: Success, but the DSP was already awake.
++ * DSP_ETIMEOUT: A timeout occured while waiting for wake
++ * confirmation.
++ * DSP_EFAIL: General failure, unable to send wake command to
++ * the DSP.
++ */
++ extern DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain,
++ u32 level);
++
++#endif /* PWR_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/pwr_sh.h b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+new file mode 100644
+index 0000000..40f1b84
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/pwr_sh.h
+@@ -0,0 +1,41 @@
++/*
++ * pwr_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== pwr_sh.h ========
++ *
++ * Power Manager shared definitions (used on both GPP and DSP sides).
++ *
++ *! Revision History
++ *! ================
++ *! 17-Apr-2002 sg: Initial.
++ */
++
++#ifndef PWR_SH_
++#define PWR_SH_
++
++#include <dspbridge/mbx_sh.h>
++
++/* valid sleep command codes that can be sent by GPP via mailbox: */
++#define PWR_DEEPSLEEP MBX_PM_DSPIDLE
++#define PWR_EMERGENCYDEEPSLEEP MBX_PM_EMERGENCYSLEEP
++#define PWR_SLEEPUNTILRESTART MBX_PM_SLEEPUNTILRESTART
++#define PWR_WAKEUP MBX_PM_DSPWAKEUP
++#define PWR_AUTOENABLE MBX_PM_PWRENABLE
++#define PWR_AUTODISABLE MBX_PM_PWRDISABLE
++#define PWR_RETENTION MBX_PM_DSPRETN
++
++#endif /* PWR_SH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/reg.h b/arch/arm/plat-omap/include/dspbridge/reg.h
+new file mode 100644
+index 0000000..5b34952
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/reg.h
+@@ -0,0 +1,257 @@
++/*
++ * reg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== reg.h ========
++ * Purpose:
++ * Provide registry functions.
++ *
++ * Public Functions:
++ * REG_DeleteValue
++ * REG_EnumKey
++ * REG_EnumValue
++ * REG_Exit
++ * REG_GetValue
++ * REG_Init
++ * REG_SetValue
++ *
++ *! Revision History:
++ *! =================
++ *! 30-Oct-2000 kc: Updated REG_SetValue & REG_GetValue; renamed
++ *! REG_DeleteEntry to REG_DeleteValue.
++ *! 29-Sep-2000 kc: Updated a REG functions for code review.
++ *! 12-Aug-2000 kc: Renamed REG_EnumValue to REG_EnumKey. Re-implemented
++ *! REG_EnumValue.
++ *! 03-Feb-2000 rr: REG_EnumValue Fxn Added
++ *! 13-Dec-1999 rr: windows.h removed
++ *! 02-Dec-1999 rr: windows.h included for retail build
++ *! 22-Nov-1999 kc: Changes from code review.
++ *! 29-Dec-1997 cr: Changes from code review.
++ *! 27-Oct-1997 cr: Added REG_DeleteValue.
++ *! 20-Oct-1997 cr: Added ability to pass bValue = NULL to REG_GetValue
++ *! and return size of reg entry in pdwValueSize.
++ *! 29-Sep-1997 cr: Added REG_SetValue
++ *! 29-Aug-1997 cr: Created.
++ */
++
++#ifndef _REG_H
++#define _REG_H
++
++#include <linux/types.h>
++
++/* ------------------------- Defines, Data Structures, Typedefs for Linux */
++#ifndef UNDER_CE
++
++#ifndef REG_SZ
++#define REG_SZ 1
++#endif
++
++#ifndef REG_BINARY
++#define REG_BINARY 3
++#endif
++
++#ifndef REG_DWORD
++#define REG_DWORD 4
++#endif
++
++#endif /* UNDER_CE */
++
++#define REG_MAXREGPATHLENGTH 255
++
++/*
++ * ======== REG_DeleteValue ========
++ * Purpose:
++ * Deletes a registry entry. NOTE: A registry entry is not the same as
++ * a registry key.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrSubkey: Path to key to open.
++ * pstrValue: Name of entry to delete.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrValue are non-NULL values.
++ * - phKey is NULL.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrValue < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ * Details:
++ */
++ extern DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue);
++
++/*
++ * ======== REG_EnumKey ========
++ * Purpose:
++ * Enumerates subkeys of the specified path to the registry key
++ * Retrieves the name of the subkey(given the index) and
++ * appends with the orignal path to form the full path.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrKey The name of the registry key to be enumerated.
++ * dwIndex Specifies the index of the subkey to retrieve.
++ * pstrSubkey: Pointer to buffer that receives full path name of the
++ * specified key + the sub-key
++ * pdwValueSize: Specifies bytes of memory pstrSubkey points to on input,
++ * on output, specifies actual memory bytes written into.
++ * If there is no sub key,pdwValueSize returns NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrKey is non-NULL value.
++ * - pdwValueSize is a valid pointer.
++ * - phKey is NULL.
++ * - length of pstrKey < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ * - strlen(pstrSubkey) is > strlen(pstrKey) &&
++ * - strlen(pstrSubkey) is < REG_MAXREGPATHLENGTH
++ */
++ extern DSP_STATUS REG_EnumKey(OPTIONAL IN HANDLE *phKey,
++ IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrSubkey,
++ IN OUT u32 *pdwValueSize);
++
++/*
++ * ======== REG_EnumValue ========
++ * Purpose:
++ * Enumerates values of a specified key. Retrieves each value name and
++ * the data associated with the value.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * dwIndex: Specifies the index of the value to retrieve.
++ * pstrKey: The name of the registry key to be enumerated.
++ * pstrValue: Pointer to buffer that receives the name of the value.
++ * pdwValueSize: Specifies bytes of memory pstrValue points to on input,
++ * On output, specifies actual memory bytes written into.
++ * If there is no value, pdwValueSize returns NULL
++ * pstrData: Pointer to buffer that receives the data of a value.
++ * pdwDataSize: Specifies bytes of memory in pstrData on input and
++ * bytes of memory written into pstrData on output.
++ * If there is no data, pdwDataSize returns NULL.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * REG initialized.
++ * phKey is NULL.
++ * pstrKey is a non-NULL value.
++ * pstrValue, pstrData, pdwValueSize and pdwDataSize are valid pointers.
++ * Length of pstrKey is less than REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_EnumValue(IN HANDLE *phKey,
++ IN u32 dwIndex,
++ IN CONST char *pstrKey,
++ IN OUT char *pstrValue,
++ IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData,
++ IN OUT u32 *pdwDataSize);
++
++/*
++ * ======== REG_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * REG initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void REG_Exit(void);
++
++/*
++ * ======== REG_GetValue ========
++ * Purpose:
++ * Retrieve a value from the registry.
++ * Parameters:
++ * phKey: Currently reserved; must be NULL.
++ * pstrSubkey: Path to key to open.
++ * pstrEntry: Name of entry to retrieve.
++ * pbValue: Upon return, points to retrieved value.
++ * pdwValueSize: Specifies bytes of memory pbValue points to on input,
++ * on output, specifies actual memory bytes written into.
++ * If pbValue is NULL, pdwValueSize reports the size of
++ * the entry in pstrEntry.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrEntry are non-NULL values.
++ * - pbValue is a valid pointer.
++ * - phKey is NULL.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrEntry < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubkey,
++ IN CONST char *pstrEntry,
++ OUT u8 *pbValue,
++ IN OUT u32 *pdwValueSize);
++
++/*
++ * ======== REG_Init ========
++ * Purpose:
++ * Initializes private state of REG module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * REG initialized.
++ */
++ extern bool REG_Init(void);
++
++/*
++ * ======== REG_SetValue ========
++ * Purpose:
++ * Set a value in the registry.
++ * Parameters:
++ * phKey: Handle to open reg key, or NULL if pSubkey is full path.
++ * pstrSubkey: Path to key to open, could be based on phKey.
++ * pstrEntry: Name of entry to set.
++ * dwType: Data type of new registry value.
++ * pbValue: Points to buffer containing new data.
++ * dwValueSize: Specifies bytes of memory bValue points to.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * - REG initialized.
++ * - pstrSubkey & pstrEntry are non-NULL values.
++ * - pbValue is a valid pointer.
++ * - phKey is NULL.
++ * - dwValuSize > 0.
++ * - length of pstrSubkey < REG_MAXREGPATHLENGTH.
++ * - length of pstrEntry < REG_MAXREGPATHLENGTH.
++ * Ensures:
++ */
++ extern DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey,
++ IN CONST char *pstrSubKey,
++ IN CONST char *pstrEntry,
++ IN CONST u32 dwType,
++ IN u8 *pbValue, IN u32 dwValueSize);
++
++#endif /* _REG_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+new file mode 100644
+index 0000000..b43fa16
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h
+@@ -0,0 +1,88 @@
++/*
++ * resourcecleanup.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef RES_CLEANUP_DISABLE
++
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/drv.h>
++
++
++extern DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
++ struct DRV_OBJECT *hDrvObject);
++
++extern DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject,
++ HANDLE hPCtxt);
++
++extern DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcUpdatestate(HANDLE pCtxt,
++ enum GPP_PROC_RES_STATE resState);
++
++extern DSP_STATUS DRV_ProcSetPID(HANDLE pCtxt, s32 hProcess);
++
++extern DSP_STATUS DRV_GetProcContext(u32 phProcess,
++ struct DRV_OBJECT *hDrvObject,
++ HANDLE hPCtxt, DSP_HNODE hNode,
++ u32 pMapAddr);
++
++extern DSP_STATUS DRV_RemoveAllResources(HANDLE pPctxt);
++
++extern DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
++ HANDLE hPCtxt, HANDLE hProcess);
++
++extern DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE nodeRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE nodeRes,
++ HANDLE pCtxt);
++
++extern void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status);
++
++extern DSP_STATUS DRV_RemoveNodeResElement(HANDLE nodeRes, HANDLE status);
++
++extern void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status);
++
++extern DSP_STATUS DRV_UpdateDMMResElement(HANDLE dmmRes, u32 pMpuAddr,
++ u32 ulSize, u32 pReqAddr,
++ u32 ppMapAddr, HANDLE hProcesso);
++
++extern DSP_STATUS DRV_InsertDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE dmmRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveDMMResElement(HANDLE dmmRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE STRMRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
++ HANDLE pPctxt);
++
++extern DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE STRMRes,
++ HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE STRMRes, HANDLE pCtxt);
++
++extern DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE pCtxt);
++
++extern DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf, u32 *pSize);
++
++extern enum NODE_STATE NODE_GetState(HANDLE hNode);
++
++#endif
+diff --git a/arch/arm/plat-omap/include/dspbridge/rmm.h b/arch/arm/plat-omap/include/dspbridge/rmm.h
+new file mode 100644
+index 0000000..5b14b8f
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rmm.h
+@@ -0,0 +1,199 @@
++/*
++ * rmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rmm.h ========
++ *
++ * This memory manager provides general heap management and arbitrary
++ * alignment for any number of memory segments, and management of overlay
++ * memory.
++ *
++ * Public functions:
++ * RMM_alloc
++ * RMM_create
++ * RMM_delete
++ * RMM_exit
++ * RMM_free
++ * RMM_init
++ *
++ *! Revision History
++ *! ================
++ *! 25-Jun-2002 jeh Added RMM_Addr. Removed RMM_reserve, RMM_stat.
++ *! 15-Oct-2001 jeh Based on rm.h in gen tree.
++ */
++
++#ifndef RMM_
++#define RMM_
++
++/*
++ * ======== RMM_Addr ========
++ * DSP address + segid
++ */
++struct RMM_Addr {
++ u32 addr;
++ s32 segid;
++} ;
++
++/*
++ * ======== RMM_Segment ========
++ * Memory segment on the DSP available for remote allocations.
++ */
++struct RMM_Segment {
++ u32 base; /* Base of the segment */
++ u32 length; /* Size of the segment (target MAUs) */
++ s32 space; /* Code or data */
++ u32 number; /* Number of Allocated Blocks */
++} ;
++
++/*
++ * ======== RMM_Target ========
++ */
++struct RMM_TargetObj;
++
++/*
++ * ======== RMM_alloc ========
++ *
++ * RMM_alloc is used to remotely allocate or reserve memory on the DSP.
++ *
++ * Parameters:
++ * target - Target returned from RMM_create().
++ * segid - Memory segment to allocate from.
++ * size - Size (target MAUS) to allocate.
++ * align - alignment.
++ * dspAddr - If reserve is FALSE, the location to store allocated
++ * address on output, otherwise, the DSP address to
++ * reserve.
++ * reserve - If TRUE, reserve the memory specified by dspAddr.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation on GPP failed.
++ * DSP_EOVERLAYMEMORY: Cannot "allocate" overlay memory because it's
++ * already in use.
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * dspAddr != NULL.
++ * size > 0
++ * reserve || target->numSegs > 0.
++ * Ensures:
++ */
++extern DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAdr, bool reserve);
++
++/*
++ * ======== RMM_create ========
++ * Create a target object with memory segments for remote allocation. If
++ * segTab == NULL or numSegs == 0, memory can only be reserved through
++ * RMM_alloc().
++ *
++ * Parameters:
++ * pTarget: - Location to store target on output.
++ * segTab: - Table of memory segments.
++ * numSegs: - Number of memory segments.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * RMM initialized.
++ * pTarget != NULL.
++ * numSegs == 0 || segTab != NULL.
++ * Ensures:
++ * Success: Valid *pTarget.
++ * Failure: *pTarget == NULL.
++ */
++extern DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
++ struct RMM_Segment segTab[], u32 numSegs);
++
++/*
++ * ======== RMM_delete ========
++ * Delete target allocated in RMM_create().
++ *
++ * Parameters:
++ * target - Target returned from RMM_create().
++ * Returns:
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * Ensures:
++ */
++extern void RMM_delete(struct RMM_TargetObj *target);
++
++/*
++ * ======== RMM_exit ========
++ * Exit the RMM module
++ *
++ * Parameters:
++ * Returns:
++ * Requires:
++ * RMM_init successfully called.
++ * Ensures:
++ */
++extern void RMM_exit(void);
++
++/*
++ * ======== RMM_free ========
++ * Free or unreserve memory allocated through RMM_alloc().
++ *
++ * Parameters:
++ * target: - Target returned from RMM_create().
++ * segid: - Segment of memory to free.
++ * dspAddr: - Address to free or unreserve.
++ * size: - Size of memory to free or unreserve.
++ * reserved: - TRUE if memory was reserved only, otherwise FALSE.
++ * Returns:
++ * Requires:
++ * RMM initialized.
++ * Valid target.
++ * reserved || segid < target->numSegs.
++ * reserve || [dspAddr, dspAddr + size] is a valid memory range.
++ * Ensures:
++ */
++extern bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 dspAddr,
++ u32 size, bool reserved);
++
++/*
++ * ======== RMM_init ========
++ * Initialize the RMM module
++ *
++ * Parameters:
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * Ensures:
++ */
++extern bool RMM_init(void);
++
++/*
++ * ======== RMM_stat ========
++ * Obtain memory segment status
++ *
++ * Parameters:
++ * segid: Segment ID of the dynamic loading segment.
++ * pMemStatBuf: Pointer to allocated buffer into which memory stats are
++ * placed.
++ * Returns:
++ * TRUE: Success.
++ * FALSE: Failure.
++ * Requires:
++ * segid < target->numSegs
++ * Ensures:
++ */
++extern bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
++ struct DSP_MEMSTAT *pMemStatBuf);
++
++#endif /* RMM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/rms_sh.h b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
+new file mode 100644
+index 0000000..5d4b49a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rms_sh.h
+@@ -0,0 +1,125 @@
++/*
++ * rms_sh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rms_sh.h ========
++ *
++ * DSP/BIOS Bridge Resource Manager Server shared definitions (used on both
++ * GPP and DSP sides).
++ *
++ *! Revision History
++ *! ================
++ *! 24-Mar-2003 vp Merged updates required for CCS2.2 transition.
++ *! 24-Feb-2003 kc Rearranged order of node types to temporarily support
++ *! legacy message node code
++ *! 23-Nov-2002 gp Converted tabs -> spaces, to fix formatting.
++ *! 13-Feb-2002 jeh Added sysstacksize element to RMS_MoreTaskArgs.
++ *! 11-Dec-2000 sg Added 'misc' element to RMS_MoreTaskArgs.
++ *! 04-Dec-2000 ag Added RMS_BUFDESC command code.
++ *! C/R code value changed to allow ORing of system/user codes.
++ *! 10-Oct-2000 sg Added 'align' field to RMS_StrmDef.
++ *! 09-Oct-2000 sg Moved pre-defined message codes here from rmsdefs.h.
++ *! 02-Oct-2000 sg Changed ticks to msec.
++ *! 24-Aug-2000 sg Moved definitions that will be exposed to app developers
++ *! to a separate file, rmsdefs.h.
++ *! 10-Aug-2000 sg Added RMS_COMMANDBUFSIZE and RMS_RESPONSEBUFSIZE; added
++ *! pre-defined command/response codes; more comments.
++ *! 09-Aug-2000 sg Added RMS_ETASK.
++ *! 08-Aug-2000 jeh Define RMS_WORD for GPP, rename DSP_MSG to RMS_DSPMSG.
++ *! Added RMS_MsgArgs, RMS_MoreTaskArgs.
++ *! 25-Jul-2000 sg: Changed SIO to STRM.
++ *! 30-Jun-2000 sg: Initial.
++ */
++
++#ifndef RMS_SH_
++#define RMS_SH_
++
++#include <dspbridge/rmstypes.h>
++
++/* Node Types: */
++#define RMS_TASK 1 /* Task node */
++#define RMS_DAIS 2 /* xDAIS socket node */
++#define RMS_MSG 3 /* Message node */
++
++/* Memory Types: */
++#define RMS_CODE 0 /* Program space */
++#define RMS_DATA 1 /* Data space */
++#define RMS_IO 2 /* I/O space */
++
++/* RM Server Command and Response Buffer Sizes: */
++#define RMS_COMMANDBUFSIZE 256 /* Size of command buffer */
++#define RMS_RESPONSEBUFSIZE 16 /* Size of response buffer */
++
++/* Pre-Defined Command/Response Codes: */
++#define RMS_EXIT 0x80000000 /* GPP->Node: shutdown */
++#define RMS_EXITACK 0x40000000 /* Node->GPP: ack shutdown */
++#define RMS_BUFDESC 0x20000000 /* Arg1 SM buf, Arg2 is SM size */
++#define RMS_KILLTASK 0x10000000 /* GPP->Node: Kill Task */
++#define RMS_USER 0x0 /* Start of user-defined msg codes */
++#define RMS_MAXUSERCODES 0xfff /* Maximum user defined C/R Codes */
++
++
++/* RM Server RPC Command Structure: */
++ struct RMS_Command {
++ RMS_WORD fxn; /* Server function address */
++ RMS_WORD arg1; /* First argument */
++ RMS_WORD arg2; /* Second argument */
++ RMS_WORD data; /* Function-specific data array */
++ } ;
++
++/*
++ * The RMS_StrmDef structure defines the parameters for both input and output
++ * streams, and is passed to a node's create function.
++ */
++ struct RMS_StrmDef {
++ RMS_WORD bufsize; /* Buffer size (in DSP words) */
++ RMS_WORD nbufs; /* Max number of bufs in stream */
++ RMS_WORD segid; /* Segment to allocate buffers */
++ RMS_WORD align; /* Alignment for allocated buffers */
++ RMS_WORD timeout; /* Timeout (msec) for blocking calls */
++ RMS_CHAR name[1]; /* Device Name (terminated by '\0') */
++ } ;
++
++/* Message node create args structure: */
++ struct RMS_MsgArgs {
++ RMS_WORD maxMessages; /* Max # simultaneous msgs to node */
++ RMS_WORD segid; /* Mem segment for NODE_allocMsgBuf */
++ RMS_WORD notifyType; /* Type of message notification */
++ RMS_WORD argLength; /* Length (in DSP chars) of arg data */
++ RMS_WORD argData; /* Arg data for node */
++ } ;
++
++/* Partial task create args structure */
++ struct RMS_MoreTaskArgs {
++ RMS_WORD priority; /* Task's runtime priority level */
++ RMS_WORD stackSize; /* Task's stack size */
++ RMS_WORD sysstackSize; /* Task's system stack size (55x) */
++ RMS_WORD stackSeg; /* Memory segment for task's stack */
++ RMS_WORD heapAddr; /* base address of the node memory heap in
++ * external memory (DSP virtual address) */
++ RMS_WORD heapSize; /* size in MAUs of the node memory heap in
++ * external memory */
++ RMS_WORD misc; /* Misc field. Not used for 'normal'
++ * task nodes; for xDAIS socket nodes
++ * specifies the IALG_Fxn pointer.
++ */
++ /* # input STRM definition structures */
++ RMS_WORD numInputStreams;
++ } ;
++
++#endif /* RMS_SH_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/rmstypes.h b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
+new file mode 100644
+index 0000000..13d752e
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/rmstypes.h
+@@ -0,0 +1,40 @@
++/*
++ * rmstypes.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== rmstypes.h ========
++ *
++ * DSP/BIOS Bridge Resource Manager Server shared data type definitions.
++ *
++ *! Revision History
++ *! ================
++ *! 06-Oct-2000 sg Added LgFxn type.
++ *! 05-Oct-2000 sg Changed RMS_STATUS to LgUns.
++ *! 31-Aug-2000 sg Added RMS_DSPMSG.
++ *! 25-Aug-2000 sg Initial.
++ */
++
++#ifndef RMSTYPES_
++#define RMSTYPES_
++#include <linux/types.h>
++/*
++ * DSP-side definitions.
++ */
++#include <dspbridge/std.h>
++typedef u32 RMS_WORD;
++typedef char RMS_CHAR;
++
++#endif /* RMSTYPES_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/services.h b/arch/arm/plat-omap/include/dspbridge/services.h
+new file mode 100644
+index 0000000..35bab0d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/services.h
+@@ -0,0 +1,63 @@
++/*
++ * services.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== services.h ========
++ * Purpose:
++ * Provide loading and unloading of SERVICES modules.
++ *
++ * Public Functions:
++ * SERVICES_Exit(void)
++ * SERVICES_Init(void)
++ *
++ *! Revision History:
++ *! ================
++ *! 01-Feb-2000 kc: Created.
++ */
++
++#ifndef SERVICES_
++#define SERVICES_
++
++#include <dspbridge/host_os.h>
++/*
++ * ======== SERVICES_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * SERVICES initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void SERVICES_Exit(void);
++
++/*
++ * ======== SERVICES_Init ========
++ * Purpose:
++ * Initializes SERVICES modules.
++ * Parameters:
++ * Returns:
++ * TRUE if all modules initialized; otherwise FALSE.
++ * Requires:
++ * Ensures:
++ * SERVICES modules initialized.
++ */
++ extern bool SERVICES_Init(void);
++
++#endif /* SERVICES_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/std.h b/arch/arm/plat-omap/include/dspbridge/std.h
+new file mode 100644
+index 0000000..ec849f4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/std.h
+@@ -0,0 +1,143 @@
++/*
++ * std.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== std.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 16-Feb-2004 vp GNU compiler 3.x defines inline keyword. Added
++ *! appropriate macros not to redefine inline keyword in
++ *! this file.
++ *! 24-Oct-2002 ashu defined _TI_ and _FIXED_ symbols for 28x.
++ *! 24-Oct-2002 ashu defined _TI_ for 24x.
++ *! 01-Mar-2002 kln changed LARGE_MODEL and Arg definition for 28x
++ *! 01-Feb-2002 kln added definitions for 28x
++ *! 08-Dec-2000 kw: added 'ArgToInt' and 'ArgToPtr' macros
++ *! 30-Nov-2000 mf: Added _64_, _6x_; removed _7d_
++ *! 30-May-2000 srid: Added __TMS320C55X__ for 55x; Arg is void * for 55 .
++ *! 18-Jun-1999 dr: Added '_TI_', fixed __inline for SUN4, added inline
++ *! 10-Feb-1999 rt: Added '55' support, changed 54's symbol to _TMS320C5XX
++ *! 29-Aug-1998 mf: fixed typo, removed obsolete targets
++ *! 08-Jun-1998 mf: _67_ is synonym for _7d_
++ *! 10-Oct-1997 rt; added _7d_ for Raytheon C7DSP triggered by _TMS320C6700
++ *! 04-Aug-1997 cc: added _29_ for _TMS320C2XX
++ *! 11-Jul-1997 dlr: _5t_, and STD_SPOXTASK keyword for Tasking
++ *! 12-Jun-1997 mf: _TMS320C60 -> _TMS320C6200
++ *! 13-Feb-1997 mf: _62_, with 32-bit LgInt
++ *! 26-Nov-1996 kw: merged bios-c00's and wsx-a27's <dspbridge/std.h> changes
++ *! *and* revision history
++ *! 12-Sep-1996 kw: added C54x #ifdef's
++ *! 21-Aug-1996 mf: removed #define main smain for _21_
++ *! 14-May-1996 gp: def'd out INT, FLOAT, and COMPLEX defines for WSX.
++ *! 11-Apr-1996 kw: define _W32_ based on _WIN32 (defined by MS compiler)
++ *! 07-Mar-1996 mg: added Win32 support
++ *! 06-Sep-1995 dh: added _77_ dynamic stack support via fxns77.h
++ *! 27-Jun-1995 dh: added _77_ support
++ *! 16-Mar-1995 mf: for _21_: #define main smain
++ *! 01-Mar-1995 mf: set _20_ and _60_ (as well as _21_ for both)
++ *! 22-Feb-1995 mf: Float is float for _SUN_ and _80_
++ *! 22-Dec-1994 mf: Added _80_ definition, for PP or MP.
++ *! 09-Dec-1994 mf: Added _53_ definition.
++ *! Added definitions of _30_, etc.
++ *! 23-Aug-1994 dh removed _21_ special case (kw)
++ *! 17-Aug-1994 dh added _51_ support
++ *! 03-Aug-1994 kw updated _80_ support
++ *! 30-Jun-1994 kw added _80_ support
++ *! 05-Apr-1994 kw: Added _SUN_ to _FLOAT_ definition
++ *! 01-Mar-1994 kw: Made Bool an int (was u16) for _56_ (more efficient).
++ *! Added _53_ support.
++ */
++
++#ifndef STD_
++#define STD_
++
++#include <linux/types.h>
++
++/*
++ * ======== _TI_ ========
++ * _TI_ is defined for all TI targets
++ */
++#if defined(_29_) || defined(_30_) || defined(_40_) || defined(_50_) || \
++ defined(_54_) || defined(_55_) || defined(_6x_) || defined(_80_) || \
++ defined(_28_) || defined(_24_)
++#define _TI_ 1
++#endif
++
++/*
++ * ======== _FLOAT_ ========
++ * _FLOAT_ is defined for all targets that natively support floating point
++ */
++#if defined(_SUN_) || defined(_30_) || defined(_40_) || defined(_67_) || \
++ defined(_80_)
++#define _FLOAT_ 1
++#endif
++
++/*
++ * ======== _FIXED_ ========
++ * _FIXED_ is defined for all fixed point target architectures
++ */
++#if defined(_29_) || defined(_50_) || defined(_54_) || defined(_55_) || \
++ defined(_62_) || defined(_64_) || defined(_28_)
++#define _FIXED_ 1
++#endif
++
++/*
++ * ======== _TARGET_ ========
++ * _TARGET_ is defined for all target architectures (as opposed to
++ * host-side software)
++ */
++#if defined(_FIXED_) || defined(_FLOAT_)
++#define _TARGET_ 1
++#endif
++
++/*
++ * 8, 16, 32-bit type definitions
++ *
++ * Sm* - 8-bit type
++ * Md* - 16-bit type
++ * Lg* - 32-bit type
++ *
++ * *s32 - signed type
++ * *u32 - unsigned type
++ * *Bits - unsigned type (bit-maps)
++ */
++
++/*
++ * Aliases for standard C types
++ */
++
++typedef s32(*Fxn) (void); /* generic function type */
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++
++/*
++ * These macros are used to cast 'Arg' types to 's32' or 'Ptr'.
++ * These macros were added for the 55x since Arg is not the same
++ * size as s32 and Ptr in 55x large model.
++ */
++#if defined(_28l_) || defined(_55l_)
++#define ArgToInt(A) ((s32)((long)(A) & 0xffff))
++#define ArgToPtr(A) ((Ptr)(A))
++#else
++#define ArgToInt(A) ((s32)(A))
++#define ArgToPtr(A) ((Ptr)(A))
++#endif
++
++#endif /* STD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/strm.h b/arch/arm/plat-omap/include/dspbridge/strm.h
+new file mode 100644
+index 0000000..5825615
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/strm.h
+@@ -0,0 +1,441 @@
++/*
++ * strm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strm.h ========
++ * Description:
++ * DSPBridge Stream Manager.
++ *
++ * Public Functions:
++ * STRM_AllocateBuffer
++ * STRM_Close
++ * STRM_Create
++ * STRM_Delete
++ * STRM_Exit
++ * STRM_FreeBuffer
++ * STRM_GetEventHandle
++ * STRM_GetInfo
++ * STRM_Idle
++ * STRM_Init
++ * STRM_Issue
++ * STRM_Open
++ * STRM_PrepareBuffer
++ * STRM_Reclaim
++ * STRM_RegisterNotify
++ * STRM_Select
++ * STRM_UnprepareBuffer
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 15-Nov-2001 ag Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
++ *! Added DSP_ESIZE error to STRM_AllocateBuffer().
++ *! 07-Jun-2001 sg Made DSPStream_AllocateBuffer fxn name plural.
++ *! 10-May-2001 jeh Code review cleanup.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name updates.
++ *! 06-Feb-2001 kc Updated DBC_Ensure for STRM_Select().
++ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open().
++ *! 25-Sep-2000 jeh Created.
++ */
++
++#ifndef STRM_
++#define STRM_
++
++#include <dspbridge/dev.h>
++
++#include <dspbridge/strmdefs.h>
++
++/*
++ * ======== STRM_AllocateBuffer ========
++ * Purpose:
++ * Allocate data buffer(s) for use with a stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer(s).
++ * uNumBufs: Number of buffers to allocate.
++ * apBuffer: Array to hold buffer addresses.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EFAIL: Failure occurred, unable to allocate buffers.
++ * DSP_ESIZE: uSize must be > 0 bytes.
++ * Requires:
++ * STRM_Init(void) called.
++ * apBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ OUT u8 **apBuffer,
++ u32 uNumBufs);
++
++/*
++ * ======== STRM_Close ========
++ * Purpose:
++ * Close a stream opened with STRM_Open().
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EPENDING: Some data buffers issued to the stream have not
++ * been reclaimed.
++ * DSP_EFAIL: Failure to close stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm);
++
++/*
++ * ======== STRM_Create ========
++ * Purpose:
++ * Create a STRM manager object. This object holds information about the
++ * device needed to open streams.
++ * Parameters:
++ * phStrmMgr: Location to store handle to STRM manager object on
++ * output.
++ * hDev: Device for this processor.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EFAIL: General failure.
++ * Requires:
++ * STRM_Init(void) called.
++ * phStrmMgr != NULL.
++ * hDev != NULL.
++ * Ensures:
++ * DSP_SOK: Valid *phStrmMgr.
++ * error: *phStrmMgr == NULL.
++ */
++ extern DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr,
++ struct DEV_OBJECT *hDev);
++
++/*
++ * ======== STRM_Delete ========
++ * Purpose:
++ * Delete the STRM Object.
++ * Parameters:
++ * hStrmMgr: Handle to STRM manager object from STRM_Create.
++ * Returns:
++ * Requires:
++ * STRM_Init(void) called.
++ * Valid hStrmMgr.
++ * Ensures:
++ * hStrmMgr is not valid.
++ */
++ extern void STRM_Delete(struct STRM_MGR *hStrmMgr);
++
++/*
++ * ======== STRM_Exit ========
++ * Purpose:
++ * Discontinue usage of STRM module.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * STRM_Init(void) successfully called before.
++ * Ensures:
++ */
++ extern void STRM_Exit(void);
++
++/*
++ * ======== STRM_FreeBuffer ========
++ * Purpose:
++ * Free buffer(s) allocated with STRM_AllocateBuffer.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * apBuffer: Array containing buffer addresses.
++ * uNumBufs: Number of buffers to be freed.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid stream handle.
++ * DSP_EFAIL: Failure occurred, unable to free buffers.
++ * Requires:
++ * STRM_Init(void) called.
++ * apBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm,
++ u8 **apBuffer, u32 uNumBufs);
++
++/*
++ * ======== STRM_GetEventHandle ========
++ * Purpose:
++ * Get stream's user event handle. This function is used when closing
++ * a stream, so the event can be closed.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * phEvent: Location to store event handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * Requires:
++ * STRM_Init(void) called.
++ * phEvent != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_GetEventHandle(struct STRM_OBJECT *hStrm,
++ OUT HANDLE *phEvent);
++
++/*
++ * ======== STRM_GetInfo ========
++ * Purpose:
++ * Get information about a stream. User's DSP_STREAMINFO is contained
++ * in STRM_INFO struct. STRM_INFO also contains Bridge private info.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pStreamInfo: Location to store stream info on output.
++ * uSteamInfoSize: Size of user's DSP_STREAMINFO structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ESIZE: uStreamInfoSize < sizeof(DSP_STREAMINFO).
++ * DSP_EFAIL: Unable to get stream info.
++ * Requires:
++ * STRM_Init(void) called.
++ * pStreamInfo != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
++ OUT struct STRM_INFO *pStreamInfo,
++ u32 uStreamInfoSize);
++
++/*
++ * ======== STRM_Idle ========
++ * Purpose:
++ * Idle a stream and optionally flush output data buffers.
++ * If this is an output stream and fFlush is TRUE, all data currently
++ * enqueued will be discarded.
++ * If this is an output stream and fFlush is FALSE, this function
++ * will block until all currently buffered data is output, or the timeout
++ * specified has been reached.
++ * After a successful call to STRM_Idle(), all buffers can immediately
++ * be reclaimed.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * fFlush: If TRUE, discard output buffers.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ETIMEOUT: A timeout occurred before the stream could be idled.
++ * DSP_ERESTART: A critical error occurred, DSP is being restarted.
++ * DSP_EFAIL: Unable to idle stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush);
++
++/*
++ * ======== STRM_Init ========
++ * Purpose:
++ * Initialize the STRM module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialization succeeded, FALSE otherwise.
++ * Requires:
++ * Ensures:
++ */
++ extern bool STRM_Init(void);
++
++/*
++ * ======== STRM_Issue ========
++ * Purpose:
++ * Send a buffer of data to a stream.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pBuf: Pointer to buffer of data to be sent to the stream.
++ * ulBytes: Number of bytes of data in the buffer.
++ * ulBufSize: Actual buffer size in bytes.
++ * dwArg: A user argument that travels with the buffer.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ESTREAMFULL: The stream is full.
++ * DSP_EFAIL: Failure occurred, unable to issue buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuf != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf,
++ u32 ulBytes, u32 ulBufSize,
++ IN u32 dwArg);
++
++/*
++ * ======== STRM_Open ========
++ * Purpose:
++ * Open a stream for sending/receiving data buffers to/from a task of
++ * DAIS socket node on the DSP.
++ * Parameters:
++ * hNode: Node handle returned from NODE_Allocate().
++ * uDir: DSP_TONODE or DSP_FROMNODE.
++ * uIndex: Stream index.
++ * pAttr: Pointer to structure containing attributes to be
++ * applied to stream. Cannot be NULL.
++ * phStrm: Location to store stream handle on output.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hNode.
++ * DSP_EDIRECTION: Invalid uDir.
++ * DSP_EVALUE: Invalid uIndex.
++ * DSP_ENODETYPE: hNode is not a task or DAIS socket node.
++ * DSP_EFAIL: Unable to open stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * phStrm != NULL.
++ * pAttr != NULL.
++ * Ensures:
++ * DSP_SOK: *phStrm is valid.
++ * error: *phStrm == NULL.
++ */
++ extern DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir,
++ u32 uIndex, IN struct STRM_ATTR *pAttr,
++ OUT struct STRM_OBJECT **phStrm);
++
++/*
++ * ======== STRM_PrepareBuffer ========
++ * Purpose:
++ * Prepare a data buffer not allocated by DSPStream_AllocateBuffers()
++ * for use with a stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer.
++ * pBuffer: Buffer address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EFAIL: Failure occurred, unable to prepare buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_PrepareBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ u8 *pBuffer);
++
++/*
++ * ======== STRM_Reclaim ========
++ * Purpose:
++ * Request a buffer back from a stream.
++ * Parameters:
++ * hStrm: Stream handle returned from STRM_Open().
++ * pBufPtr: Location to store pointer to reclaimed buffer.
++ * pulBytes: Location where number of bytes of data in the
++ * buffer will be written.
++ * pulBufSize: Location where actual buffer size will be written.
++ * pdwArg: Location where user argument that travels with
++ * the buffer will be written.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_ETIMEOUT: A timeout occurred before a buffer could be
++ * retrieved.
++ * DSP_EFAIL: Failure occurred, unable to reclaim buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBufPtr != NULL.
++ * pulBytes != NULL.
++ * pdwArg != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm,
++ OUT u8 **pBufPtr, u32 *pulBytes,
++ u32 *pulBufSize, u32 *pdwArg);
++
++/*
++ * ======== STRM_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this stream.
++ * Parameters:
++ * hStrm: Stream handle returned by STRM_Open().
++ * uEventMask: Mask of types of events to be notified about.
++ * uNotifyType: Type of notification to be sent.
++ * hNotification: Handle to be used for notification.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EMEMORY: Insufficient memory on GPP.
++ * DSP_EVALUE: uEventMask is invalid.
++ * DSP_ENOTIMPL: Notification type specified by uNotifyType is not
++ * supported.
++ * Requires:
++ * STRM_Init(void) called.
++ * hNotification != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++/*
++ * ======== STRM_Select ========
++ * Purpose:
++ * Select a ready stream.
++ * Parameters:
++ * aStrmTab: Array of stream handles returned from STRM_Open().
++ * nStrms: Number of stream handles in array.
++ * pMask: Location to store mask of ready streams on output.
++ * uTimeout: Timeout value (milliseconds).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ERANGE: nStrms out of range.
++
++ * DSP_EHANDLE: Invalid stream handle in array.
++ * DSP_ETIMEOUT: A timeout occurred before a stream became ready.
++ * DSP_EFAIL: Failure occurred, unable to select a stream.
++ * Requires:
++ * STRM_Init(void) called.
++ * aStrmTab != NULL.
++ * nStrms > 0.
++ * pMask != NULL.
++ * Ensures:
++ * DSP_SOK: *pMask != 0 || uTimeout == 0.
++ * Error: *pMask == 0.
++ */
++ extern DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab,
++ u32 nStrms,
++ OUT u32 *pMask, u32 uTimeout);
++
++/*
++ * ======== STRM_UnprepareBuffer ========
++ * Purpose:
++ * Unprepare a data buffer that was previously prepared for a stream
++ * with DSPStream_PrepareBuffer(), and that will no longer be used with
++ * the stream.
++ * Parameter:
++ * hStrm: Stream handle returned from STRM_Open().
++ * uSize: Size (GPP bytes) of the buffer.
++ * pBuffer: Buffer address.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hStrm.
++ * DSP_EFAIL: Failure occurred, unable to unprepare buffer.
++ * Requires:
++ * STRM_Init(void) called.
++ * pBuffer != NULL.
++ * Ensures:
++ */
++ extern DSP_STATUS STRM_UnprepareBuffer(struct STRM_OBJECT *hStrm,
++ u32 uSize,
++ u8 *pBuffer);
++
++#endif /* STRM_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/strmdefs.h b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
+new file mode 100644
+index 0000000..44d217a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/strmdefs.h
+@@ -0,0 +1,57 @@
++/*
++ * strmdefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strmdefs.h ========
++ * Purpose:
++ * Global STRM constants and types.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Nov-2001 ag Added STRM_INFO..
++ *! 25-Sep-2000 jeh Created.
++ */
++
++#ifndef STRMDEFS_
++#define STRMDEFS_
++
++#define STRM_MAXEVTNAMELEN 32
++
++ struct STRM_MGR;
++
++ struct STRM_OBJECT;
++
++ struct STRM_ATTR {
++ HANDLE hUserEvent;
++ char *pstrEventName;
++ void *pVirtBase; /* Process virtual base address of
++ * mapped SM */
++ u32 ulVirtSize; /* Size of virtual space in bytes */
++ struct DSP_STREAMATTRIN *pStreamAttrIn;
++ } ;
++
++ struct STRM_INFO {
++ enum DSP_STRMMODE lMode; /* transport mode of
++ * stream(DMA, ZEROCOPY..) */
++ u32 uSegment; /* Segment strm allocs from. 0 is local mem */
++ void *pVirtBase; /* " " Stream'process virt base */
++ struct DSP_STREAMINFO *pUser; /* User's stream information
++ * returned */
++ } ;
++
++#endif /* STRMDEFS_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/sync.h b/arch/arm/plat-omap/include/dspbridge/sync.h
+new file mode 100644
+index 0000000..fa3ff8d
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/sync.h
+@@ -0,0 +1,340 @@
++/*
++ * sync.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== sync.h ========
++ * Purpose:
++ * Provide synchronization services.
++ *
++ * Public Functions:
++ * SYNC_CloseEvent
++ * SYNC_DeleteCS
++ * SYNC_EnterCS
++ * SYNC_Exit
++ * SYNC_Init
++ * SYNC_InitializeCS
++ * SYNC_LeaveCS
++ * SYNC_OpenEvent
++ * SYNC_PostMessage
++ * SYNC_ResetEvent
++ * SYNC_SetEvent
++ * SYNC_WaitOnEvent
++ * SYNC_WaitOnMultipleEvents
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
++ *! 01-Dec-1999 ag: Added #define SYNC_MAXNAMELENGTH.
++ *! 04-Nov-1999 kc: Added critical section functions and objects to SYNC.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 24-Sep-1999 kc: Added WinCE notes.
++ *! 20-Oct-1997 gp: Removed unused SYNC_ critical section and must complete fxns
++ *! Added SYNC_HOBJECT, SYNC_ATTRS, and object validation, and
++ *! merged SYNC_DestroyEvent into SYNC_CloseEvent, and merged
++ *! SYNC_CreateEvent into SYNC_OpenEvent.
++ *! 07-Oct-1997 gp: Added SYNC_Create/DestroyEvent (for NT testing).
++ *! 06-Oct-1997 gp: Added SYNC_OpenEvent.
++ *! 03-Jun-1997 gp: Added SYNC_{Begin|End}CritSection() functions.
++ *! 03-Jan-1997 gp: Added SYNC_INFINITE define.
++ *! 05-Aug-1996 gp: Created.
++ */
++
++#ifndef _SYNC_H
++#define _SYNC_H
++
++#define SIGNATURECS 0x53435953 /* "SYCS" (in reverse) */
++#define SIGNATUREDPCCS 0x53445953 /* "SYDS" (in reverse) */
++
++/* Special timeout value indicating an infinite wait: */
++#define SYNC_INFINITE 0xffffffff
++
++/* Maximum string length of a named event */
++#define SYNC_MAXNAMELENGTH 32
++
++/* Generic SYNC object: */
++ struct SYNC_OBJECT;
++
++/* Generic SYNC CS object: */
++struct SYNC_CSOBJECT {
++ u32 dwSignature; /* used for object validation */
++ struct semaphore sem;
++} ;
++
++/* SYNC object attributes: */
++ struct SYNC_ATTRS {
++ HANDLE hUserEvent; /* Platform's User Mode synch. object. */
++ HANDLE hKernelEvent; /* Platform's Kernel Mode sync. object. */
++ u32 dwReserved1; /* For future expansion. */
++ u32 dwReserved2; /* For future expansion. */
++ } ;
++
++/*
++ * ======== SYNC_CloseEvent ========
++ * Purpose:
++ * Close this event handle, freeing resources allocated in SYNC_OpenEvent
++ * if necessary.
++ * Parameters:
++ * hEvent: Handle to a synchronization event, created/opened in
++ * SYNC_OpenEvent.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EFAIL: Failed to close event handle.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ * Any subsequent usage of hEvent would be invalid.
++ */
++ extern DSP_STATUS SYNC_CloseEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_DeleteCS ========
++ * Purpose:
++ * Delete a critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_DeleteCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_EnterCS ========
++ * Purpose:
++ * Enter the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_EnterCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern void SYNC_Exit(void);
++
++/*
++ * ======== SYNC_Init ========
++ * Purpose:
++ * Initializes private state of SYNC module.
++ * Parameters:
++ * Returns:
++ * TRUE if initialized; FALSE if error occured.
++ * Requires:
++ * Ensures:
++ * SYNC initialized.
++ */
++ extern bool SYNC_Init(void);
++
++/*
++ * ======== SYNC_InitializeCS ========
++ * Purpose:
++ * Initialize the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Out of memory.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj);
++
++/*
++ * ======== SYNC_InitializeDPCCS ========
++ * Purpose:
++ * Initialize the critical section between process context and DPC.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Out of memory.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT
++ **phCSObj);
++
++/*
++ * ======== SYNC_LeaveCS ========
++ * Purpose:
++ * Leave the critical section.
++ * Parameters:
++ * hCSObj: critical section handle.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_LeaveCS(IN struct SYNC_CSOBJECT *hCSObj);
++
++/*
++ * ======== SYNC_OpenEvent ========
++ * Purpose:
++ * Create/open and initialize an event object for thread synchronization,
++ * which is initially in the non-signalled state.
++ * Parameters:
++ * phEvent: Pointer to location to receive the event object handle.
++ * pAttrs: Pointer to SYNC_ATTRS object containing initial SYNC
++ * SYNC_OBJECT attributes. If this pointer is NULL, then
++ * SYNC_OpenEvent will create and manage an OS specific
++ * syncronization object.
++ * pAttrs->hUserEvent: Platform's User Mode synchronization object.
++ *
++ * The behaviour of the SYNC methods depend on the value of
++ * the hUserEvent attr:
++ *
++ * 1. (hUserEvent == NULL):
++ * A user mode event is created.
++ * 2. (hUserEvent != NULL):
++ * A user mode event is supplied by the caller of SYNC_OpenEvent().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Unable to create user mode event.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EINVALIDARG SYNC_ATTRS values are invalid.
++ * Requires:
++ * - SYNC initialized.
++ * - phEvent != NULL.
++ * Ensures:
++ * If function succeeded, pEvent->hEvent must be a valid event handle.
++ */
++ extern DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
++ IN OPTIONAL struct SYNC_ATTRS
++ *pAttrs);
++
++/*
++ * ========= SYNC_PostMessage ========
++ * Purpose:
++ * To post a windows message
++ * Parameters:
++ * hWindow: Handle to the window
++ * uMsg: Message to be posted
++ * Returns:
++ * DSP_SOK: Success
++ * DSP_EFAIL: Post message failed
++ * DSP_EHANDLE: Invalid Window handle
++ * Requires:
++ * SYNC initialized
++ * Ensures
++ */
++ extern DSP_STATUS SYNC_PostMessage(IN HANDLE hWindow, IN u32 uMsg);
++
++/*
++ * ======== SYNC_ResetEvent ========
++ * Purpose:
++ * Reset a syncronization event object state to non-signalled.
++ * Parameters:
++ * hEvent: Handle to a sync event.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EFAIL: Failed to reset event.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_ResetEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_SetEvent ========
++ * Purpose:
++ * Signal the event. Will unblock one waiting thread.
++ * Parameters:
++ * hEvent: Handle to an event object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to signal event.
++ * DSP_EHANDLE: Invalid handle.
++ * Requires:
++ * SYNC initialized.
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_SetEvent(IN struct SYNC_OBJECT *hEvent);
++
++/*
++ * ======== SYNC_WaitOnEvent ========
++ * Purpose:
++ * Wait for an event to be signalled, up to the specified timeout.
++ * Parameters:
++ * hEvent: Handle to an event object.
++ * dwTimeOut: The time-out interval, in milliseconds.
++ * The function returns if the interval elapses, even if
++ * the object's state is nonsignaled.
++ * If zero, the function tests the object's state and
++ * returns immediately.
++ * If SYNC_INFINITE, the function's time-out interval
++ * never elapses.
++ * Returns:
++ * DSP_SOK: The object was signalled.
++ * DSP_EHANDLE: Invalid handle.
++ * SYNC_E_FAIL: Wait failed, possibly because the process terminated.
++ * SYNC_E_TIMEOUT: Timeout expired while waiting for event to be signalled.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_WaitOnEvent(IN struct SYNC_OBJECT *hEvent,
++ IN u32 dwTimeOut);
++
++/*
++ * ======== SYNC_WaitOnMultipleEvents ========
++ * Purpose:
++ * Wait for any of an array of events to be signalled, up to the
++ * specified timeout.
++ * Note: dwTimeOut must be SYNC_INFINITE to signal infinite wait.
++ * Parameters:
++ * hSyncEvents: Array of handles to event objects.
++ * uCount: Number of event handles.
++ * dwTimeOut: The time-out interval, in milliseconds.
++ * The function returns if the interval elapses, even if
++ * no event is signalled.
++ * If zero, the function tests the object's state and
++ * returns immediately.
++ * If SYNC_INFINITE, the function's time-out interval
++ * never elapses.
++ * puIndex: Location to store index of event that was signalled.
++ * Returns:
++ * DSP_SOK: The object was signalled.
++ * SYNC_E_FAIL: Wait failed, possibly because the process terminated.
++ * SYNC_E_TIMEOUT: Timeout expired before event was signalled.
++ * DSP_EMEMORY: Memory allocation failed.
++ * Requires:
++ * Ensures:
++ */
++ extern DSP_STATUS SYNC_WaitOnMultipleEvents(IN struct SYNC_OBJECT
++ **hSyncEvents,
++ IN u32 uCount,
++ IN u32 dwTimeout,
++ OUT u32 *puIndex);
++
++#endif /* _SYNC_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/util.h b/arch/arm/plat-omap/include/dspbridge/util.h
+new file mode 100644
+index 0000000..e6815ca
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/util.h
+@@ -0,0 +1,122 @@
++/*
++ * util.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== util.h ========
++ * Purpose:
++ * Provide general purpose utility functions.
++ *
++ * Public Functions:
++ * UTIL_CDTestDll
++ * UTIL_CmdLineToArgs
++ * UTIL_Exit
++ * UTIL_GetSysInfo
++ * UTIL_Init
++ */
++
++#ifndef _UTIL_H
++#define _UTIL_H
++
++#include <linux/delay.h>
++#include <linux/sched.h>
++
++#include <dspbridge/utildefs.h>
++
++/*
++ * ======== UTIL_CDTestDll ========
++ * Purpose:
++ * Provides test entry point in class driver context.
++ * Parameters:
++ * cArgc: test module command line input count.
++ * ppArgv: test module command line args.
++ * Returns:
++ * 0 if successful, a negative value otherwise.
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ */
++ extern u32 UTIL_CDTestDll(IN s32 cArgc, IN char **ppArgv);
++
++/*
++ * ======== UTIL_CmdLineToArgs ========
++ * Purpose:
++ * This function re-creates C-style cmd line argc & argv from WinMain()
++ * cmd line args.
++ * Parameters:
++ * s8 *pszProgName - The name of the program currently being executed.
++ * s8 *argv[] - The argument vector.
++ * s8 *pCmdLine - The pointer to the command line.
++ * bool fHasProgName - Indicats whether a program name is supplied.
++ * Returns:
++ * Returns the number of arguments found.
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ */
++ extern s32 UTIL_CmdLineToArgs(IN char *pszProgName,
++ IN char *argv[UTIL_MAXARGVS],
++ IN char *pCmdLine, IN bool fHasProgName);
++
++/*
++ * ======== UTIL_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ * Parameters:
++ * Returns:
++ * Requires:
++ * UTIL initialized.
++ * Ensures:
++ * Resources used by module are freed when cRef reaches zero.
++ */
++ extern inline void UTIL_Exit(void)
++ {
++ }
++/*
++ * ======== UTIL_GetSysInfo ========
++ * Purpose:
++ * This function return platform specific system information.
++ *
++ * Parameters:
++ * pSysInfo - address to store the system information.
++ * Returns:
++ * DSP_SOK
++ * S_FAIL
++ * Requires:
++ * UTIL initialized.
++ * pSysInfo != NULL
++ * Ensures:
++ */
++ extern DSP_STATUS UTIL_GetSysInfo(OUT struct UTIL_SYSINFO *pSysInfo);
++
++/*
++ * ======== UTIL_Init ========
++ * Purpose:
++ * Initializes private state of UTIL module.
++ * Parameters:
++ * Returns:
++ * TRUE if success, else FALSE.
++ * Requires:
++ * Ensures:
++ * UTIL initialized.
++ */
++ extern inline bool UTIL_Init(void)
++ {
++ return true;
++ }
++
++#endif /* _UTIL_H */
+diff --git a/arch/arm/plat-omap/include/dspbridge/utildefs.h b/arch/arm/plat-omap/include/dspbridge/utildefs.h
+new file mode 100644
+index 0000000..bd53a5a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/utildefs.h
+@@ -0,0 +1,51 @@
++/*
++ * utildefs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== utildefs.h ========
++ * Purpose:
++ * Global UTIL constants and types, shared between WCD and DSPSYS.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 kc Removed wIOPort* entries from UTIL_HOSTCONFIG.
++ *! 12-Aug-2000 ag Added UTIL_SYSINFO typedef.
++ *! 08-Oct-1999 rr Adopted for WinCE where test fxns will be added in util.h
++ *! 26-Dec-1996 cr Created.
++ */
++
++#ifndef UTILDEFS_
++#define UTILDEFS_
++
++/* constants taken from configmg.h */
++#define UTIL_MAXMEMREGS 9
++#define UTIL_MAXIOPORTS 20
++#define UTIL_MAXIRQS 7
++#define UTIL_MAXDMACHNLS 7
++
++/* misc. constants */
++#define UTIL_MAXARGVS 10
++
++/* Platform specific important info */
++ struct UTIL_SYSINFO {
++ /* Granularity of page protection; usually 1k or 4k */
++ u32 dwPageSize;
++ u32 dwAllocationGranularity; /* VM granularity, usually 64K */
++ u32 dwNumberOfProcessors; /* Used as sanity check */
++ } ;
++
++#endif /* UTILDEFS_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/uuidutil.h b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
+new file mode 100644
+index 0000000..af4aaec
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/uuidutil.h
+@@ -0,0 +1,74 @@
++/*
++ * uuidutil.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== uuidutil.h ========
++ * Description:
++ * This file contains the specification of UUID helper functions.
++ *
++ *! Revision History
++ *! ================
++ *! 09-Nov-2000 kc: Modified description of UUID utility functions.
++ *! 29-Sep-2000 kc: Appended "UUID_" prefix to UUID helper functions.
++ *! 10-Aug-2000 kc: Created.
++ *!
++ */
++
++#ifndef UUIDUTIL_
++#define UUIDUTIL_
++
++#define MAXUUIDLEN 37
++
++/*
++ * ======== UUID_UuidToString ========
++ * Purpose:
++ * Converts a DSP_UUID to an ANSI string.
++ * Parameters:
++ * pUuid: Pointer to a DSP_UUID object.
++ * pszUuid: Pointer to a buffer to receive a NULL-terminated UUID
++ * string.
++ * size: Maximum size of the pszUuid string.
++ * Returns:
++ * Requires:
++ * pUuid & pszUuid are non-NULL values.
++ * Ensures:
++ * Lenghth of pszUuid is less than MAXUUIDLEN.
++ * Details:
++ * UUID string limit currently set at MAXUUIDLEN.
++ */
++ void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
++ s32 size);
++
++/*
++ * ======== UUID_UuidFromString ========
++ * Purpose:
++ * Converts an ANSI string to a DSP_UUID.
++ * Parameters:
++ * pszUuid: Pointer to a string that represents a DSP_UUID object.
++ * pUuid: Pointer to a DSP_UUID object.
++ * Returns:
++ * Requires:
++ * pUuid & pszUuid are non-NULL values.
++ * Ensures:
++ * Details:
++ * We assume the string representation of a UUID has the following format:
++ * "12345678_1234_1234_1234_123456789abc".
++ */
++ extern void UUID_UuidFromString(IN char *pszUuid,
++ OUT struct DSP_UUID *pUuid);
++
++#endif /* UUIDUTIL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wcd.h b/arch/arm/plat-omap/include/dspbridge/wcd.h
+new file mode 100644
+index 0000000..5a7d47a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wcd.h
+@@ -0,0 +1,61 @@
++/*
++ * wcd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wcd.h ========
++ * Description:
++ * 'Bridge class driver library functions, object definitions, and
++ * return error/status codes. To be included by 'Bridge mini drivers.
++ *
++ * Public Functions:
++ * See mem.h and dbg.h.
++ *
++ * Notes:
++ * 'Bridge Class Driver services exported to WMD's are initialized by the
++ * WCD on behalf of the WMD. WMD's must not call module Init/Exit
++ * functions.
++ *
++ * To ensure WMD binary compatibility across different platforms,
++ * for the same processor, a WMD must restrict its usage of system
++ * services to those exported by the 'Bridge class library.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Jun-2000 jeh Added dev.h
++ *! 01-Nov-1999 ag: #WINCE# WCD_MAJOR_VERSION=8 & WCD_MINOR_VERSION=0 to match
++ *! dll stamps.
++ *! 0.80 - 0.89 Alpha, 0.90 - 0.99 Beta, 1.00 - 1.10 FCS.
++ *! 17-Sep-1997 gp: Changed size of CFG_HOSTRES structure; and ISR_Install API;
++ *! Changed WCD_MINOR_VERSION 3 -> 4.
++ *! 15-Sep-1997 gp: Moved WCD_(Un)registerMinidriver to drv.
++ *! 25-Jul-1997 cr: Added WCD_UnregisterMinidriver.
++ *! 22-Jul-1997 cr: Added WCD_RegisterMinidriver, WCD_MINOR_VERSION 2 -> 3.
++ *! 12-Nov-1996 gp: Defined port io macros.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 16-Jul-1996 gp: Added CHNL fxns; updated WCD lib version to 2.
++ *! 10-May-1996 gp: Separated WMD def.s' into wmd.h.
++ *! 03-May-1996 gp: Created.
++ */
++
++#ifndef WCD_
++#define WCD_
++
++/* This WCD Library Version: */
++#define WCD_MAJOR_VERSION (u32)8 /* .8x - Alpha, .9x - Beta, 1.x FCS */
++#define WCD_MINOR_VERSION (u32)0
++
++#endif /* WCD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wcdioctl.h b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+new file mode 100644
+index 0000000..04b13ab
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wcdioctl.h
+@@ -0,0 +1,519 @@
++/*
++ * wcdioctl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wcdioctl.h ========
++ * Purpose:
++ * Contains structures and commands that are used for interaction
++ * between the DDSP API and class driver.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping structs & offsets
++ *! 15-Oct-2002 kc Updated definitions for private PERF module.
++ *! 16-Aug-2002 map Added ARGS_MGR_REGISTEROBJECT & ARGS_MGR_UNREGISTEROBJECT
++ *! Added CMD_MGR_REGISTEROBJECT_OFFSET &
++ *! CMD_MGR_UNREGISTEROBJECT_OFFSET
++ *! 15-Jan-2002 ag Added actaul bufSize to ARGS_STRM_[RECLAIM][ISSUE].
++ *! 15-Nov-2001 ag change to STRMINFO in ARGS_STRM_GETINFO.
++ *! 11-Sep-2001 ag ARGS_CMM_GETHANDLE defn uses DSP_HPROCESSOR.
++ *! 23-Apr-2001 jeh Added pStatus to NODE_TERMINATE args.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name updates.
++ *! 22-Nov-2000 kc: Added CMD_MGR_GETPERF_DATA_OFFSET for acquiring PERF stats.
++ *! 27-Oct-2000 jeh Added timeouts to NODE_GETMESSAGE, NODE_PUTMESSAGE args.
++ *! Removed NODE_GETMESSAGESTRM args.
++ *! 11-Oct-2000 ag: Added SM mgr(CMM) args.
++ *! 27-Sep-2000 jeh Removed struct DSP_BUFFERATTR param from
++ *! ARGS_STRM_ALLOCATEBUFFER.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 07-Sep-2000 jeh Changed HANDLE to DSP_HNOTIFICATION in RegisterNotify args.
++ *! Added DSP_STRMATTR to DSPNode_Connect args.
++ *! 04-Aug-2000 rr: MEM and UTIL added to RM.
++ *! 27-Jul-2000 rr: NODE, MGR,STRM and PROC added
++ *! 27-Jun-2000 rr: Modifed to Use either PM or DSP/BIOS Bridge
++ *! IFDEF to build for PM or DSP/BIOS Bridge
++ *! 28-Jan-2000 rr: NT_CMD_FROM_OFFSET moved out to dsptrap.h
++ *! 24-Jan-2000 rr: Merged with Scott's code.
++ *! 21-Jan-2000 sg: In ARGS_CHNL_GETMODE changed mode to be u32 to be
++ *! consistent with chnldefs.h.
++ *! 11-Jan-2000 rr: CMD_CFG_GETCDVERSION_OFFSET added.
++ *! 12-Nov-1999 rr: CMD_BRD_MONITOR_OFFSET added
++ *! 09-Nov-1999 kc: Added MEMRY and enabled CMD_BRD_IOCTL_OFFSET.
++ *! 05-Nov-1999 ag: Added CHNL.
++ *! 02-Nov-1999 kc: Removed field from ARGS_UTIL_TESTDLL.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 08-Oct-1999 rr: Util control offsets added.
++ *! 13-Sep-1999 kc: Added ARGS_UTIL_TESTDLL for PM test infrastructure.
++ *! 19-Aug-1999 rr: Created from WSX. Minimal Implementaion of BRD_Start and BRD
++ *! and BRD_Stop. IOCTL Offsets and CTRL Code.
++ */
++
++#ifndef WCDIOCTL_
++#define WCDIOCTL_
++
++#include <dspbridge/mem.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/strmdefs.h>
++#include <dspbridge/dbdcd.h>
++
++union Trapped_Args {
++
++ /* MGR Module */
++ struct {
++ u32 uNode;
++ struct DSP_NDBPROPS __user *pNDBProps;
++ u32 uNDBPropsSize;
++ u32 __user *puNumNodes;
++ } ARGS_MGR_ENUMNODE_INFO;
++
++ struct {
++ u32 uProcessor;
++ struct DSP_PROCESSORINFO __user *pProcessorInfo;
++ u32 uProcessorInfoSize;
++ u32 __user *puNumProcs;
++ } ARGS_MGR_ENUMPROC_INFO;
++
++ struct {
++ struct DSP_UUID *pUuid;
++ enum DSP_DCDOBJTYPE objType;
++ char *pszPathName;
++ } ARGS_MGR_REGISTEROBJECT;
++
++ struct {
++ struct DSP_UUID *pUuid;
++ enum DSP_DCDOBJTYPE objType;
++ } ARGS_MGR_UNREGISTEROBJECT;
++
++ struct {
++ struct DSP_NOTIFICATION __user*__user *aNotifications;
++ u32 uCount;
++ u32 __user *puIndex;
++ u32 uTimeout;
++ } ARGS_MGR_WAIT;
++
++ /* PROC Module */
++ struct {
++ u32 uProcessor;
++ struct DSP_PROCESSORATTRIN __user *pAttrIn;
++ DSP_HPROCESSOR __user *phProcessor;
++ } ARGS_PROC_ATTACH;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 dwCmd;
++ struct DSP_CBDATA __user *pArgs;
++ } ARGS_PROC_CTRL;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_DETACH;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ DSP_HNODE __user *aNodeTab;
++ u32 uNodeTabSize;
++ u32 __user *puNumNodes;
++ u32 __user *puAllocated;
++ } ARGS_PROC_ENUMNODE_INFO;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 uResourceType;
++ struct DSP_RESOURCEINFO *pResourceInfo;
++ u32 uResourceInfoSize;
++ } ARGS_PROC_ENUMRESOURCES;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_PROCESSORSTATE __user *pProcStatus;
++ u32 uStateInfoSize;
++ } ARGS_PROC_GETSTATE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u8 __user *pBuf;
++
++ #ifndef RES_CLEANUP_DISABLE
++ u8 __user *pSize;
++ #endif
++ u32 uMaxSize;
++ } ARGS_PROC_GETTRACE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ s32 iArgc;
++ char __user*__user *aArgv;
++ char *__user *aEnvp;
++ } ARGS_PROC_LOAD;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_PROC_REGISTER_NOTIFY;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_START;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *__user *ppRsvAddr;
++ } ARGS_PROC_RSVMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *pRsvAddr;
++ } ARGS_PROC_UNRSVMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ void *pReqAddr;
++ void *__user *ppMapAddr;
++ u32 ulMapAttr;
++ } ARGS_PROC_MAPMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ u32 ulSize;
++ void *pMapAddr;
++ } ARGS_PROC_UNMAPMEM;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ u32 ulFlags;
++ } ARGS_PROC_FLUSHMEMORY;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ } ARGS_PROC_STOP;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ void *pMpuAddr;
++ u32 ulSize;
++ } ARGS_PROC_INVALIDATEMEMORY;
++
++
++ /* NODE Module */
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_UUID __user *pNodeID;
++ struct DSP_CBDATA __user *pArgs;
++ struct DSP_NODEATTRIN __user *pAttrIn;
++ DSP_HNODE __user *phNode;
++ } ARGS_NODE_ALLOCATE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uSize;
++ struct DSP_BUFFERATTR __user *pAttr;
++ u8 *__user *pBuffer;
++ } ARGS_NODE_ALLOCMSGBUF;
++
++ struct {
++ DSP_HNODE hNode;
++ s32 iPriority;
++ } ARGS_NODE_CHANGEPRIORITY;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uStream;
++ DSP_HNODE hOtherNode;
++ u32 uOtherStream;
++ struct DSP_STRMATTR __user *pAttrs;
++ struct DSP_CBDATA __user *pConnParam;
++ } ARGS_NODE_CONNECT;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_CREATE;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_DELETE;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_BUFFERATTR __user *pAttr;
++ u8 *pBuffer;
++ } ARGS_NODE_FREEMSGBUF;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_NODEATTR __user *pAttr;
++ u32 uAttrSize;
++ } ARGS_NODE_GETATTR;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_MSG __user *pMessage;
++ u32 uTimeout;
++ } ARGS_NODE_GETMESSAGE;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_PAUSE;
++
++ struct {
++ DSP_HNODE hNode;
++ struct DSP_MSG __user *pMessage;
++ u32 uTimeout;
++ } ARGS_NODE_PUTMESSAGE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_NODE_REGISTERNOTIFY;
++
++ struct {
++ DSP_HNODE hNode;
++ } ARGS_NODE_RUN;
++
++ struct {
++ DSP_HNODE hNode;
++ DSP_STATUS __user *pStatus;
++ } ARGS_NODE_TERMINATE;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct DSP_UUID __user *pNodeID;
++ struct DSP_NDBPROPS __user *pNodeProps;
++ } ARGS_NODE_GETUUIDPROPS;
++
++ /* STRM module */
++
++ struct {
++ DSP_HSTREAM hStream;
++ u32 uSize;
++ u8 *__user *apBuffer;
++ u32 uNumBufs;
++ } ARGS_STRM_ALLOCATEBUFFER;
++
++ struct {
++ DSP_HSTREAM hStream;
++ } ARGS_STRM_CLOSE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *__user *apBuffer;
++ u32 uNumBufs;
++ } ARGS_STRM_FREEBUFFER;
++
++ struct {
++ DSP_HSTREAM hStream;
++ HANDLE *phEvent;
++ } ARGS_STRM_GETEVENTHANDLE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ struct STRM_INFO __user *pStreamInfo;
++ u32 uStreamInfoSize;
++ } ARGS_STRM_GETINFO;
++
++ struct {
++ DSP_HSTREAM hStream;
++ bool bFlush;
++ } ARGS_STRM_IDLE;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *pBuffer;
++ u32 dwBytes;
++ u32 dwBufSize;
++ u32 dwArg;
++ } ARGS_STRM_ISSUE;
++
++ struct {
++ DSP_HNODE hNode;
++ u32 uDirection;
++ u32 uIndex;
++ struct STRM_ATTR __user *pAttrIn;
++ DSP_HSTREAM __user *phStream;
++ } ARGS_STRM_OPEN;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u8 *__user *pBufPtr;
++ u32 __user *pBytes;
++ u32 __user *pBufSize;
++ u32 __user *pdwArg;
++ } ARGS_STRM_RECLAIM;
++
++ struct {
++ DSP_HSTREAM hStream;
++ u32 uEventMask;
++ u32 uNotifyType;
++ struct DSP_NOTIFICATION __user *hNotification;
++ } ARGS_STRM_REGISTERNOTIFY;
++
++ struct {
++ DSP_HSTREAM __user *aStreamTab;
++ u32 nStreams;
++ u32 __user *pMask;
++ u32 uTimeout;
++ } ARGS_STRM_SELECT;
++
++ /* CMM Module */
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ u32 uSize;
++ struct CMM_ATTRS *pAttrs;
++ OUT void **ppBufVA;
++ } ARGS_CMM_ALLOCBUF;
++
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ void *pBufPA;
++ u32 ulSegId;
++ } ARGS_CMM_FREEBUF;
++
++ struct {
++ DSP_HPROCESSOR hProcessor;
++ struct CMM_OBJECT *__user *phCmmMgr;
++ } ARGS_CMM_GETHANDLE;
++
++ struct {
++ struct CMM_OBJECT *hCmmMgr;
++ struct CMM_INFO __user *pCmmInfo;
++ } ARGS_CMM_GETINFO;
++
++ /* MEM Module */
++ struct {
++ u32 cBytes;
++ enum MEM_POOLATTRS type;
++ void *pMem;
++ } ARGS_MEM_ALLOC;
++
++ struct {
++ u32 cBytes;
++ enum MEM_POOLATTRS type;
++ void *pMem;
++ } ARGS_MEM_CALLOC;
++
++ struct {
++ void *pMem;
++ } ARGS_MEM_FREE;
++
++ struct {
++ void *pBuffer;
++ u32 cSize;
++ void *pLockedBuffer;
++ } ARGS_MEM_PAGELOCK;
++
++ struct {
++ void *pBuffer;
++ u32 cSize;
++ } ARGS_MEM_PAGEUNLOCK;
++
++ /* UTIL module */
++ struct {
++ s32 cArgc;
++ char **ppArgv;
++ } ARGS_UTIL_TESTDLL;
++} ;
++
++#define CMD_BASE 1
++
++/* MGR module offsets */
++#define CMD_MGR_BASE_OFFSET CMD_BASE
++#define CMD_MGR_ENUMNODE_INFO_OFFSET (CMD_MGR_BASE_OFFSET + 0)
++#define CMD_MGR_ENUMPROC_INFO_OFFSET (CMD_MGR_BASE_OFFSET + 1)
++#define CMD_MGR_REGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 2)
++#define CMD_MGR_UNREGISTEROBJECT_OFFSET (CMD_MGR_BASE_OFFSET + 3)
++#define CMD_MGR_WAIT_OFFSET (CMD_MGR_BASE_OFFSET + 4)
++
++#ifndef RES_CLEANUP_DISABLE
++#define CMD_MGR_RESOUCES_OFFSET (CMD_MGR_BASE_OFFSET + 5)
++#define CMD_MGR_END_OFFSET CMD_MGR_RESOUCES_OFFSET
++#else
++#define CMD_MGR_END_OFFSET CMD_MGR_WAIT_OFFSET
++#endif
++
++#define CMD_PROC_BASE_OFFSET (CMD_MGR_END_OFFSET + 1)
++#define CMD_PROC_ATTACH_OFFSET (CMD_PROC_BASE_OFFSET + 0)
++#define CMD_PROC_CTRL_OFFSET (CMD_PROC_BASE_OFFSET + 1)
++#define CMD_PROC_DETACH_OFFSET (CMD_PROC_BASE_OFFSET + 2)
++#define CMD_PROC_ENUMNODE_OFFSET (CMD_PROC_BASE_OFFSET + 3)
++#define CMD_PROC_ENUMRESOURCES_OFFSET (CMD_PROC_BASE_OFFSET + 4)
++#define CMD_PROC_GETSTATE_OFFSET (CMD_PROC_BASE_OFFSET + 5)
++#define CMD_PROC_GETTRACE_OFFSET (CMD_PROC_BASE_OFFSET + 6)
++#define CMD_PROC_LOAD_OFFSET (CMD_PROC_BASE_OFFSET + 7)
++#define CMD_PROC_REGISTERNOTIFY_OFFSET (CMD_PROC_BASE_OFFSET + 8)
++#define CMD_PROC_START_OFFSET (CMD_PROC_BASE_OFFSET + 9)
++#define CMD_PROC_RSVMEM_OFFSET (CMD_PROC_BASE_OFFSET + 10)
++#define CMD_PROC_UNRSVMEM_OFFSET (CMD_PROC_BASE_OFFSET + 11)
++#define CMD_PROC_MAPMEM_OFFSET (CMD_PROC_BASE_OFFSET + 12)
++#define CMD_PROC_UNMAPMEM_OFFSET (CMD_PROC_BASE_OFFSET + 13)
++#define CMD_PROC_FLUSHMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 14)
++#define CMD_PROC_STOP_OFFSET (CMD_PROC_BASE_OFFSET + 15)
++#define CMD_PROC_INVALIDATEMEMORY_OFFSET (CMD_PROC_BASE_OFFSET + 16)
++#define CMD_PROC_END_OFFSET CMD_PROC_INVALIDATEMEMORY_OFFSET
++
++
++#define CMD_NODE_BASE_OFFSET (CMD_PROC_END_OFFSET + 1)
++#define CMD_NODE_ALLOCATE_OFFSET (CMD_NODE_BASE_OFFSET + 0)
++#define CMD_NODE_ALLOCMSGBUF_OFFSET (CMD_NODE_BASE_OFFSET + 1)
++#define CMD_NODE_CHANGEPRIORITY_OFFSET (CMD_NODE_BASE_OFFSET + 2)
++#define CMD_NODE_CONNECT_OFFSET (CMD_NODE_BASE_OFFSET + 3)
++#define CMD_NODE_CREATE_OFFSET (CMD_NODE_BASE_OFFSET + 4)
++#define CMD_NODE_DELETE_OFFSET (CMD_NODE_BASE_OFFSET + 5)
++#define CMD_NODE_FREEMSGBUF_OFFSET (CMD_NODE_BASE_OFFSET + 6)
++#define CMD_NODE_GETATTR_OFFSET (CMD_NODE_BASE_OFFSET + 7)
++#define CMD_NODE_GETMESSAGE_OFFSET (CMD_NODE_BASE_OFFSET + 8)
++#define CMD_NODE_PAUSE_OFFSET (CMD_NODE_BASE_OFFSET + 9)
++#define CMD_NODE_PUTMESSAGE_OFFSET (CMD_NODE_BASE_OFFSET + 10)
++#define CMD_NODE_REGISTERNOTIFY_OFFSET (CMD_NODE_BASE_OFFSET + 11)
++#define CMD_NODE_RUN_OFFSET (CMD_NODE_BASE_OFFSET + 12)
++#define CMD_NODE_TERMINATE_OFFSET (CMD_NODE_BASE_OFFSET + 13)
++#define CMD_NODE_GETUUIDPROPS_OFFSET (CMD_NODE_BASE_OFFSET + 14)
++#define CMD_NODE_END_OFFSET CMD_NODE_GETUUIDPROPS_OFFSET
++
++#define CMD_STRM_BASE_OFFSET (CMD_NODE_END_OFFSET + 1)
++#define CMD_STRM_ALLOCATEBUFFER_OFFSET (CMD_STRM_BASE_OFFSET + 0)
++#define CMD_STRM_CLOSE_OFFSET (CMD_STRM_BASE_OFFSET + 1)
++#define CMD_STRM_FREEBUFFER_OFFSET (CMD_STRM_BASE_OFFSET + 2)
++#define CMD_STRM_GETEVENTHANDLE_OFFSET (CMD_STRM_BASE_OFFSET + 3)
++#define CMD_STRM_GETINFO_OFFSET (CMD_STRM_BASE_OFFSET + 4)
++#define CMD_STRM_IDLE_OFFSET (CMD_STRM_BASE_OFFSET + 5)
++#define CMD_STRM_ISSUE_OFFSET (CMD_STRM_BASE_OFFSET + 6)
++#define CMD_STRM_OPEN_OFFSET (CMD_STRM_BASE_OFFSET + 7)
++#define CMD_STRM_RECLAIM_OFFSET (CMD_STRM_BASE_OFFSET + 8)
++#define CMD_STRM_REGISTERNOTIFY_OFFSET (CMD_STRM_BASE_OFFSET + 9)
++#define CMD_STRM_SELECT_OFFSET (CMD_STRM_BASE_OFFSET + 10)
++#define CMD_STRM_END_OFFSET CMD_STRM_SELECT_OFFSET
++
++/* Communication Memory Manager (UCMM) */
++#define CMD_CMM_BASE_OFFSET (CMD_STRM_END_OFFSET + 1)
++#define CMD_CMM_ALLOCBUF_OFFSET (CMD_CMM_BASE_OFFSET + 0)
++#define CMD_CMM_FREEBUF_OFFSET (CMD_CMM_BASE_OFFSET + 1)
++#define CMD_CMM_GETHANDLE_OFFSET (CMD_CMM_BASE_OFFSET + 2)
++#define CMD_CMM_GETINFO_OFFSET (CMD_CMM_BASE_OFFSET + 3)
++#define CMD_CMM_END_OFFSET CMD_CMM_GETINFO_OFFSET
++
++#define CMD_BASE_END_OFFSET CMD_CMM_END_OFFSET
++#endif /* WCDIOCTL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmd.h b/arch/arm/plat-omap/include/dspbridge/wmd.h
+new file mode 100644
+index 0000000..f584038
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmd.h
+@@ -0,0 +1,1193 @@
++/*
++ * wmd.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmd.h ========
++ * Purpose:
++ * 'Bridge mini driver entry point and interface function declarations.
++ *
++ * Public Functions:
++ * WMD_DRV_Entry
++ *
++ * Notes:
++ * The 'Bridge class driver obtains it's function interface to
++ * the 'Bridge mini driver via a call to WMD_DRV_Entry().
++ *
++ * 'Bridge Class Driver services exported to WMD's are initialized by the
++ * WCD on behalf of the WMD.
++ *
++ * WMD function DBC Requires and Ensures are also made by the WCD on
++ * behalf of the WMD, to simplify the WMD code.
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs - WMD_BRD_MemMap/UnMap
++ *! 01-Mar-2004 vp Added filename argument to WMD_DRV_Entry function.
++ *! 29-Aug-2002 map Added WMD_BRD_MemWrite()
++ *! 26-Aug-2002 map Added WMD_BRD_MemCopy()
++ *! 07-Jan-2002 ag Added cBufSize to WMD_CHNL_AddIOReq().
++ *! 05-Nov-2001 kc: Added error handling DEH functions.
++ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify().
++ *! 17-Nov-2000 jeh Added WMD_MSG and WMD_IO definitions.
++ *! 01-Nov-2000 jeh Added more error codes to WMD_CHNL_RegisterNotify().
++ *! 13-Oct-2000 jeh Added dwArg to WMD_CHNL_AddIOReq(), added WMD_CHNL_IDLE
++ *! and WMD_CHNL_RegisterNotify for DSPStream support.
++ *! 17-Jan-2000 rr: WMD_BRD_SETSTATE Added.
++ *! 30-Jul-1997 gp: Split wmd IOCTL space into reserved and private.
++ *! 07-Nov-1996 gp: Updated for code review.
++ *! 18-Oct-1996 gp: Added WMD_E_HARDWARE return code from WMD_BRD_Monitor.
++ *! 09-Sep-1996 gp: Subtly altered the semantics of WMD_CHNL_GetInfo().
++ *! 02-Aug-1996 gp: Ensured on BRD_Start that interrupts to the PC are enabled.
++ *! 11-Jul-1996 gp: Added CHNL interface. Note stronger DBC_Require conditions.
++ *! 29-May-1996 gp: Removed WCD_ prefix from functions imported from WCD.LIB.
++ *! 29-May-1996 gp: Made OUT param first in WMD_DEV_Create().
++ *! 09-May-1996 gp: Created.
++ */
++
++#ifndef WMD_
++#define WMD_
++
++#include <dspbridge/brddefs.h>
++#include <dspbridge/cfgdefs.h>
++#include <dspbridge/chnlpriv.h>
++#include <dspbridge/dehdefs.h>
++#include <dspbridge/devdefs.h>
++#include <dspbridge/iodefs.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * Any IOCTLS at or above this value are reserved for standard WMD
++ * interfaces.
++ */
++#define WMD_RESERVEDIOCTLBASE 0x8000
++
++/* Handle to mini-driver's private device context. */
++ struct WMD_DEV_CONTEXT;
++
++/*---------------------------------------------------------------------------*/
++/* 'Bridge MINI DRIVER FUNCTION TYPES */
++/*---------------------------------------------------------------------------*/
++
++/*
++ * ======== WMD_BRD_Monitor ========
++ * Purpose:
++ * Bring the board to the BRD_IDLE (monitor) state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_HARDWARE: A test of hardware assumptions/integrity failed.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_IDLE state;
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(
++ *WMD_BRD_MONITOR) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_BRD_SETSTATE ========
++ * Purpose:
++ * Sets the Mini driver state
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulBrdState: Board state
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * ulBrdState <= BRD_LASTSTATE.
++ * Ensures:
++ * ulBrdState <= BRD_LASTSTATE.
++ * Update the Board state to the specified state.
++ */
++ typedef DSP_STATUS(
++ *WMD_BRD_SETSTATE) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 ulBrdState);
++
++/*
++ * ======== WMD_BRD_Start ========
++ * Purpose:
++ * Bring board to the BRD_RUNNING (start) state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * dwDSPAddr: DSP address at which to start execution.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Board is in monitor (BRD_IDLE) state.
++ * Ensures:
++ * DSP_SOK: Board is in BRD_RUNNING state.
++ * Interrupts to the PC are enabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_START) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 dwDSPAddr);
++
++/*
++ * ======== WMD_BRD_MemCopy ========
++ * Purpose:
++ * Copy memory from one DSP address to another
++ * Parameters:
++ * pDevContext: Pointer to context handle
++ * ulDspDestAddr: DSP address to copy to
++ * ulDspSrcAddr: DSP address to copy from
++ * ulNumBytes: Number of bytes to copy
++ * ulMemType: What section of memory to copy to
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * pDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_RUNNING state.
++ * Interrupts to the PC are enabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMCOPY) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ u32 ulDspDestAddr,
++ u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType);
++/*
++ * ======== WMD_BRD_MemWrite ========
++ * Purpose:
++ * Write a block of host memory into a DSP address, into a given memory
++ * space. Unlike WMD_BRD_Write, this API does reset the DSP
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMWRITE) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_BRD_MemMap ========
++ * Purpose:
++ * Map a MPU memory region to a DSP/IVA memory space
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulMpuAddr: MPU memory region start address.
++ * ulVirtAddr: DSP/IVA memory region u8 address.
++ * ulNumBytes: Number of bytes to map.
++ * mapAttrs: Mapping attributes (e.g. endianness).
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMMAP) (struct WMD_DEV_CONTEXT
++ *hDevContext, u32 ulMpuAddr,
++ u32 ulVirtAddr, u32 ulNumBytes,
++ u32 ulMapAttrs);
++
++/*
++ * ======== WMD_BRD_MemUnMap ========
++ * Purpose:
++ * UnMap an MPU memory region from DSP/IVA memory space
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * ulVirtAddr: DSP/IVA memory region u8 address.
++ * ulNumBytes: Number of bytes to unmap.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_BRD_MEMUNMAP) (struct WMD_DEV_CONTEXT
++ *hDevContext,
++ u32 ulVirtAddr,
++ u32 ulNumBytes);
++
++/*
++ * ======== WMD_BRD_Stop ========
++ * Purpose:
++ * Bring board to the BRD_STOPPED state.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL
++ * Ensures:
++ * DSP_SOK: Board is in BRD_STOPPED (stop) state;
++ * Interrupts to the PC are disabled.
++ * else: Board state is indeterminate.
++ */
++ typedef DSP_STATUS(*WMD_BRD_STOP) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_BRD_Status ========
++ * Purpose:
++ * Report the current state of the board.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device context.
++ * pdwState: Ptr to BRD status variable.
++ * Returns:
++ * DSP_SOK:
++ * Requires:
++ * pdwState != NULL;
++ * hDevContext != NULL
++ * Ensures:
++ * *pdwState is one of {BRD_STOPPED, BRD_IDLE, BRD_RUNNING, BRD_UNKNOWN};
++ */
++ typedef DSP_STATUS(*
++ WMD_BRD_STATUS) (struct WMD_DEV_CONTEXT *hDevContext,
++ OUT BRD_STATUS * pdwState);
++
++/*
++ * ======== WMD_BRD_Read ========
++ * Purpose:
++ * Read a block of DSP memory, from a given memory space, into a host
++ * buffer.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * pHostBuf: Pointer to host buffer (Destination).
++ * dwDSPAddr: Address on DSP board (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP from which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ * Will not write more than ulNumBytes bytes into pHostBuf.
++ */
++typedef DSP_STATUS(*WMD_BRD_READ) (struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pHostBuf,
++ u32 dwDSPAddr,
++ u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_BRD_Write ========
++ * Purpose:
++ * Write a block of host memory into a DSP address, into a given memory
++ * space.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwDSPAddr: Address on DSP board (Destination).
++ * pHostBuf: Pointer to host buffer (Source).
++ * ulNumBytes: Number of bytes to transfer.
++ * ulMemType: Memory space on DSP to which to transfer.
++ * Returns:
++ * DSP_SOK: Success.
++ * WMD_E_TIMEOUT: Timeout occured waiting for a response from hardware.
++ * DSP_EFAIL: Other, unspecified error.
++ * Requires:
++ * hDevContext != NULL;
++ * pHostBuf != NULL.
++ * Ensures:
++ */
++typedef DSP_STATUS(*WMD_BRD_WRITE)(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pHostBuf,
++ u32 dwDSPAddr,
++ u32 ulNumBytes,
++ u32 ulMemType);
++
++/*
++ * ======== WMD_CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given 'Bridge board.
++ * Parameters:
++ * phChnlMgr: Location to store a channel manager object on output.
++ * hDevObject: Handle to a device object.
++ * pMgrAttrs: Channel manager attributes.
++ * pMgrAttrs->cChannels: Max channels
++ * pMgrAttrs->bIRQ: Channel's I/O IRQ number.
++ * pMgrAttrs->fShared: TRUE if the IRQ is shareable.
++ * pMgrAttrs->uWordSize: DSP Word size in equivalent PC bytes..
++ * pMgrAttrs->dwSMBase: Base physical address of shared memory, if any.
++ * pMgrAttrs->uSMLength: Bytes of shared memory block.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * CHNL_E_ISR: Unable to plug ISR for given IRQ.
++ * CHNL_E_NOMEMMAP: Couldn't map physical address to a virtual one.
++ * Requires:
++ * phChnlMgr != NULL.
++ * pMgrAttrs != NULL
++ * pMgrAttrs field are all valid:
++ * 0 < cChannels <= CHNL_MAXCHANNELS.
++ * bIRQ <= 15.
++ * uWordSize > 0.
++ * IsValidHandle(hDevObject)
++ * No channel manager exists for this board.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CREATE)(OUT struct CHNL_MGR
++ **phChnlMgr,
++ struct DEV_OBJECT
++ *hDevObject,
++ IN CONST struct
++ CHNL_MGRATTRS *pMgrAttrs);
++
++/*
++ * ======== WMD_CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ * Parameters:
++ * hChnlMgr: Channel manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr was invalid.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: Cancels I/O on each open channel. Closes each open channel.
++ * CHNL_Create may subsequently be called for the same device.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_DESTROY) (struct CHNL_MGR
++ *hChnlMgr);
++/*
++ * ======== WMD_DEH_Notify ========
++ * Purpose:
++ * When notified of DSP error, take appropriate action.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * ulEventMask: Indicate the type of exception
++ * dwErrInfo: Error information
++ * Returns:
++ *
++ * Requires:
++ * hDehMgr != NULL;
++ * ulEventMask with a valid exception
++ * Ensures:
++ */
++ typedef void (*WMD_DEH_NOTIFY)(struct DEH_MGR *hDehMgr,
++ u32 ulEventMask, u32 dwErrInfo);
++
++
++/*
++ * ======== WMD_CHNL_Open ========
++ * Purpose:
++ * Open a new half-duplex channel to the DSP board.
++ * Parameters:
++ * phChnl: Location to store a channel object handle.
++ * hChnlMgr: Handle to channel manager, as returned by CHNL_GetMgr().
++ * uMode: One of {CHNL_MODETODSP, CHNL_MODEFROMDSP} specifies
++ * direction of data transfer.
++ * uChnlId: If CHNL_PICKFREE is specified, the channel manager will
++ * select a free channel id (default);
++ * otherwise this field specifies the id of the channel.
++ * pAttrs: Channel attributes. Attribute fields are as follows:
++ * pAttrs->uIOReqs: Specifies the maximum number of I/O requests which can
++ * be pending at any given time. All request packets are
++ * preallocated when the channel is opened.
++ * pAttrs->hEvent: This field allows the user to supply an auto reset
++ * event object for channel I/O completion notifications.
++ * It is the responsibility of the user to destroy this
++ * object AFTER closing the channel.
++ * This channel event object can be retrieved using
++ * CHNL_GetEventHandle().
++ * pAttrs->hReserved: The kernel mode handle of this event object.
++ *
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: hChnlMgr is invalid.
++ * DSP_EMEMORY: Insufficient memory for requested resources.
++ * DSP_EINVALIDARG: Invalid number of IOReqs.
++ * CHNL_E_OUTOFSTREAMS: No free channels available.
++ * CHNL_E_BADCHANID: Channel ID is out of range.
++ * CHNL_E_CHANBUSY: Channel is in use.
++ * CHNL_E_NOIORPS: No free IO request packets available for
++ * queuing.
++ * Requires:
++ * phChnl != NULL.
++ * pAttrs != NULL.
++ * pAttrs->hEvent is a valid event handle.
++ * pAttrs->hReserved is the kernel mode handle for pAttrs->hEvent.
++ * Ensures:
++ * DSP_SOK: *phChnl is a valid channel.
++ * else: *phChnl is set to NULL if (phChnl != NULL);
++ */
++ typedef DSP_STATUS(*WMD_CHNL_OPEN) (OUT struct CHNL_OBJECT
++ **phChnl,
++ struct CHNL_MGR *hChnlMgr,
++ CHNL_MODE uMode,
++ u32 uChnlId,
++ CONST IN OPTIONAL struct
++ CHNL_ATTRS *pAttrs);
++
++/*
++ * ======== WMD_CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ * Parameters:
++ * hChnl: Handle to a channel object.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * No thread must be blocked on this channel's I/O completion event.
++ * Ensures:
++ * DSP_SOK: hChnl is no longer valid.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CLOSE) (struct CHNL_OBJECT *hChnl);
++
++/*
++ * ======== WMD_CHNL_AddIOReq ========
++ * Purpose:
++ * Enqueue an I/O request for data transfer on a channel to the DSP.
++ * The direction (mode) is specified in the channel object. Note the DSP
++ * address is specified for channels opened in direct I/O mode.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * pHostBuf: Host buffer address source.
++ * cBytes: Number of PC bytes to transfer. A zero value indicates
++ * that this buffer is the last in the output channel.
++ * A zero value is invalid for an input channel.
++ *! cBufSize: Actual buffer size in host bytes.
++ * dwDspAddr: DSP address for transfer. (Currently ignored).
++ * dwArg: A user argument that travels with the buffer.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pHostBuf is invalid.
++ * CHNL_E_NOEOS: User cannot mark EOS on an input channel.
++ * CHNL_E_CANCELLED: I/O has been cancelled on this channel. No further
++ * I/O is allowed.
++ * CHNL_E_EOS: End of stream was already marked on a previous
++ * IORequest on this channel. No further I/O is expected.
++ * CHNL_E_BUFSIZE: Buffer submitted to this output channel is larger than
++ * the size of the physical shared memory output window.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: The buffer will be transferred if the channel is ready;
++ * otherwise, will be queued for transfer when the channel becomes
++ * ready. In any case, notifications of I/O completion are
++ * asynchronous.
++ * If cBytes is 0 for an output channel, subsequent CHNL_AddIOReq's
++ * on this channel will fail with error code CHNL_E_EOS. The
++ * corresponding IOC for this I/O request will have its status flag
++ * set to CHNL_IOCSTATEOS.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_ADDIOREQ) (struct CHNL_OBJECT
++ *hChnl,
++ void *pHostBuf,
++ u32 cBytes,
++ u32 cBufSize,
++ OPTIONAL u32 dwDspAddr,
++ u32 dwArg);
++
++/*
++ * ======== WMD_CHNL_GetIOC ========
++ * Purpose:
++ * Dequeue an I/O completion record, which contains information about the
++ * completed I/O request.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: A value of CHNL_IOCNOWAIT will simply dequeue the
++ * first available IOC.
++ * pIOC: On output, contains host buffer address, bytes
++ * transferred, and status of I/O completion.
++ * pIOC->status: See chnldefs.h.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pIOC is invalid.
++ * CHNL_E_NOIOC: CHNL_IOCNOWAIT was specified as the dwTimeOut parameter
++ * yet no I/O completions were queued.
++ * Requires:
++ * dwTimeOut == CHNL_IOCNOWAIT.
++ * Ensures:
++ * DSP_SOK: if there are any remaining IOC's queued before this call
++ * returns, the channel event object will be left in a signalled
++ * state.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETIOC) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC);
++
++/*
++ * ======== WMD_CHNL_CancelIO ========
++ * Purpose:
++ * Return all I/O requests to the client which have not yet been
++ * transferred. The channel's I/O completion object is
++ * signalled, and all the I/O requests are queued as IOC's, with the
++ * status field set to CHNL_IOCSTATCANCEL.
++ * This call is typically used in abort situations, and is a prelude to
++ * CHNL_Close();
++ * Parameters:
++ * hChnl: Channel object handle.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * Ensures:
++ * Subsequent I/O requests to this channel will not be accepted.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_CANCELIO) (struct CHNL_OBJECT
++ *hChnl);
++
++/*
++ * ======== WMD_CHNL_FlushIO ========
++ * Purpose:
++ * For an output stream (to the DSP), indicates if any IO requests are in
++ * the output request queue. For input streams (from the DSP), will
++ * cancel all pending IO requests.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: Timeout value for flush operation.
++ * Returns:
++ * DSP_SOK: Success;
++ * S_CHNLIOREQUEST: Returned if any IORequests are in the output queue.
++ * DSP_EHANDLE: Invalid hChnl.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: No I/O requests will be pending on this channel.
++ */
++ typedef DSP_STATUS(*WMD_CHNL_FLUSHIO) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut);
++
++/*
++ * ======== WMD_CHNL_GetInfo ========
++ * Purpose:
++ * Retrieve information related to a channel.
++ * Parameters:
++ * hChnl: Handle to a valid channel object, or NULL.
++ * pInfo: Location to store channel info.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * DSP_EPOINTER: pInfo == NULL.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: pInfo points to a filled in CHNL_INFO struct,
++ * if (pInfo != NULL).
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETINFO) (struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO
++ *pChnlInfo);
++
++/*
++ * ======== WMD_CHNL_GetMgrInfo ========
++ * Purpose:
++ * Retrieve information related to the channel manager.
++ * Parameters:
++ * hChnlMgr: Handle to a valid channel manager, or NULL.
++ * uChnlID: Channel ID.
++ * pMgrInfo: Location to store channel manager info.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnlMgr.
++ * DSP_EPOINTER: pMgrInfo == NULL.
++ * CHNL_E_BADCHANID: Invalid channel ID.
++ * Requires:
++ * Ensures:
++ * DSP_SOK: pMgrInfo points to a filled in CHNL_MGRINFO
++ * struct, if (pMgrInfo != NULL).
++ */
++ typedef DSP_STATUS(*WMD_CHNL_GETMGRINFO) (struct CHNL_MGR
++ *hChnlMgr,
++ u32 uChnlID,
++ OUT struct CHNL_MGRINFO
++ *pMgrInfo);
++
++/*
++ * ======== WMD_CHNL_Idle ========
++ * Purpose:
++ * Idle a channel. If this is an input channel, or if this is an output
++ * channel and fFlush is TRUE, all currently enqueued buffers will be
++ * dequeued (data discarded for output channel).
++ * If this is an output channel and fFlush is FALSE, this function
++ * will block until all currently buffered data is output, or the timeout
++ * specified has been reached.
++ *
++ * Parameters:
++ * hChnl: Channel object handle.
++ * dwTimeOut: If output channel and fFlush is FALSE, timeout value
++ * to wait for buffers to be output. (Not used for
++ * input channel).
++ * fFlush: If output channel and fFlush is TRUE, discard any
++ * currently buffered data. If FALSE, wait for currently
++ * buffered data to be output, or timeout, whichever
++ * occurs first. fFlush is ignored for input channel.
++ * Returns:
++ * DSP_SOK: Success;
++ * DSP_EHANDLE: Invalid hChnl.
++ * CHNL_E_WAITTIMEOUT: Timeout occured before channel could be idled.
++ * Requires:
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_IDLE) (struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ bool fFlush);
++
++/*
++ * ======== WMD_CHNL_RegisterNotify ========
++ * Purpose:
++ * Register for notification of events on a channel.
++ * Parameters:
++ * hChnl: Channel object handle.
++ * uEventMask: Type of events to be notified about: IO completion
++ * (DSP_STREAMIOCOMPLETION) or end of stream
++ * (DSP_STREAMDONE).
++ * uNotifyType: DSP_SIGNALEVENT.
++ * hNotification: Handle of a DSP_NOTIFICATION object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * DSP_EVALUE: uEventMask is 0 and hNotification was not
++ * previously registered.
++ * DSP_EHANDLE: NULL hNotification, hNotification event name
++ * too long, or hNotification event name NULL.
++ * Requires:
++ * Valid hChnl.
++ * hNotification != NULL.
++ * (uEventMask & ~(DSP_STREAMIOCOMPLETION | DSP_STREAMDONE)) == 0.
++ * uNotifyType == DSP_SIGNALEVENT.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_CHNL_REGISTERNOTIFY)
++ (struct CHNL_OBJECT *hChnl,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_DEV_Create ========
++ * Purpose:
++ * Complete creation of the device object for this board.
++ * Parameters:
++ * phDevContext: Ptr to location to store a WMD device context.
++ * hDevObject: Handle to a Device Object, created and managed by WCD.
++ * pConfig: Ptr to configuration parameters provided by the Windows
++ * Configuration Manager during device loading.
++ * pDspConfig: DSP resources, as specified in the registry key for this
++ * device.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory for device context.
++ * WMD_E_BADCONFIG: One or more of the host or DSP configuration
++ * parameters did not satisfy hardware assumptions
++ * made by this WMD.
++ * Requires:
++ * phDevContext != NULL;
++ * hDevObject != NULL;
++ * pConfig != NULL;
++ * pDspConfig != NULL;
++ * Fields in pConfig and pDspConfig contain valid values.
++ * Ensures:
++ * DSP_SOK: All mini-driver specific DSP resource and other
++ * board context has been allocated.
++ * DSP_EMEMORY: WMD failed to allocate resources.
++ * Any acquired resources have been freed. The WCD will
++ * not call WMD_DEV_Destroy() if WMD_DEV_Create() fails.
++ * Details:
++ * Called during the CONFIGMG's Device_Init phase. Based on host and
++ * DSP configuration information, create a board context, a handle to
++ * which is passed into other WMD BRD and CHNL functions. The
++ * board context contains state information for the device. Since the
++ * addresses of all IN pointer parameters may be invalid when this
++ * function returns, they must not be stored into the device context
++ * structure.
++ */
++ typedef DSP_STATUS(*WMD_DEV_CREATE) (OUT struct WMD_DEV_CONTEXT
++ **phDevContext,
++ struct DEV_OBJECT
++ *hDevObject,
++ IN CONST struct CFG_HOSTRES
++ *pConfig,
++ IN CONST struct CFG_DSPRES
++ *pDspConfig);
++
++/*
++ * ======== WMD_DEV_Ctrl ========
++ * Purpose:
++ * Mini-driver specific interface.
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device info.
++ * dwCmd: WMD defined command code.
++ * pArgs: Pointer to an arbitrary argument structure.
++ * Returns:
++ * DSP_SOK or DSP_EFAIL. Actual command error codes should be passed back
++ * in the pArgs structure, and are defined by the WMD implementor.
++ * Requires:
++ * All calls are currently assumed to be synchronous. There are no
++ * IOCTL completion routines provided.
++ * Ensures:
++ */
++typedef DSP_STATUS(*WMD_DEV_CTRL)(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwCmd,
++ IN OUT void *pArgs);
++
++/*
++ * ======== WMD_DEV_Destroy ========
++ * Purpose:
++ * Deallocate WMD device extension structures and all other resources
++ * acquired by the mini-driver.
++ * No calls to other mini driver functions may subsequently
++ * occur, except for WMD_DEV_Create().
++ * Parameters:
++ * hDevContext: Handle to mini-driver defined device information.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Failed to release a resource previously acquired.
++ * Requires:
++ * hDevContext != NULL;
++ * Ensures:
++ * DSP_SOK: Device context is freed.
++ */
++ typedef DSP_STATUS(*WMD_DEV_DESTROY) (struct WMD_DEV_CONTEXT
++ *hDevContext);
++
++/*
++ * ======== WMD_DEH_Create ========
++ * Purpose:
++ * Create an object that manages DSP exceptions from the GPP.
++ * Parameters:
++ * phDehMgr: Location to store DEH manager on output.
++ * hDevObject: Handle to DEV object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * hDevObject != NULL;
++ * phDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_CREATE) (OUT struct DEH_MGR
++ **phDehMgr,
++ struct DEV_OBJECT
++ *hDevObject);
++
++/*
++ * ======== WMD_DEH_Destroy ========
++ * Purpose:
++ * Destroy the DEH object.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Destroy failed.
++ * Requires:
++ * hDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_DESTROY) (struct DEH_MGR *hDehMgr);
++
++/*
++ * ======== WMD_DEH_RegisterNotify ========
++ * Purpose:
++ * Register for DEH event notification.
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Destroy failed.
++ * Requires:
++ * hDehMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_REGISTERNOTIFY)
++ (struct DEH_MGR *hDehMgr,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_DEH_GetInfo ========
++ * Purpose:
++ * Get DSP exception info.
++ * Parameters:
++ * phDehMgr: Location to store DEH manager on output.
++ * pErrInfo: Ptr to error info structure.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * phDehMgr != NULL;
++ * pErrorInfo != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_DEH_GETINFO) (struct DEH_MGR *phDehMgr,
++ struct DSP_ERRORINFO *pErrInfo);
++
++/*
++ * ======== WMD_IO_Create ========
++ * Purpose:
++ * Create an object that manages I/O between CHNL and MSG.
++ * Parameters:
++ * phIOMgr: Location to store IO manager on output.
++ * hChnlMgr: Handle to channel manager.
++ * hMsgMgr: Handle to message manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * hDevObject != NULL;
++ * Channel manager already created;
++ * Message manager already created;
++ * pMgrAttrs != NULL;
++ * phIOMgr != NULL;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_CREATE) (OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++/*
++ * ======== WMD_IO_Destroy ========
++ * Purpose:
++ * Destroy object created in WMD_IO_Create.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Memory allocation failure.
++ * DSP_EFAIL: Creation failed.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_DESTROY) (struct IO_MGR *hIOMgr);
++
++/*
++ * ======== WMD_IO_OnLoaded ========
++ * Purpose:
++ * Called whenever a program is loaded to update internal data. For
++ * example, if shared memory is used, this function would update the
++ * shared memory location and address.
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal failure occurred.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_ONLOADED) (struct IO_MGR *hIOMgr);
++
++/*
++ * ======== WMD_IO_GETPROCLOAD ========
++ * Purpose:
++ * Called to get the Processor's current and predicted load
++ * Parameters:
++ * hIOMgr: IO Manager.
++ * pProcLoadStat Processor Load statistics
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EFAIL: Internal failure occurred.
++ * Requires:
++ * Valid hIOMgr;
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_IO_GETPROCLOAD)(struct IO_MGR *hIOMgr,
++ struct DSP_PROCLOADSTAT *pProcLoadStat);
++
++/*
++ * ======== WMD_MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ * Parameters:
++ * phMsgMgr: Location to store MSG manager on output.
++ * hDevObject: Handle to a device object.
++ * msgCallback: Called whenever an RMS_EXIT message is received.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * phMsgMgr != NULL.
++ * msgCallback != NULL.
++ * hDevObject != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_CREATE)
++ (OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++/*
++ * ======== WMD_MSG_CreateQueue ========
++ * Purpose:
++ * Create a MSG queue for sending or receiving messages from a Message
++ * node on the DSP.
++ * Parameters:
++ * hMsgMgr: MSG queue manager handle returned from
++ * WMD_MSG_Create.
++ * phMsgQueue: Location to store MSG queue on output.
++ * dwId: Identifier for messages (node environment pointer).
++ * uMaxMsgs: Max number of simultaneous messages for the node.
++ * h: Handle passed to hMsgMgr->msgCallback().
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * phMsgQueue != NULL.
++ * h != NULL.
++ * uMaxMsgs > 0.
++ * Ensures:
++ * phMsgQueue !=NULL <==> DSP_SOK.
++ */
++ typedef DSP_STATUS(*WMD_MSG_CREATEQUEUE)
++ (struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs, HANDLE h);
++
++/*
++ * ======== WMD_MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in WMD_MSG_Create().
++ * Parameters:
++ * hMsgMgr: Handle returned from WMD_MSG_Create().
++ * Returns:
++ * Requires:
++ * Valid hMsgMgr.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_DELETE) (struct MSG_MGR *hMsgMgr);
++
++/*
++ * ======== WMD_MSG_DeleteQueue ========
++ * Purpose:
++ * Delete a MSG queue allocated in WMD_MSG_CreateQueue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * Returns:
++ * Requires:
++ * Valid hMsgQueue.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_DELETEQUEUE) (struct MSG_QUEUE *hMsgQueue);
++
++/*
++ * ======== WMD_MSG_Get ========
++ * Purpose:
++ * Get a message from a MSG queue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * pMsg: Location to copy message into.
++ * uTimeout: Timeout to wait for a message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: Timeout occurred.
++ * DSP_EFAIL: No frames available for message (uMaxMessages too
++ * small).
++ * Requires:
++ * Valid hMsgQueue.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_GET) (struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== WMD_MSG_Put ========
++ * Purpose:
++ * Put a message onto a MSG queue.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * pMsg: Pointer to message.
++ * uTimeout: Timeout to wait for a message.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_ETIMEOUT: Timeout occurred.
++ * DSP_EFAIL: No frames available for message (uMaxMessages too
++ * small).
++ * Requires:
++ * Valid hMsgQueue.
++ * pMsg != NULL.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_PUT) (struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++/*
++ * ======== WMD_MSG_RegisterNotify ========
++ * Purpose:
++ * Register notification for when a message is ready.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * uEventMask: Type of events to be notified about: Must be
++ * DSP_NODEMESSAGEREADY, or 0 to unregister.
++ * uNotifyType: DSP_SIGNALEVENT.
++ * hNotification: Handle of notification object.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Insufficient memory.
++ * Requires:
++ * Valid hMsgQueue.
++ * hNotification != NULL.
++ * uNotifyType == DSP_SIGNALEVENT.
++ * uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0.
++ * Ensures:
++ */
++ typedef DSP_STATUS(*WMD_MSG_REGISTERNOTIFY)
++ (struct MSG_QUEUE *hMsgQueue,
++ u32 uEventMask, u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification);
++
++/*
++ * ======== WMD_MSG_SetQueueId ========
++ * Purpose:
++ * Set message queue id to node environment. Allows WMD_MSG_CreateQueue
++ * to be called in NODE_Allocate, before the node environment is known.
++ * Parameters:
++ * hMsgQueue: Handle to MSG queue returned from
++ * WMD_MSG_CreateQueue.
++ * dwId: Node environment pointer.
++ * Returns:
++ * Requires:
++ * Valid hMsgQueue.
++ * dwId != 0.
++ * Ensures:
++ */
++ typedef void(*WMD_MSG_SETQUEUEID) (struct MSG_QUEUE *hMsgQueue,
++ u32 dwId);
++
++/*
++ * 'Bridge Mini Driver (WMD) interface function table.
++ *
++ * The information in this table is filled in by the specific mini-driver,
++ * and copied into the 'Bridge class driver's own space. If any interface
++ * function field is set to a value of NULL, then the class driver will
++ * consider that function not implemented, and return the error code
++ * DSP_ENOTIMPL when a WMD client attempts to call that function.
++ *
++ * This function table contains WCD version numbers, which are used by the
++ * WMD loader to help ensure backwards compatility between older WMD's and a
++ * newer 'Bridge Class Driver. These must be set to WCD_MAJOR_VERSION
++ * and WCD_MINOR_VERSION, respectively.
++ *
++ * A mini-driver need not export a CHNL interface. In this case, *all* of
++ * the WMD_CHNL_* entries must be set to NULL.
++ */
++ struct WMD_DRV_INTERFACE {
++ u32 dwWCDMajorVersion; /* Set to WCD_MAJOR_VERSION. */
++ u32 dwWCDMinorVersion; /* Set to WCD_MINOR_VERSION. */
++ WMD_DEV_CREATE pfnDevCreate; /* Create device context */
++ WMD_DEV_DESTROY pfnDevDestroy; /* Destroy device context */
++ WMD_DEV_CTRL pfnDevCntrl; /* Optional vendor interface */
++ WMD_BRD_MONITOR pfnBrdMonitor; /* Load and/or start monitor */
++ WMD_BRD_START pfnBrdStart; /* Start DSP program. */
++ WMD_BRD_STOP pfnBrdStop; /* Stop/reset board. */
++ WMD_BRD_STATUS pfnBrdStatus; /* Get current board status. */
++ WMD_BRD_READ pfnBrdRead; /* Read board memory */
++ WMD_BRD_WRITE pfnBrdWrite; /* Write board memory. */
++ WMD_BRD_SETSTATE pfnBrdSetState; /* Sets the Board State */
++ WMD_BRD_MEMCOPY pfnBrdMemCopy; /* Copies DSP Memory */
++ WMD_BRD_MEMWRITE pfnBrdMemWrite; /* Write DSP Memory w/o halt */
++ WMD_BRD_MEMMAP pfnBrdMemMap; /* Maps MPU mem to DSP mem */
++ WMD_BRD_MEMUNMAP pfnBrdMemUnMap; /* Unmaps MPU mem to DSP mem */
++ WMD_CHNL_CREATE pfnChnlCreate; /* Create channel manager. */
++ WMD_CHNL_DESTROY pfnChnlDestroy; /* Destroy channel manager. */
++ WMD_CHNL_OPEN pfnChnlOpen; /* Create a new channel. */
++ WMD_CHNL_CLOSE pfnChnlClose; /* Close a channel. */
++ WMD_CHNL_ADDIOREQ pfnChnlAddIOReq; /* Req I/O on a channel. */
++ WMD_CHNL_GETIOC pfnChnlGetIOC; /* Wait for I/O completion. */
++ WMD_CHNL_CANCELIO pfnChnlCancelIO; /* Cancl I/O on a channel. */
++ WMD_CHNL_FLUSHIO pfnChnlFlushIO; /* Flush I/O. */
++ WMD_CHNL_GETINFO pfnChnlGetInfo; /* Get channel specific info */
++ /* Get channel manager info. */
++ WMD_CHNL_GETMGRINFO pfnChnlGetMgrInfo;
++ WMD_CHNL_IDLE pfnChnlIdle; /* Idle the channel */
++ /* Register for notif. */
++ WMD_CHNL_REGISTERNOTIFY pfnChnlRegisterNotify;
++ WMD_DEH_CREATE pfnDehCreate; /* Create DEH manager */
++ WMD_DEH_DESTROY pfnDehDestroy; /* Destroy DEH manager */
++ WMD_DEH_NOTIFY pfnDehNotify; /* Notify of DSP error */
++ /* register for deh notif. */
++ WMD_DEH_REGISTERNOTIFY pfnDehRegisterNotify;
++ WMD_DEH_GETINFO pfnDehGetInfo; /* register for deh notif. */
++ WMD_IO_CREATE pfnIOCreate; /* Create IO manager */
++ WMD_IO_DESTROY pfnIODestroy; /* Destroy IO manager */
++ WMD_IO_ONLOADED pfnIOOnLoaded; /* Notify of program loaded */
++ /* Get Processor's current and predicted load */
++ WMD_IO_GETPROCLOAD pfnIOGetProcLoad;
++ WMD_MSG_CREATE pfnMsgCreate; /* Create message manager */
++ /* Create message queue */
++ WMD_MSG_CREATEQUEUE pfnMsgCreateQueue;
++ WMD_MSG_DELETE pfnMsgDelete; /* Delete message manager */
++ /* Delete message queue */
++ WMD_MSG_DELETEQUEUE pfnMsgDeleteQueue;
++ WMD_MSG_GET pfnMsgGet; /* Get a message */
++ WMD_MSG_PUT pfnMsgPut; /* Send a message */
++ /* Register for notif. */
++ WMD_MSG_REGISTERNOTIFY pfnMsgRegisterNotify;
++ /* Set message queue id */
++ WMD_MSG_SETQUEUEID pfnMsgSetQueueId;
++ } ;
++
++/*
++ * ======== WMD_DRV_Entry ========
++ * Purpose:
++ * Registers WMD functions with the class driver. Called only once
++ * by the WCD. The caller will first check WCD version compatibility, and
++ * then copy the interface functions into its own memory space.
++ * Parameters:
++ * ppDrvInterface Pointer to a location to receive a pointer to the
++ * mini driver interface.
++ * Returns:
++ * Requires:
++ * The code segment this function resides in must expect to be discarded
++ * after completion.
++ * Ensures:
++ * ppDrvInterface pointer initialized to WMD's function interface.
++ * No system resources are acquired by this function.
++ * Details:
++ * Win95: Called during the Device_Init phase.
++ */
++ void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
++ IN CONST char *pstrWMDFileName);
++
++#endif /* WMD_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdchnl.h b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+new file mode 100644
+index 0000000..2c1f072
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdchnl.h
+@@ -0,0 +1,90 @@
++/*
++ * wmdchnl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdchnl.h ========
++ * Description:
++ * Declares the upper edge channel class library functions required by
++ * all WMD / WCD driver interface tables. These functions are implemented
++ * by every class of WMD channel library.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * The function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Jan-2002 ag Added cBufSize to WMD_CHNL_AddIOReq().
++ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
++ *! WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream
++ *! support.
++ *! 11-Jul-1996 gp: Created.
++ */
++
++#ifndef WMDCHNL_
++#define WMDCHNL_
++
++ extern DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS
++ *pMgrAttrs);
++
++ extern DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr);
++
++ extern DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
++ struct CHNL_MGR *hChnlMgr,
++ CHNL_MODE uMode,
++ u32 uChnlId,
++ CONST IN OPTIONAL struct CHNL_ATTRS
++ *pAttrs);
++
++ extern DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl);
++
++ extern DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl,
++ void *pHostBuf,
++ u32 cBytes, u32 cBufSize,
++ OPTIONAL u32 dwDspAddr,
++ u32 dwArg);
++
++ extern DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC);
++
++ extern DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl);
++
++ extern DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut);
++
++ extern DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO *pInfo);
++
++ extern DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr,
++ u32 uChnlID,
++ OUT struct CHNL_MGRINFO
++ *pMgrInfo);
++
++ extern DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl,
++ u32 dwTimeOut, bool fFlush);
++
++ extern DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++#endif /* WMDCHNL_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmddeh.h b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
+new file mode 100644
+index 0000000..dd50a3a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmddeh.h
+@@ -0,0 +1,64 @@
++/*
++ * wmddeh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmddeh.h ========
++ * Description:
++ * Defines upper edge DEH functions required by all WMD/WCD driver
++ * interface tables.
++ *
++ * Public Functions:
++ * WMD_DEH_Create
++ * IVA_DEH_Create
++ * WMD_DEH_Destroy
++ * WMD_DEH_GetInfo
++ * WMD_DEH_RegisterNotify
++ * WMD_DEH_Notify
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: added IVA_DEH_Create.
++ *! 13-Sep-2001 kc: created.
++ */
++
++#ifndef WMDDEH_
++#define WMDDEH_
++
++#include <dspbridge/devdefs.h>
++
++#include <dspbridge/dehdefs.h>
++
++ extern DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
++ struct DEV_OBJECT *hDevObject);
++
++ extern DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr);
++
++ extern DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
++ struct DSP_ERRORINFO *pErrInfo);
++
++ extern DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++ extern void WMD_DEH_Notify(struct DEH_MGR *hDehMgr,
++ u32 ulEventMask, u32 dwErrInfo);
++#endif /* WMDDEH_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdio.h b/arch/arm/plat-omap/include/dspbridge/wmdio.h
+new file mode 100644
+index 0000000..8525474
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdio.h
+@@ -0,0 +1,53 @@
++/*
++ * wmdio.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdio.h ========
++ * Description:
++ * Declares the upper edge IO functions required by
++ * all WMD / WCD driver interface tables.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 27-Feb-2004 vp Added IVA releated function.
++ *! 06-Nov-2000 jeh Created.
++ */
++
++#ifndef WMDIO_
++#define WMDIO_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/iodefs.h>
++
++ extern DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs);
++
++ extern DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr);
++
++ extern DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr);
++
++ extern DSP_STATUS IVA_IO_OnLoaded(struct IO_MGR *hIOMgr);
++ extern DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
++ OUT struct DSP_PROCLOADSTAT *pProcStat);
++
++#endif /* WMDIO_ */
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdioctl.h b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+new file mode 100644
+index 0000000..a41c61a
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdioctl.h
+@@ -0,0 +1,91 @@
++/*
++ * wmdioctl.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdioctl.h ========
++ * Description:
++ * BRIDGE Minidriver BRD_IOCtl reserved command definitions.
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb Updated HW typedefs
++ *! 16-Feb-2004 vp Added MMU endianness attributes to WMDIOCTL_EXTPROC
++ *! 21-Mar-2003 sb Changed WMDIOCTL_NUMOFMMUTLB from 7 to 32
++ *! 14-May-2001 sg Added codes for PWR.
++ *! 10-Aug-2001 ag Added _SETMMUCONFIG ioctl used for DSP-MMU init.
++ *! 16-Nov-1999 rajesh ?
++ *! 18-Jun-1998 ag Moved EMIF, SDRAM_C, & CE space init to ENBLEXTMEM ioctl.
++ *! Added ENBLEXTMEM, RESETDSP, UNRESETDSP & ASSERTSIG ioctls.
++ *! 07-Jun-1998 ag Added JTAG_SELECT, MAP_TBC, GET_CONFIGURATION ioctls.
++ *! 26-Jan-1998 jeh: Added START, RECV, and SEND ioctls.
++ *! 07-Nov-1997 nn: Added command to interrupt DSP for interrupt test.
++ *! 20-Oct-1997 nn: Added commands for getting and resetting interrupt count.
++ *! 17-Oct-1997 gp: Moved to src/wmd. Standardized prefix.
++ *! 08-Oct-1997 nn: Created.
++ */
++
++#ifndef WMDIOCTL_
++#define WMDIOCTL_
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* Any IOCTLS at or above this value are reserved for standard WMD interfaces.*/
++#define WMDIOCTL_RESERVEDBASE 0x8000
++
++#define WMDIOCTL_CHNLREAD (WMDIOCTL_RESERVEDBASE + 0x10)
++#define WMDIOCTL_CHNLWRITE (WMDIOCTL_RESERVEDBASE + 0x20)
++#define WMDIOCTL_GETINTRCOUNT (WMDIOCTL_RESERVEDBASE + 0x30)
++#define WMDIOCTL_RESETINTRCOUNT (WMDIOCTL_RESERVEDBASE + 0x40)
++#define WMDIOCTL_INTERRUPTDSP (WMDIOCTL_RESERVEDBASE + 0x50)
++#define WMDIOCTL_SETMMUCONFIG (WMDIOCTL_RESERVEDBASE + 0x60) /* DMMU */
++#define WMDIOCTL_PWRCONTROL (WMDIOCTL_RESERVEDBASE + 0x70) /* PWR */
++
++/* attention, modifiers:
++ * Some of these control enumerations are made visible to user for power
++ * control, so any changes to this list, should also be updated in the user
++ * header file 'dbdefs.h' ***/
++/* These ioctls are reserved for PWR power commands for the DSP */
++#define WMDIOCTL_DEEPSLEEP (WMDIOCTL_PWRCONTROL + 0x0)
++#define WMDIOCTL_EMERGENCYSLEEP (WMDIOCTL_PWRCONTROL + 0x1)
++#define WMDIOCTL_WAKEUP (WMDIOCTL_PWRCONTROL + 0x2)
++#define WMDIOCTL_PWRENABLE (WMDIOCTL_PWRCONTROL + 0x3)
++#define WMDIOCTL_PWRDISABLE (WMDIOCTL_PWRCONTROL + 0x4)
++#define WMDIOCTL_CLK_CTRL (WMDIOCTL_PWRCONTROL + 0x7)
++#define WMDIOCTL_PWR_HIBERNATE (WMDIOCTL_PWRCONTROL + 0x8) /*DSP Initiated
++ * Hibernate*/
++#define WMDIOCTL_PRESCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0x9)
++#define WMDIOCTL_POSTSCALE_NOTIFY (WMDIOCTL_PWRCONTROL + 0xA)
++#define WMDIOCTL_CONSTRAINT_REQUEST (WMDIOCTL_PWRCONTROL + 0xB)
++
++/* Number of actual DSP-MMU TLB entrries */
++#define WMDIOCTL_NUMOFMMUTLB 32
++
++struct WMDIOCTL_EXTPROC {
++ u32 ulDspVa; /* DSP virtual address */
++ u32 ulGppPa; /* GPP physical address */
++ /* GPP virtual address. __va does not work for ioremapped addresses */
++ u32 ulGppVa;
++ u32 ulSize; /* Size of the mapped memory in bytes */
++ enum HW_Endianism_t endianism;
++ enum HW_MMUMixedSize_t mixedMode;
++ enum HW_ElementSize_t elemSize;
++};
++
++#endif /* WMDIOCTL_ */
++
+diff --git a/arch/arm/plat-omap/include/dspbridge/wmdmsg.h b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+new file mode 100644
+index 0000000..81198d4
+--- /dev/null
++++ b/arch/arm/plat-omap/include/dspbridge/wmdmsg.h
+@@ -0,0 +1,70 @@
++/*
++ * wmdmsg.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== wmdmsg.h ========
++ * Description:
++ * Declares the upper edge message class library functions required by
++ * all WMD / WCD driver interface tables. These functions are
++ * implemented by every class of WMD channel library.
++ *
++ * Public Functions:
++ *
++ * Notes:
++ * Function comment headers reside with the function typedefs in wmd.h.
++ *
++ *! Revision History:
++ *! ================
++ *! 06-Dec-2000 jeh Added uEventMask to WMD_MSG_RegisterNotify(). Added
++ *! WMD_MSG_SetQueueId().
++ *! 17-Nov-2000 jeh Created.
++ */
++
++#ifndef WMDMSG_
++#define WMDMSG_
++
++#include <dspbridge/msgdefs.h>
++
++ extern DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject,
++ MSG_ONEXIT msgCallback);
++
++ extern DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs,
++ HANDLE h);
++
++ extern void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr);
++
++ extern void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue);
++
++ extern DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg, u32 uTimeout);
++
++ extern DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg,
++ u32 uTimeout);
++
++ extern DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue,
++ u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION
++ *hNotification);
++
++ extern void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId);
++
++#endif /* WMDMSG_ */
+diff --git a/drivers/Makefile b/drivers/Makefile
+index fec4d8e..6fcee09 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -42,6 +42,7 @@ obj-$(CONFIG_PARPORT) += parport/
+ obj-y += base/ block/ misc/ mfd/ net/ media/
+ obj-y += i2c/
+ obj-y += cbus/
++obj-$(CONFIG_MPU_BRIDGE) += dsp/bridge/
+ obj-$(CONFIG_NUBUS) += nubus/
+ obj-$(CONFIG_ATM) += atm/
+ obj-y += macintosh/
+diff --git a/drivers/dsp/bridge/Kbuild b/drivers/dsp/bridge/Kbuild
+new file mode 100644
+index 0000000..3432ff2
+--- /dev/null
++++ b/drivers/dsp/bridge/Kbuild
+@@ -0,0 +1,39 @@
++obj-$(CONFIG_MPU_BRIDGE) += bridgedriver.o
++
++libgen = gen/gb.o gen/gt.o gen/gs.o gen/gh.o gen/_gt_para.o gen/uuidutil.o
++libservices = services/csl.o services/mem.o services/list.o services/dpc.o \
++ services/kfile.o services/sync.o \
++ services/clk.o services/cfg.o services/reg.o \
++ services/regsup.o services/ntfy.o \
++ services/dbg.o services/services.o
++libwmd = wmd/chnl_sm.o wmd/msg_sm.o wmd/io_sm.o wmd/tiomap3430.o \
++ wmd/tiomap3430_pwr.o wmd/tiomap_sm.o wmd/tiomap_io.o \
++ wmd/mmu_fault.o wmd/ue_deh.o
++libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o pmgr/wcd.o \
++ pmgr/dmm.o pmgr/cmm.o pmgr/dbll.o
++librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \
++ rmgr/proc.o rmgr/pwr.o rmgr/rmm.o rmgr/strm.o rmgr/dspdrv.o \
++ rmgr/nldr.o rmgr/drv_interface.o
++libdload = dynload/cload.o dynload/getsection.o dynload/reloc.o
++libhw = hw/hw_prcm.o hw/hw_dspssC64P.o hw/hw_mmu.o hw/hw_mbox.o
++
++bridgedriver-objs = $(libgen) $(libservices) $(libwmd) $(libpmgr) $(librmgr) \
++ $(libdload) $(libhw)
++
++# Debug
++ifeq ($(CONFIG_BRIDGE_DEBUG),y)
++ccflags-y += -DGT_TRACE -DDEBUG
++endif
++
++#Machine dependent
++ccflags-y += -D_TI_ -D_DB_TIOMAP -DTMS32060 \
++ -DTICFG_PROC_VER -DTICFG_EVM_TYPE -DCHNL_SMCLASS \
++ -DCHNL_MESSAGES -DUSE_LEVEL_1_MACROS
++
++#Header files
++ccflags-y += -Idrivers/dsp/bridge/services
++ccflags-y += -Idrivers/dsp/bridge/wmd
++ccflags-y += -Idrivers/dsp/bridge/pmgr
++ccflags-y += -Idrivers/dsp/bridge/rmgr
++ccflags-y += -Idrivers/dsp/bridge/hw
++ccflags-y += -Iarch/arm
+diff --git a/drivers/dsp/bridge/Kconfig b/drivers/dsp/bridge/Kconfig
+new file mode 100644
+index 0000000..2fed82c
+--- /dev/null
++++ b/drivers/dsp/bridge/Kconfig
+@@ -0,0 +1,36 @@
++#
++# DSP Bridge Driver Support
++#
++
++menuconfig MPU_BRIDGE
++ tristate "DSP Bridge driver"
++ default n
++ help
++ DSP/BIOS Bridge is designed for platforms that contain a GPP and
++ one or more attached DSPs. The GPP is considered the master or
++ "host" processor, and the attached DSPs are processing resources
++ that can be utilized by applications and drivers running on the GPP.
++
++config BRIDGE_DVFS
++ bool "Enable Bridge Dynamic Voltage and Frequency Scaling (DVFS)"
++ depends on MPU_BRIDGE && OMAP_PM_SRF
++ default n
++ help
++ DVFS allows DSP Bridge to initiate the operating point change to
++ scale the chip voltage and frequency in order to match the
++ performance and power consumption to the current processing
++ requirements.
++
++config BRIDGE_MEMPOOL_SIZE
++ hex "Physical memory pool size (Byte)"
++ depends on MPU_BRIDGE
++ default 0x600000
++ help
++ Allocate specified size of memory at booting time to avoid allocation
++ failure under heavy memory fragmentation after some use time.
++
++config BRIDGE_DEBUG
++ bool "DSP Bridge Debug Support"
++ depends on MPU_BRIDGE
++ help
++ Say Y to enable Bridge debugging capabilities
+diff --git a/drivers/dsp/bridge/dynload/cload.c b/drivers/dsp/bridge/dynload/cload.c
+new file mode 100644
+index 0000000..271ab81
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/cload.c
+@@ -0,0 +1,1854 @@
++/*
++ * cload.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include "header.h"
++
++#include "module_list.h"
++#define LINKER_MODULES_HEADER ("_" MODULES_HEADER)
++
++/*
++ * we use the fact that DOFF section records are shaped just like
++ * LDR_SECTION_INFO to reduce our section storage usage. This macro marks
++ * the places where that assumption is made
++ */
++#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
++
++/*
++ * forward references
++ */
++static void dload_symbols(struct dload_state *dlthis);
++static void dload_data(struct dload_state *dlthis);
++static void allocate_sections(struct dload_state *dlthis);
++static void string_table_free(struct dload_state *dlthis);
++static void symbol_table_free(struct dload_state *dlthis);
++static void section_table_free(struct dload_state *dlthis);
++static void init_module_handle(struct dload_state *dlthis);
++#if BITS_PER_AU > BITS_PER_BYTE
++static char *unpack_name(struct dload_state *dlthis, u32 soffset);
++#endif
++
++static const char CINITNAME[] = { ".cinit" };
++static const char LOADER_DLLVIEW_ROOT[] = { "?DLModules?" };
++
++/*
++ * Error strings
++ */
++static const char E_READSTRM[] = { "Error reading %s from input stream" };
++static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
++static const char E_TGTALLOC[] =
++ { "Target memory allocate failed, section %s size " FMT_UI32 };
++static const char E_INITFAIL[] = { "%s to target address " FMT_UI32 " failed" };
++static const char E_DLVWRITE[] = { "Write to DLLview list failed" };
++static const char E_ICONNECT[] = { "Connect call to init interface failed" };
++static const char E_CHECKSUM[] = { "Checksum failed on %s" };
++
++/*************************************************************************
++ * Procedure dload_error
++ *
++ * Parameters:
++ * errtxt description of the error, printf style
++ * ... additional information
++ *
++ * Effect:
++ * Reports or records the error as appropriate.
++ ************************************************************************/
++void dload_error(struct dload_state *dlthis, const char *errtxt, ...)
++{
++ va_list args;
++
++ va_start(args, errtxt);
++ dlthis->mysym->Error_Report(dlthis->mysym, errtxt, args);
++ va_end(args);
++ dlthis->dload_errcount += 1;
++
++} /* dload_error */
++
++#define DL_ERROR(zza, zzb) dload_error(dlthis, zza, zzb)
++
++/*************************************************************************
++ * Procedure dload_syms_error
++ *
++ * Parameters:
++ * errtxt description of the error, printf style
++ * ... additional information
++ *
++ * Effect:
++ * Reports or records the error as appropriate.
++ ************************************************************************/
++void dload_syms_error(struct Dynamic_Loader_Sym *syms, const char *errtxt, ...)
++{
++ va_list args;
++
++ va_start(args, errtxt);
++ syms->Error_Report(syms, errtxt, args);
++ va_end(args);
++}
++
++/*************************************************************************
++ * Procedure Dynamic_Load_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new
++ * image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references
++ * resolved as necessary, and the resulting executable bits are placed
++ * into target memory using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle,
++ * and zero is returned. On error, the number of errors detected is
++ * returned. Individual errors are reported during the load process
++ * using syms->Error_Report().
++ ***********************************************************************/
++int Dynamic_Load_Module(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms ,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, DLOAD_mhandle *mhandle)
++{
++ register unsigned *dp, sz;
++ struct dload_state dl_state; /* internal state for this call */
++
++ /* blast our internal state */
++ dp = (unsigned *)&dl_state;
++ for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ /* Enable _only_ BSS initialization if enabled by user */
++ if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
++ dl_state.myoptions = DLOAD_INITBSS;
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ dload_error(&dl_state, "Required parameter is NULL");
++ } else {
++ dl_state.strm = module;
++ dl_state.mysym = syms;
++ dload_headers(&dl_state);
++ if (!dl_state.dload_errcount)
++ dload_strings(&dl_state, false);
++ if (!dl_state.dload_errcount)
++ dload_sections(&dl_state);
++
++ if (init && !dl_state.dload_errcount) {
++ if (init->connect(init)) {
++ dl_state.myio = init;
++ dl_state.myalloc = alloc;
++ /* do now, before reducing symbols */
++ allocate_sections(&dl_state);
++ } else
++ dload_error(&dl_state, E_ICONNECT);
++ }
++
++ if (!dl_state.dload_errcount) {
++ /* fix up entry point address */
++ unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
++ if (sref < dl_state.allocated_secn_count)
++ dl_state.dfile_hdr.df_entrypt +=
++ dl_state.ldr_sections[sref].run_addr;
++
++ dload_symbols(&dl_state);
++ }
++
++ if (init && !dl_state.dload_errcount)
++ dload_data(&dl_state);
++
++ init_module_handle(&dl_state);
++
++ if (dl_state.myio) {
++ if ((!dl_state.dload_errcount) &&
++ (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF)) {
++ if (init != NULL) {
++ if (!init->execute(init,
++ dl_state.dfile_hdr.df_entrypt))
++ dload_error(&dl_state,
++ "Init->Execute Failed");
++ } else {
++ dload_error(&dl_state, "init is NULL");
++ }
++ }
++ init->release(init);
++ }
++
++ symbol_table_free(&dl_state);
++ section_table_free(&dl_state);
++ string_table_free(&dl_state);
++
++ if (dl_state.dload_errcount) {
++ Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
++ init);
++ dl_state.myhandle = NULL;
++ }
++ }
++
++ if (mhandle)
++ *mhandle = dl_state.myhandle; /* give back the handle */
++
++ return dl_state.dload_errcount;
++} /* DLOAD_File */
++
++/*************************************************************************
++ * Procedure Dynamic_Open_Module
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ * init Target-side memory initialization
++ * options Option flags DLOAD_*
++ * mhandle A module handle for use with Dynamic_Unload
++ *
++ * Effect:
++ * The module image is read using *module. Target storage for the new
++ * image is
++ * obtained from *alloc. Symbols defined and referenced by the module are
++ * managed using *syms. The image is then relocated and references
++ * resolved as necessary, and the resulting executable bits are placed
++ * into target memory using *init.
++ *
++ * Returns:
++ * On a successful load, a module handle is placed in *mhandle,
++ * and zero is returned. On error, the number of errors detected is
++ * returned. Individual errors are reported during the load process
++ * using syms->Error_Report().
++ ***********************************************************************/
++int
++Dynamic_Open_Module(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init,
++ unsigned options, DLOAD_mhandle *mhandle)
++{
++ register unsigned *dp, sz;
++ struct dload_state dl_state; /* internal state for this call */
++
++ /* blast our internal state */
++ dp = (unsigned *)&dl_state;
++ for (sz = sizeof(dl_state) / sizeof(unsigned); sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ /* Enable _only_ BSS initialization if enabled by user */
++ if ((options & DLOAD_INITBSS) == DLOAD_INITBSS)
++ dl_state.myoptions = DLOAD_INITBSS;
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ dload_error(&dl_state, "Required parameter is NULL");
++ } else {
++ dl_state.strm = module;
++ dl_state.mysym = syms;
++ dload_headers(&dl_state);
++ if (!dl_state.dload_errcount)
++ dload_strings(&dl_state, false);
++ if (!dl_state.dload_errcount)
++ dload_sections(&dl_state);
++
++ if (init && !dl_state.dload_errcount) {
++ if (init->connect(init)) {
++ dl_state.myio = init;
++ dl_state.myalloc = alloc;
++ /* do now, before reducing symbols */
++ allocate_sections(&dl_state);
++ } else
++ dload_error(&dl_state, E_ICONNECT);
++ }
++
++ if (!dl_state.dload_errcount) {
++ /* fix up entry point address */
++ unsigned sref = dl_state.dfile_hdr.df_entry_secn - 1;
++ if (sref < dl_state.allocated_secn_count)
++ dl_state.dfile_hdr.df_entrypt +=
++ dl_state.ldr_sections[sref].run_addr;
++
++ dload_symbols(&dl_state);
++ }
++
++ init_module_handle(&dl_state);
++
++ if (dl_state.myio) {
++ if ((!dl_state.dload_errcount)
++ && (dl_state.dfile_hdr.df_entry_secn != DN_UNDEF))
++ if (!init->execute(init,
++ dl_state.dfile_hdr.df_entrypt))
++ dload_error(&dl_state,
++ "Init->Execute Failed");
++ init->release(init);
++ }
++
++ symbol_table_free(&dl_state);
++ section_table_free(&dl_state);
++ string_table_free(&dl_state);
++
++ if (dl_state.dload_errcount) {
++ Dynamic_Unload_Module(dl_state.myhandle, syms, alloc,
++ init);
++ dl_state.myhandle = NULL;
++ }
++ }
++
++ if (mhandle)
++ *mhandle = dl_state.myhandle; /* give back the handle */
++
++ return dl_state.dload_errcount;
++} /* DLOAD_File */
++
++/*************************************************************************
++ * Procedure dload_headers
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Loads the DOFF header and verify record. Deals with any byte-order
++ * issues and checks them for validity.
++ ************************************************************************/
++#define COMBINED_HEADER_SIZE (sizeof(struct doff_filehdr_t)+ \
++ sizeof(struct doff_verify_rec_t))
++
++void dload_headers(struct dload_state *dlthis)
++{
++ u32 map;
++
++ /* Read the header and the verify record as one. If we don't get it
++ all, we're done */
++ if (dlthis->strm->read_buffer(dlthis->strm, &dlthis->dfile_hdr,
++ COMBINED_HEADER_SIZE) != COMBINED_HEADER_SIZE) {
++ DL_ERROR(E_READSTRM, "File Headers");
++ return;
++ }
++ /*
++ * Verify that we have the byte order of the file correct.
++ * If not, must fix it before we can continue
++ */
++ map = REORDER_MAP(dlthis->dfile_hdr.df_byte_reshuffle);
++ if (map != REORDER_MAP(BYTE_RESHUFFLE_VALUE)) {
++ /* input is either byte-shuffled or bad */
++ if ((map & 0xFCFCFCFC) == 0) { /* no obviously bogus bits */
++ dload_reorder(&dlthis->dfile_hdr, COMBINED_HEADER_SIZE,
++ map);
++ }
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ BYTE_RESHUFFLE_VALUE) {
++ /* didn't fix the problem, the byte swap map is bad */
++ dload_error(dlthis,
++ "Bad byte swap map " FMT_UI32 " in header",
++ dlthis->dfile_hdr.df_byte_reshuffle);
++ return;
++ }
++ dlthis->reorder_map = map; /* keep map for future use */
++ }
++
++ /*
++ * Verify checksum of header and verify record
++ */
++ if (~dload_checksum(&dlthis->dfile_hdr,
++ sizeof(struct doff_filehdr_t)) ||
++ ~dload_checksum(&dlthis->verify,
++ sizeof(struct doff_verify_rec_t))) {
++ DL_ERROR(E_CHECKSUM, "header or verify record");
++ return;
++ }
++#if HOST_ENDIANNESS
++ dlthis->dfile_hdr.df_byte_reshuffle = map; /* put back for later */
++#endif
++
++ /* Check for valid target ID */
++ if ((dlthis->dfile_hdr.df_target_id != TARGET_ID) &&
++ -(dlthis->dfile_hdr.df_target_id != TMS470_ID)) {
++ dload_error(dlthis, "Bad target ID 0x%x and TARGET_ID 0x%x",
++ dlthis->dfile_hdr.df_target_id, TARGET_ID);
++ return;
++ }
++ /* Check for valid file format */
++ if ((dlthis->dfile_hdr.df_doff_version != DOFF0)) {
++ dload_error(dlthis, "Bad DOFF version 0x%x",
++ dlthis->dfile_hdr.df_doff_version);
++ return;
++ }
++
++ /*
++ * Apply reasonableness checks to count fields
++ */
++ if (dlthis->dfile_hdr.df_strtab_size > MAX_REASONABLE_STRINGTAB) {
++ dload_error(dlthis, "Excessive string table size " FMT_UI32,
++ dlthis->dfile_hdr.df_strtab_size);
++ return;
++ }
++ if (dlthis->dfile_hdr.df_no_scns > MAX_REASONABLE_SECTIONS) {
++ dload_error(dlthis, "Excessive section count 0x%x",
++ dlthis->dfile_hdr.df_no_scns);
++ return;
++ }
++#ifndef TARGET_ENDIANNESS
++ /*
++ * Check that endianness does not disagree with explicit specification
++ */
++ if ((dlthis->dfile_hdr.df_flags >> ALIGN_COFF_ENDIANNESS) &
++ dlthis->myoptions & ENDIANNESS_MASK) {
++ dload_error(dlthis,
++ "Input endianness disagrees with specified option");
++ return;
++ }
++ dlthis->big_e_target = dlthis->dfile_hdr.df_flags & DF_BIG;
++#endif
++
++} /* dload_headers */
++
++/* COFF Section Processing
++ *
++ * COFF sections are read in and retained intact. Each record is embedded
++ * in a new structure that records the updated load and
++ * run addresses of the section */
++
++static const char SECN_ERRID[] = { "section" };
++
++/*************************************************************************
++ * Procedure dload_sections
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Loads the section records into an internal table.
++ ************************************************************************/
++void
++dload_sections(struct dload_state *dlthis)
++{
++ s16 siz;
++ struct doff_scnhdr_t *shp;
++ unsigned nsecs = dlthis->dfile_hdr.df_no_scns;
++
++ /* allocate space for the DOFF section records */
++ siz = nsecs * sizeof(struct doff_scnhdr_t);
++ shp = (struct doff_scnhdr_t *)dlthis->mysym->Allocate(dlthis->mysym,
++ siz);
++ if (!shp) { /* not enough storage */
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ dlthis->sect_hdrs = shp;
++
++ /* read in the section records */
++ if (dlthis->strm->read_buffer(dlthis->strm, shp, siz) != siz) {
++ DL_ERROR(E_READSTRM, SECN_ERRID);
++ return;
++ }
++
++ /* if we need to fix up byte order, do it now */
++ if (dlthis->reorder_map)
++ dload_reorder(shp, siz, dlthis->reorder_map);
++
++ /* check for validity */
++ if (~dload_checksum(dlthis->sect_hdrs, siz) !=
++ dlthis->verify.dv_scn_rec_checksum) {
++ DL_ERROR(E_CHECKSUM, SECN_ERRID);
++ return;
++ }
++
++} /* dload_sections */
++
++/*****************************************************************************
++ * Procedure allocate_sections
++ *
++ * Parameters:
++ * alloc target memory allocator class
++ *
++ * Effect:
++ * Assigns new (target) addresses for sections
++ *****************************************************************************/
++static void allocate_sections(struct dload_state *dlthis)
++{
++ u16 curr_sect, nsecs, siz;
++ struct doff_scnhdr_t *shp;
++ struct LDR_SECTION_INFO *asecs;
++ struct my_handle *hndl;
++ nsecs = dlthis->dfile_hdr.df_no_scns;
++ if (!nsecs)
++ return;
++ if ((dlthis->myalloc == NULL) &&
++ (dlthis->dfile_hdr.df_target_scns > 0)) {
++ DL_ERROR("Arg 3 (alloc) required but NULL", 0);
++ return;
++ }
++ /* allocate space for the module handle, which we will
++ * keep for unload purposes */
++ siz = dlthis->dfile_hdr.df_target_scns *
++ sizeof(struct LDR_SECTION_INFO) + MY_HANDLE_SIZE;
++ hndl = (struct my_handle *)dlthis->mysym->Allocate(dlthis->mysym, siz);
++ if (!hndl) { /* not enough storage */
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ /* initialize the handle header */
++ hndl->dm.hnext = hndl->dm.hprev = hndl; /* circular list */
++ hndl->dm.hroot = NULL;
++ hndl->dm.dbthis = 0;
++ dlthis->myhandle = hndl; /* save away for return */
++ /* pointer to the section list of allocated sections */
++ dlthis->ldr_sections = asecs = hndl->secns;
++ /* * Insert names into all sections, make copies of
++ the sections we allocate */
++ shp = dlthis->sect_hdrs;
++ for (curr_sect = 0; curr_sect < nsecs; curr_sect++) {
++ u32 soffset = shp->ds_offset;
++#if BITS_PER_AU <= BITS_PER_BYTE
++ /* attempt to insert the name of this section */
++ if (soffset < dlthis->dfile_hdr.df_strtab_size)
++ DOFFSEC_IS_LDRSEC(shp)->name = dlthis->str_head +
++ soffset;
++ else {
++ dload_error(dlthis, "Bad name offset in section %d",
++ curr_sect);
++ DOFFSEC_IS_LDRSEC(shp)->name = NULL;
++ }
++#endif
++ /* allocate target storage for sections that require it */
++ if (DS_NEEDS_ALLOCATION(shp)) {
++ *asecs = *DOFFSEC_IS_LDRSEC(shp);
++ asecs->context = 0; /* zero the context field */
++#if BITS_PER_AU > BITS_PER_BYTE
++ asecs->name = unpack_name(dlthis, soffset);
++ dlthis->debug_string_size = soffset + dlthis->temp_len;
++#else
++ dlthis->debug_string_size = soffset;
++#endif
++ if (dlthis->myalloc != NULL) {
++ if (!dlthis->myalloc->Allocate(dlthis->myalloc, asecs,
++ DS_ALIGNMENT(asecs->type))) {
++ dload_error(dlthis, E_TGTALLOC, asecs->name,
++ asecs->size);
++ return;
++ }
++ }
++ /* keep address deltas in original section table */
++ shp->ds_vaddr = asecs->load_addr - shp->ds_vaddr;
++ shp->ds_paddr = asecs->run_addr - shp->ds_paddr;
++ dlthis->allocated_secn_count += 1;
++ } /* allocate target storage */
++ shp += 1;
++ asecs += 1;
++ }
++#if BITS_PER_AU <= BITS_PER_BYTE
++ dlthis->debug_string_size +=
++ strlen(dlthis->str_head + dlthis->debug_string_size) + 1;
++#endif
++} /* allocate sections */
++
++/*************************************************************************
++ * Procedure section_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the symbol table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ ************************************************************************/
++static void section_table_free(struct dload_state *dlthis)
++{
++ struct doff_scnhdr_t *shp;
++
++ shp = dlthis->sect_hdrs;
++ if (shp)
++ dlthis->mysym->Deallocate(dlthis->mysym, shp);
++
++} /* section_table_free */
++
++/*************************************************************************
++ * Procedure dload_strings
++ *
++ * Parameters:
++ * sec_names_only If true only read in the "section names"
++ * portion of the string table
++ *
++ * Effect:
++ * Loads the DOFF string table into memory. DOFF keeps all strings in a
++ * big unsorted array. We just read that array into memory in bulk.
++ ************************************************************************/
++static const char S_STRINGTBL[] = { "string table" };
++void dload_strings(struct dload_state *dlthis, boolean sec_names_only)
++{
++ u32 ssiz;
++ char *strbuf;
++
++ if (sec_names_only) {
++ ssiz = BYTE_TO_HOST(DOFF_ALIGN
++ (dlthis->dfile_hdr.df_scn_name_size));
++ } else {
++ ssiz = BYTE_TO_HOST(DOFF_ALIGN
++ (dlthis->dfile_hdr.df_strtab_size));
++ }
++ if (ssiz == 0)
++ return;
++
++ /* get some memory for the string table */
++#if BITS_PER_AU > BITS_PER_BYTE
++ strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz +
++ dlthis->dfile_hdr.df_max_str_len);
++#else
++ strbuf = (char *)dlthis->mysym->Allocate(dlthis->mysym, ssiz);
++#endif
++ if (strbuf == NULL) {
++ DL_ERROR(E_ALLOC, ssiz);
++ return;
++ }
++ dlthis->str_head = strbuf;
++#if BITS_PER_AU > BITS_PER_BYTE
++ dlthis->str_temp = strbuf + ssiz;
++#endif
++ /* read in the strings and verify them */
++ if ((unsigned)(dlthis->strm->read_buffer(dlthis->strm, strbuf,
++ ssiz)) != ssiz) {
++ DL_ERROR(E_READSTRM, S_STRINGTBL);
++ }
++ /* if we need to fix up byte order, do it now */
++#ifndef _BIG_ENDIAN
++ if (dlthis->reorder_map)
++ dload_reorder(strbuf, ssiz, dlthis->reorder_map);
++
++ if ((!sec_names_only) && (~dload_checksum(strbuf, ssiz) !=
++ dlthis->verify.dv_str_tab_checksum)) {
++ DL_ERROR(E_CHECKSUM, S_STRINGTBL);
++ }
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ HOST_BYTE_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
++ /* put strings in big-endian order, not in PC order */
++ dload_reorder(strbuf, ssiz, HOST_BYTE_ORDER(dlthis->dfile_hdr.
++ df_byte_reshuffle));
++ }
++ if ((!sec_names_only) && (~dload_reverse_checksum(strbuf, ssiz) !=
++ dlthis->verify.dv_str_tab_checksum)) {
++ DL_ERROR(E_CHECKSUM, S_STRINGTBL);
++ }
++#endif
++} /* dload_strings */
++
++/*************************************************************************
++ * Procedure string_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the string table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ *************************************************************************/
++static void string_table_free(struct dload_state *dlthis)
++{
++ if (dlthis->str_head)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
++
++} /* string_table_free */
++
++/*
++ * Symbol Table Maintenance Functions
++ *
++ * COFF symbols are read by dload_symbols(), which is called after
++ * sections have been allocated. Symbols which might be used in
++ * relocation (ie, not debug info) are retained in an internal temporary
++ * compressed table (type Local_Symbol). A particular symbol is recovered
++ * by index by calling dload_find_symbol(). dload_find_symbol
++ * reconstructs a more explicit representation (type SLOTVEC) which is
++ * used by reloc.c
++ */
++/* real size of debug header */
++#define DBG_HDR_SIZE (sizeof(struct dll_module) - sizeof(struct dll_sect))
++
++static const char SYM_ERRID[] = { "symbol" };
++
++/**************************************************************************
++ * Procedure dload_symbols
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Reads in symbols and retains ones that might be needed for relocation
++ * purposes.
++ ************************************************************************/
++/* size of symbol buffer no bigger than target data buffer, to limit stack
++ * usage*/
++#define MY_SYM_BUF_SIZ (BYTE_TO_HOST(IMAGE_PACKET_SIZE)/\
++ sizeof(struct doff_syment_t))
++
++static void dload_symbols(struct dload_state *dlthis)
++{
++ u32 s_count, siz, dsiz, symbols_left;
++ u32 checks;
++ struct Local_Symbol *sp;
++ struct dynload_symbol *symp;
++ struct dynload_symbol *newsym;
++
++ s_count = dlthis->dfile_hdr.df_no_syms;
++ if (s_count == 0)
++ return;
++
++ /* We keep a local symbol table for all of the symbols in the input.
++ * This table contains only section & value info, as we do not have
++ * to do any name processing for locals. We reuse this storage
++ * as a temporary for .dllview record construction.
++ * Allocate storage for the whole table.*/
++ siz = s_count * sizeof(struct Local_Symbol);
++ dsiz = DBG_HDR_SIZE +
++ (sizeof(struct dll_sect) * dlthis->allocated_secn_count) +
++ BYTE_TO_HOST_ROUND(dlthis->debug_string_size + 1);
++ if (dsiz > siz)
++ siz = dsiz; /* larger of symbols and .dllview temp */
++ sp = (struct Local_Symbol *)dlthis->mysym->Allocate(dlthis->mysym, siz);
++ if (!sp) {
++ DL_ERROR(E_ALLOC, siz);
++ return;
++ }
++ dlthis->local_symtab = sp;
++ /* Read the symbols in the input, store them in the table, and post any
++ * globals to the global symbol table. In the process, externals
++ become defined from the global symbol table */
++ checks = dlthis->verify.dv_sym_tab_checksum;
++ symbols_left = s_count;
++ do { /* read all symbols */
++ char *sname;
++ u32 val;
++ s32 delta;
++ struct doff_syment_t *input_sym;
++ unsigned syms_in_buf;
++ struct doff_syment_t my_sym_buf[MY_SYM_BUF_SIZ];
++ input_sym = my_sym_buf;
++ syms_in_buf = symbols_left > MY_SYM_BUF_SIZ ?
++ MY_SYM_BUF_SIZ : symbols_left;
++ siz = syms_in_buf * sizeof(struct doff_syment_t);
++ if (dlthis->strm->read_buffer(dlthis->strm, input_sym, siz) !=
++ siz) {
++ DL_ERROR(E_READSTRM, SYM_ERRID);
++ return;
++ }
++ if (dlthis->reorder_map)
++ dload_reorder(input_sym, siz, dlthis->reorder_map);
++
++ checks += dload_checksum(input_sym, siz);
++ do { /* process symbols in buffer */
++ symbols_left -= 1;
++ /* attempt to derive the name of this symbol */
++ sname = NULL;
++ if (input_sym->dn_offset > 0) {
++#if BITS_PER_AU <= BITS_PER_BYTE
++ if ((u32) input_sym->dn_offset <
++ dlthis->dfile_hdr.df_strtab_size)
++ sname = dlthis->str_head +
++ BYTE_TO_HOST(input_sym->dn_offset);
++ else
++ dload_error(dlthis,
++ "Bad name offset in symbol %d",
++ symbols_left);
++#else
++ sname = unpack_name(dlthis,
++ input_sym->dn_offset);
++#endif
++ }
++ val = input_sym->dn_value;
++ delta = 0;
++ sp->sclass = input_sym->dn_sclass;
++ sp->secnn = input_sym->dn_scnum;
++ /* if this is an undefined symbol,
++ * define it (or fail) now */
++ if (sp->secnn == DN_UNDEF) {
++ /* pointless for static undefined */
++ if (input_sym->dn_sclass != DN_EXT)
++ goto loop_cont;
++
++ /* try to define symbol from previously
++ * loaded images */
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, sname);
++ if (!symp) {
++ DL_ERROR
++ ("Undefined external symbol %s",
++ sname);
++ goto loop_cont;
++ }
++ val = delta = symp->value;
++ goto loop_cont;
++ }
++ /* symbol defined by this module */
++ if (sp->secnn > 0) { /* symbol references a section */
++ if ((unsigned)sp->secnn <=
++ dlthis->allocated_secn_count) {
++ /* section was allocated */
++ struct doff_scnhdr_t *srefp =
++ &dlthis->sect_hdrs
++ [sp->secnn - 1];
++
++ if (input_sym->dn_sclass ==
++ DN_STATLAB ||
++ input_sym->dn_sclass == DN_EXTLAB){
++ /* load */
++ delta = srefp->ds_vaddr;
++ } else {
++ /* run */
++ delta = srefp->ds_paddr;
++ }
++ val += delta;
++ }
++ goto loop_itr;
++ }
++ /* This symbol is an absolute symbol */
++ if (sp->secnn == DN_ABS && ((sp->sclass == DN_EXT) ||
++ (sp->sclass == DN_EXTLAB))) {
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, sname);
++ if (!symp)
++ goto loop_itr;
++ /* This absolute symbol is already defined. */
++ if (symp->value == input_sym->dn_value) {
++ /* If symbol values are equal, continue
++ * but don't add to the global symbol
++ * table */
++ sp->value = val;
++ sp->delta = delta;
++ sp += 1;
++ input_sym += 1;
++ continue;
++ } else {
++ /* If symbol values are not equal,
++ * return with redefinition error */
++ DL_ERROR("Absolute symbol %s is "
++ "defined multiple times with "
++ "different values", sname);
++ return;
++ }
++ }
++loop_itr:
++ /* if this is a global symbol, post it to the
++ * global table */
++ if (input_sym->dn_sclass == DN_EXT ||
++ input_sym->dn_sclass == DN_EXTLAB) {
++ /* Keep this global symbol for subsequent
++ * modules. Don't complain on error, to allow
++ * symbol API to suppress global symbols */
++ if (!sname)
++ goto loop_cont;
++
++ newsym = dlthis->mysym->Add_To_Symbol_Table
++ (dlthis->mysym, sname,
++ (unsigned)dlthis->myhandle);
++ if (newsym)
++ newsym->value = val;
++
++ } /* global */
++loop_cont:
++ sp->value = val;
++ sp->delta = delta;
++ sp += 1;
++ input_sym += 1;
++ } while ((syms_in_buf -= 1) > 0); /* process sym in buffer */
++ } while (symbols_left > 0); /* read all symbols */
++ if (~checks)
++ dload_error(dlthis, "Checksum of symbols failed");
++
++} /* dload_symbols */
++
++/*****************************************************************************
++ * Procedure symbol_table_free
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Frees any state used by the symbol table.
++ *
++ * WARNING:
++ * This routine is not allowed to declare errors!
++ *****************************************************************************/
++static void symbol_table_free(struct dload_state *dlthis)
++{
++ if (dlthis->local_symtab) {
++ if (dlthis->dload_errcount) { /* blow off our symbols */
++ dlthis->mysym->Purge_Symbol_Table(dlthis->mysym,
++ (unsigned)dlthis->myhandle);
++ }
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->local_symtab);
++ }
++} /* symbol_table_free */
++
++/* .cinit Processing
++ *
++ * The dynamic loader does .cinit interpretation. cload_cinit()
++ * acts as a special write-to-target function, in that it takes relocated
++ * data from the normal data flow, and interprets it as .cinit actions.
++ * Because the normal data flow does not necessarily process the whole
++ * .cinit section in one buffer, cload_cinit() must be prepared to
++ * interpret the data piecemeal. A state machine is used for this
++ * purpose.
++ */
++
++/* The following are only for use by reloc.c and things it calls */
++static const struct LDR_SECTION_INFO CINIT_INFO_INIT = { CINITNAME, 0, 0,
++ (LDR_ADDR) -1, 0, DLOAD_BSS, 0 };
++
++/*************************************************************************
++ * Procedure cload_cinit
++ *
++ * Parameters:
++ * ipacket Pointer to data packet to be loaded
++ *
++ * Effect:
++ * Interprets the data in the buffer as .cinit data, and performs the
++ * appropriate initializations.
++ ************************************************************************/
++static void cload_cinit(struct dload_state *dlthis,
++ struct image_packet_t *ipacket)
++{
++#if TDATA_TO_HOST(CINIT_COUNT)*BITS_PER_AU > 16
++ s32 init_count, left;
++#else
++ s16 init_count, left;
++#endif
++ unsigned char *pktp = ipacket->i_bits;
++ unsigned char *pktend = pktp +
++ BYTE_TO_HOST_ROUND(ipacket->i_packet_size);
++ int temp;
++ LDR_ADDR atmp;
++ struct LDR_SECTION_INFO cinit_info;
++
++ /* PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER. */
++ while (true) {
++ left = pktend - pktp;
++ switch (dlthis->cinit_state) {
++ case CI_count: /* count field */
++ if (left < TDATA_TO_HOST(CINIT_COUNT))
++ goto loopexit;
++ temp = dload_unpack(dlthis, (TgtAU_t *)pktp,
++ CINIT_COUNT * TDATA_AU_BITS, 0,
++ ROP_SGN);
++ pktp += TDATA_TO_HOST(CINIT_COUNT);
++ /* negative signifies BSS table, zero means done */
++ if (temp <= 0) {
++ dlthis->cinit_state = CI_done;
++ break;
++ }
++ dlthis->cinit_count = temp;
++ dlthis->cinit_state = CI_address;
++ break;
++#if CINIT_ALIGN < CINIT_ADDRESS
++ case CI_partaddress:
++ pktp -= TDATA_TO_HOST(CINIT_ALIGN);
++ /* back up pointer into space courtesy of caller */
++ *(uint16_t *)pktp = dlthis->cinit_addr;
++ /* stuff in saved bits !! FALL THRU !! */
++#endif
++ case CI_address: /* Address field for a copy packet */
++ if (left < TDATA_TO_HOST(CINIT_ADDRESS)) {
++#if CINIT_ALIGN < CINIT_ADDRESS
++ if (left == TDATA_TO_HOST(CINIT_ALIGN)) {
++ /* address broken into halves */
++ dlthis->cinit_addr = *(uint16_t *)pktp;
++ /* remember 1st half */
++ dlthis->cinit_state = CI_partaddress;
++ left = 0;
++ }
++#endif
++ goto loopexit;
++ }
++ atmp = dload_unpack(dlthis, (TgtAU_t *)pktp,
++ CINIT_ADDRESS * TDATA_AU_BITS, 0,
++ ROP_UNS);
++ pktp += TDATA_TO_HOST(CINIT_ADDRESS);
++#if CINIT_PAGE_BITS > 0
++ dlthis->cinit_page = atmp &
++ ((1 << CINIT_PAGE_BITS) - 1);
++ atmp >>= CINIT_PAGE_BITS;
++#else
++ dlthis->cinit_page = CINIT_DEFAULT_PAGE;
++#endif
++ dlthis->cinit_addr = atmp;
++ dlthis->cinit_state = CI_copy;
++ break;
++ case CI_copy: /* copy bits to the target */
++ init_count = HOST_TO_TDATA(left);
++ if (init_count > dlthis->cinit_count)
++ init_count = dlthis->cinit_count;
++ if (init_count == 0)
++ goto loopexit; /* get more bits */
++ cinit_info = CINIT_INFO_INIT;
++ cinit_info.page = dlthis->cinit_page;
++ if (!dlthis->myio->writemem(dlthis->myio, pktp,
++ TDATA_TO_TADDR(dlthis->cinit_addr),
++ &cinit_info,
++ TDATA_TO_HOST(init_count))) {
++ dload_error(dlthis, E_INITFAIL, "write",
++ dlthis->cinit_addr);
++ }
++ dlthis->cinit_count -= init_count;
++ if (dlthis->cinit_count <= 0) {
++ dlthis->cinit_state = CI_count;
++ init_count = (init_count + CINIT_ALIGN - 1) &
++ -CINIT_ALIGN;
++ /* align to next init */
++ }
++ pktp += TDATA_TO_HOST(init_count);
++ dlthis->cinit_addr += init_count;
++ break;
++ case CI_done: /* no more .cinit to do */
++ return;
++ } /* switch (cinit_state) */
++ } /* while */
++
++loopexit:
++ if (left > 0) {
++ dload_error(dlthis, "%d bytes left over in cinit packet", left);
++ dlthis->cinit_state = CI_done; /* left over bytes are bad */
++ }
++} /* cload_cinit */
++
++/* Functions to interface to reloc.c
++ *
++ * reloc.c is the relocation module borrowed from the linker, with
++ * minimal (we hope) changes for our purposes. cload_sect_data() invokes
++ * this module on a section to relocate and load the image data for that
++ * section. The actual read and write actions are supplied by the global
++ * routines below.
++ */
++
++/************************************************************************
++ * Procedure relocate_packet
++ *
++ * Parameters:
++ * ipacket Pointer to an image packet to relocate
++ *
++ * Effect:
++ * Performs the required relocations on the packet. Returns a checksum
++ * of the relocation operations.
++ ************************************************************************/
++#define MY_RELOC_BUF_SIZ 8
++/* careful! exists at the same time as the image buffer*/
++static int relocate_packet(struct dload_state *dlthis,
++ struct image_packet_t *ipacket, u32 *checks)
++{
++ u32 rnum;
++
++ rnum = ipacket->i_num_relocs;
++ do { /* all relocs */
++ unsigned rinbuf;
++ int siz;
++ struct reloc_record_t *rp, rrec[MY_RELOC_BUF_SIZ];
++ rp = rrec;
++ rinbuf = rnum > MY_RELOC_BUF_SIZ ? MY_RELOC_BUF_SIZ : rnum;
++ siz = rinbuf * sizeof(struct reloc_record_t);
++ if (dlthis->strm->read_buffer(dlthis->strm, rp, siz) != siz) {
++ DL_ERROR(E_READSTRM, "relocation");
++ return 0;
++ }
++ /* reorder the bytes if need be */
++ if (dlthis->reorder_map)
++ dload_reorder(rp, siz, dlthis->reorder_map);
++
++ *checks += dload_checksum(rp, siz);
++ do {
++ /* perform the relocation operation */
++ dload_relocate(dlthis, (TgtAU_t *) ipacket->i_bits, rp);
++ rp += 1;
++ rnum -= 1;
++ } while ((rinbuf -= 1) > 0);
++ } while (rnum > 0); /* all relocs */
++ return 1;
++} /* dload_read_reloc */
++
++#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
++
++/* VERY dangerous */
++static const char IMAGEPAK[] = { "image packet" };
++
++/*************************************************************************
++ * Procedure dload_data
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Read image data from input file, relocate it, and download it to the
++ * target.
++ ************************************************************************/
++static void dload_data(struct dload_state *dlthis)
++{
++ u16 curr_sect;
++ struct doff_scnhdr_t *sptr = dlthis->sect_hdrs;
++ struct LDR_SECTION_INFO *lptr = dlthis->ldr_sections;
++#ifdef OPT_ZERO_COPY_LOADER
++ boolean bZeroCopy = false;
++#endif
++ u8 *pDest;
++
++ struct {
++ struct image_packet_t ipacket;
++ u8 bufr[BYTE_TO_HOST(IMAGE_PACKET_SIZE)];
++ } ibuf;
++
++ /* Indicates whether CINIT processing has occurred */
++ boolean cinit_processed = false;
++
++ /* Loop through the sections and load them one at a time.
++ */
++ for (curr_sect = 0; curr_sect < dlthis->dfile_hdr.df_no_scns;
++ curr_sect += 1) {
++ if (DS_NEEDS_DOWNLOAD(sptr)) {
++ s32 nip;
++ LDR_ADDR image_offset = 0;
++ /* set relocation info for this section */
++ if (curr_sect < dlthis->allocated_secn_count)
++ dlthis->delta_runaddr = sptr->ds_paddr;
++ else {
++ lptr = DOFFSEC_IS_LDRSEC(sptr);
++ dlthis->delta_runaddr = 0;
++ }
++ dlthis->image_secn = lptr;
++#if BITS_PER_AU > BITS_PER_BYTE
++ lptr->name = unpack_name(dlthis, sptr->ds_offset);
++#endif
++ nip = sptr->ds_nipacks;
++ while ((nip -= 1) >= 0) { /* process packets */
++
++ s32 ipsize;
++ u32 checks;
++ /* get the fixed header bits */
++ if (dlthis->strm->read_buffer(dlthis->strm,
++ &ibuf.ipacket, IPH_SIZE) != IPH_SIZE) {
++ DL_ERROR(E_READSTRM, IMAGEPAK);
++ return;
++ }
++ /* reorder the header if need be */
++ if (dlthis->reorder_map) {
++ dload_reorder(&ibuf.ipacket, IPH_SIZE,
++ dlthis->reorder_map);
++ }
++ /* now read the rest of the packet */
++ ipsize =
++ BYTE_TO_HOST(DOFF_ALIGN
++ (ibuf.ipacket.i_packet_size));
++ if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
++ DL_ERROR("Bad image packet size %d",
++ ipsize);
++ return;
++ }
++ pDest = ibuf.bufr;
++#ifdef OPT_ZERO_COPY_LOADER
++ bZeroCopy = false;
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_CINIT) {
++ dlthis->myio->writemem(dlthis->myio,
++ &pDest, lptr->load_addr +
++ image_offset, lptr, 0);
++ bZeroCopy = (pDest != ibuf.bufr);
++ }
++#endif
++ /* End of determination */
++
++ if (dlthis->strm->read_buffer(dlthis->strm,
++ ibuf.bufr, ipsize) != ipsize) {
++ DL_ERROR(E_READSTRM, IMAGEPAK);
++ return;
++ }
++ ibuf.ipacket.i_bits = pDest;
++
++ /* reorder the bytes if need be */
++#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
++ if (dlthis->reorder_map) {
++ dload_reorder(pDest, ipsize,
++ dlthis->reorder_map);
++ }
++ checks = dload_checksum(pDest, ipsize);
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ TARGET_ORDER(REORDER_MAP
++ (BYTE_RESHUFFLE_VALUE))) {
++ /* put image bytes in big-endian order,
++ * not PC order */
++ dload_reorder(pDest, ipsize,
++ TARGET_ORDER
++ (dlthis->dfile_hdr.df_byte_reshuffle));
++ }
++#if TARGET_AU_BITS > 8
++ checks = dload_reverse_checksum_16(pDest,
++ ipsize);
++#else
++ checks = dload_reverse_checksum(pDest,
++ ipsize);
++#endif
++#endif
++
++ checks += dload_checksum(&ibuf.ipacket,
++ IPH_SIZE);
++ /* relocate the image bits as needed */
++ if (ibuf.ipacket.i_num_relocs) {
++ dlthis->image_offset = image_offset;
++ if (!relocate_packet(dlthis,
++ &ibuf.ipacket, &checks))
++ return; /* serious error */
++ }
++ if (~checks)
++ DL_ERROR(E_CHECKSUM, IMAGEPAK);
++ /* stuff the result into target memory */
++ if (DLOAD_SECT_TYPE(sptr) == DLOAD_CINIT) {
++ cload_cinit(dlthis, &ibuf.ipacket);
++ cinit_processed = true;
++ } else {
++#ifdef OPT_ZERO_COPY_LOADER
++ if (!bZeroCopy) {
++#endif
++
++ if (!dlthis->myio->writemem
++ (dlthis->myio, ibuf.bufr,
++ lptr->load_addr + image_offset, lptr,
++ BYTE_TO_HOST
++ (ibuf.ipacket.i_packet_size))) {
++ DL_ERROR(
++ "Write to " FMT_UI32 " failed",
++ lptr->load_addr + image_offset);
++ }
++#ifdef OPT_ZERO_COPY_LOADER
++ }
++#endif
++
++ }
++ image_offset +=
++ BYTE_TO_TADDR(ibuf.ipacket.i_packet_size);
++ } /* process packets */
++ /* if this is a BSS section, we may want to fill it */
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
++ goto loop_cont;
++
++ if (!(dlthis->myoptions & DLOAD_INITBSS))
++ goto loop_cont;
++
++ if (cinit_processed) {
++ /* Don't clear BSS after load-time
++ * initialization */
++ DL_ERROR
++ ("Zero-initialization at " FMT_UI32 " after "
++ "load-time initialization!", lptr->load_addr);
++ goto loop_cont;
++ }
++ /* fill the .bss area */
++ dlthis->myio->fillmem(dlthis->myio,
++ TADDR_TO_HOST(lptr->load_addr),
++ lptr, TADDR_TO_HOST(lptr->size),
++ dload_fill_bss);
++ goto loop_cont;
++ } /* if DS_DOWNLOAD_MASK */
++ /* If not loading, but BSS, zero initialize */
++ if (DLOAD_SECT_TYPE(sptr) != DLOAD_BSS)
++ goto loop_cont;
++
++ if (!(dlthis->myoptions & DLOAD_INITBSS))
++ goto loop_cont;
++
++ if (curr_sect >= dlthis->allocated_secn_count)
++ lptr = DOFFSEC_IS_LDRSEC(sptr);
++
++ if (cinit_processed) {
++ /*Don't clear BSS after load-time initialization */
++ DL_ERROR(
++ "Zero-initialization at " FMT_UI32 " attempted after "
++ "load-time initialization!", lptr->load_addr);
++ goto loop_cont;
++ }
++ /* fill the .bss area */
++ dlthis->myio->fillmem(dlthis->myio,
++ TADDR_TO_HOST(lptr->load_addr), lptr,
++ TADDR_TO_HOST(lptr->size), dload_fill_bss);
++loop_cont:
++ sptr += 1;
++ lptr += 1;
++ } /* load sections */
++} /* dload_data */
++
++/*************************************************************************
++ * Procedure dload_reorder
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be byte-swapped
++ * dsiz size of the data to be reordered in sizeof() units.
++ * map 32-bit map defining how to reorder the data. Value
++ * must be REORDER_MAP() of some permutation
++ * of 0x00 01 02 03
++ *
++ * Effect:
++ * Re-arranges the bytes in each word according to the map specified.
++ *
++ ************************************************************************/
++/* mask for byte shift count */
++#define SHIFT_COUNT_MASK (3 << LOG_BITS_PER_BYTE)
++
++void dload_reorder(void *data, int dsiz, unsigned int map)
++{
++ register u32 tmp, tmap, datv;
++ u32 *dp = (u32 *)data;
++
++ map <<= LOG_BITS_PER_BYTE; /* align map with SHIFT_COUNT_MASK */
++ do {
++ tmp = 0;
++ datv = *dp;
++ tmap = map;
++ do {
++ tmp |= (datv & BYTE_MASK) << (tmap & SHIFT_COUNT_MASK);
++ tmap >>= BITS_PER_BYTE;
++ } while (datv >>= BITS_PER_BYTE);
++ *dp++ = tmp;
++ } while ((dsiz -= sizeof(u32)) > 0);
++} /* dload_reorder */
++
++/*************************************************************************
++ * Procedure dload_checksum
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be checksummed
++ * siz size of the data to be checksummed in sizeof() units.
++ *
++ * Effect:
++ * Returns a checksum of the specified block
++ *
++ ************************************************************************/
++u32 dload_checksum(void *data, unsigned siz)
++{
++ u32 sum;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++ for (left = siz; left > 0; left -= sizeof(u32))
++ sum += *dp++;
++ return sum;
++} /* dload_checksum */
++
++#if HOST_ENDIANNESS
++/*************************************************************************
++ * Procedure dload_reverse_checksum
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be checksummed
++ * siz size of the data to be checksummed in sizeof() units.
++ *
++ * Effect:
++ * Returns a checksum of the specified block, which is assumed to be bytes
++ * in big-endian order.
++ *
++ * Notes:
++ * In a big-endian host, things like the string table are stored as bytes
++ * in host order. But dllcreate always checksums in little-endian order.
++ * It is most efficient to just handle the difference a word at a time.
++ *
++ ***********************************************************************/
++u32 dload_reverse_checksum(void *data, unsigned siz)
++{
++ u32 sum, temp;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++
++ for (left = siz; left > 0; left -= sizeof(u32)) {
++ temp = *dp++;
++ sum += temp << BITS_PER_BYTE * 3;
++ sum += temp >> BITS_PER_BYTE * 3;
++ sum += (temp >> BITS_PER_BYTE) & (BYTE_MASK << BITS_PER_BYTE);
++ sum += (temp & (BYTE_MASK << BITS_PER_BYTE)) << BITS_PER_BYTE;
++ }
++
++ return sum;
++} /* dload_reverse_checksum */
++
++#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
++u32 dload_reverse_checksum_16(void *data, unsigned siz)
++{
++ uint_fast32_t sum, temp;
++ u32 *dp;
++ int left;
++
++ sum = 0;
++ dp = (u32 *)data;
++
++ for (left = siz; left > 0; left -= sizeof(u32)) {
++ temp = *dp++;
++ sum += temp << BITS_PER_BYTE * 2;
++ sum += temp >> BITS_PER_BYTE * 2;
++ }
++
++ return sum;
++} /* dload_reverse_checksum_16 */
++#endif
++#endif
++
++/*************************************************************************
++ * Procedure swap_words
++ *
++ * Parameters:
++ * data 32-bit aligned pointer to data to be swapped
++ * siz size of the data to be swapped.
++ * bitmap Bit map of how to swap each 32-bit word; 1 => 2 shorts,
++ * 0 => 1 long
++ *
++ * Effect:
++ * Swaps the specified data according to the specified map
++ *
++ ************************************************************************/
++static void swap_words(void *data, unsigned siz, unsigned bitmap)
++{
++ register int i;
++#if TARGET_AU_BITS < 16
++ register u16 *sp;
++#endif
++ register u32 *lp;
++
++ siz /= sizeof(u16);
++
++#if TARGET_AU_BITS < 16
++ /* pass 1: do all the bytes */
++ i = siz;
++ sp = (u16 *) data;
++ do {
++ register u16 tmp;
++ tmp = *sp;
++ *sp++ = SWAP16BY8(tmp);
++ } while ((i -= 1) > 0);
++#endif
++
++#if TARGET_AU_BITS < 32
++ /* pass 2: fixup the 32-bit words */
++ i = siz >> 1;
++ lp = (u32 *) data;
++ do {
++ if ((bitmap & 1) == 0) {
++ register u32 tmp;
++ tmp = *lp;
++ *lp = SWAP32BY16(tmp);
++ }
++ lp += 1;
++ bitmap >>= 1;
++ } while ((i -= 1) > 0);
++#endif
++} /* swap_words */
++
++/*************************************************************************
++ * Procedure copy_tgt_strings
++ *
++ * Parameters:
++ * dstp Destination address. Assumed to be 32-bit aligned
++ * srcp Source address. Assumed to be 32-bit aligned
++ * charcount Number of characters to copy.
++ *
++ * Effect:
++ * Copies strings from the source (which is in usual .dof file order on
++ * the loading processor) to the destination buffer (which should be in proper
++ * target addressable unit order). Makes sure the last string in the
++ * buffer is NULL terminated (for safety).
++ * Returns the first unused destination address.
++ ************************************************************************/
++static char *copy_tgt_strings(void *dstp, void *srcp, unsigned charcount)
++{
++ register TgtAU_t *src = (TgtAU_t *)srcp;
++ register TgtAU_t *dst = (TgtAU_t *)dstp;
++ register int cnt = charcount;
++ do {
++#if TARGET_AU_BITS <= BITS_PER_AU
++ /* byte-swapping issues may exist for strings on target */
++ *dst++ = *src++;
++#elif TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)
++ register TgtAU_t tmp;
++ tmp = *src++;
++ *dst++ = SWAP16BY8(tmp); /* right for TARGET_AU_BITS == 16 */
++#else
++ *dst++ = *src++;
++#endif
++ } while ((cnt -= (sizeof(TgtAU_t) * BITS_PER_AU / BITS_PER_BYTE)) > 0);
++ /*apply force to make sure that the string table has null terminator */
++#if (BITS_PER_AU == BITS_PER_BYTE) && (TARGET_AU_BITS == BITS_PER_BYTE)
++ dst[-1] = 0;
++#elif TARGET_BIG_ENDIAN
++ dst[-1] &= ~BYTE_MASK; /* big-endian */
++#else
++ dst[-1] &= (1 << (BITS_PER_AU - BITS_PER_BYTE)) - 1; /* little endian */
++#endif
++ return (char *)dst;
++} /* copy_tgt_strings */
++
++/*************************************************************************
++ * Procedure init_module_handle
++ *
++ * Parameters:
++ * none
++ *
++ * Effect:
++ * Initializes the module handle we use to enable unloading, and installs
++ * the debug information required by the target.
++ *
++ * Notes:
++ * The handle returned from Dynamic_Load_Module needs to encapsulate all the
++ * allocations done for the module, and enable them plus the modules symbols to
++ * be deallocated.
++ *
++ ************************************************************************/
++#ifndef _BIG_ENDIAN
++static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
++ (LDR_ADDR) -1, DBG_LIST_PAGE, DLOAD_DATA, 0 };
++#else
++static const struct LDR_SECTION_INFO DLLVIEW_INFO_INIT = { ".dllview", 0, 0,
++ (LDR_ADDR) -1, DLOAD_DATA, DBG_LIST_PAGE, 0 };
++#endif
++static void init_module_handle(struct dload_state *dlthis)
++{
++ struct my_handle *hndl;
++ u16 curr_sect;
++ struct LDR_SECTION_INFO *asecs;
++ struct dll_module *dbmod;
++ struct dll_sect *dbsec;
++ struct dbg_mirror_root *mlist;
++ register char *cp;
++ struct modules_header mhdr;
++ struct LDR_SECTION_INFO dllview_info;
++ struct dynload_symbol *debug_mirror_sym;
++ hndl = dlthis->myhandle;
++ if (!hndl)
++ return; /* must be errors detected, so forget it */
++ hndl->secn_count = dlthis->allocated_secn_count << 1;
++#ifndef TARGET_ENDIANNESS
++ if (dlthis->big_e_target)
++ hndl->secn_count += 1; /* flag for big-endian */
++#endif
++ if (dlthis->dload_errcount)
++ return; /* abandon if errors detected */
++ /* Locate the symbol that names the header for the CCS debug list
++ of modules. If not found, we just don't generate the debug record.
++ If found, we create our modules list. We make sure to create the
++ LOADER_DLLVIEW_ROOT even if there is no relocation info to record,
++ just to try to put both symbols in the same symbol table and
++ module.*/
++ debug_mirror_sym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
++ LOADER_DLLVIEW_ROOT);
++ if (!debug_mirror_sym) {
++ struct dynload_symbol *dlmodsym;
++ struct dbg_mirror_root *mlst;
++
++ /* our root symbol is not yet present;
++ check if we have DLModules defined */
++ dlmodsym = dlthis->mysym->Find_Matching_Symbol(dlthis->mysym,
++ LINKER_MODULES_HEADER);
++ if (!dlmodsym)
++ return; /* no DLModules list so no debug info */
++ /* if we have DLModules defined, construct our header */
++ mlst = (struct dbg_mirror_root *)
++ dlthis->mysym->Allocate(dlthis->mysym,
++ sizeof(struct dbg_mirror_root));
++ if (!mlst) {
++ DL_ERROR(E_ALLOC, sizeof(struct dbg_mirror_root));
++ return;
++ }
++ mlst->hnext = NULL;
++ mlst->changes = 0;
++ mlst->refcount = 0;
++ mlst->dbthis = TDATA_TO_TADDR(dlmodsym->value);
++ /* add our root symbol */
++ debug_mirror_sym = dlthis->mysym->Add_To_Symbol_Table
++ (dlthis->mysym, LOADER_DLLVIEW_ROOT,
++ (unsigned)dlthis->myhandle);
++ if (!debug_mirror_sym) {
++ /* failed, recover memory */
++ dlthis->mysym->Deallocate(dlthis->mysym, mlst);
++ return;
++ }
++ debug_mirror_sym->value = (u32)mlst;
++ }
++ /* First create the DLLview record and stuff it into the buffer.
++ Then write it to the DSP. Record pertinent locations in our hndl,
++ and add it to the per-processor list of handles with debug info.*/
++#ifndef DEBUG_HEADER_IN_LOADER
++ mlist = (struct dbg_mirror_root *)debug_mirror_sym->value;
++ if (!mlist)
++ return;
++#else
++ mlist = (struct dbg_mirror_root *)&debug_list_header;
++#endif
++ hndl->dm.hroot = mlist; /* set pointer to root into our handle */
++ if (!dlthis->allocated_secn_count)
++ return; /* no load addresses to be recorded */
++ /* reuse temporary symbol storage */
++ dbmod = (struct dll_module *) dlthis->local_symtab;
++ /* Create the DLLview record in the memory we retain for our handle*/
++ dbmod->num_sects = dlthis->allocated_secn_count;
++ dbmod->timestamp = dlthis->verify.dv_timdat;
++ dbmod->version = INIT_VERSION;
++ dbmod->verification = VERIFICATION;
++ asecs = dlthis->ldr_sections;
++ dbsec = dbmod->sects;
++ for (curr_sect = dlthis->allocated_secn_count;
++ curr_sect > 0; curr_sect -= 1) {
++ dbsec->sect_load_adr = asecs->load_addr;
++ dbsec->sect_run_adr = asecs->run_addr;
++ dbsec += 1;
++ asecs += 1;
++ }
++ /* now cram in the names */
++ cp = copy_tgt_strings(dbsec, dlthis->str_head,
++ dlthis->debug_string_size);
++
++ /* round off the size of the debug record, and remember same */
++ hndl->dm.dbsiz = HOST_TO_TDATA_ROUND(cp - (char *)dbmod);
++ *cp = 0; /* strictly to make our test harness happy */
++ dllview_info = DLLVIEW_INFO_INIT;
++ dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
++ /* Initialize memory context to default heap */
++ dllview_info.context = 0;
++ hndl->dm.context = 0;
++ /* fill in next pointer and size */
++ if (mlist->hnext) {
++ dbmod->next_module = TADDR_TO_TDATA(mlist->hnext->dm.dbthis);
++ dbmod->next_module_size = mlist->hnext->dm.dbsiz;
++ } else {
++ dbmod->next_module_size = 0;
++ dbmod->next_module = 0;
++ }
++ /* allocate memory for on-DSP DLLview debug record */
++ if (!dlthis->myalloc)
++ return;
++ if (!dlthis->myalloc->Allocate(dlthis->myalloc, &dllview_info,
++ HOST_TO_TADDR(sizeof(u32)))) {
++ return;
++ }
++ /* Store load address of .dllview section */
++ hndl->dm.dbthis = dllview_info.load_addr;
++ /* Store memory context (segid) in which .dllview section
++ * was allocated */
++ hndl->dm.context = dllview_info.context;
++ mlist->refcount += 1;
++ /* swap bytes in the entire debug record, but not the string table */
++ if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
++ swap_words(dbmod, (char *)dbsec - (char *)dbmod,
++ DLL_MODULE_BITMAP);
++ }
++ /* Update the DLLview list on the DSP write new record */
++ if (!dlthis->myio->writemem(dlthis->myio, dbmod,
++ dllview_info.load_addr, &dllview_info,
++ TADDR_TO_HOST(dllview_info.size))) {
++ return;
++ }
++ /* write new header */
++ mhdr.first_module_size = hndl->dm.dbsiz;
++ mhdr.first_module = TADDR_TO_TDATA(dllview_info.load_addr);
++ /* swap bytes in the module header, if needed */
++ if (TARGET_ENDIANNESS_DIFFERS(TARGET_BIG_ENDIAN)) {
++ swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
++ MODULES_HEADER_BITMAP);
++ }
++ dllview_info = DLLVIEW_INFO_INIT;
++ if (!dlthis->myio->writemem(dlthis->myio, &mhdr, mlist->dbthis,
++ &dllview_info, sizeof(struct modules_header) -
++ sizeof(u16))) {
++ return;
++ }
++ /* Add the module handle to this processor's list
++ of handles with debug info */
++ hndl->dm.hnext = mlist->hnext;
++ if (hndl->dm.hnext)
++ hndl->dm.hnext->dm.hprev = hndl;
++ hndl->dm.hprev = (struct my_handle *) mlist;
++ mlist->hnext = hndl; /* insert after root*/
++} /* init_module_handle */
++
++/*************************************************************************
++ * Procedure Dynamic_Unload_Module
++ *
++ * Parameters:
++ * mhandle A module handle from Dynamic_Load_Module
++ * syms Host-side symbol table and malloc/free functions
++ * alloc Target-side memory allocation
++ *
++ * Effect:
++ * The module specified by mhandle is unloaded. Unloading causes all
++ * target memory to be deallocated, all symbols defined by the module to
++ * be purged, and any host-side storage used by the dynamic loader for
++ * this module to be released.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report().
++ ************************************************************************/
++int Dynamic_Unload_Module(DLOAD_mhandle mhandle,
++ struct Dynamic_Loader_Sym *syms,
++ struct Dynamic_Loader_Allocate *alloc,
++ struct Dynamic_Loader_Initialize *init)
++{
++ s16 curr_sect;
++ struct LDR_SECTION_INFO *asecs;
++ struct my_handle *hndl;
++ struct dbg_mirror_root *root;
++ unsigned errcount = 0;
++ struct LDR_SECTION_INFO dllview_info = DLLVIEW_INFO_INIT;
++ struct modules_header mhdr;
++
++ hndl = (struct my_handle *)mhandle;
++ if (!hndl)
++ return 0; /* if handle is null, nothing to do */
++ /* Clear out the module symbols
++ * Note that if this is the module that defined MODULES_HEADER
++ (the head of the target debug list)
++ * then this operation will blow away that symbol.
++ It will therefore be impossible for subsequent
++ * operations to add entries to this un-referenceable list.*/
++ if (!syms)
++ return 1;
++ syms->Purge_Symbol_Table(syms, (unsigned) hndl);
++ /* Deallocate target memory for sections */
++ asecs = hndl->secns;
++ if (alloc)
++ for (curr_sect = (hndl->secn_count >> 1); curr_sect > 0;
++ curr_sect -= 1) {
++ asecs->name = NULL;
++ alloc->Deallocate(alloc, asecs++);
++ }
++ root = hndl->dm.hroot;
++ if (!root) {
++ /* there is a debug list containing this module */
++ goto func_end;
++ }
++ if (!hndl->dm.dbthis) { /* target-side dllview record exists */
++ goto loop_end;
++ }
++ /* Retrieve memory context in which .dllview was allocated */
++ dllview_info.context = hndl->dm.context;
++ if (hndl->dm.hprev == hndl)
++ goto exitunltgt;
++
++ /* target-side dllview record is in list */
++ /* dequeue this record from our GPP-side mirror list */
++ hndl->dm.hprev->dm.hnext = hndl->dm.hnext;
++ if (hndl->dm.hnext)
++ hndl->dm.hnext->dm.hprev = hndl->dm.hprev;
++ /* Update next_module of previous entry in target list
++ * We are using mhdr here as a surrogate for either a
++ struct modules_header or a dll_module */
++ if (hndl->dm.hnext) {
++ mhdr.first_module = TADDR_TO_TDATA(hndl->dm.hnext->dm.dbthis);
++ mhdr.first_module_size = hndl->dm.hnext->dm.dbsiz;
++ } else {
++ mhdr.first_module = 0;
++ mhdr.first_module_size = 0;
++ }
++ if (!init)
++ goto exitunltgt;
++
++ if (!init->connect(init)) {
++ dload_syms_error(syms, E_ICONNECT);
++ errcount += 1;
++ goto exitunltgt;
++ }
++ /* swap bytes in the module header, if needed */
++ if (TARGET_ENDIANNESS_DIFFERS(hndl->secn_count & 0x1)) {
++ swap_words(&mhdr, sizeof(struct modules_header) - sizeof(u16),
++ MODULES_HEADER_BITMAP);
++ }
++ if (!init->writemem(init, &mhdr, hndl->dm.hprev->dm.dbthis,
++ &dllview_info, sizeof(struct modules_header) -
++ sizeof(mhdr.update_flag))) {
++ dload_syms_error(syms, E_DLVWRITE);
++ errcount += 1;
++ }
++ /* update change counter */
++ root->changes += 1;
++ if (!init->writemem(init, &(root->changes),
++ root->dbthis + HOST_TO_TADDR
++ (sizeof(mhdr.first_module) +
++ sizeof(mhdr.first_module_size)),
++ &dllview_info,
++ sizeof(mhdr.update_flag))) {
++ dload_syms_error(syms, E_DLVWRITE);
++ errcount += 1;
++ }
++ init->release(init);
++exitunltgt:
++ /* release target storage */
++ dllview_info.size = TDATA_TO_TADDR(hndl->dm.dbsiz);
++ dllview_info.load_addr = hndl->dm.dbthis;
++ if (alloc)
++ alloc->Deallocate(alloc, &dllview_info);
++ root->refcount -= 1;
++ /* target-side dllview record exists */
++loop_end:
++#ifndef DEBUG_HEADER_IN_LOADER
++ if (root->refcount <= 0) {
++ /* if all references gone, blow off the header */
++ /* our root symbol may be gone due to the Purge above,
++ but if not, do not destroy the root */
++ if (syms->Find_Matching_Symbol
++ (syms, LOADER_DLLVIEW_ROOT) == NULL)
++ syms->Deallocate(syms, root);
++ }
++#endif
++func_end:
++ /* there is a debug list containing this module */
++ syms->Deallocate(syms, mhandle); /* release our storage */
++ return errcount;
++} /* Dynamic_Unload_Module */
++
++#if BITS_PER_AU > BITS_PER_BYTE
++/*************************************************************************
++ * Procedure unpack_name
++ *
++ * Parameters:
++ * soffset Byte offset into the string table
++ *
++ * Effect:
++ * Returns a pointer to the string specified by the offset supplied, or
++ * NULL for error.
++ *
++ ************************************************************************/
++static char *unpack_name(struct dload_state *dlthis, u32 soffset)
++{
++ u8 tmp, *src;
++ char *dst;
++
++ if (soffset >= dlthis->dfile_hdr.df_strtab_size) {
++ dload_error(dlthis, "Bad string table offset " FMT_UI32,
++ soffset);
++ return NULL;
++ }
++ src = (uint_least8_t *)dlthis->str_head +
++ (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
++ dst = dlthis->str_temp;
++ if (soffset & 1)
++ *dst++ = *src++; /* only 1 character in first word */
++ do {
++ tmp = *src++;
++ *dst = (tmp >> BITS_PER_BYTE);
++ if (!(*dst++))
++ break;
++ } while ((*dst++ = tmp & BYTE_MASK));
++ dlthis->temp_len = dst - dlthis->str_temp;
++ /* squirrel away length including terminating null */
++ return dlthis->str_temp;
++} /* unpack_name */
++#endif
+diff --git a/drivers/dsp/bridge/dynload/dlclasses_hdr.h b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
+new file mode 100644
+index 0000000..04f136e
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/dlclasses_hdr.h
+@@ -0,0 +1,41 @@
++/*
++ * dlclasses_hdr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _DLCLASSES_HDR_H
++#define _DLCLASSES_HDR_H
++
++/*****************************************************************************
++ *****************************************************************************
++ *
++ * DLCLASSES_HDR.H
++ *
++ * Sample classes in support of the dynamic loader
++ *
++ * These are just concrete derivations of the virtual ones in dynamic_loader.h
++ * with a few additional interfaces for init, etc.
++ *****************************************************************************
++ *****************************************************************************/
++
++#include <dspbridge/dynamic_loader.h>
++
++#include "DLstream.h"
++#include "DLsymtab.h"
++#include "DLalloc.h"
++#include "DLinit.h"
++
++#endif /* _DLCLASSES_HDR_H */
+diff --git a/drivers/dsp/bridge/dynload/dload_internal.h b/drivers/dsp/bridge/dynload/dload_internal.h
+new file mode 100644
+index 0000000..78f5058
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/dload_internal.h
+@@ -0,0 +1,237 @@
++/*
++ * dload_internal.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef __DLOAD_INTERNAL__
++#define __DLOAD_INTERNAL__
++
++#include <linux/types.h>
++
++/*
++ * Internal state definitions for the dynamic loader
++ */
++
++#define TRUE 1
++#define FALSE 0
++typedef int boolean;
++
++
++/* type used for relocation intermediate results */
++typedef s32 RVALUE;
++
++/* unsigned version of same; must have at least as many bits */
++typedef u32 URVALUE;
++
++/*
++ * Dynamic loader configuration constants
++ */
++/* error issued if input has more sections than this limit */
++#define REASONABLE_SECTION_LIMIT 100
++
++/* (Addressable unit) value used to clear BSS section */
++#define dload_fill_bss 0
++
++/*
++ * Reorder maps explained (?)
++ *
++ * The doff file format defines a 32-bit pattern used to determine the
++ * byte order of an image being read. That value is
++ * BYTE_RESHUFFLE_VALUE == 0x00010203
++ * For purposes of the reorder routine, we would rather have the all-is-OK
++ * for 32-bits pattern be 0x03020100. This first macro makes the
++ * translation from doff file header value to MAP value: */
++#define REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
++/* This translation is made in dload_headers. Thereafter, the all-is-OK
++ * value for the maps stored in dlthis is REORDER_MAP(BYTE_RESHUFFLE_VALUE).
++ * But sadly, not all bits of the doff file are 32-bit integers.
++ * The notable exceptions are strings and image bits.
++ * Strings obey host byte order: */
++#if defined(_BIG_ENDIAN)
++#define HOST_BYTE_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
++#else
++#define HOST_BYTE_ORDER(cookedmap) (cookedmap)
++#endif
++/* Target bits consist of target AUs (could be bytes, or 16-bits,
++ * or 32-bits) stored as an array in host order. A target order
++ * map is defined by: */
++#if !defined(_BIG_ENDIAN) || TARGET_AU_BITS > 16
++#define TARGET_ORDER(cookedmap) (cookedmap)
++#elif TARGET_AU_BITS > 8
++#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x2020202)
++#else
++#define TARGET_ORDER(cookedmap) ((cookedmap) ^ 0x3030303)
++#endif
++
++/* forward declaration for handle returned by dynamic loader */
++struct my_handle;
++
++/*
++ * a list of module handles, which mirrors the debug list on the target
++ */
++struct dbg_mirror_root {
++ /* must be same as dbg_mirror_list; __DLModules address on target */
++ u32 dbthis;
++ struct my_handle *hnext; /* must be same as dbg_mirror_list */
++ u16 changes; /* change counter */
++ u16 refcount; /* number of modules referencing this root */
++} ;
++
++struct dbg_mirror_list {
++ u32 dbthis;
++ struct my_handle *hnext, *hprev;
++ struct dbg_mirror_root *hroot;
++ u16 dbsiz;
++ u32 context; /* Save context for .dllview memory allocation */
++} ;
++
++#define VARIABLE_SIZE 1
++/*
++ * the structure we actually return as an opaque module handle
++ */
++struct my_handle {
++ struct dbg_mirror_list dm; /* !!! must be first !!! */
++ /* sections following << 1, LSB is set for big-endian target */
++ u16 secn_count;
++ struct LDR_SECTION_INFO secns[VARIABLE_SIZE];
++} ;
++#define MY_HANDLE_SIZE (sizeof(struct my_handle) -\
++ sizeof(struct LDR_SECTION_INFO))
++/* real size of my_handle */
++
++/*
++ * reduced symbol structure used for symbols during relocation
++ */
++struct Local_Symbol {
++ s32 value; /* Relocated symbol value */
++ s32 delta; /* Original value in input file */
++ s16 secnn; /* section number */
++ s16 sclass; /* symbol class */
++} ;
++
++/*
++ * States of the .cinit state machine
++ */
++enum cinit_mode {
++ CI_count = 0, /* expecting a count */
++ CI_address, /* expecting an address */
++#if CINIT_ALIGN < CINIT_ADDRESS /* handle case of partial address field */
++ CI_partaddress, /* have only part of the address */
++#endif
++ CI_copy, /* in the middle of copying data */
++ CI_done /* end of .cinit table */
++};
++
++/*
++ * The internal state of the dynamic loader, which is passed around as
++ * an object
++ */
++struct dload_state {
++ struct Dynamic_Loader_Stream *strm; /* The module input stream */
++ struct Dynamic_Loader_Sym *mysym; /* Symbols for this session */
++ struct Dynamic_Loader_Allocate *myalloc; /* target memory allocator */
++ struct Dynamic_Loader_Initialize *myio; /* target memory initializer */
++ unsigned myoptions; /* Options parameter Dynamic_Load_Module */
++
++ char *str_head; /* Pointer to string table */
++#if BITS_PER_AU > BITS_PER_BYTE
++ char *str_temp; /* Pointer to temporary buffer for strings */
++ /* big enough to hold longest string */
++ unsigned temp_len; /* length of last temporary string */
++ char *xstrings; /* Pointer to buffer for expanded */
++ /* strings for sec names */
++#endif
++ /* Total size of strings for DLLView section names */
++ unsigned debug_string_size;
++ /* Pointer to parallel section info for allocated sections only */
++ struct doff_scnhdr_t *sect_hdrs; /* Pointer to section table */
++ struct LDR_SECTION_INFO *ldr_sections;
++#if TMS32060
++ /* The address of the start of the .bss section */
++ LDR_ADDR bss_run_base;
++#endif
++ struct Local_Symbol *local_symtab; /* Relocation symbol table */
++
++ /* pointer to DL section info for the section being relocated */
++ struct LDR_SECTION_INFO *image_secn;
++ /* change in run address for current section during relocation */
++ LDR_ADDR delta_runaddr;
++ LDR_ADDR image_offset; /* offset of current packet in section */
++ enum cinit_mode cinit_state; /* current state of cload_cinit() */
++ int cinit_count; /* the current count */
++ LDR_ADDR cinit_addr; /* the current address */
++ s16 cinit_page; /* the current page */
++ /* Handle to be returned by Dynamic_Load_Module */
++ struct my_handle *myhandle;
++ unsigned dload_errcount; /* Total # of errors reported so far */
++ /* Number of target sections that require allocation and relocation */
++ unsigned allocated_secn_count;
++#ifndef TARGET_ENDIANNESS
++ boolean big_e_target; /* Target data in big-endian format */
++#endif
++ /* map for reordering bytes, 0 if not needed */
++ u32 reorder_map;
++ struct doff_filehdr_t dfile_hdr; /* DOFF file header structure */
++ struct doff_verify_rec_t verify; /* Verify record */
++
++ int relstkidx; /* index into relocation value stack */
++ /* relocation value stack used in relexp.c */
++ RVALUE relstk[STATIC_EXPR_STK_SIZE];
++
++} ;
++
++#ifdef TARGET_ENDIANNESS
++#define TARGET_BIG_ENDIAN TARGET_ENDIANNESS
++#else
++#define TARGET_BIG_ENDIAN (dlthis->big_e_target)
++#endif
++
++/*
++ * Exports from cload.c to rest of the world
++ */
++extern void dload_error(struct dload_state *dlthis, const char *errtxt, ...);
++extern void dload_syms_error(struct Dynamic_Loader_Sym *syms,
++ const char *errtxt, ...);
++extern void dload_headers(struct dload_state *dlthis);
++extern void dload_strings(struct dload_state *dlthis, boolean sec_names_only);
++extern void dload_sections(struct dload_state *dlthis);
++extern void dload_reorder(void *data, int dsiz, u32 map);
++extern u32 dload_checksum(void *data, unsigned siz);
++
++#if HOST_ENDIANNESS
++extern uint32_t dload_reverse_checksum(void *data, unsigned siz);
++#if (TARGET_AU_BITS > 8) && (TARGET_AU_BITS < 32)
++extern uint32_t dload_reverse_checksum_16(void *data, unsigned siz);
++#endif
++#endif
++
++#define is_data_scn(zzz) (DLOAD_SECTION_TYPE((zzz)->type) != DLOAD_TEXT)
++#define is_data_scn_num(zzz) \
++ (DLOAD_SECT_TYPE(&dlthis->sect_hdrs[(zzz)-1]) != DLOAD_TEXT)
++
++/*
++ * exported by reloc.c
++ */
++extern void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
++ struct reloc_record_t *rp);
++
++extern RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn);
++
++extern int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn);
++
++#endif /* __DLOAD_INTERNAL__ */
+diff --git a/drivers/dsp/bridge/dynload/doff.h b/drivers/dsp/bridge/dynload/doff.h
+new file mode 100644
+index 0000000..2b8fc37
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/doff.h
+@@ -0,0 +1,347 @@
++/*
++ * doff.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*****************************************************************************/
++/* DOFF.H - Structures & definitions used for dynamically */
++/* loaded modules file format. This format is a reformatted */
++/* version of COFF.(see coff.h for details) It optimizes the */
++/* layout for the dynamic loader. */
++/* */
++/* .dof files, when viewed as a sequence of 32-bit integers, look the same */
++/* on big-endian and little-endian machines. */
++/*****************************************************************************/
++#ifndef _DOFF_H
++#define _DOFF_H
++
++#ifndef UINT32_C
++#define UINT32_C(zzz) ((u32)zzz)
++#endif
++
++#define BYTE_RESHUFFLE_VALUE UINT32_C(0x00010203)
++
++/* DOFF file header containing fields categorizing the remainder of the file */
++struct doff_filehdr_t {
++
++ /* string table size, including filename, in bytes */
++ u32 df_strtab_size;
++
++ /* entry point if one exists */
++ u32 df_entrypt;
++
++ /* identifies byte ordering of file;
++ * always set to BYTE_RESHUFFLE_VALUE */
++ u32 df_byte_reshuffle;
++
++ /* Size of the string table up to and including the last section name */
++ /* Size includes the name of the COFF file also */
++ u32 df_scn_name_size;
++
++#ifndef _BIG_ENDIAN
++ /* number of symbols */
++ u16 df_no_syms;
++
++ /* length in bytes of the longest string, including terminating NULL */
++ /* excludes the name of the file */
++ u16 df_max_str_len;
++
++ /* total number of sections including no-load ones */
++ u16 df_no_scns;
++
++ /* number of sections containing target code allocated or downloaded */
++ u16 df_target_scns;
++
++ /* unique id for dll file format & version */
++ u16 df_doff_version;
++
++ /* identifies ISA */
++ u16 df_target_id;
++
++ /* useful file flags */
++ u16 df_flags;
++
++ /* section reference for entry point, N_UNDEF for none, */
++ /* N_ABS for absolute address */
++ s16 df_entry_secn;
++#else
++ /* length of the longest string, including terminating NULL */
++ u16 df_max_str_len;
++
++ /* number of symbols */
++ u16 df_no_syms;
++
++ /* number of sections containing target code allocated or downloaded */
++ u16 df_target_scns;
++
++ /* total number of sections including no-load ones */
++ u16 df_no_scns;
++
++ /* identifies ISA */
++ u16 df_target_id;
++
++ /* unique id for dll file format & version */
++ u16 df_doff_version;
++
++ /* section reference for entry point, N_UNDEF for none, */
++ /* N_ABS for absolute address */
++ s16 df_entry_secn;
++
++ /* useful file flags */
++ u16 df_flags;
++#endif
++ /* checksum for file header record */
++ u32 df_checksum;
++
++} ;
++
++/* flags in the df_flags field */
++#define DF_LITTLE 0x100
++#define DF_BIG 0x200
++#define DF_BYTE_ORDER (DF_LITTLE | DF_BIG)
++
++/* Supported processors */
++#define TMS470_ID 0x97
++#define LEAD_ID 0x98
++#define TMS32060_ID 0x99
++#define LEAD3_ID 0x9c
++
++/* Primary processor for loading */
++#if TMS32060
++#define TARGET_ID TMS32060_ID
++#endif
++
++/* Verification record containing values used to test integrity of the bits */
++struct doff_verify_rec_t {
++
++ /* time and date stamp */
++ u32 dv_timdat;
++
++ /* checksum for all section records */
++ u32 dv_scn_rec_checksum;
++
++ /* checksum for string table */
++ u32 dv_str_tab_checksum;
++
++ /* checksum for symbol table */
++ u32 dv_sym_tab_checksum;
++
++ /* checksum for verification record */
++ u32 dv_verify_rec_checksum;
++
++} ;
++
++/* String table is an array of null-terminated strings. The first entry is
++ * the filename, which is added by DLLcreate. No new structure definitions
++ * are required.
++ */
++
++/* Section Records including information on the corresponding image packets */
++/*
++ * !!WARNING!!
++ *
++ * This structure is expected to match in form LDR_SECTION_INFO in
++ * dynamic_loader.h
++ */
++
++struct doff_scnhdr_t {
++
++ s32 ds_offset; /* offset into string table of name */
++ s32 ds_paddr; /* RUN address, in target AU */
++ s32 ds_vaddr; /* LOAD address, in target AU */
++ s32 ds_size; /* section size, in target AU */
++#ifndef _BIG_ENDIAN
++ u16 ds_page; /* memory page id */
++ u16 ds_flags; /* section flags */
++#else
++ u16 ds_flags; /* section flags */
++ u16 ds_page; /* memory page id */
++#endif
++ u32 ds_first_pkt_offset;
++ /* Absolute byte offset into the file */
++ /* where the first image record resides */
++
++ s32 ds_nipacks; /* number of image packets */
++
++};
++
++/* Symbol table entry */
++struct doff_syment_t {
++
++ s32 dn_offset; /* offset into string table of name */
++ s32 dn_value; /* value of symbol */
++#ifndef _BIG_ENDIAN
++ s16 dn_scnum; /* section number */
++ s16 dn_sclass; /* storage class */
++#else
++ s16 dn_sclass; /* storage class */
++ s16 dn_scnum; /* section number, 1-based */
++#endif
++
++} ;
++
++/* special values for dn_scnum */
++#define DN_UNDEF 0 /* undefined symbol */
++#define DN_ABS (-1) /* value of symbol is absolute */
++/* special values for dn_sclass */
++#define DN_EXT 2
++#define DN_STATLAB 20
++#define DN_EXTLAB 21
++
++/* Default value of image bits in packet */
++/* Configurable by user on the command line */
++#define IMAGE_PACKET_SIZE 1024
++
++/* An image packet contains a chunk of data from a section along with */
++/* information necessary for its processing. */
++struct image_packet_t {
++
++ s32 i_num_relocs; /* number of relocations for */
++ /* this packet */
++
++ s32 i_packet_size; /* number of bytes in array */
++ /* "bits" occupied by */
++ /* valid data. Could be */
++ /* < IMAGE_PACKET_SIZE to */
++ /* prevent splitting a */
++ /* relocation across packets. */
++ /* Last packet of a section */
++ /* will most likely contain */
++ /* < IMAGE_PACKET_SIZE bytes */
++ /* of valid data */
++
++ s32 i_checksum; /* Checksum for image packet */
++ /* and the corresponding */
++ /* relocation records */
++
++ u8 *i_bits; /* Actual data in section */
++
++};
++
++/* The relocation structure definition matches the COFF version. Offsets */
++/* however are relative to the image packet base not the section base. */
++struct reloc_record_t {
++
++ s32 r_vaddr;
++
++ /* expressed in target AUs */
++
++ union {
++ struct {
++#ifndef _BIG_ENDIAN
++ u8 _offset; /* bit offset of rel fld */
++ u8 _fieldsz; /* size of rel fld */
++ u8 _wordsz; /* # bytes containing rel fld */
++ u8 _dum1;
++ u16 _dum2;
++ u16 _type;
++#else
++ unsigned _dum1:8;
++ unsigned _wordsz:8; /* # bytes containing rel fld */
++ unsigned _fieldsz:8; /* size of rel fld */
++ unsigned _offset:8; /* bit offset of rel fld */
++ u16 _type;
++ u16 _dum2;
++#endif
++ } _r_field;
++
++ struct {
++ u32 _spc; /* image packet relative PC */
++#ifndef _BIG_ENDIAN
++ u16 _dum;
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _dum;
++#endif
++ } _r_spc;
++
++ struct {
++ u32 _uval; /* constant value */
++#ifndef _BIG_ENDIAN
++ u16 _dum;
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _dum;
++#endif
++ } _r_uval;
++
++ struct {
++ s32 _symndx; /* 32-bit sym tbl index */
++#ifndef _BIG_ENDIAN
++ u16 _disp; /* extra addr encode data */
++ u16 _type; /* relocation type */
++#else
++ u16 _type; /* relocation type */
++ u16 _disp; /* extra addr encode data */
++#endif
++ } _r_sym;
++ } _u_reloc;
++
++} ;
++
++/* abbreviations for convenience */
++#ifndef r_type
++#define r_type _u_reloc._r_sym._type
++#define r_uval _u_reloc._r_uval._uval
++#define r_symndx _u_reloc._r_sym._symndx
++#define r_offset _u_reloc._r_field._offset
++#define r_fieldsz _u_reloc._r_field._fieldsz
++#define r_wordsz _u_reloc._r_field._wordsz
++#define r_disp _u_reloc._r_sym._disp
++#endif
++
++/*****************************************************************************/
++/* */
++/* Important DOFF macros used for file processing */
++/* */
++/*****************************************************************************/
++
++/* DOFF Versions */
++#define DOFF0 0
++
++/* Return the address/size >= to addr that is at a 32-bit boundary */
++/* This assumes that a byte is 8 bits */
++#define DOFF_ALIGN(addr) (((addr) + 3) & ~UINT32_C(3))
++
++/*****************************************************************************/
++/* */
++/* The DOFF section header flags field is laid out as follows: */
++/* */
++/* Bits 0-3 : Section Type */
++/* Bit 4 : Set when section requires target memory to be allocated by DL */
++/* Bit 5 : Set when section requires downloading */
++/* Bits 8-11: Alignment, same as COFF */
++/* */
++/*****************************************************************************/
++
++/* Enum for DOFF section types (bits 0-3 of flag): See dynamic_loader.h */
++
++/* Macros to help processing of sections */
++#define DLOAD_SECT_TYPE(s_hdr) ((s_hdr)->ds_flags & 0xF)
++
++/* DS_ALLOCATE indicates whether a section needs space on the target */
++#define DS_ALLOCATE_MASK 0x10
++#define DS_NEEDS_ALLOCATION(s_hdr) ((s_hdr)->ds_flags & DS_ALLOCATE_MASK)
++
++/* DS_DOWNLOAD indicates that the loader needs to copy bits */
++#define DS_DOWNLOAD_MASK 0x20
++#define DS_NEEDS_DOWNLOAD(s_hdr) ((s_hdr)->ds_flags & DS_DOWNLOAD_MASK)
++
++/* Section alignment requirement in AUs */
++#define DS_ALIGNMENT(ds_flags) (1 << (((ds_flags) >> 8) & 0xF))
++
++#endif /* _DOFF_H */
+diff --git a/drivers/dsp/bridge/dynload/getsection.c b/drivers/dsp/bridge/dynload/getsection.c
+new file mode 100644
+index 0000000..78a301a
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/getsection.c
+@@ -0,0 +1,412 @@
++/*
++ * getsection.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#include <dspbridge/getsection.h>
++#include "header.h"
++
++/*
++ * Error strings
++ */
++static const char E_READSTRM[] = { "Error reading %s from input stream" };
++static const char E_SEEK[] = { "Set file position to %d failed" };
++static const char E_ISIZ[] = { "Bad image packet size %d" };
++static const char E_CHECKSUM[] = { "Checksum failed on %s" };
++static const char E_RELOC[] = { "DLOAD_GetSection unable to read"
++ "sections containing relocation entries"};
++#if BITS_PER_AU > BITS_PER_BYTE
++static const char E_ALLOC[] = { "Syms->Allocate( %d ) failed" };
++static const char E_STBL[] = { "Bad string table offset " FMT_UI32 };
++#endif
++
++/*
++ * we use the fact that DOFF section records are shaped just like
++ * LDR_SECTION_INFO to reduce our section storage usage. These macros
++ * marks the places where that assumption is made
++ */
++#define DOFFSEC_IS_LDRSEC(pdoffsec) ((struct LDR_SECTION_INFO *)(pdoffsec))
++#define LDRSEC_IS_DOFFSEC(ldrsec) ((struct doff_scnhdr_t *)(ldrsec))
++
++/***************************************************************/
++/********************* SUPPORT FUNCTIONS ***********************/
++/***************************************************************/
++
++#if BITS_PER_AU > BITS_PER_BYTE
++/**************************************************************************
++ * Procedure unpack_sec_name
++ *
++ * Parameters:
++ * dlthis Handle from DLOAD_module_open for this module
++ * soffset Byte offset into the string table
++ * dst Place to store the expanded string
++ *
++ * Effect:
++ * Stores a string from the string table into the destination, expanding
++ * it in the process. Returns a pointer just past the end of the stored
++ * string on success, or NULL on failure.
++ *
++ *************************************************************************/
++static char *unpack_sec_name(struct dload_state *dlthis,
++ u32 soffset, char *dst)
++{
++ u8 tmp, *src;
++
++ if (soffset >= dlthis->dfile_hdr.df_scn_name_size) {
++ dload_error(dlthis, E_STBL, soffset);
++ return NULL;
++ }
++ src = (u8 *)dlthis->str_head +
++ (soffset >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE));
++ if (soffset & 1)
++ *dst++ = *src++; /* only 1 character in first word */
++ do {
++ tmp = *src++;
++ *dst = (tmp >> BITS_PER_BYTE)
++ if (!(*dst++))
++ break;
++ } while ((*dst++ = tmp & BYTE_MASK));
++
++ return dst;
++}
++
++/**************************************************************************
++ * Procedure expand_sec_names
++ *
++ * Parameters:
++ * dlthis Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Allocates a buffer, unpacks and copies strings from string table into it.
++ * Stores a pointer to the buffer into a state variable.
++ **************************************************************************/
++static void expand_sec_names(struct dload_state *dlthis)
++{
++ char *xstrings, *curr, *next;
++ u32 xsize;
++ u16 sec;
++ struct LDR_SECTION_INFO *shp;
++ /* assume worst-case size requirement */
++ xsize = dlthis->dfile_hdr.df_max_str_len * dlthis->dfile_hdr.df_no_scns;
++ xstrings = (char *)dlthis->mysym->Allocate(dlthis->mysym, xsize);
++ if (xstrings == NULL) {
++ dload_error(dlthis, E_ALLOC, xsize);
++ return;
++ }
++ dlthis->xstrings = xstrings;
++ /* For each sec, copy and expand its name */
++ curr = xstrings;
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ next = unpack_sec_name(dlthis, *(u32 *) &shp->name, curr);
++ if (next == NULL)
++ break; /* error */
++ shp->name = curr;
++ curr = next;
++ }
++}
++
++#endif
++
++/***************************************************************/
++/********************* EXPORTED FUNCTIONS **********************/
++/***************************************************************/
++
++/**************************************************************************
++ * Procedure DLOAD_module_open
++ *
++ * Parameters:
++ * module The input stream that supplies the module image
++ * syms Host-side malloc/free and error reporting functions.
++ * Other methods are unused.
++ *
++ * Effect:
++ * Reads header information from a dynamic loader module using the
++ specified
++ * stream object, and returns a handle for the module information. This
++ * handle may be used in subsequent query calls to obtain information
++ * contained in the module.
++ *
++ * Returns:
++ * NULL if an error is encountered, otherwise a module handle for use
++ * in subsequent operations.
++ **************************************************************************/
++DLOAD_module_info DLOAD_module_open(struct Dynamic_Loader_Stream *module,
++ struct Dynamic_Loader_Sym *syms)
++{
++ struct dload_state *dlthis; /* internal state for this call */
++ unsigned *dp, sz;
++ u32 sec_start;
++#if BITS_PER_AU <= BITS_PER_BYTE
++ u16 sec;
++#endif
++
++ /* Check that mandatory arguments are present */
++ if (!module || !syms) {
++ if (syms != NULL)
++ dload_syms_error(syms, "Required parameter is NULL");
++
++ return NULL;
++ }
++
++ dlthis = (struct dload_state *)
++ syms->Allocate(syms, sizeof(struct dload_state));
++ if (!dlthis) {
++ /* not enough storage */
++ dload_syms_error(syms, "Can't allocate module info");
++ return NULL;
++ }
++
++ /* clear our internal state */
++ dp = (unsigned *)dlthis;
++ for (sz = sizeof(struct dload_state) / sizeof(unsigned);
++ sz > 0; sz -= 1)
++ *dp++ = 0;
++
++ dlthis->strm = module;
++ dlthis->mysym = syms;
++
++ /* read in the doff image and store in our state variable */
++ dload_headers(dlthis);
++
++ if (!dlthis->dload_errcount)
++ dload_strings(dlthis, true);
++
++ /* skip ahead past the unread portion of the string table */
++ sec_start = sizeof(struct doff_filehdr_t) +
++ sizeof(struct doff_verify_rec_t) +
++ BYTE_TO_HOST(DOFF_ALIGN(dlthis->dfile_hdr.df_strtab_size));
++
++ if (dlthis->strm->set_file_posn(dlthis->strm, sec_start) != 0) {
++ dload_error(dlthis, E_SEEK, sec_start);
++ return NULL;
++ }
++
++ if (!dlthis->dload_errcount)
++ dload_sections(dlthis);
++
++ if (dlthis->dload_errcount) {
++ DLOAD_module_close(dlthis); /* errors, blow off our state */
++ dlthis = NULL;
++ return NULL;
++ }
++#if BITS_PER_AU > BITS_PER_BYTE
++ /* Expand all section names from the string table into the */
++ /* state variable, and convert section names from a relative */
++ /* string table offset to a pointers to the expanded string. */
++ expand_sec_names(dlthis);
++#else
++ /* Convert section names from a relative string table offset */
++ /* to a pointer into the string table. */
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ struct LDR_SECTION_INFO *shp =
++ DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ shp->name = dlthis->str_head + *(u32 *)&shp->name;
++ }
++#endif
++
++ return dlthis;
++}
++
++/***************************************************************************
++ * Procedure DLOAD_GetSectionInfo
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionName Pointer to the string name of the section desired
++ * sectionInfo Address of a section info structure pointer to be
++ * initialized
++ *
++ * Effect:
++ * Finds the specified section in the module information, and initializes
++ * the provided struct LDR_SECTION_INFO pointer.
++ *
++ * Returns:
++ * true for success, false for section not found
++ **************************************************************************/
++int DLOAD_GetSectionInfo(DLOAD_module_info minfo, const char *sectionName,
++ const struct LDR_SECTION_INFO **const sectionInfo)
++{
++ struct dload_state *dlthis;
++ struct LDR_SECTION_INFO *shp;
++ u16 sec;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return false;
++
++ for (sec = 0; sec < dlthis->dfile_hdr.df_no_scns; sec++) {
++ shp = DOFFSEC_IS_LDRSEC(&dlthis->sect_hdrs[sec]);
++ if (strcmp(sectionName, shp->name) == 0) {
++ *sectionInfo = shp;
++ return true;
++ }
++ }
++
++ return false;
++}
++
++#define IPH_SIZE (sizeof(struct image_packet_t) - sizeof(u32))
++#define REVERSE_REORDER_MAP(rawmap) ((rawmap) ^ 0x3030303)
++
++/**************************************************************************
++ * Procedure DLOAD_GetSection
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ * sectionInfo Pointer to a section info structure for the desired
++ * section
++ * sectionData Buffer to contain the section initialized data
++ *
++ * Effect:
++ * Copies the initialized data for the specified section into the
++ * supplied buffer.
++ *
++ * Returns:
++ * true for success, false for section not found
++ **************************************************************************/
++int DLOAD_GetSection(DLOAD_module_info minfo,
++ const struct LDR_SECTION_INFO *sectionInfo, void *sectionData)
++{
++ struct dload_state *dlthis;
++ u32 pos;
++ struct doff_scnhdr_t *sptr = NULL;
++ s32 nip;
++ struct image_packet_t ipacket;
++ s32 ipsize;
++ u32 checks;
++ s8 *dest = (s8 *)sectionData;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return false;
++ sptr = LDRSEC_IS_DOFFSEC(sectionInfo);
++ if (sptr == NULL)
++ return false;
++
++ /* skip ahead to the start of the first packet */
++ pos = BYTE_TO_HOST(DOFF_ALIGN((u32) sptr->ds_first_pkt_offset));
++ if (dlthis->strm->set_file_posn(dlthis->strm, pos) != 0) {
++ dload_error(dlthis, E_SEEK, pos);
++ return false;
++ }
++
++ nip = sptr->ds_nipacks;
++ while ((nip -= 1) >= 0) { /* for each packet */
++ /* get the fixed header bits */
++ if (dlthis->strm->
++ read_buffer(dlthis->strm, &ipacket, IPH_SIZE) != IPH_SIZE) {
++ dload_error(dlthis, E_READSTRM, "image packet");
++ return false;
++ }
++ /* reorder the header if need be */
++ if (dlthis->reorder_map)
++ dload_reorder(&ipacket, IPH_SIZE, dlthis->reorder_map);
++
++ /* Now read the packet image bits. Note: round the size up to
++ * the next multiple of 4 bytes; this is what checksum
++ * routines want. */
++ ipsize = BYTE_TO_HOST(DOFF_ALIGN(ipacket.i_packet_size));
++ if (ipsize > BYTE_TO_HOST(IMAGE_PACKET_SIZE)) {
++ dload_error(dlthis, E_ISIZ, ipsize);
++ return false;
++ }
++ if (dlthis->strm->read_buffer
++ (dlthis->strm, dest, ipsize) != ipsize) {
++ dload_error(dlthis, E_READSTRM, "image packet");
++ return false;
++ }
++ /* reorder the bytes if need be */
++#if !defined(_BIG_ENDIAN) || (TARGET_AU_BITS > 16)
++ if (dlthis->reorder_map)
++ dload_reorder(dest, ipsize, dlthis->reorder_map);
++
++ checks = dload_checksum(dest, ipsize);
++#else
++ if (dlthis->dfile_hdr.df_byte_reshuffle !=
++ TARGET_ORDER(REORDER_MAP(BYTE_RESHUFFLE_VALUE))) {
++ /* put image bytes in big-endian order, not PC order */
++ dload_reorder(dest, ipsize,
++ TARGET_ORDER(dlthis->dfile_hdr.
++ df_byte_reshuffle));
++ }
++#if TARGET_AU_BITS > 8
++ checks = dload_reverse_checksum_16(dest, ipsize);
++#else
++ checks = dload_reverse_checksum(dest, ipsize);
++#endif
++#endif
++ checks += dload_checksum(&ipacket, IPH_SIZE);
++
++ /* NYI: unable to handle relocation entries here. Reloc
++ * entries referring to fields that span the packet boundaries
++ * may result in packets of sizes that are not multiple of
++ * 4 bytes. Our checksum implementation works on 32-bit words
++ * only. */
++ if (ipacket.i_num_relocs != 0) {
++ dload_error(dlthis, E_RELOC, ipsize);
++ return false;
++ }
++
++ if (~checks) {
++ dload_error(dlthis, E_CHECKSUM, "image packet");
++ return false;
++ }
++
++ /*Advance destination ptr by the size of the just-read packet*/
++ dest += ipsize;
++ }
++
++ return true;
++}
++
++/***************************************************************************
++ * Procedure DLOAD_module_close
++ *
++ * Parameters:
++ * minfo Handle from DLOAD_module_open for this module
++ *
++ * Effect:
++ * Releases any storage associated with the module handle. On return,
++ * the module handle is invalid.
++ *
++ * Returns:
++ * Zero for success. On error, the number of errors detected is returned.
++ * Individual errors are reported using syms->Error_Report(), where syms was
++ * an argument to DLOAD_module_open
++ **************************************************************************/
++void DLOAD_module_close(DLOAD_module_info minfo)
++{
++ struct dload_state *dlthis;
++
++ dlthis = (struct dload_state *)minfo;
++ if (!dlthis)
++ return;
++
++ if (dlthis->str_head)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->str_head);
++
++ if (dlthis->sect_hdrs)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->sect_hdrs);
++
++#if BITS_PER_AU > BITS_PER_BYTE
++ if (dlthis->xstrings)
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis->xstrings);
++
++#endif
++
++ dlthis->mysym->Deallocate(dlthis->mysym, dlthis);
++}
+diff --git a/drivers/dsp/bridge/dynload/header.h b/drivers/dsp/bridge/dynload/header.h
+new file mode 100644
+index 0000000..0de744b
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/header.h
+@@ -0,0 +1,59 @@
++/*
++ * header.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#define TRUE 1
++#define FALSE 0
++#ifndef NULL
++#define NULL 0
++#endif
++
++#include <linux/string.h>
++#define DL_STRCMP strcmp
++
++/* maximum parenthesis nesting in relocation stack expressions */
++#define STATIC_EXPR_STK_SIZE 10
++
++#include <linux/types.h>
++typedef unsigned int uint_least32_t;
++typedef unsigned short int uint_least16_t;
++
++#include "doff.h"
++#include <dspbridge/dynamic_loader.h>
++#include "params.h"
++#include "dload_internal.h"
++#include "reloc_table.h"
++
++/*
++ * Plausibility limits
++ *
++ * These limits are imposed upon the input DOFF file as a check for validity.
++ * They are hard limits, in that the load will fail if they are exceeded.
++ * The numbers selected are arbitrary, in that the loader implementation does
++ * not require these limits.
++ */
++
++/* maximum number of bytes in string table */
++#define MAX_REASONABLE_STRINGTAB (0x100000)
++/* maximum number of code,data,etc. sections */
++#define MAX_REASONABLE_SECTIONS (200)
++/* maximum number of linker symbols */
++#define MAX_REASONABLE_SYMBOLS (100000)
++
++/* shift count to align F_BIG with DLOAD_LITTLE */
++#define ALIGN_COFF_ENDIANNESS 7
++#define ENDIANNESS_MASK (DF_BYTE_ORDER >> ALIGN_COFF_ENDIANNESS)
+diff --git a/drivers/dsp/bridge/dynload/module_list.h b/drivers/dsp/bridge/dynload/module_list.h
+new file mode 100644
+index 0000000..9c4876a
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/module_list.h
+@@ -0,0 +1,161 @@
++/*
++ * dspbridge/mpu_driver/src/dynload/module_list.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*============================================================================
++ Filename: module_list.h
++
++ Copyright (C) 2002 Texas Instruments Incorporated
++
++
++ This C header file gives the layout of the data structure created by the
++ dynamic loader to describe the set of modules loaded into the DSP.
++
++ Linked List Structure:
++ ----------------------
++ The data structure defined here is a singly-linked list. The list
++ represents the set of modules which are currently loaded in the DSP memory.
++ The first entry in the list is a header record which contains a flag
++ representing the state of the list. The rest of the entries in the list
++ are module records.
++
++ Global symbol _DLModules designates the first record in the list (i.e. the
++ header record). This symbol must be defined in any program that wishes to
++ use DLLview plug-in.
++
++ String Representation:
++ ----------------------
++ The string names of the module and its sections are stored in a block of
++ memory which follows the module record itself. The strings are ordered:
++ module name first, followed by section names in order from the first
++ section to the last. String names are tightly packed arrays of 8-bit
++ characters (two characters per 16-bit word on the C55x). Strings are
++ zero-byte-terminated.
++
++ Creating and updating the list:
++-------------------------------
++ Upon loading a new module into the DSP memory the dynamic loader inserts a
++new module record as the first module record in the list. The fields of
++ this module record are initialized to reflect the properties of the module.
++ The dynamic loader does NOT increment the flag/counter in the list's header
++ record.
++
++ Upon unloading a module from the DSP memory the dynamic loader removes the
++module's record from this list. The dynamic loader also increments the
++ flag/counter in the list's header record to indicate that the list has been
++ changed.
++
++============================================================================*/
++
++#ifndef _MODULE_LIST_H_
++#define _MODULE_LIST_H_
++
++#include <linux/types.h>
++
++/* Global pointer to the modules_header structure*/
++#define MODULES_HEADER "_DLModules"
++#define MODULES_HEADER_NO_UNDERSCORE "DLModules"
++
++/* Initial version number*/
++#define INIT_VERSION 1
++
++/* Verification number -- to be recorded in each module record */
++#define VERIFICATION 0x79
++
++/* forward declarations */
++struct dll_module;
++struct dll_sect;
++
++/* the first entry in the list is the modules_header record;
++ * its address is contained in the global _DLModules pointer */
++struct modules_header {
++
++ /* Address of the first dll_module record in the list or NULL.
++ Note: for C55x this is a word address (C55x data is word-addressable)*/
++ u32 first_module;
++
++ /* Combined storage size (in target addressable units) of the
++ * dll_module record which follows this header record, or zero
++ * if the list is empty. This size includes the module's string table.
++ * Note: for C55x the unit is a 16-bit word */
++ u16 first_module_size;
++
++ /* Counter is incremented whenever a module record is removed from
++ * the list */
++ u16 update_flag;
++
++} ;
++
++/* for each 32-bits in above structure, a bitmap, LSB first, whose bits are:
++ * 0 => a 32-bit value, 1 => 2 16-bit values */
++#define MODULES_HEADER_BITMAP 0x2 /* swapping bitmap for type modules_header */
++
++/* information recorded about each section in a module */
++struct dll_sect {
++
++ /* Load-time address of the section.
++ * Note: for C55x this is a byte address for program sections, and
++ * a word address for data sections. C55x program memory is
++ * byte-addressable, while data memory is word-addressable. */
++ u32 sect_load_adr;
++
++ /* Run-time address of the section.
++ * Note 1: for C55x this is a byte address for program sections, and
++ * a word address for data sections.
++ * Note 2: for C55x two most significant bits of this field indicate
++ * the section type: '00' for a code section, '11' for a data section
++ * (C55 addresses are really only 24-bits wide). */
++ u32 sect_run_adr;
++
++} ;
++
++/* the rest of the entries in the list are module records */
++struct dll_module {
++
++ /* Address of the next dll_module record in the list, or 0 if this is
++ * the last record in the list.
++ * Note: for C55x this is a word address (C55x data is
++ * word-addressable) */
++ u32 next_module;
++
++ /* Combined storage size (in target addressable units) of the
++ * dll_module record which follows this one, or zero if this is the
++ * last record in the list. This size includes the module's string
++ * table.
++ * Note: for C55x the unit is a 16-bit word. */
++ u16 next_module_size;
++
++ /* version number of the tooling; set to INIT_VERSION for Phase 1 */
++ u16 version;
++
++ /* the verification word; set to VERIFICATION */
++ u16 verification;
++
++ /* Number of sections in the sects array */
++ u16 num_sects;
++
++ /* Module's "unique" id; copy of the timestamp from the host
++ * COFF file */
++ u32 timestamp;
++
++ /* Array of num_sects elements of the module's section records */
++ struct dll_sect sects[1];
++} ;
++
++/* for each 32 bits in above structure, a bitmap, LSB first, whose bits are:
++ * 0 => a 32-bit value, 1 => 2 16-bit values */
++#define DLL_MODULE_BITMAP 0x6 /* swapping bitmap for type dll_module */
++
++#endif /* _MODULE_LIST_H_ */
+diff --git a/drivers/dsp/bridge/dynload/params.h b/drivers/dsp/bridge/dynload/params.h
+new file mode 100644
+index 0000000..ade430d
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/params.h
+@@ -0,0 +1,231 @@
++/*
++ * params.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++/******************************************************************************
++ *
++ * This file defines host and target properties for all machines
++ * supported by the dynamic loader. To be tedious...
++ *
++ * host == the machine on which the dynamic loader runs
++ * target == the machine that the dynamic loader is loading
++ *
++ * Host and target may or may not be the same, depending upon the particular
++ * use.
++ *****************************************************************************/
++
++/******************************************************************************
++ *
++ * Host Properties
++ *
++ *****************************************************************************/
++
++#define BITS_PER_BYTE 8 /* bits in the standard PC/SUN byte */
++#define LOG_BITS_PER_BYTE 3 /* log base 2 of same */
++#define BYTE_MASK ((1U<<BITS_PER_BYTE)-1)
++
++#if defined(__TMS320C55X__) || defined(_TMS320C5XX)
++#define BITS_PER_AU 16
++#define LOG_BITS_PER_AU 4
++ /* use this print string in error messages for uint32_t */
++#define FMT_UI32 "0x%lx"
++#define FMT8_UI32 "%08lx" /* same but no 0x, fixed width field */
++#else
++#define BITS_PER_AU 8 /* bits in the smallest addressable data storage unit */
++#define LOG_BITS_PER_AU 3 /* log base 2 of the same; useful for shift counts */
++#define FMT_UI32 "0x%x"
++#define FMT8_UI32 "%08x"
++#endif
++
++/* generic fastest method for swapping bytes and shorts */
++#define SWAP32BY16(zz) (((zz) << 16) | ((zz) >> 16))
++#define SWAP16BY8(zz) (((zz) << 8) | ((zz) >> 8))
++
++/* !! don't be tempted to insert type definitions here; use <stdint.h> !! */
++
++/******************************************************************************
++ *
++ * Target Properties
++ *
++ *****************************************************************************/
++
++
++/*--------------------------------------------------------------------------*/
++/* TMS320C6x Target Specific Parameters (byte-addressable) */
++/*--------------------------------------------------------------------------*/
++#if TMS32060
++#define MEMORG 0x0L /* Size of configured memory */
++#define MEMSIZE 0x0L /* (full address space) */
++
++#define CINIT_ALIGN 8 /* alignment of cinit record in TDATA AUs */
++#define CINIT_COUNT 4 /* width of count field in TDATA AUs */
++#define CINIT_ADDRESS 4 /* width of address field in TDATA AUs */
++#define CINIT_PAGE_BITS 0 /* Number of LSBs of address that
++ * are page number */
++
++#define LENIENT_SIGNED_RELEXPS 0 /* DOES SIGNED ALLOW MAX UNSIGNED */
++
++#undef TARGET_ENDIANNESS /* may be big or little endian */
++
++/* align a target address to a word boundary */
++#define TARGET_WORD_ALIGN(zz) (((zz) + 0x3) & -0x4)
++#endif
++
++
++/*--------------------------------------------------------------------------
++ *
++ * DEFAULT SETTINGS and DERIVED PROPERTIES
++ *
++ * This section establishes defaults for values not specified above
++ *--------------------------------------------------------------------------*/
++#ifndef TARGET_AU_BITS
++#define TARGET_AU_BITS 8 /* width of the target addressable unit */
++#define LOG_TARGET_AU_BITS 3 /* log2 of same */
++#endif
++
++#ifndef CINIT_DEFAULT_PAGE
++#define CINIT_DEFAULT_PAGE 0 /* default .cinit page number */
++#endif
++
++#ifndef DATA_RUN2LOAD
++#define DATA_RUN2LOAD(zz) (zz) /* translate data run address to load address */
++#endif
++
++#ifndef DBG_LIST_PAGE
++#define DBG_LIST_PAGE 0 /* page number for .dllview section */
++#endif
++
++#ifndef TARGET_WORD_ALIGN
++/* align a target address to a word boundary */
++#define TARGET_WORD_ALIGN(zz) (zz)
++#endif
++
++#ifndef TDATA_TO_TADDR
++#define TDATA_TO_TADDR(zz) (zz) /* target data address to target AU address */
++#define TADDR_TO_TDATA(zz) (zz) /* target AU address to target data address */
++#define TDATA_AU_BITS TARGET_AU_BITS /* bits per data AU */
++#define LOG_TDATA_AU_BITS LOG_TARGET_AU_BITS
++#endif
++
++/*
++ *
++ * Useful properties and conversions derived from the above
++ *
++ */
++
++/*
++ * Conversions between host and target addresses
++ */
++#if LOG_BITS_PER_AU == LOG_TARGET_AU_BITS
++/* translate target addressable unit to host address */
++#define TADDR_TO_HOST(x) (x)
++/* translate host address to target addressable unit */
++#define HOST_TO_TADDR(x) (x)
++#elif LOG_BITS_PER_AU > LOG_TARGET_AU_BITS
++#define TADDR_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
++#define HOST_TO_TADDR(x) ((x) << (LOG_BITS_PER_AU-LOG_TARGET_AU_BITS))
++#else
++#define TADDR_TO_HOST(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_AU))
++#endif
++
++#if LOG_BITS_PER_AU == LOG_TDATA_AU_BITS
++/* translate target addressable unit to host address */
++#define TDATA_TO_HOST(x) (x)
++/* translate host address to target addressable unit */
++#define HOST_TO_TDATA(x) (x)
++/* translate host address to target addressable unit, round up */
++#define HOST_TO_TDATA_ROUND(x) (x)
++/* byte offset to host offset, rounded up for TDATA size */
++#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
++#elif LOG_BITS_PER_AU > LOG_TDATA_AU_BITS
++#define TDATA_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define HOST_TO_TDATA(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define HOST_TO_TDATA_ROUND(x) ((x) << (LOG_BITS_PER_AU-LOG_TDATA_AU_BITS))
++#define BYTE_TO_HOST_TDATA_ROUND(x) BYTE_TO_HOST_ROUND(x)
++#else
++#define TDATA_TO_HOST(x) ((x) << (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TDATA(x) ((x) >> (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define HOST_TO_TDATA_ROUND(x) (((x) +\
++ (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))-1) >>\
++ (LOG_TDATA_AU_BITS-LOG_BITS_PER_AU))
++#define BYTE_TO_HOST_TDATA_ROUND(x) (BYTE_TO_HOST((x) +\
++ (1<<(LOG_TDATA_AU_BITS-LOG_BITS_PER_BYTE))-1) &\
++ -(TDATA_AU_BITS/BITS_PER_AU))
++#endif
++
++/*
++ * Input in DOFF format is always expresed in bytes, regardless of loading host
++ * so we wind up converting from bytes to target and host units even when the
++ * host is not a byte machine.
++ */
++#if LOG_BITS_PER_AU == LOG_BITS_PER_BYTE
++#define BYTE_TO_HOST(x) (x)
++#define BYTE_TO_HOST_ROUND(x) (x)
++#define HOST_TO_BYTE(x) (x)
++#elif LOG_BITS_PER_AU >= LOG_BITS_PER_BYTE
++#define BYTE_TO_HOST(x) ((x) >> (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#define BYTE_TO_HOST_ROUND(x) ((x + (BITS_PER_AU/BITS_PER_BYTE-1)) >>\
++ (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#define HOST_TO_BYTE(x) ((x) << (LOG_BITS_PER_AU - LOG_BITS_PER_BYTE))
++#else
++/* lets not try to deal with sub-8-bit byte machines */
++#endif
++
++#if LOG_TARGET_AU_BITS == LOG_BITS_PER_BYTE
++/* translate target addressable unit to byte address */
++#define TADDR_TO_BYTE(x) (x)
++/* translate byte address to target addressable unit */
++#define BYTE_TO_TADDR(x) (x)
++#elif LOG_TARGET_AU_BITS > LOG_BITS_PER_BYTE
++#define TADDR_TO_BYTE(x) ((x) << (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
++#define BYTE_TO_TADDR(x) ((x) >> (LOG_TARGET_AU_BITS-LOG_BITS_PER_BYTE))
++#else
++/* lets not try to deal with sub-8-bit byte machines */
++#endif
++
++#ifdef _BIG_ENDIAN
++#define HOST_ENDIANNESS 1
++#else
++#define HOST_ENDIANNESS 0
++#endif
++
++#ifdef TARGET_ENDIANNESS
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (HOST_ENDIANNESS^TARGET_ENDIANNESS)
++#elif HOST_ENDIANNESS
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (!(rtend))
++#else
++#define TARGET_ENDIANNESS_DIFFERS(rtend) (rtend)
++#endif
++
++/* the unit in which we process target image data */
++#if TARGET_AU_BITS <= 8
++typedef u8 TgtAU_t;
++#elif TARGET_AU_BITS <= 16
++typedef u16 TgtAU_t;
++#else
++typedef u32 TgtAU_t;
++#endif
++
++/* size of that unit */
++#if TARGET_AU_BITS < BITS_PER_AU
++#define TGTAU_BITS BITS_PER_AU
++#define LOG_TGTAU_BITS LOG_BITS_PER_AU
++#else
++#define TGTAU_BITS TARGET_AU_BITS
++#define LOG_TGTAU_BITS LOG_TARGET_AU_BITS
++#endif
+diff --git a/drivers/dsp/bridge/dynload/reloc.c b/drivers/dsp/bridge/dynload/reloc.c
+new file mode 100644
+index 0000000..54e460e
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc.c
+@@ -0,0 +1,425 @@
++/*
++ * reloc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include "header.h"
++
++#if TMS32060
++/* the magic symbol for the start of BSS */
++static const char BSSSYMBOL[] = {".bss"};
++#endif
++
++#if TMS32060
++#include "reloc_table_c6000.c"
++#endif
++
++#if TMS32060
++/* From coff.h - ignore these relocation operations */
++#define R_C60ALIGN 0x76 /* C60: Alignment info for compressor */
++#define R_C60FPHEAD 0x77 /* C60: Explicit assembly directive */
++#define R_C60NOCMP 0x100 /* C60: Don't compress this code scn */
++#endif
++
++/**************************************************************************
++ * Procedure dload_unpack
++ *
++ * Parameters:
++ * data pointer to storage unit containing lowest host address of
++ * image data
++ * fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
++ * offset Offset from LSB, 0 <= offset < BITS_PER_AU
++ * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
++ *
++ * Effect:
++ * Extracts the specified field and returns it.
++ **************************************************************************/
++RVALUE dload_unpack(struct dload_state *dlthis, TgtAU_t *data, int fieldsz,
++ int offset, unsigned sgn)
++{
++ register RVALUE objval;
++ register int shift, direction;
++ register TgtAU_t *dp = data;
++
++ fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value*/
++ /* * collect up enough bits to contain the desired field */
++ if (TARGET_BIG_ENDIAN) {
++ dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
++ direction = -1;
++ } else
++ direction = 1;
++ objval = *dp >> offset;
++ shift = TGTAU_BITS - offset;
++ while (shift <= fieldsz) {
++ dp += direction;
++ objval += (RVALUE)*dp << shift;
++ shift += TGTAU_BITS;
++ }
++
++ /* * sign or zero extend the value appropriately */
++ if (sgn == ROP_UNS)
++ objval &= (2 << fieldsz) - 1;
++ else {
++ shift = sizeof(RVALUE) * BITS_PER_AU-1 - fieldsz;
++ objval = (objval << shift) >> shift;
++ }
++
++ return objval;
++
++} /* dload_unpack */
++
++
++/**************************************************************************
++ * Procedure dload_repack
++ *
++ * Parameters:
++ * val Value to insert
++ * data Pointer to storage unit containing lowest host address of
++ * image data
++ * fieldsz Size of bit field, 0 < fieldsz <= sizeof(RVALUE)*BITS_PER_AU
++ * offset Offset from LSB, 0 <= offset < BITS_PER_AU
++ * sgn Signedness of the field (ROP_SGN, ROP_UNS, ROP_MAX, ROP_ANY)
++ *
++ * Effect:
++ * Stuffs the specified value in the specified field. Returns 0 for
++ * success
++ * or 1 if the value will not fit in the specified field according to the
++ * specified signedness rule.
++ **************************************************************************/
++static const unsigned char ovf_limit[] = {1, 2, 2};
++int dload_repack(struct dload_state *dlthis, RVALUE val, TgtAU_t *data,
++ int fieldsz, int offset, unsigned sgn)
++{
++ register URVALUE objval, mask;
++ register int shift, direction;
++ register TgtAU_t *dp = data;
++
++
++ fieldsz -= 1; /* avoid nastiness with 32-bit shift of 32-bit value */
++ /* clip the bits */
++ mask = ((UINT32_C(2) << fieldsz) - 1);
++ objval = (val & mask);
++ /* * store the bits through the specified mask */
++ if (TARGET_BIG_ENDIAN) {
++ dp += (fieldsz + offset) >> LOG_TGTAU_BITS;
++ direction = -1;
++ } else
++ direction = 1;
++
++ /* insert LSBs */
++ *dp = (*dp & ~(mask << offset)) + (objval << offset);
++ shift = TGTAU_BITS-offset;
++ /* align mask and objval with AU boundary */
++ objval >>= shift;
++ mask >>= shift;
++
++ while (mask) {
++ dp += direction;
++ *dp = (*dp & ~mask) + objval;
++ objval >>= TGTAU_BITS;
++ mask >>= TGTAU_BITS;
++ }
++
++ /*
++ * check for overflow
++ */
++ if (sgn) {
++ unsigned tmp = (val >> fieldsz) + (sgn & 0x1);
++ if (tmp > ovf_limit[sgn-1])
++ return 1;
++ }
++ return 0;
++
++} /* dload_repack */
++
++/* lookup table for the scaling amount in a C6x instruction */
++#if TMS32060
++#define SCALE_BITS 4 /* there are 4 bits in the scale field */
++#define SCALE_MASK 0x7 /* we really only use the bottom 3 bits */
++static const u8 C60_Scale[SCALE_MASK+1] = {
++ 1, 0, 0, 0, 1, 1, 2, 2
++};
++#endif
++
++/**************************************************************************
++ * Procedure dload_relocate
++ *
++ * Parameters:
++ * data Pointer to base of image data
++ * rp Pointer to relocation operation
++ *
++ * Effect:
++ * Performs the specified relocation operation
++ **************************************************************************/
++void dload_relocate(struct dload_state *dlthis, TgtAU_t *data,
++ struct reloc_record_t *rp)
++{
++ RVALUE val = 0;
++ RVALUE reloc_amt = 0;
++ unsigned int fieldsz = 0;
++ unsigned int offset = 0;
++ unsigned int reloc_info = 0;
++ unsigned int reloc_action = 0;
++ register int rx = 0;
++ RVALUE *stackp = NULL;
++ int top;
++ struct Local_Symbol *svp = NULL;
++#ifdef RFV_SCALE
++ unsigned int scale = 0;
++#endif
++
++ rx = HASH_FUNC(rp->r_type);
++ while (rop_map1[rx] != rp->r_type) {
++ rx = HASH_L(rop_map2[rx]);
++ if (rx < 0) {
++#if TMS32060
++ switch (rp->r_type) {
++ case R_C60ALIGN:
++ case R_C60NOCMP:
++ case R_C60FPHEAD:
++ /* Ignore these reloc types and return */
++ break;
++ default:
++ /* Unknown reloc type, print error and return */
++ dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
++ }
++#else
++ dload_error(dlthis, "Bad coff operator 0x%x", rp->r_type);
++#endif
++ return;
++ }
++ }
++ rx = HASH_I(rop_map2[rx]);
++ if ((rx < (sizeof(rop_action)/sizeof(uint_least16_t)))
++ && (rx < (sizeof(rop_info)/sizeof(uint_least16_t))) && (rx > 0)) {
++ reloc_action = rop_action[rx]; reloc_info = rop_info[rx];
++ } else {
++ dload_error(dlthis, "Buffer Overflow - Array Index Out of Bounds");
++ }
++
++ /* Compute the relocation amount for the referenced symbol, if any */
++ reloc_amt = rp->r_uval;
++ if (RFV_SYM(reloc_info)) { /* relocation uses a symbol reference */
++ if ((u32)rp->r_symndx < dlthis->dfile_hdr.df_no_syms) {
++ /* real symbol reference */
++ svp = &dlthis->local_symtab[rp->r_symndx];
++ reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
++ svp->delta : svp->value;
++ }
++ /* reloc references current section */
++ else if (rp->r_symndx == -1)
++ reloc_amt = (RFV_SYM(reloc_info) == ROP_SYMD) ?
++ dlthis->delta_runaddr : dlthis->image_secn->run_addr;
++ } /* relocation uses a symbol reference */
++ /* Handle stack adjustment */
++ val = 0;
++ top = RFV_STK(reloc_info);
++ if (top) {
++ top += dlthis->relstkidx - RSTK_UOP;
++ if (top >= STATIC_EXPR_STK_SIZE) {
++ dload_error(dlthis,
++ "Expression stack overflow in %s at offset "
++ FMT_UI32, dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ return;
++ }
++ val = dlthis->relstk[dlthis->relstkidx];
++ dlthis->relstkidx = top;
++ stackp = &dlthis->relstk[top];
++ }
++ /* Derive field position and size, if we need them */
++ if (reloc_info & ROP_RW) { /* read or write action in our future */
++ fieldsz = RFV_WIDTH(reloc_action);
++ if (fieldsz) { /* field info from table */
++ offset = RFV_POSN(reloc_action);
++ if (TARGET_BIG_ENDIAN)
++ /* make sure r_vaddr is the lowest target
++ * address containing bits */
++ rp->r_vaddr += RFV_BIGOFF(reloc_info);
++ } else { /* field info from relocation op */
++ fieldsz = rp->r_fieldsz; offset = rp->r_offset;
++ if (TARGET_BIG_ENDIAN)
++ /* make sure r_vaddr is the lowest target
++ address containing bits */
++ rp->r_vaddr += (rp->r_wordsz - offset - fieldsz)
++ >> LOG_TARGET_AU_BITS;
++ }
++ data = (TgtAU_t *)((char *)data + TADDR_TO_HOST(rp->r_vaddr));
++ /* compute lowest host location of referenced data */
++#if BITS_PER_AU > TARGET_AU_BITS
++ /* conversion from target address to host address may lose
++ address bits; add loss to offset */
++ if (TARGET_BIG_ENDIAN) {
++ offset += -((rp->r_vaddr << LOG_TARGET_AU_BITS) +
++ offset + fieldsz) &
++ (BITS_PER_AU-TARGET_AU_BITS);
++ } else {
++ offset += (rp->r_vaddr << LOG_TARGET_AU_BITS) &
++ (BITS_PER_AU-1);
++ }
++#endif
++#ifdef RFV_SCALE
++ scale = RFV_SCALE(reloc_info);
++#endif
++ }
++ /* read the object value from the current image, if so ordered */
++ if (reloc_info & ROP_R) { /* relocation reads current image value */
++ val = dload_unpack(dlthis, data, fieldsz, offset,
++ RFV_SIGN(reloc_info));
++#ifdef RFV_SCALE
++ val <<= scale;
++#endif
++ }
++ /* perform the necessary arithmetic */
++ switch (RFV_ACTION(reloc_action)) { /* relocation actions */
++ case RACT_VAL:
++ break;
++ case RACT_ASGN:
++ val = reloc_amt;
++ break;
++ case RACT_ADD:
++ val += reloc_amt;
++ break;
++ case RACT_PCR:
++ /*-----------------------------------------------------------
++ * Handle special cases of jumping from absolute sections
++ * (special reloc type) or to absolute destination
++ * (symndx == -1). In either case, set the appropriate
++ * relocation amount to 0.
++ *-----------------------------------------------------------*/
++ if (rp->r_symndx == -1)
++ reloc_amt = 0;
++ val += reloc_amt - dlthis->delta_runaddr;
++ break;
++ case RACT_ADDISP:
++ val += rp->r_disp + reloc_amt;
++ break;
++ case RACT_ASGPC:
++ val = dlthis->image_secn->run_addr + reloc_amt;
++ break;
++ case RACT_PLUS:
++ if (stackp != NULL)
++ val += *stackp;
++ break;
++ case RACT_SUB:
++ if (stackp != NULL)
++ val = *stackp - val;
++ break;
++ case RACT_NEG:
++ val = -val;
++ break;
++ case RACT_MPY:
++ if (stackp != NULL)
++ val *= *stackp;
++ break;
++ case RACT_DIV:
++ if (stackp != NULL)
++ val = *stackp / val;
++ break;
++ case RACT_MOD:
++ if (stackp != NULL)
++ val = *stackp % val;
++ break;
++ case RACT_SR:
++ if (val >= sizeof(RVALUE) * BITS_PER_AU)
++ val = 0;
++ else if (stackp != NULL)
++ val = (URVALUE)*stackp >> val;
++ break;
++ case RACT_ASR:
++ if (val >= sizeof(RVALUE)*BITS_PER_AU)
++ val = sizeof(RVALUE)*BITS_PER_AU - 1;
++ else if (stackp != NULL)
++ val = *stackp >> val;
++ break;
++ case RACT_SL:
++ if (val >= sizeof(RVALUE)*BITS_PER_AU)
++ val = 0;
++ else if (stackp != NULL)
++ val = *stackp << val;
++ break;
++ case RACT_AND:
++ if (stackp != NULL)
++ val &= *stackp;
++ break;
++ case RACT_OR:
++ if (stackp != NULL)
++ val |= *stackp;
++ break;
++ case RACT_XOR:
++ if (stackp != NULL)
++ val ^= *stackp;
++ break;
++ case RACT_NOT:
++ val = ~val;
++ break;
++#if TMS32060
++ case RACT_C6SECT:
++ /* actually needed address of secn containing symbol */
++ if (svp != NULL) {
++ if (rp->r_symndx >= 0)
++ if (svp->secnn > 0)
++ reloc_amt = dlthis->ldr_sections
++ [svp->secnn-1].run_addr;
++ }
++ /* !!! FALL THRU !!! */
++ case RACT_C6BASE:
++ if (dlthis->bss_run_base == 0) {
++ struct dynload_symbol *symp;
++ symp = dlthis->mysym->Find_Matching_Symbol
++ (dlthis->mysym, BSSSYMBOL);
++ /* lookup value of global BSS base */
++ if (symp)
++ dlthis->bss_run_base = symp->value;
++ else
++ dload_error(dlthis,
++ "Global BSS base referenced in %s offset"\
++ FMT_UI32 " but not defined",
++ dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ }
++ reloc_amt -= dlthis->bss_run_base;
++ /* !!! FALL THRU !!! */
++ case RACT_C6DSPL:
++ /* scale factor determined by 3 LSBs of field */
++ scale = C60_Scale[val & SCALE_MASK];
++ offset += SCALE_BITS;
++ fieldsz -= SCALE_BITS;
++ val >>= SCALE_BITS; /* ignore the scale field hereafter */
++ val <<= scale;
++ val += reloc_amt; /* do the usual relocation */
++ if (((1 << scale)-1) & val)
++ dload_error(dlthis,
++ "Unaligned reference in %s offset " FMT_UI32,
++ dlthis->image_secn->name,
++ rp->r_vaddr + dlthis->image_offset);
++ break;
++#endif
++ } /* relocation actions */
++ /* * Put back result as required */
++ if (reloc_info & ROP_W) { /* relocation writes image value */
++#ifdef RFV_SCALE
++ val >>= scale;
++#endif
++ if (dload_repack(dlthis, val, data, fieldsz, offset,
++ RFV_SIGN(reloc_info))) {
++ dload_error(dlthis, "Relocation value " FMT_UI32
++ " overflows %d bits in %s offset " FMT_UI32, val,
++ fieldsz, dlthis->image_secn->name,
++ dlthis->image_offset + rp->r_vaddr);
++ }
++ } else if (top)
++ *stackp = val;
++} /* reloc_value */
++
+diff --git a/drivers/dsp/bridge/dynload/reloc_table.h b/drivers/dsp/bridge/dynload/reloc_table.h
+new file mode 100644
+index 0000000..6326146
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc_table.h
+@@ -0,0 +1,102 @@
++/*
++ * reloc_table.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef __RELOC_TABLE_H__
++#define __RELOC_TABLE_H__
++/*
++ * Table of relocation operator properties
++ */
++#include <linux/types.h>
++
++/* How does this relocation operation access the program image? */
++#define ROP_N 0 /* does not access image */
++#define ROP_R 1 /* read from image */
++#define ROP_W 2 /* write to image */
++#define ROP_RW 3 /* read from and write to image */
++
++/* For program image access, what are the overflow rules for the bit field? */
++/* Beware! Procedure repack depends on this encoding */
++#define ROP_ANY 0 /* no overflow ever, just truncate the value */
++#define ROP_SGN 1 /* signed field */
++#define ROP_UNS 2 /* unsigned field */
++#define ROP_MAX 3 /* allow maximum range of either signed or unsigned */
++
++/* How does the relocation operation use the symbol reference */
++#define ROP_IGN 0 /* no symbol is referenced */
++#define ROP_LIT 0 /* use rp->r_uval literal field */
++#define ROP_SYM 1 /* symbol value is used in relocation */
++#define ROP_SYMD 2 /* delta value vs last link is used */
++
++/* How does the reloc op use the stack? */
++#define RSTK_N 0 /* Does not use */
++#define RSTK_POP 1 /* Does a POP */
++#define RSTK_UOP 2 /* Unary op, stack position unaffected */
++#define RSTK_PSH 3 /* Does a push */
++
++/*
++ * Computational actions performed by the dynamic loader
++ */
++enum Dload_Actions {
++ RACT_VAL, /* don't alter the current val (from stack or mem fetch) */
++ RACT_ASGN, /* set value to reference amount (from symbol reference) */
++ RACT_ADD, /* add reference to value */
++ RACT_PCR, /* add reference minus PC delta to value */
++ RACT_ADDISP, /* add reference plus r_disp */
++ RACT_ASGPC, /* set value to section address plus reference */
++
++ RACT_PLUS, /* stack + */
++ RACT_SUB, /* stack - */
++ RACT_NEG, /* stack unary - */
++
++ RACT_MPY, /* stack * */
++ RACT_DIV, /* stack / */
++ RACT_MOD, /* stack % */
++
++ RACT_SR, /* stack unsigned >> */
++ RACT_ASR, /* stack signed >> */
++ RACT_SL, /* stack << */
++ RACT_AND, /* stack & */
++ RACT_OR, /* stack | */
++ RACT_XOR, /* stack ^ */
++ RACT_NOT, /* stack ~ */
++ RACT_C6SECT, /* for C60 R_SECT op */
++ RACT_C6BASE, /* for C60 R_BASE op */
++ RACT_C6DSPL, /* for C60 scaled 15-bit displacement */
++ RACT_PCR23T /* for ARM Thumb long branch */
++};
++
++/*
++ * macros used to extract values
++ */
++#define RFV_POSN(aaa) ((aaa) & 0xF)
++#define RFV_WIDTH(aaa) (((aaa) >> 4) & 0x3F)
++#define RFV_ACTION(aaa) ((aaa) >> 10)
++
++#define RFV_SIGN(iii) (((iii) >> 2) & 0x3)
++#define RFV_SYM(iii) (((iii) >> 4) & 0x3)
++#define RFV_STK(iii) (((iii) >> 6) & 0x3)
++#define RFV_ACCS(iii) ((iii) & 0x3)
++
++#if (TMS32060)
++#define RFV_SCALE(iii) ((iii) >> 11)
++#define RFV_BIGOFF(iii) (((iii) >> 8) & 0x7)
++#else
++#define RFV_BIGOFF(iii) ((iii) >> 8)
++#endif
++
++#endif /* __RELOC_TABLE_H__ */
+diff --git a/drivers/dsp/bridge/dynload/reloc_table_c6000.c b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
+new file mode 100644
+index 0000000..978834c
+--- /dev/null
++++ b/drivers/dsp/bridge/dynload/reloc_table_c6000.c
+@@ -0,0 +1,258 @@
++/*
++ * reloc_table_c6000.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/* Tables generated for c6000 */
++
++#define HASH_FUNC(zz) (((((zz) + 1) * UINT32_C(1845)) >> 11) & 63)
++#define HASH_L(zz) ((zz) >> 8)
++#define HASH_I(zz) ((zz) & 0xFF)
++
++static const u16 rop_map1[] = {
++ 0,
++ 1,
++ 2,
++ 20,
++ 4,
++ 5,
++ 6,
++ 15,
++ 80,
++ 81,
++ 82,
++ 83,
++ 84,
++ 85,
++ 86,
++ 87,
++ 17,
++ 18,
++ 19,
++ 21,
++ 16,
++ 16394,
++ 16404,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 32,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 65535,
++ 40,
++ 112,
++ 113,
++ 65535,
++ 16384,
++ 16385,
++ 16386,
++ 16387,
++ 16388,
++ 16389,
++ 16390,
++ 16391,
++ 16392,
++ 16393,
++ 16395,
++ 16396,
++ 16397,
++ 16398,
++ 16399,
++ 16400,
++ 16401,
++ 16402,
++ 16403,
++ 16405,
++ 16406,
++ 65535,
++ 65535,
++ 65535
++};
++
++static const s16 rop_map2[] = {
++ -256,
++ -255,
++ -254,
++ -245,
++ -253,
++ -252,
++ -251,
++ -250,
++ -241,
++ -240,
++ -239,
++ -238,
++ -237,
++ -236,
++ 1813,
++ 5142,
++ -248,
++ -247,
++ 778,
++ -244,
++ -249,
++ -221,
++ -211,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -243,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -1,
++ -242,
++ -233,
++ -232,
++ -1,
++ -231,
++ -230,
++ -229,
++ -228,
++ -227,
++ -226,
++ -225,
++ -224,
++ -223,
++ 5410,
++ -220,
++ -219,
++ -218,
++ -217,
++ -216,
++ -215,
++ -214,
++ -213,
++ 5676,
++ -210,
++ -209,
++ -1,
++ -1,
++ -1
++};
++
++static const u16 rop_action[] = {
++ 2560,
++ 2304,
++ 2304,
++ 2432,
++ 2432,
++ 2560,
++ 2176,
++ 2304,
++ 2560,
++ 3200,
++ 3328,
++ 3584,
++ 3456,
++ 2304,
++ 4208,
++ 20788,
++ 21812,
++ 3415,
++ 3245,
++ 2311,
++ 4359,
++ 19764,
++ 2311,
++ 3191,
++ 3280,
++ 6656,
++ 7680,
++ 8704,
++ 9728,
++ 10752,
++ 11776,
++ 12800,
++ 13824,
++ 14848,
++ 15872,
++ 16896,
++ 17920,
++ 18944,
++ 0,
++ 0,
++ 0,
++ 0,
++ 1536,
++ 1536,
++ 1536,
++ 5632,
++ 512,
++ 0
++};
++
++static const u16 rop_info[] = {
++ 0,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 35,
++ 39,
++ 39,
++ 39,
++ 39,
++ 35,
++ 34,
++ 283,
++ 299,
++ 4135,
++ 4391,
++ 291,
++ 33059,
++ 283,
++ 295,
++ 4647,
++ 4135,
++ 64,
++ 64,
++ 128,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 64,
++ 128,
++ 201,
++ 197,
++ 74,
++ 70,
++ 208,
++ 196,
++ 200,
++ 192,
++ 192,
++ 66
++};
+diff --git a/drivers/dsp/bridge/gen/_gt_para.c b/drivers/dsp/bridge/gen/_gt_para.c
+new file mode 100644
+index 0000000..181fe41
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/_gt_para.c
+@@ -0,0 +1,107 @@
++/*
++ * _gt_para.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _gt_para.c ========
++ * Description:
++ * Configuration parameters for GT. This file is separated from
++ * gt.c so that GT_assert() can reference the error function without
++ * forcing the linker to include all the code for GT_set(), GT_init(),
++ * etc. into a fully bound image. Thus, GT_assert() can be retained in
++ * a program for which GT_?trace() has been compiled out.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 vp: Code Review Updates.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 03-Jul-2001 rr: Removed kfuncs.h because of build errors.
++ *! 07-Dec-1999 ag: Fxn error now causes a WinCE DebugBreak;
++ *! 30-Aug-1999 ag: Now uses GP_printf for printf and error.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- Function Prototypes */
++static void error(char *msg, ...);
++static s32 GT_nop(void);
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++struct GT_Config _GT_params = {
++ (Fxn) printk, /* printf */
++ (Fxn) NULL, /* procid */
++ (Fxn) GT_nop, /* taskid */
++ (Fxn) error, /* error */
++};
++
++/* ----------------------------------- Globals */
++struct GT_Config *GT = &_GT_params;
++
++/*
++ * ======== GT_nop ========
++ */
++static s32 GT_nop(void)
++{
++ return 0;
++}
++
++/*
++ * ======== error ========
++ * purpose:
++ * Prints error onto the standard output.
++ */
++static void error(char *fmt, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++
++ va_list va;
++
++ va_start(va, fmt);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++
++ printk("ERROR: ");
++ printk(fmt, arg1, arg2, arg3, arg4, arg5, arg6);
++
++#if defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)
++ if (in_interrupt()) {
++ printk(KERN_INFO "Not stopping after error since ISR/DPC "
++ "are disabled\n");
++ } else {
++ set_current_state(TASK_INTERRUPTIBLE);
++ flush_signals(current);
++ schedule();
++ flush_signals(current);
++ printk(KERN_INFO "Signaled in error function\n");
++ }
++#endif
++}
+diff --git a/drivers/dsp/bridge/gen/gb.c b/drivers/dsp/bridge/gen/gb.c
+new file mode 100644
+index 0000000..1d21e97
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gb.c
+@@ -0,0 +1,182 @@
++/*
++ * gb.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gb.c ========
++ * Description: Generic bitmap operations.
++ *
++ *! Revision History
++ *! ================
++ *! 24-Feb-2003 vp Code review updates.
++ *! 17-Dec-2002 map Fixed GB_minset(), GB_empty(), and GB_full(),
++ *! to ensure only 'len' bits are considered in the map
++ *! 18-Oct-2002 sb Ported to Linux platform.
++ *! 06-Dec-2001 jeh Fixed bug in GB_minclear().
++ *!
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <linux/types.h>
++/* ----------------------------------- This */
++#include <dspbridge/gs.h>
++#include <dspbridge/gb.h>
++
++typedef GB_BitNum GB_WordNum;
++
++struct GB_TMap {
++ GB_BitNum len;
++ GB_WordNum wcnt;
++ u32 *words;
++};
++
++/*
++ * ======== GB_clear ========
++ * purpose:
++ * Clears a bit in the bit map.
++ */
++
++void GB_clear(struct GB_TMap *map, GB_BitNum bitn)
++{
++ u32 mask;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ map->words[bitn / BITS_PER_LONG] &= ~mask;
++}
++
++/*
++ * ======== GB_create ========
++ * purpose:
++ * Creates a bit map.
++ */
++
++struct GB_TMap *GB_create(GB_BitNum len)
++{
++ struct GB_TMap *map;
++ GB_WordNum i;
++ map = (struct GB_TMap *)GS_alloc(sizeof(struct GB_TMap));
++ if (map != NULL) {
++ map->len = len;
++ map->wcnt = len / BITS_PER_LONG + 1;
++ map->words = (u32 *)GS_alloc(map->wcnt * sizeof(u32));
++ if (map->words != NULL) {
++ for (i = 0; i < map->wcnt; i++)
++ map->words[i] = 0L;
++
++ } else {
++ GS_frees(map, sizeof(struct GB_TMap));
++ map = NULL;
++ }
++ }
++
++ return map;
++}
++
++/*
++ * ======== GB_delete ========
++ * purpose:
++ * Frees a bit map.
++ */
++
++void GB_delete(struct GB_TMap *map)
++{
++ GS_frees(map->words, map->wcnt * sizeof(u32));
++ GS_frees(map, sizeof(struct GB_TMap));
++}
++
++/*
++ * ======== GB_findandset ========
++ * purpose:
++ * Finds a free bit and sets it.
++ */
++GB_BitNum GB_findandset(struct GB_TMap *map)
++{
++ GB_BitNum bitn;
++
++ bitn = GB_minclear(map);
++
++ if (bitn != GB_NOBITS)
++ GB_set(map, bitn);
++
++ return bitn;
++}
++
++/*
++ * ======== GB_minclear ========
++ * purpose:
++ * returns the location of the first unset bit in the bit map.
++ */
++GB_BitNum GB_minclear(struct GB_TMap *map)
++{
++ GB_BitNum bit_location = 0;
++ GB_BitNum bitAcc = 0;
++ GB_WordNum i;
++ GB_BitNum bit;
++ u32 *word;
++
++ for (word = map->words, i = 0; i < map->wcnt; word++, i++) {
++ if (~*word) {
++ for (bit = 0; bit < BITS_PER_LONG; bit++, bitAcc++) {
++ if (bitAcc == map->len)
++ return GB_NOBITS;
++
++ if (~*word & (1L << bit)) {
++ bit_location = i * BITS_PER_LONG + bit;
++ return bit_location;
++ }
++
++ }
++ } else {
++ bitAcc += BITS_PER_LONG;
++ }
++ }
++
++ return GB_NOBITS;
++}
++
++/*
++ * ======== GB_set ========
++ * purpose:
++ * Sets a bit in the bit map.
++ */
++
++void GB_set(struct GB_TMap *map, GB_BitNum bitn)
++{
++ u32 mask;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ map->words[bitn / BITS_PER_LONG] |= mask;
++}
++
++/*
++ * ======== GB_test ========
++ * purpose:
++ * Returns true if the bit is set in the specified location.
++ */
++
++bool GB_test(struct GB_TMap *map, GB_BitNum bitn)
++{
++ bool state;
++ u32 mask;
++ u32 word;
++
++ mask = 1L << (bitn % BITS_PER_LONG);
++ word = map->words[bitn / BITS_PER_LONG];
++ state = word & mask ? TRUE : FALSE;
++
++ return state;
++}
+diff --git a/drivers/dsp/bridge/gen/gh.c b/drivers/dsp/bridge/gen/gh.c
+new file mode 100644
+index 0000000..a20ae16
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gh.c
+@@ -0,0 +1,191 @@
++/*
++ * gh.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gh.c ========
++ */
++
++#include <dspbridge/std.h>
++
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/gs.h>
++
++#include <dspbridge/gh.h>
++
++struct Elem {
++ struct Elem *next;
++ u8 data[1];
++};
++
++struct GH_THashTab {
++ u16 maxBucket;
++ u16 valSize;
++ struct Elem **buckets;
++ u16(*hash) (void *, u16);
++ bool(*match) (void *, void *);
++ void(*delete) (void *);
++};
++
++static void Nop(void *p);
++static s32 curInit;
++static void myfree(void *ptr, s32 size);
++
++/*
++ * ======== GH_create ========
++ */
++
++struct GH_THashTab *GH_create(u16 maxBucket, u16 valSize,
++ u16(*hash)(void *, u16), bool(*match)(void *, void *),
++ void(*delete)(void *))
++{
++ struct GH_THashTab *hashTab;
++ u16 i;
++ hashTab = (struct GH_THashTab *)GS_alloc(sizeof(struct GH_THashTab));
++ if (hashTab == NULL)
++ return NULL;
++ hashTab->maxBucket = maxBucket;
++ hashTab->valSize = valSize;
++ hashTab->hash = hash;
++ hashTab->match = match;
++ hashTab->delete = delete == NULL ? Nop : delete;
++
++ hashTab->buckets = (struct Elem **)
++ GS_alloc(sizeof(struct Elem *) * maxBucket);
++ if (hashTab->buckets == NULL) {
++ GH_delete(hashTab);
++ return NULL;
++ }
++
++ for (i = 0; i < maxBucket; i++)
++ hashTab->buckets[i] = NULL;
++
++ return hashTab;
++}
++
++/*
++ * ======== GH_delete ========
++ */
++void GH_delete(struct GH_THashTab *hashTab)
++{
++ struct Elem *elem, *next;
++ u16 i;
++
++ if (hashTab != NULL) {
++ if (hashTab->buckets != NULL) {
++ for (i = 0; i < hashTab->maxBucket; i++) {
++ for (elem = hashTab->buckets[i]; elem != NULL;
++ elem = next) {
++ next = elem->next;
++ (*hashTab->delete) (elem->data);
++ myfree(elem, sizeof(struct Elem) - 1 +
++ hashTab->valSize);
++ }
++ }
++
++ myfree(hashTab->buckets, sizeof(struct Elem *)
++ * hashTab->maxBucket);
++ }
++
++ myfree(hashTab, sizeof(struct GH_THashTab));
++ }
++}
++
++/*
++ * ======== GH_exit ========
++ */
++
++void GH_exit(void)
++{
++ if (curInit-- == 1)
++ GS_exit();
++
++}
++
++/*
++ * ======== GH_find ========
++ */
++
++void *GH_find(struct GH_THashTab *hashTab, void *key)
++{
++ struct Elem *elem;
++
++ elem = hashTab->buckets[(*hashTab->hash)(key, hashTab->maxBucket)];
++
++ for (; elem; elem = elem->next) {
++ if ((*hashTab->match)(key, elem->data))
++ return elem->data;
++ }
++
++ return NULL;
++}
++
++/*
++ * ======== GH_init ========
++ */
++
++void GH_init(void)
++{
++ if (curInit++ == 0)
++ GS_init();
++}
++
++/*
++ * ======== GH_insert ========
++ */
++
++void *GH_insert(struct GH_THashTab *hashTab, void *key, void *value)
++{
++ struct Elem *elem;
++ u16 i;
++ char *src, *dst;
++
++ elem = (struct Elem *)GS_alloc(sizeof(struct Elem) - 1 +
++ hashTab->valSize);
++ if (elem != NULL) {
++
++ dst = (char *)elem->data;
++ src = (char *)value;
++ for (i = 0; i < hashTab->valSize; i++)
++ *dst++ = *src++;
++
++ i = (*hashTab->hash)(key, hashTab->maxBucket);
++ elem->next = hashTab->buckets[i];
++ hashTab->buckets[i] = elem;
++
++ return elem->data;
++ }
++
++ return NULL;
++}
++
++/*
++ * ======== Nop ========
++ */
++/* ARGSUSED */
++static void Nop(void *p)
++{
++ p = p; /* stifle compiler warning */
++}
++
++/*
++ * ======== myfree ========
++ */
++static void myfree(void *ptr, s32 size)
++{
++ GS_free(ptr);
++}
+diff --git a/drivers/dsp/bridge/gen/gs.c b/drivers/dsp/bridge/gen/gs.c
+new file mode 100644
+index 0000000..ef5f923
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gs.c
+@@ -0,0 +1,108 @@
++/*
++ * gs.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gs.c ========
++ * Description:
++ * General storage memory allocator services.
++ *
++ *! Revision History
++ *! ================
++ *! 29-Sep-1999 ag: Un-commented MEM_Init in GS_init().
++ *! 14-May-1997 mg: Modified to use new GS API for GS_free() and GS_frees().
++ *! 06-Nov-1996 gp: Re-commented MEM_Init in GS_init(). GS needs GS_Exit().
++ *! 21-Oct-1996 db: Un-commented MEM_Init in GS_init().
++ *! 21-May-1996 mg: Created from original stdlib implementation.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <linux/types.h>
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/gs.h>
++
++/* ----------------------------------- Globals */
++static u32 cumsize;
++
++/*
++ * ======== GS_alloc ========
++ * purpose:
++ * Allocates memory of the specified size.
++ */
++void *GS_alloc(u32 size)
++{
++ void *p;
++
++ p = MEM_Calloc(size, MEM_PAGED);
++ if (p == NULL)
++ return NULL;
++ cumsize += size;
++ return p;
++}
++
++/*
++ * ======== GS_exit ========
++ * purpose:
++ * Discontinue the usage of the GS module.
++ */
++void GS_exit(void)
++{
++ MEM_Exit();
++}
++
++/*
++ * ======== GS_free ========
++ * purpose:
++ * Frees the memory.
++ */
++void GS_free(void *ptr)
++{
++ MEM_Free(ptr);
++ /* ack! no size info */
++ /* cumsize -= size; */
++}
++
++/*
++ * ======== GS_frees ========
++ * purpose:
++ * Frees the memory.
++ */
++void GS_frees(void *ptr, u32 size)
++{
++ MEM_Free(ptr);
++ cumsize -= size;
++}
++
++/*
++ * ======== GS_init ========
++ * purpose:
++ * Initializes the GS module.
++ */
++void GS_init(void)
++{
++ static bool curInit;
++
++ if (curInit == false) {
++ curInit = true;
++
++ MEM_Init();
++ }
++}
+diff --git a/drivers/dsp/bridge/gen/gt.c b/drivers/dsp/bridge/gen/gt.c
+new file mode 100644
+index 0000000..452d6e6
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/gt.c
+@@ -0,0 +1,348 @@
++/*
++ * gt.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== gt.c ========
++ * Description: This module implements the trace mechanism for bridge.
++ *
++ *! Revision History
++ *! ================
++ *! 16-May-1997 dr Changed GT_Config member names to conform to coding
++ *! standards.
++ *! 23-Apr-1997 ge Check for GT->TIDFXN for NULL before calling it.
++ *! 03-Jan-1997 ge Changed GT_Config structure member names to eliminate
++ *! preprocessor confusion with other macros.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/gt.h>
++
++#define GT_WILD '*'
++
++#define GT_CLEAR '='
++#define GT_ON '+'
++#define GT_OFF '-'
++
++enum GT_State {
++ GT_SEP,
++ GT_FIRST,
++ GT_SECOND,
++ GT_OP,
++ GT_DIGITS
++} ;
++
++#ifdef CONFIG_BRIDGE_DEBUG
++static char *GT_1format = "%s - %d: ";
++static char *GT_2format = "%s - %d(%d): ";
++#endif /* CONFIG_BRIDGE_DEBUG */
++
++static unsigned char *GT_tMask[GT_BOUND];
++
++static bool curInit;
++static char *separator;
++static unsigned char tabMem[GT_BOUND][sizeof(unsigned char) * GT_BOUND];
++
++static void error(char *string);
++static void setMask(s16 index1, s16 index2, char op, unsigned char mask);
++
++/*
++ * ======== _GT_create ========
++ * purpose:
++ * Creates GT mask.
++ */
++void _GT_create(struct GT_Mask *mask, char *modName)
++{
++ mask->modName = modName;
++ mask->flags = &(GT_tMask[modName[0] - 'A'][modName[1] - 'A']);
++}
++
++/*
++ * ======== GT_init ========
++ * purpose:
++ * Initializes GT module.
++ */
++#ifdef GT_init
++#undef GT_init
++#endif
++void GT_init(void)
++{
++ register unsigned char index1;
++ register unsigned char index2;
++
++ if (!curInit) {
++ curInit = true;
++
++ separator = " ,;/";
++
++ for (index1 = 0; index1 < GT_BOUND; index1++) {
++ GT_tMask[index1] = tabMem[index1];
++ for (index2 = 0; index2 < GT_BOUND; index2++) {
++ /* no tracing */
++ GT_tMask[index1][index2] = 0x00;
++ }
++ }
++ }
++}
++
++/*
++ * ======== _GT_set ========
++ * purpose:
++ * Sets the trace string format.
++ */
++
++void _GT_set(char *str)
++{
++ enum GT_State state;
++ char *sep;
++ s16 index1 = GT_BOUND; /* indicates all values */
++ s16 index2 = GT_BOUND; /* indicates all values */
++ char op = GT_CLEAR;
++ bool maskValid;
++ s16 digit;
++ register unsigned char mask = 0x0; /* no tracing */
++
++ if (str == NULL)
++ return;
++
++ maskValid = false;
++ state = GT_SEP;
++ while (*str != '\0') {
++ switch ((s32) state) {
++ case (s32) GT_SEP:
++ maskValid = false;
++ sep = separator;
++ while (*sep != '\0') {
++ if (*str == *sep) {
++ str++;
++ break;
++ } else {
++ sep++;
++ }
++ }
++ if (*sep == '\0')
++ state = GT_FIRST;
++
++ break;
++ case (s32) GT_FIRST:
++ if (*str == GT_WILD) {
++ /* indicates all values */
++ index1 = GT_BOUND;
++ /* indicates all values */
++ index2 = GT_BOUND;
++ state = GT_OP;
++ } else {
++ if (*str >= 'a')
++ index1 = (s16) (*str - 'a');
++ else
++ index1 = (s16) (*str - 'A');
++ if ((index1 >= 0) && (index1 < GT_BOUND))
++ state = GT_SECOND;
++ else
++ state = GT_SEP;
++ }
++ str++;
++ break;
++ case (s32) GT_SECOND:
++ if (*str == GT_WILD) {
++ index2 = GT_BOUND; /* indicates all values */
++ state = GT_OP;
++ str++;
++ } else {
++ if (*str >= 'a')
++ index2 = (s16) (*str - 'a');
++ else
++ index2 = (s16) (*str - 'A');
++ if ((index2 >= 0) && (index2 < GT_BOUND)) {
++ state = GT_OP;
++ str++;
++ } else {
++ state = GT_SEP;
++ }
++ }
++ break;
++ case (s32) GT_OP:
++ op = *str;
++ mask = 0x0; /* no tracing */
++ switch (op) {
++ case (s32) GT_CLEAR:
++ maskValid = true;
++ case (s32) GT_ON:
++ case (s32) GT_OFF:
++ state = GT_DIGITS;
++ str++;
++ break;
++ default:
++ state = GT_SEP;
++ break;
++ }
++ break;
++ case (s32) GT_DIGITS:
++ digit = (s16) (*str - '0');
++ if ((digit >= 0) && (digit <= 7)) {
++ mask |= (0x01 << digit);
++ maskValid = true;
++ str++;
++ } else {
++ if (maskValid == true) {
++ setMask(index1, index2, op, mask);
++ maskValid = false;
++ }
++ state = GT_SEP;
++ }
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++
++ if (maskValid)
++ setMask(index1, index2, op, mask);
++}
++
++/*
++ * ======== _GT_trace ========
++ * purpose:
++ * Prints the input string onto standard output
++ */
++
++s32 _GT_trace(struct GT_Mask *mask, char *format, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++ va_list va;
++
++ va_start(va, format);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++#ifdef DEBUG
++ if (GT->PIDFXN == NULL) {
++ printk(GT_1format, mask->modName, GT->TIDFXN ?
++ (*GT->TIDFXN)() : 0);
++ } else {
++ printk(GT_2format, mask->modName, (*GT->PIDFXN)(),
++ GT->TIDFXN ? (*GT->TIDFXN)() : 0);
++ }
++#endif
++ printk(format, arg1, arg2, arg3, arg4, arg5, arg6);
++
++ return 0;
++}
++
++/*
++ * ======== error ========
++ * purpose:
++ * Prints errors onto the standard output.
++ */
++static void error(char *string)
++{
++ printk("GT: %s", string);
++}
++
++/*
++ * ======== setmask ========
++ * purpose:
++ * Sets mask for the GT module.
++ */
++
++static void setMask(s16 index1, s16 index2, char op, u8 mask)
++{
++ register s16 index;
++
++ if (index1 < GT_BOUND) {
++ if (index2 < GT_BOUND) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ } else {
++ for (index2--; index2 >= 0; index2--) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++ }
++ } else {
++ for (index1--; index1 >= 0; index1--) {
++ if (index2 < GT_BOUND) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index2] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index2] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index2] &= ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ } else {
++ index = GT_BOUND;
++ for (index--; index >= 0; index--) {
++ switch (op) {
++ case (s32) GT_CLEAR:
++ GT_tMask[index1][index] = mask;
++ break;
++ case (s32) GT_ON:
++ GT_tMask[index1][index] |= mask;
++ break;
++ case (s32) GT_OFF:
++ GT_tMask[index1][index] &=
++ ~mask;
++ break;
++ default:
++ error("illegal trace mask");
++ break;
++ }
++ }
++ }
++ }
++ }
++}
+diff --git a/drivers/dsp/bridge/gen/uuidutil.c b/drivers/dsp/bridge/gen/uuidutil.c
+new file mode 100644
+index 0000000..a45f448
+--- /dev/null
++++ b/drivers/dsp/bridge/gen/uuidutil.c
+@@ -0,0 +1,238 @@
++/*
++ * uuidutil.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== uuidutil.c ========
++ * Description:
++ * This file contains the implementation of UUID helper functions.
++ *
++ *! Revision History
++ *! ================
++ *! 23-Feb-2003 vp: Code review updates.
++ *! 18-Oct-2003 vp: Ported to Linux platform.
++ *! 31-Aug-2000 rr: UUID_UuidFromString bug fixed.
++ *! 29-Aug-2000 rr: Modified UUID_UuidFromString.
++ *! 09-Nov-2000 kc: Modified UUID_UuidFromString to simplify implementation.
++ *! 30-Oct-2000 kc: Modified UUID utility module function prefix.
++ *! 10-Aug-2000 kc: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/uuidutil.h>
++
++/*
++ * ======== UUID_UuidToString ========
++ * Purpose:
++ * Converts a struct DSP_UUID to a string.
++ * Note: snprintf format specifier is:
++ * %[flags] [width] [.precision] [{h | l | I64 | L}]type
++ */
++void UUID_UuidToString(IN struct DSP_UUID *pUuid, OUT char *pszUuid,
++ IN s32 size)
++{
++ s32 i; /* return result from snprintf. */
++
++ DBC_Require(pUuid && pszUuid);
++
++ i = snprintf(pszUuid, size,
++ "%.8X_%.4X_%.4X_%.2X%.2X_%.2X%.2X%.2X%.2X%.2X%.2X",
++ pUuid->ulData1, pUuid->usData2, pUuid->usData3,
++ pUuid->ucData4, pUuid->ucData5, pUuid->ucData6[0],
++ pUuid->ucData6[1], pUuid->ucData6[2], pUuid->ucData6[3],
++ pUuid->ucData6[4], pUuid->ucData6[5]);
++
++ DBC_Ensure(i != -1);
++}
++
++/*
++ * ======== htoi ========
++ * Purpose:
++ * Converts a hex value to a decimal integer.
++ */
++
++static int htoi(char c)
++{
++ switch (c) {
++ case '0':
++ return 0;
++ case '1':
++ return 1;
++ case '2':
++ return 2;
++ case '3':
++ return 3;
++ case '4':
++ return 4;
++ case '5':
++ return 5;
++ case '6':
++ return 6;
++ case '7':
++ return 7;
++ case '8':
++ return 8;
++ case '9':
++ return 9;
++ case 'A':
++ return 10;
++ case 'B':
++ return 11;
++ case 'C':
++ return 12;
++ case 'D':
++ return 13;
++ case 'E':
++ return 14;
++ case 'F':
++ return 15;
++ case 'a':
++ return 10;
++ case 'b':
++ return 11;
++ case 'c':
++ return 12;
++ case 'd':
++ return 13;
++ case 'e':
++ return 14;
++ case 'f':
++ return 15;
++ }
++ return 0;
++}
++
++/*
++ * ======== UUID_UuidFromString ========
++ * Purpose:
++ * Converts a string to a struct DSP_UUID.
++ */
++void UUID_UuidFromString(IN char *pszUuid, OUT struct DSP_UUID *pUuid)
++{
++ char c;
++ s32 i, j;
++ s32 result;
++ char *temp = pszUuid;
++
++ result = 0;
++ for (i = 0; i < 8; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ulData1 = result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 4; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->usData2 = (u16)result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 4; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->usData3 = (u16)result;
++
++ /* Step over underscore */
++ temp++;
++
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData4 = (u8)result;
++
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData5 = (u8)result;
++
++ /* Step over underscore */
++ temp++;
++
++ for (j = 0; j < 6; j++) {
++ result = 0;
++ for (i = 0; i < 2; i++) {
++ /* Get first character in string */
++ c = *temp;
++
++ /* Increase the results by new value */
++ result *= 16;
++ result += htoi(c);
++
++ /* Go to next character in string */
++ temp++;
++ }
++ pUuid->ucData6[j] = (u8)result;
++ }
++}
+diff --git a/drivers/dsp/bridge/hw/EasiGlobal.h b/drivers/dsp/bridge/hw/EasiGlobal.h
+new file mode 100644
+index 0000000..b023826
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/EasiGlobal.h
+@@ -0,0 +1,42 @@
++/*
++ * EasiGlobal.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef __EASIGLOBAL_H
++#define __EASIGLOBAL_H
++#include <linux/types.h>
++
++/*
++ * DEFINE: READ_ONLY, WRITE_ONLY & READ_WRITE
++ *
++ * DESCRIPTION: Defines used to describe register types for EASI-checker tests.
++ */
++
++#define READ_ONLY 1
++#define WRITE_ONLY 2
++#define READ_WRITE 3
++
++/*
++ * MACRO: _DEBUG_LEVEL_1_EASI
++ *
++ * DESCRIPTION: A MACRO which can be used to indicate that a particular beach
++ * register access function was called.
++ *
++ * NOTE: We currently dont use this functionality.
++ */
++#define _DEBUG_LEVEL_1_EASI(easiNum) ((void)0)
++
++#endif /* __EASIGLOBAL_H */
++
+diff --git a/drivers/dsp/bridge/hw/GlobalTypes.h b/drivers/dsp/bridge/hw/GlobalTypes.h
+new file mode 100644
+index 0000000..9004a37
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/GlobalTypes.h
+@@ -0,0 +1,325 @@
++/*
++ * GlobalTypes.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== GlobalTypes.h ========
++ * Description:
++ * Global HW definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __GLOBALTYPES_H
++#define __GLOBALTYPES_H
++
++/*
++ * Definition: TRUE, FALSE
++ *
++ * DESCRIPTION: Boolean Definitions
++ */
++#ifndef TRUE
++#define FALSE 0
++#define TRUE (!(FALSE))
++#endif
++
++/*
++ * Definition: NULL
++ *
++ * DESCRIPTION: Invalid pointer
++ */
++#ifndef NULL
++#define NULL (void *)0
++#endif
++
++/*
++ * Definition: RET_CODE_BASE
++ *
++ * DESCRIPTION: Base value for return code offsets
++ */
++#define RET_CODE_BASE 0
++
++/*
++ * Definition: *BIT_OFFSET
++ *
++ * DESCRIPTION: offset in bytes from start of 32-bit word.
++ */
++#define LOWER_16BIT_OFFSET 0
++#define UPPER_16BIT_OFFSET 2
++
++#define LOWER_8BIT_OFFSET 0
++#define LOWER_MIDDLE_8BIT_OFFSET 1
++#define UPPER_MIDDLE_8BIT_OFFSET 2
++#define UPPER_8BIT_OFFSET 3
++
++#define LOWER_8BIT_OF16_OFFSET 0
++#define UPPER_8BIT_OF16_OFFSET 1
++
++/*
++ * Definition: *BIT_SHIFT
++ *
++ * DESCRIPTION: offset in bits from start of 32-bit word.
++ */
++#define LOWER_16BIT_SHIFT 0
++#define UPPER_16BIT_SHIFT 16
++
++#define LOWER_8BIT_SHIFT 0
++#define LOWER_MIDDLE_8BIT_SHIFT 8
++#define UPPER_MIDDLE_8BIT_SHIFT 16
++#define UPPER_8BIT_SHIFT 24
++
++#define LOWER_8BIT_OF16_SHIFT 0
++#define UPPER_8BIT_OF16_SHIFT 8
++
++
++/*
++ * Definition: LOWER_16BIT_MASK
++ *
++ * DESCRIPTION: 16 bit mask used for inclusion of lower 16 bits i.e. mask out
++ * the upper 16 bits
++ */
++#define LOWER_16BIT_MASK 0x0000FFFF
++
++
++/*
++ * Definition: LOWER_8BIT_MASK
++ *
++ * DESCRIPTION: 8 bit masks used for inclusion of 8 bits i.e. mask out
++ * the upper 16 bits
++ */
++#define LOWER_8BIT_MASK 0x000000FF
++
++/*
++ * Definition: RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits, upper16Bits)
++ *
++ * DESCRIPTION: Returns a 32 bit value given a 16 bit lower value and a 16
++ * bit upper value
++ */
++#define RETURN_32BITS_FROM_16LOWER_AND_16UPPER(lower16Bits,upper16Bits)\
++ (((((u32)lower16Bits) & LOWER_16BIT_MASK)) | \
++ (((((u32)upper16Bits) & LOWER_16BIT_MASK) << UPPER_16BIT_SHIFT)))
++
++/*
++ * Definition: RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower16Bits, upper16Bits)
++ *
++ * DESCRIPTION: Returns a 16 bit value given a 8 bit lower value and a 8
++ * bit upper value
++ */
++#define RETURN_16BITS_FROM_8LOWER_AND_8UPPER(lower8Bits,upper8Bits)\
++ (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
++ (((((u32)upper8Bits) & LOWER_8BIT_MASK) << UPPER_8BIT_OF16_SHIFT)))
++
++/*
++ * Definition: RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,
++ * lowerUpper8Bits, upper8Bits)
++ *
++ * DESCRIPTION: Returns a 32 bit value given four 8 bit values
++ */
++#define RETURN_32BITS_FROM_4_8BIT_VALUES(lower8Bits, lowerMiddle8Bits,\
++ lowerUpper8Bits, upper8Bits)\
++ (((((u32)lower8Bits) & LOWER_8BIT_MASK)) | \
++ (((((u32)lowerMiddle8Bits) & LOWER_8BIT_MASK) <<\
++ LOWER_MIDDLE_8BIT_SHIFT)) | \
++ (((((u32)lowerUpper8Bits) & LOWER_8BIT_MASK) <<\
++ UPPER_MIDDLE_8BIT_SHIFT)) | \
++ (((((u32)upper8Bits) & LOWER_8BIT_MASK) <<\
++ UPPER_8BIT_SHIFT)))
++
++/*
++ * Definition: READ_LOWER_16BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 16 lower bits of 32bit value
++ */
++#define READ_LOWER_16BITS_OF_32(value32bits)\
++ ((u16)((u32)(value32bits) & LOWER_16BIT_MASK))
++
++/*
++ * Definition: READ_UPPER_16BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 16 lower bits of 32bit value
++ */
++#define READ_UPPER_16BITS_OF_32(value32bits)\
++ (((u16)((u32)(value32bits) >> UPPER_16BIT_SHIFT)) &\
++ LOWER_16BIT_MASK)
++
++
++/*
++ * Definition: READ_LOWER_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower bits of 32bit value
++ */
++#define READ_LOWER_8BITS_OF_32(value32bits)\
++ ((u8)((u32)(value32bits) & LOWER_8BIT_MASK))
++
++/*
++ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower middle bits of 32bit value
++ */
++#define READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
++ LOWER_8BIT_MASK)
++
++/*
++ * Definition: READ_LOWER_MIDDLE_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 lower middle bits of 32bit value
++ */
++#define READ_UPPER_MIDDLE_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> LOWER_MIDDLE_8BIT_SHIFT)) &\
++ LOWER_8BIT_MASK)
++
++/*
++ * Definition: READ_UPPER_8BITS_OF_32(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 upper bits of 32bit value
++ */
++#define READ_UPPER_8BITS_OF_32(value32bits)\
++ (((u8)((u32)(value32bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
++
++
++/*
++ * Definition: READ_LOWER_8BITS_OF_16(value16bits)
++ *
++ * DESCRIPTION: Returns a 8 lower bits of 16bit value
++ */
++#define READ_LOWER_8BITS_OF_16(value16bits)\
++ ((u8)((u16)(value16bits) & LOWER_8BIT_MASK))
++
++/*
++ * Definition: READ_UPPER_8BITS_OF_16(value32bits)
++ *
++ * DESCRIPTION: Returns a 8 upper bits of 16bit value
++ */
++#define READ_UPPER_8BITS_OF_16(value16bits)\
++ (((u8)((u32)(value16bits) >> UPPER_8BIT_SHIFT)) & LOWER_8BIT_MASK)
++
++
++
++/* UWORD16: 16 bit tpyes */
++
++
++/* REG_UWORD8, REG_WORD8: 8 bit register types */
++typedef volatile unsigned char REG_UWORD8;
++typedef volatile signed char REG_WORD8;
++
++/* REG_UWORD16, REG_WORD16: 16 bit register types */
++#ifndef OMAPBRIDGE_TYPES
++typedef volatile unsigned short REG_UWORD16;
++#endif
++typedef volatile short REG_WORD16;
++
++/* REG_UWORD32, REG_WORD32: 32 bit register types */
++typedef volatile unsigned long REG_UWORD32;
++
++/* FLOAT
++ *
++ * Type to be used for floating point calculation. Note that floating point
++ * calculation is very CPU expensive, and you should only use if you
++ * absolutely need this. */
++
++
++/* boolean_t: Boolean Type True, False */
++/* ReturnCode_t: Return codes to be returned by all library functions */
++typedef enum ReturnCode_label {
++ RET_OK = 0,
++ RET_FAIL = -1,
++ RET_BAD_NULL_PARAM = -2,
++ RET_PARAM_OUT_OF_RANGE = -3,
++ RET_INVALID_ID = -4,
++ RET_EMPTY = -5,
++ RET_FULL = -6,
++ RET_TIMEOUT = -7,
++ RET_INVALID_OPERATION = -8,
++
++ /* Add new error codes at end of above list */
++
++ RET_NUM_RET_CODES /* this should ALWAYS be LAST entry */
++} ReturnCode_t, *pReturnCode_t;
++
++/* MACRO: RD_MEM_8, WR_MEM_8
++ *
++ * DESCRIPTION: 32 bit memory access macros
++ */
++#define RD_MEM_8(addr) ((u8)(*((u8 *)(addr))))
++#define WR_MEM_8(addr, data) (*((u8 *)(addr)) = (u8)(data))
++
++/* MACRO: RD_MEM_8_VOLATILE, WR_MEM_8_VOLATILE
++ *
++ * DESCRIPTION: 8 bit register access macros
++ */
++#define RD_MEM_8_VOLATILE(addr) ((u8)(*((REG_UWORD8 *)(addr))))
++#define WR_MEM_8_VOLATILE(addr, data) (*((REG_UWORD8 *)(addr)) = (u8)(data))
++
++
++/*
++ * MACRO: RD_MEM_16, WR_MEM_16
++ *
++ * DESCRIPTION: 16 bit memory access macros
++ */
++#define RD_MEM_16(addr) ((u16)(*((u16 *)(addr))))
++#define WR_MEM_16(addr, data) (*((u16 *)(addr)) = (u16)(data))
++
++/*
++ * MACRO: RD_MEM_16_VOLATILE, WR_MEM_16_VOLATILE
++ *
++ * DESCRIPTION: 16 bit register access macros
++ */
++#define RD_MEM_16_VOLATILE(addr) ((u16)(*((REG_UWORD16 *)(addr))))
++#define WR_MEM_16_VOLATILE(addr, data) (*((REG_UWORD16 *)(addr)) =\
++ (u16)(data))
++
++/*
++ * MACRO: RD_MEM_32, WR_MEM_32
++ *
++ * DESCRIPTION: 32 bit memory access macros
++ */
++#define RD_MEM_32(addr) ((u32)(*((u32 *)(addr))))
++#define WR_MEM_32(addr, data) (*((u32 *)(addr)) = (u32)(data))
++
++/*
++ * MACRO: RD_MEM_32_VOLATILE, WR_MEM_32_VOLATILE
++ *
++ * DESCRIPTION: 32 bit register access macros
++ */
++#define RD_MEM_32_VOLATILE(addr) ((u32)(*((REG_UWORD32 *)(addr))))
++#define WR_MEM_32_VOLATILE(addr, data) (*((REG_UWORD32 *)(addr)) =\
++ (u32)(data))
++
++/* Not sure if this all belongs here */
++
++#define CHECK_RETURN_VALUE(actualValue, expectedValue, returnCodeIfMismatch,\
++ spyCodeIfMisMatch)
++#define CHECK_RETURN_VALUE_RET(actualValue, expectedValue, returnCodeIfMismatch)
++#define CHECK_RETURN_VALUE_RES(actualValue, expectedValue, spyCodeIfMisMatch)
++#define CHECK_RETURN_VALUE_RET_VOID(actualValue, expectedValue,\
++ spyCodeIfMisMatch)
++
++#define CHECK_INPUT_PARAM(actualValue, invalidValue, returnCodeIfMismatch,\
++ spyCodeIfMisMatch)
++#define CHECK_INPUT_PARAM_NO_SPY(actualValue, invalidValue,\
++ returnCodeIfMismatch)
++#define CHECK_INPUT_RANGE(actualValue, minValidValue, maxValidValue,\
++ returnCodeIfMismatch, spyCodeIfMisMatch)
++#define CHECK_INPUT_RANGE_NO_SPY(actualValue, minValidValue, maxValidValue,\
++ returnCodeIfMismatch)
++#define CHECK_INPUT_RANGE_MIN0(actualValue, maxValidValue,\
++ returnCodeIfMismatch, spyCodeIfMisMatch)
++#define CHECK_INPUT_RANGE_NO_SPY_MIN0(actualValue, maxValidValue,\
++ returnCodeIfMismatch)
++
++#endif /* __GLOBALTYPES_H */
+diff --git a/drivers/dsp/bridge/hw/IPIAccInt.h b/drivers/dsp/bridge/hw/IPIAccInt.h
+new file mode 100644
+index 0000000..b88a58c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/IPIAccInt.h
+@@ -0,0 +1,41 @@
++/*
++ * IPIAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _IPI_ACC_INT_H
++#define _IPI_ACC_INT_H
++
++/* Bitfield mask and offset declarations */
++#define SYSC_IVA2BOOTMOD_OFFSET 0x404
++#define SYSC_IVA2BOOTADDR_OFFSET 0x400
++#define SYSC_IVA2BOOTADDR_MASK 0xfffffc00
++
++
++/* The following represent the enumerated values for each bitfield */
++
++enum IPIIPI_SYSCONFIGAutoIdleE {
++ IPIIPI_SYSCONFIGAutoIdleclkfree = 0x0000,
++ IPIIPI_SYSCONFIGAutoIdleautoclkgate = 0x0001
++} ;
++
++enum IPIIPI_ENTRYElemSizeValueE {
++ IPIIPI_ENTRYElemSizeValueElemSz8b = 0x0000,
++ IPIIPI_ENTRYElemSizeValueElemSz16b = 0x0001,
++ IPIIPI_ENTRYElemSizeValueElemSz32b = 0x0002,
++ IPIIPI_ENTRYElemSizeValueReserved = 0x0003
++} ;
++
++#endif /* _IPI_ACC_INT_H */
++/* EOF */
+diff --git a/drivers/dsp/bridge/hw/IVA2RegAcM.h b/drivers/dsp/bridge/hw/IVA2RegAcM.h
+new file mode 100644
+index 0000000..6c1e300
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/IVA2RegAcM.h
+@@ -0,0 +1,28 @@
++/*
++ * IVA1RegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++
++#ifndef _IVA2_REG_ACM_H
++#define _IVA2_REG_ACM_H
++
++#include <GlobalTypes.h>
++#include <EasiGlobal.h>
++
++#define SYSC_IVA2BOOTMOD_OFFSET 0x404
++#define SYSC_IVA2BOOTADDR_OFFSET 0x400
++
++#endif
+diff --git a/drivers/dsp/bridge/hw/MLBAccInt.h b/drivers/dsp/bridge/hw/MLBAccInt.h
+new file mode 100644
+index 0000000..7a03c6a
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MLBAccInt.h
+@@ -0,0 +1,132 @@
++/*
++ * MLBAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _MLB_ACC_INT_H
++#define _MLB_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32 (MLB_BASE_EASIL1 + 3)
++#define EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32 (MLB_BASE_EASIL1 + 4)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32 (MLB_BASE_EASIL1 + 7)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32 (MLB_BASE_EASIL1 + 17)
++#define EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32 (MLB_BASE_EASIL1 + 29)
++#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32 \
++ (MLB_BASE_EASIL1 + 33)
++#define EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32 (MLB_BASE_EASIL1 + 39)
++#define EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32 (MLB_BASE_EASIL1 + 44)
++#define EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32 \
++ (MLB_BASE_EASIL1 + 50)
++#define EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32 \
++ (MLB_BASE_EASIL1 + 51)
++#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32 \
++ (MLB_BASE_EASIL1 + 56)
++#define EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32 \
++ (MLB_BASE_EASIL1 + 57)
++#define EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32 \
++ (MLB_BASE_EASIL1 + 60)
++#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32 \
++ (MLB_BASE_EASIL1 + 62)
++#define EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32 \
++ (MLB_BASE_EASIL1 + 63)
++#define EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32 \
++ (MLB_BASE_EASIL1 + 192)
++#define EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32 \
++ (MLB_BASE_EASIL1 + 193)
++
++/* Register set MAILBOX_MESSAGE___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET (u32)(0x0040)
++#define MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_MESSAGE___REGSET_0_15 */
++
++#define MLB_MAILBOX_MESSAGE___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_FIFOSTATUS___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET (u32)(0x0080)
++#define MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_FIFOSTATUS___REGSET_0_15 */
++
++#define MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_MSGSTATUS___REGSET_0_15 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET (u32)(0x00c0)
++#define MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP (u32)(0x0004)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_MSGSTATUS___REGSET_0_15 */
++
++#define MLB_MAILBOX_MSGSTATUS___0_15_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_IRQSTATUS___REGSET_0_3 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET (u32)(0x0100)
++#define MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP (u32)(0x0008)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_IRQSTATUS___REGSET_0_3 */
++
++#define MLB_MAILBOX_IRQSTATUS___0_3_OFFSET (u32)(0x0)
++
++
++/* Register set MAILBOX_IRQENABLE___REGSET_0_3 address offset, bank address
++ * increment and number of banks */
++
++#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET (u32)(0x0104)
++#define MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP (u32)(0x0008)
++
++/* Register offset address definitions relative to register set
++ * MAILBOX_IRQENABLE___REGSET_0_3 */
++
++#define MLB_MAILBOX_IRQENABLE___0_3_OFFSET (u32)(0x0)
++
++
++/* Register offset address definitions */
++
++#define MLB_MAILBOX_SYSCONFIG_OFFSET (u32)(0x10)
++#define MLB_MAILBOX_SYSSTATUS_OFFSET (u32)(0x14)
++
++
++/* Bitfield mask and offset declarations */
++
++#define MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK (u32)(0x18)
++#define MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET (u32)(3)
++#define MLB_MAILBOX_SYSCONFIG_SoftReset_MASK (u32)(0x2)
++#define MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET (u32)(1)
++#define MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK (u32)(0x1)
++#define MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET (u32)(0)
++#define MLB_MAILBOX_SYSSTATUS_ResetDone_MASK (u32)(0x1)
++#define MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET (u32)(0)
++#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK (u32)(0x1)
++#define MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET (u32)(0)
++#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK (u32)(0x7f)
++#define MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET (u32)(0)
++
++#endif /* _MLB_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/MLBRegAcM.h b/drivers/dsp/bridge/hw/MLBRegAcM.h
+new file mode 100644
+index 0000000..747a2e1
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MLBRegAcM.h
+@@ -0,0 +1,200 @@
++/*
++ * MLBRegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _MLB_REG_ACM_H
++#define _MLB_REG_ACM_H
++
++#include <GlobalTypes.h>
++#include <EasiGlobal.h>
++#include "MLBAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++#define MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+ \
++ MLB_MAILBOX_SYSCONFIG_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGWriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGSIdleModeRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
++ MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK) >>\
++ MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGSIdleModeWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE(((u32)(baseAddress)) +\
++ offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSIdleModeWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_SIdleMode_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_SIdleMode_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGSoftResetWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGSoftResetWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_SoftReset_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_SoftReset_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_SoftReset_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSCONFIGAutoIdleRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSCONFIG_OFFSET)))) &\
++ MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK) >>\
++ MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET))
++
++
++#define MLBMAILBOX_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
++{\
++ const u32 offset = MLB_MAILBOX_SYSCONFIG_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSCONFIGAutoIdleWrite32);\
++ data &= ~(MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK);\
++ newValue <<= MLB_MAILBOX_SYSCONFIG_AutoIdle_OFFSET;\
++ newValue &= MLB_MAILBOX_SYSCONFIG_AutoIdle_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_SYSSTATUSResetDoneRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_SYSSTATUSResetDoneRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (MLB_MAILBOX_SYSSTATUS_OFFSET)))) &\
++ MLB_MAILBOX_SYSSTATUS_ResetDone_MASK) >>\
++ MLB_MAILBOX_SYSSTATUS_ResetDone_OFFSET))
++
++
++#define MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MESSAGE___0_15_OFFSET+(\
++ (bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP))))
++
++
++#define MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_MESSAGE___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MESSAGE___0_15_OFFSET +\
++ ((bank)*MLB_MAILBOX_MESSAGE___REGSET_0_15_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_MESSAGE___0_15WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_FIFOSTATUS___0_15ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP))))
++
++
++#define MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_FIFOSTATUS___0_15FifoFullMBmRead32),\
++ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_FIFOSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_FIFOSTATUS___REGSET_0_15_STEP)))) &\
++ MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_MASK) >>\
++ MLB_MAILBOX_FIFOSTATUS___0_15_FifoFullMBm_OFFSET))
++
++
++#define MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(\
++ EASIL1_MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32),\
++ (((RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_MSGSTATUS___REGSET_0_15_OFFSET +\
++ MLB_MAILBOX_MSGSTATUS___0_15_OFFSET+\
++ ((bank)*MLB_MAILBOX_MSGSTATUS___REGSET_0_15_STEP)))) &\
++ MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_MASK) >>\
++ MLB_MAILBOX_MSGSTATUS___0_15_NbOfMsgMBm_OFFSET))
++
++
++#define MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET+\
++ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP))))
++
++
++#define MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_IRQSTATUS___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQSTATUS___0_3_OFFSET +\
++ ((bank)*MLB_MAILBOX_IRQSTATUS___REGSET_0_3_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQSTATUS___0_3WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress, bank)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+\
++ (MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQENABLE___0_3_OFFSET+\
++ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP))))
++
++
++#define MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, bank, value)\
++{\
++ const u32 offset = MLB_MAILBOX_IRQENABLE___REGSET_0_3_OFFSET +\
++ MLB_MAILBOX_IRQENABLE___0_3_OFFSET +\
++ ((bank)*MLB_MAILBOX_IRQENABLE___REGSET_0_3_STEP);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MLBMAILBOX_IRQENABLE___0_3WriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _MLB_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/MMUAccInt.h b/drivers/dsp/bridge/hw/MMUAccInt.h
+new file mode 100644
+index 0000000..6ca1573
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MMUAccInt.h
+@@ -0,0 +1,76 @@
++/*
++ * MMUAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _MMU_ACC_INT_H
++#define _MMU_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_MMUMMU_SYSCONFIGReadRegister32 (MMU_BASE_EASIL1 + 3)
++#define EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32 (MMU_BASE_EASIL1 + 17)
++#define EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32 (MMU_BASE_EASIL1 + 39)
++#define EASIL1_MMUMMU_IRQSTATUSWriteRegister32 (MMU_BASE_EASIL1 + 51)
++#define EASIL1_MMUMMU_IRQENABLEReadRegister32 (MMU_BASE_EASIL1 + 102)
++#define EASIL1_MMUMMU_IRQENABLEWriteRegister32 (MMU_BASE_EASIL1 + 103)
++#define EASIL1_MMUMMU_WALKING_STTWLRunningRead32 (MMU_BASE_EASIL1 + 156)
++#define EASIL1_MMUMMU_CNTLTWLEnableRead32 (MMU_BASE_EASIL1 + 174)
++#define EASIL1_MMUMMU_CNTLTWLEnableWrite32 (MMU_BASE_EASIL1 + 180)
++#define EASIL1_MMUMMU_CNTLMMUEnableWrite32 (MMU_BASE_EASIL1 + 190)
++#define EASIL1_MMUMMU_FAULT_ADReadRegister32 (MMU_BASE_EASIL1 + 194)
++#define EASIL1_MMUMMU_TTBWriteRegister32 (MMU_BASE_EASIL1 + 198)
++#define EASIL1_MMUMMU_LOCKReadRegister32 (MMU_BASE_EASIL1 + 203)
++#define EASIL1_MMUMMU_LOCKWriteRegister32 (MMU_BASE_EASIL1 + 204)
++#define EASIL1_MMUMMU_LOCKBaseValueRead32 (MMU_BASE_EASIL1 + 205)
++#define EASIL1_MMUMMU_LOCKCurrentVictimRead32 (MMU_BASE_EASIL1 + 209)
++#define EASIL1_MMUMMU_LOCKCurrentVictimWrite32 (MMU_BASE_EASIL1 + 211)
++#define EASIL1_MMUMMU_LOCKCurrentVictimSet32 (MMU_BASE_EASIL1 + 212)
++#define EASIL1_MMUMMU_LD_TLBReadRegister32 (MMU_BASE_EASIL1 + 213)
++#define EASIL1_MMUMMU_LD_TLBWriteRegister32 (MMU_BASE_EASIL1 + 214)
++#define EASIL1_MMUMMU_CAMWriteRegister32 (MMU_BASE_EASIL1 + 226)
++#define EASIL1_MMUMMU_RAMWriteRegister32 (MMU_BASE_EASIL1 + 268)
++#define EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32 (MMU_BASE_EASIL1 + 322)
++
++/* Register offset address definitions */
++#define MMU_MMU_SYSCONFIG_OFFSET 0x10
++#define MMU_MMU_IRQSTATUS_OFFSET 0x18
++#define MMU_MMU_IRQENABLE_OFFSET 0x1c
++#define MMU_MMU_WALKING_ST_OFFSET 0x40
++#define MMU_MMU_CNTL_OFFSET 0x44
++#define MMU_MMU_FAULT_AD_OFFSET 0x48
++#define MMU_MMU_TTB_OFFSET 0x4c
++#define MMU_MMU_LOCK_OFFSET 0x50
++#define MMU_MMU_LD_TLB_OFFSET 0x54
++#define MMU_MMU_CAM_OFFSET 0x58
++#define MMU_MMU_RAM_OFFSET 0x5c
++#define MMU_MMU_GFLUSH_OFFSET 0x60
++#define MMU_MMU_FLUSH_ENTRY_OFFSET 0x64
++/* Bitfield mask and offset declarations */
++#define MMU_MMU_SYSCONFIG_IdleMode_MASK 0x18
++#define MMU_MMU_SYSCONFIG_IdleMode_OFFSET 3
++#define MMU_MMU_SYSCONFIG_AutoIdle_MASK 0x1
++#define MMU_MMU_SYSCONFIG_AutoIdle_OFFSET 0
++#define MMU_MMU_WALKING_ST_TWLRunning_MASK 0x1
++#define MMU_MMU_WALKING_ST_TWLRunning_OFFSET 0
++#define MMU_MMU_CNTL_TWLEnable_MASK 0x4
++#define MMU_MMU_CNTL_TWLEnable_OFFSET 2
++#define MMU_MMU_CNTL_MMUEnable_MASK 0x2
++#define MMU_MMU_CNTL_MMUEnable_OFFSET 1
++#define MMU_MMU_LOCK_BaseValue_MASK 0xfc00
++#define MMU_MMU_LOCK_BaseValue_OFFSET 10
++#define MMU_MMU_LOCK_CurrentVictim_MASK 0x3f0
++#define MMU_MMU_LOCK_CurrentVictim_OFFSET 4
++
++#endif /* _MMU_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/MMURegAcM.h b/drivers/dsp/bridge/hw/MMURegAcM.h
+new file mode 100644
+index 0000000..e46fdcb
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/MMURegAcM.h
+@@ -0,0 +1,253 @@
++/*
++ * MMURegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++#ifndef _MMU_REG_ACM_H
++#define _MMU_REG_ACM_H
++
++#include <GlobalTypes.h>
++
++#include <EasiGlobal.h>
++
++#include "MMUAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++
++#define MMUMMU_SYSCONFIGReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_SYSCONFIG_OFFSET))
++
++
++#define MMUMMU_SYSCONFIGIdleModeWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGIdleModeWrite32);\
++ data &= ~(MMU_MMU_SYSCONFIG_IdleMode_MASK);\
++ newValue <<= MMU_MMU_SYSCONFIG_IdleMode_OFFSET;\
++ newValue &= MMU_MMU_SYSCONFIG_IdleMode_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_SYSCONFIGAutoIdleWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_SYSCONFIG_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_SYSCONFIGAutoIdleWrite32);\
++ data &= ~(MMU_MMU_SYSCONFIG_AutoIdle_MASK);\
++ newValue <<= MMU_MMU_SYSCONFIG_AutoIdle_OFFSET;\
++ newValue &= MMU_MMU_SYSCONFIG_AutoIdle_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_IRQSTATUSReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_IRQSTATUS_OFFSET))
++
++
++#define MMUMMU_IRQSTATUSWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_IRQSTATUS_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQSTATUSWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_IRQENABLEReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_IRQENABLE_OFFSET))
++
++
++#define MMUMMU_IRQENABLEWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_IRQENABLE_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_IRQENABLEWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_WALKING_STTWLRunningRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_WALKING_STTWLRunningRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_WALKING_ST_OFFSET))))\
++ & MMU_MMU_WALKING_ST_TWLRunning_MASK) >>\
++ MMU_MMU_WALKING_ST_TWLRunning_OFFSET))
++
++
++#define MMUMMU_CNTLTWLEnableRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_CNTL_OFFSET)))) &\
++ MMU_MMU_CNTL_TWLEnable_MASK) >>\
++ MMU_MMU_CNTL_TWLEnable_OFFSET))
++
++
++#define MMUMMU_CNTLTWLEnableWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CNTL_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLTWLEnableWrite32);\
++ data &= ~(MMU_MMU_CNTL_TWLEnable_MASK);\
++ newValue <<= MMU_MMU_CNTL_TWLEnable_OFFSET;\
++ newValue &= MMU_MMU_CNTL_TWLEnable_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_CNTLMMUEnableWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CNTL_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CNTLMMUEnableWrite32);\
++ data &= ~(MMU_MMU_CNTL_MMUEnable_MASK);\
++ newValue <<= MMU_MMU_CNTL_MMUEnable_OFFSET;\
++ newValue &= MMU_MMU_CNTL_MMUEnable_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_FAULT_ADReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FAULT_ADReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_FAULT_AD_OFFSET))
++
++
++#define MMUMMU_TTBWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_TTB_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_TTBWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_LOCK_OFFSET))
++
++
++#define MMUMMU_LOCKWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKBaseValueRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
++ MMU_MMU_LOCK_BaseValue_MASK) >>\
++ MMU_MMU_LOCK_BaseValue_OFFSET))
++
++
++#define MMUMMU_LOCKBaseValueWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKBaseValueWrite32);\
++ data &= ~(MMU_MMU_LOCK_BaseValue_MASK);\
++ newValue <<= MMU_MMU_LOCK_BaseValue_OFFSET;\
++ newValue &= MMU_MMU_LOCK_BaseValue_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKCurrentVictimRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimRead32),\
++ (((RD_MEM_32_VOLATILE(((baseAddress)+(MMU_MMU_LOCK_OFFSET)))) &\
++ MMU_MMU_LOCK_CurrentVictim_MASK) >>\
++ MMU_MMU_LOCK_CurrentVictim_OFFSET))
++
++
++#define MMUMMU_LOCKCurrentVictimWrite32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LOCK_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((baseAddress)+offset);\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimWrite32);\
++ data &= ~(MMU_MMU_LOCK_CurrentVictim_MASK);\
++ newValue <<= MMU_MMU_LOCK_CurrentVictim_OFFSET;\
++ newValue &= MMU_MMU_LOCK_CurrentVictim_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(baseAddress+offset, newValue);\
++}
++
++
++#define MMUMMU_LOCKCurrentVictimSet32(var, value)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LOCKCurrentVictimSet32),\
++ (((var) & ~(MMU_MMU_LOCK_CurrentVictim_MASK)) |\
++ (((value) << MMU_MMU_LOCK_CurrentVictim_OFFSET) &\
++ MMU_MMU_LOCK_CurrentVictim_MASK)))
++
++
++#define MMUMMU_LD_TLBReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBReadRegister32),\
++ RD_MEM_32_VOLATILE((baseAddress)+MMU_MMU_LD_TLB_OFFSET))
++
++
++#define MMUMMU_LD_TLBWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_LD_TLB_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_LD_TLBWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_CAMWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_CAM_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_CAMWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_RAMWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_RAM_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_RAMWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#define MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = MMU_MMU_FLUSH_ENTRY_OFFSET;\
++ register u32 newValue = (value);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_MMUMMU_FLUSH_ENTRYWriteRegister32);\
++ WR_MEM_32_VOLATILE((baseAddress)+offset, newValue);\
++}
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _MMU_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/PRCMAccInt.h b/drivers/dsp/bridge/hw/PRCMAccInt.h
+new file mode 100644
+index 0000000..42baa68
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/PRCMAccInt.h
+@@ -0,0 +1,300 @@
++/*
++ * PRCMAccInt.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _PRCM_ACC_INT_H
++#define _PRCM_ACC_INT_H
++
++/* Mappings of level 1 EASI function numbers to function names */
++
++#define EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32 \
++ (PRCM_BASE_EASIL1 + 349)
++#define EASIL1_PRCMCM_FCLKEN1_COREReadRegister32 (PRCM_BASE_EASIL1 + 743)
++#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32 (PRCM_BASE_EASIL1 + 951)
++#define EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32 (PRCM_BASE_EASIL1 + 961)
++#define EASIL1_PRCMCM_ICLKEN1_COREReadRegister32 \
++ (PRCM_BASE_EASIL1 + 1087)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32 \
++ (PRCM_BASE_EASIL1 + 1105)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32 \
++ (PRCM_BASE_EASIL1 + 1305)
++#define EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32 \
++ (PRCM_BASE_EASIL1 + 1315)
++#define EASIL1_PRCMCM_CLKSEL1_CORECLKSEL_L3ReadIssel132 \
++ (PRCM_BASE_EASIL1 + 2261)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32 \
++ (PRCM_BASE_EASIL1 + 2364)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2365)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2366)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32 \
++ (PRCM_BASE_EASIL1 + 2380)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2381)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2382)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2397)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2398)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32 \
++ (PRCM_BASE_EASIL1 + 2413)
++#define EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32 \
++ (PRCM_BASE_EASIL1 + 2414)
++#define EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32 \
++ (PRCM_BASE_EASIL1 + 3747)
++#define EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32 (PRCM_BASE_EASIL1 + 3834)
++#define EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32 \
++ (PRCM_BASE_EASIL1 + 3846)
++#define EASIL1_PRCMCM_IDLEST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 3850)
++#define EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32 (PRCM_BASE_EASIL1 + 3857)
++#define EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32 (PRCM_BASE_EASIL1 + 3863)
++#define EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32 \
++ (PRCM_BASE_EASIL1 + 3877)
++#define EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32 (PRCM_BASE_EASIL1 + 3927)
++#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32 \
++ (PRCM_BASE_EASIL1 + 3941)
++#define EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 3965)
++#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32 \
++ (PRCM_BASE_EASIL1 + 3987)
++#define EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 3993)
++#define EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32 (PRCM_BASE_EASIL1 + 3997)
++#define EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32 \
++ (PRCM_BASE_EASIL1 + 4025)
++#define EASIL1_PRCMRM_RSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4029)
++#define EASIL1_PRCMRM_RSTST_DSPWriteRegister32 (PRCM_BASE_EASIL1 + 4030)
++#define EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32 \
++ (PRCM_BASE_EASIL1 + 4165)
++#define EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32 \
++ (PRCM_BASE_EASIL1 + 4193)
++#define EASIL1_PRCMPM_PWSTST_DSPReadRegister32 (PRCM_BASE_EASIL1 + 4197)
++#define EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32 \
++ (PRCM_BASE_EASIL1 + 4198)
++#define EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32 \
++ (PRCM_BASE_EASIL1 + 4235)
++#define EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4368)
++#define EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4370)
++#define EASIL1_CM_CLKSEL_PER_GPT5Write32k32 (PRCM_BASE_EASIL1 + 4372)
++#define EASIL1_CM_CLKSEL_PER_GPT6Write32k32 (PRCM_BASE_EASIL1 + 4373)
++#define EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32 \
++ (PRCM_BASE_EASIL1 + 4374)
++#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32 \
++ (PRCM_BASE_EASIL1 + 4375)
++#define EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32 \
++ (PRCM_BASE_EASIL1 + 4376)
++#define EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32 \
++ (PRCM_BASE_EASIL1 + 4377)
++#define EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32 \
++ (PRCM_BASE_EASIL1 + 4378)
++#define EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32 (PRCM_BASE_EASIL1 + 4379)
++
++/* Register offset address definitions */
++
++#define PRCM_PRCM_CLKCFG_CTRL_OFFSET (u32)(0x80)
++#define PRCM_CM_FCLKEN1_CORE_OFFSET (u32)(0x200)
++#define PRCM_CM_ICLKEN1_CORE_OFFSET (u32)(0x210)
++#define PRCM_CM_CLKSEL2_CORE_OFFSET (u32)(0x244)
++#define PRCM_CM_CLKSEL1_PLL_OFFSET (u32)(0x540)
++#define PRCM_CM_ICLKEN_DSP_OFFSET (u32)(0x810)
++#define PRCM_CM_IDLEST_DSP_OFFSET (u32)(0x820)
++#define PRCM_CM_AUTOIDLE_DSP_OFFSET (u32)(0x830)
++#define PRCM_CM_CLKSEL_DSP_OFFSET (u32)(0x840)
++#define PRCM_CM_CLKSTCTRL_DSP_OFFSET (u32)(0x848)
++#define PRCM_RM_RSTCTRL_DSP_OFFSET (u32)(0x850)
++#define PRCM_RM_RSTST_DSP_OFFSET (u32)(0x858)
++#define PRCM_PM_PWSTCTRL_DSP_OFFSET (u32)(0x8e0)
++#define PRCM_PM_PWSTST_DSP_OFFSET (u32)(0x8e4)
++#define PRCM_PM_PWSTST_IVA2_OFFSET (u32)(0xE4)
++#define PRCM_PM_PWSTCTRL_IVA2_OFFSET (u32)(0xE0)
++#define PRCM_CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x48)
++#define CM_CLKSEL_PER_OFFSET (u32)(0x40)
++
++/* Bitfield mask and offset declarations */
++
++#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK (u32)(0x1)
++#define PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET (u32)(0)
++
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK (u32)(0x400)
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET (u32)(10)
++
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK (u32)(0x200)
++#define PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET (u32)(9)
++
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK (u32)(0x400)
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET (u32)(10)
++
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK (u32)(0x200)
++#define PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET (u32)(9)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK (u32)(0xc000)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET (u32)(14)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK (u32)(0x3000)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET (u32)(12)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK (u32)(0xc00)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET (u32)(10)
++
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK (u32)(0x300)
++#define PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET (u32)(8)
++
++#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK (u32)(0x3800000)
++#define PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET (u32)(23)
++
++#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK (u32)(0x2)
++#define PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_IDLEST_DSP_ST_IPI_MASK (u32)(0x2)
++#define PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK (u32)(0x2)
++#define PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET (u32)(1)
++
++#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK (u32)(0x80)
++#define PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET (u32)(7)
++
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK (u32)(0x60)
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET (u32)(5)
++
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK (u32)(0x1f)
++#define PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET (u32)(0)
++
++#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK (u32)(0x1)
++#define PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTCTRL_DSP_ForceState_MASK (u32)(0x40000)
++#define PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET (u32)(18)
++
++#define PRCM_PM_PWSTCTRL_DSP_PowerState_MASK (u32)(0x3)
++#define PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK (u32)(0x3)
++#define PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTST_DSP_InTransition_MASK (u32)(0x100000)
++#define PRCM_PM_PWSTST_DSP_InTransition_OFFSET (u32)(20)
++
++#define PRCM_PM_PWSTST_IVA2_InTransition_MASK (u32)(0x100000)
++#define PRCM_PM_PWSTST_IVA2_InTransition_OFFSET (u32)(20)
++
++#define PRCM_PM_PWSTST_DSP_PowerStateSt_MASK (u32)(0x3)
++#define PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET (u32)(0)
++
++#define PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK (u32)(0x3)
++#define PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET (u32)(0)
++
++#define CM_FCLKEN_PER_OFFSET (u32)(0x0)
++#define CM_FCLKEN_PER_GPT5_OFFSET (u32)(6)
++#define CM_FCLKEN_PER_GPT5_MASK (u32)(0x40)
++
++#define CM_FCLKEN_PER_GPT6_OFFSET (u32)(7)
++#define CM_FCLKEN_PER_GPT6_MASK (u32)(0x80)
++
++#define CM_ICLKEN_PER_OFFSET (u32)(0x10)
++#define CM_ICLKEN_PER_GPT5_OFFSET (u32)(6)
++#define CM_ICLKEN_PER_GPT5_MASK (u32)(0x40)
++
++#define CM_ICLKEN_PER_GPT6_OFFSET (u32)(7)
++#define CM_ICLKEN_PER_GPT6_MASK (u32)(0x80)
++
++#define CM_CLKSEL_PER_GPT5_OFFSET (u32)(3)
++#define CM_CLKSEL_PER_GPT5_MASK (u32)(0x8)
++
++#define CM_CLKSEL_PER_GPT6_OFFSET (u32)(4)
++#define CM_CLKSEL_PER_GPT6_MASK (u32)(0x10)
++
++
++#define CM_FCLKEN_IVA2_OFFSET (u32)(0x0)
++#define CM_FCLKEN_IVA2_EN_MASK (u32)(0x1)
++#define CM_FCLKEN_IVA2_EN_OFFSET (u32)(0x0)
++
++#define CM_IDLEST_IVA2_OFFSET (u32)(0x20)
++#define CM_IDLEST_IVA2_ST_IVA2_MASK (u32) (0x01)
++#define CM_IDLEST_IVA2_ST_IVA2_OFFSET (u32) (0x00)
++
++#define CM_FCLKEN1_CORE_OFFSET (u32)(0xA00)
++
++#define CM_ICLKEN1_CORE_OFFSET (u32)(0xA10)
++#define CM_ICLKEN1_CORE_EN_MAILBOXES_MASK (u32)(0x00000080) /* bit 7 */
++#define CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET (u32)(7)
++
++#define CM_CLKSTCTRL_IVA2_OFFSET (u32)(0x0)
++#define CM_CLKSTCTRL_IVA2_MASK (u32)(0x3)
++
++
++#define PRM_RSTCTRL_IVA2_OFFSET (u32)(0x50)
++#define PRM_RSTCTRL_IVA2_RST1_MASK (u32)(0x1)
++#define PRM_RSTCTRL_IVA2_RST1_OFFSET (u32)(0x0)
++#define PRM_RSTCTRL_IVA2_RST2_MASK (u32)(0x2)
++#define PRM_RSTCTRL_IVA2_RST2_OFFSET (u32)(0x1)
++#define PRM_RSTCTRL_IVA2_RST3_MASK (u32)(0x4)
++#define PRM_RSTCTRL_IVA2_RST3_OFFSET (u32)(0x2)
++
++
++/* The following represent the enumerated values for each bitfield */
++
++enum PRCMPRCM_CLKCFG_CTRLValid_configE {
++ PRCMPRCM_CLKCFG_CTRLValid_configUpdated = 0x0000,
++ PRCMPRCM_CLKCFG_CTRLValid_configClk_valid = 0x0001
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT8E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT832k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT8Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT7E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT732k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT7Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT6E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT632k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT6Reserved = 0x0003
++} ;
++
++enum PRCMCM_CLKSEL2_CORECLKSEL_GPT5E {
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT532k = 0x0000,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys = 0x0001,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext = 0x0002,
++ PRCMCM_CLKSEL2_CORECLKSEL_GPT5Reserved = 0x0003
++} ;
++
++enum PRCMPM_PWSTCTRL_DSPPowerStateE {
++ PRCMPM_PWSTCTRL_DSPPowerStateON = 0x0000,
++ PRCMPM_PWSTCTRL_DSPPowerStateRET = 0x0001,
++ PRCMPM_PWSTCTRL_DSPPowerStateReserved = 0x0002,
++ PRCMPM_PWSTCTRL_DSPPowerStateOFF = 0x0003
++} ;
++
++enum PRCMPM_PWSTCTRL_IVA2PowerStateE {
++ PRCMPM_PWSTCTRL_IVA2PowerStateON = 0x0003,
++ PRCMPM_PWSTCTRL_IVA2PowerStateRET = 0x0001,
++ PRCMPM_PWSTCTRL_IVA2PowerStateReserved = 0x0002,
++ PRCMPM_PWSTCTRL_IVA2PowerStateOFF = 0x0000
++} ;
++
++#endif /* _PRCM_ACC_INT_H */
+diff --git a/drivers/dsp/bridge/hw/PRCMRegAcM.h b/drivers/dsp/bridge/hw/PRCMRegAcM.h
+new file mode 100644
+index 0000000..91cb33c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/PRCMRegAcM.h
+@@ -0,0 +1,669 @@
++/*
++ * PRCMRegAcM.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#ifndef _PRCM_REG_ACM_H
++#define _PRCM_REG_ACM_H
++
++#include <GlobalTypes.h>
++
++#include <EasiGlobal.h>
++
++#include "PRCMAccInt.h"
++
++#if defined(USE_LEVEL_1_MACROS)
++
++#define PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32(baseAddress)\
++{\
++ const u32 offset = PRCM_PRCM_CLKCFG_CTRL_OFFSET;\
++ const u32 newValue = \
++ (u32)PRCMPRCM_CLKCFG_CTRLValid_configClk_valid <<\
++ PRCM_PRCM_CLKCFG_CTRL_Valid_config_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(\
++ EASIL1_PRCMPRCM_CLKCFG_CTRLValid_configWriteClk_valid32);\
++ data &= ~(PRCM_PRCM_CLKCFG_CTRL_Valid_config_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_FCLKEN_PERReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_FCLKEN_PER_OFFSET))
++
++
++#define CM_ICLKEN_PERReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_ICLKEN_PER_OFFSET))
++
++
++#define CM_FCLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_FCLKEN_PER_GPT5_MASK);\
++ newValue <<= CM_FCLKEN_PER_GPT5_OFFSET;\
++ newValue &= CM_FCLKEN_PER_GPT5_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_FCLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_PER_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_FCLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_FCLKEN_PER_GPT6_MASK);\
++ newValue <<= CM_FCLKEN_PER_GPT6_OFFSET;\
++ newValue &= CM_FCLKEN_PER_GPT6_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_ICLKEN_PER_GPT5WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_ICLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_ICLKEN_PER_GPT5_MASK);\
++ newValue <<= CM_ICLKEN_PER_GPT5_OFFSET;\
++ newValue &= CM_ICLKEN_PER_GPT5_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_ICLKEN_PER_GPT6WriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = CM_ICLKEN_PER_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_ICLKEN_PER_GPT5WriteRegister32);\
++ data &= ~(CM_ICLKEN_PER_GPT6_MASK);\
++ newValue <<= CM_ICLKEN_PER_GPT6_OFFSET;\
++ newValue &= CM_ICLKEN_PER_GPT6_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define CM_FCLKEN1_COREReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_FCLKEN1_CORE_OFFSET))
++
++
++#define PRCMCM_FCLKEN1_COREEN_GPT8Write32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT8Write32);\
++ data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK);\
++ newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT8_OFFSET;\
++ newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT8_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_FCLKEN1_COREEN_GPT7Write32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_FCLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN1_COREEN_GPT7Write32);\
++ data &= ~(PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK);\
++ newValue <<= PRCM_CM_FCLKEN1_CORE_EN_GPT7_OFFSET;\
++ newValue &= PRCM_CM_FCLKEN1_CORE_EN_GPT7_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define CM_ICLKEN1_COREReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+CM_ICLKEN1_CORE_OFFSET))
++
++
++#define CM_ICLKEN1_COREEN_MAILBOXESWrite32(baseAddress, value)\
++{\
++ const u32 offset = CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_MAILBOXESWrite32);\
++ data &= ~(CM_ICLKEN1_CORE_EN_MAILBOXES_MASK);\
++ newValue <<= CM_ICLKEN1_CORE_EN_MAILBOXES_OFFSET;\
++ newValue &= CM_ICLKEN1_CORE_EN_MAILBOXES_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN1_COREEN_GPT8Write32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT8Write32);\
++ data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK);\
++ newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT8_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT8_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN1_COREEN_GPT7Write32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN1_CORE_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN1_COREEN_GPT7Write32);\
++ data &= ~(PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK);\
++ newValue <<= PRCM_CM_ICLKEN1_CORE_EN_GPT7_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN1_CORE_EN_GPT7_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT832k <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8Write32k32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT8Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT8WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT8_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT732k <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7Write32k32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT7Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT7WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT7_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT6Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT6WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_CLKSEL_PER_GPT5Write32k32(baseAddress)\
++{\
++ const u32 offset = CM_CLKSEL_PER_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
++ CM_CLKSEL_PER_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT5Write32k32);\
++ data &= ~(CM_CLKSEL_PER_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define CM_CLKSEL_PER_GPT6Write32k32(baseAddress)\
++{\
++ const u32 offset = CM_CLKSEL_PER_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT532k <<\
++ CM_CLKSEL_PER_GPT6_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_CM_CLKSEL_PER_GPT6Write32k32);\
++ data &= ~(CM_CLKSEL_PER_GPT6_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Sys <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteSys32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32(baseAddress)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL2_CORE_OFFSET;\
++ const u32 newValue = (u32)PRCMCM_CLKSEL2_CORECLKSEL_GPT5Ext <<\
++ PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL2_CORECLKSEL_GPT5WriteExt32);\
++ data &= ~(PRCM_CM_CLKSEL2_CORE_CLKSEL_GPT5_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL1_PLLAPLLs_ClkinRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_CLKSEL1_PLL_OFFSET)))) &\
++ PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_MASK) >>\
++ PRCM_CM_CLKSEL1_PLL_APLLs_Clkin_OFFSET))
++
++
++#define CM_FCLKEN_IVA2EN_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = CM_FCLKEN_IVA2_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_FCLKEN_DSPEN_DSPWrite32);\
++ data &= ~(CM_FCLKEN_IVA2_EN_MASK);\
++ newValue <<= CM_FCLKEN_IVA2_EN_OFFSET;\
++ newValue &= CM_FCLKEN_IVA2_EN_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_ICLKEN_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_ICLKEN_DSPEN_DSP_IPIWrite32);\
++ data &= ~(PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK);\
++ newValue <<= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_OFFSET;\
++ newValue &= PRCM_CM_ICLKEN_DSP_EN_DSP_IPI_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_IDLEST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_CM_IDLEST_DSP_OFFSET))
++
++
++#define PRCMCM_IDLEST_DSPST_IPIRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_IPIRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_IDLEST_DSP_OFFSET)))) &\
++ PRCM_CM_IDLEST_DSP_ST_IPI_MASK) >>\
++ PRCM_CM_IDLEST_DSP_ST_IPI_OFFSET))
++
++
++#define PRM_IDLEST_IVA2ST_IVA2Read32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_IDLEST_DSPST_DSPRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (CM_IDLEST_IVA2_OFFSET)))) &\
++ CM_IDLEST_IVA2_ST_IVA2_MASK) >>\
++ CM_IDLEST_IVA2_ST_IVA2_OFFSET))
++
++
++#define PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_AUTOIDLE_DSP_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_AUTOIDLE_DSPAUTO_DSP_IPIWrite32);\
++ data &= ~(PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK);\
++ newValue <<= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_OFFSET;\
++ newValue &= PRCM_CM_AUTOIDLE_DSP_AUTO_DSP_IPI_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPSYNC_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPSYNC_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_SYNC_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_SYNC_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSP_IFWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_IF_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSEL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSEL_DSPCLKSEL_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSEL_DSP_CLKSEL_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSTCTRL_IVA2_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_IVA2WriteRegister32);\
++ data &= ~(CM_CLKSTCTRL_IVA2_MASK);\
++ newValue <<= CM_CLKSTCTRL_IVA2_OFFSET;\
++ newValue &= CM_CLKSTCTRL_IVA2_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_CM_CLKSTCTRL_DSP_OFFSET)))) &\
++ PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK) >>\
++ PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET))
++
++
++#define PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_CM_CLKSTCTRL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMCM_CLKSTCTRL_DSPAutostate_DSPWrite32);\
++ data &= ~(PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK);\
++ newValue <<= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_OFFSET;\
++ newValue &= PRCM_CM_CLKSTCTRL_DSP_Autostate_DSP_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_RM_RSTCTRL_DSP_OFFSET))
++
++
++#define PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST1_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST1_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST1_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST2_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST2_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST2_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress,value)\
++{\
++ const u32 offset = PRM_RSTCTRL_IVA2_OFFSET;\
++ register u32 data =\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTCTRL_DSPRST1_DSPWrite32);\
++ data &= ~(PRM_RSTCTRL_IVA2_RST3_MASK);\
++ newValue <<= PRM_RSTCTRL_IVA2_RST3_OFFSET;\
++ newValue &= PRM_RSTCTRL_IVA2_RST3_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMRM_RSTST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_RM_RSTST_DSP_OFFSET))
++
++
++#define PRCMRM_RSTST_DSPWriteRegister32(baseAddress,value)\
++{\
++ const u32 offset = PRCM_RM_RSTST_DSP_OFFSET;\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMRM_RSTST_DSPWriteRegister32);\
++ WR_MEM_32_VOLATILE(((u32)(baseAddress))+offset, newValue);\
++}
++
++
++#define PRCMPM_PWSTCTRL_DSPForceStateWrite32(baseAddress, value)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
++ register u32 data = \
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+offset);\
++ register u32 newValue = ((u32)(value));\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPForceStateWrite32);\
++ data &= ~(PRCM_PM_PWSTCTRL_DSP_ForceState_MASK);\
++ newValue <<= PRCM_PM_PWSTCTRL_DSP_ForceState_OFFSET;\
++ newValue &= PRCM_PM_PWSTCTRL_DSP_ForceState_MASK;\
++ newValue |= data;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, newValue);\
++}
++
++
++#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateON <<\
++ PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32);\
++ data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_IVA2_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_IVA2PowerStateOFF <<\
++ PRCM_PM_PWSTCTRL_IVA2_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32);\
++ data &= ~(PRCM_PM_PWSTCTRL_IVA2_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress)\
++{\
++ const u32 offset = PRCM_PM_PWSTCTRL_DSP_OFFSET;\
++ const u32 newValue = (u32)PRCMPM_PWSTCTRL_DSPPowerStateRET <<\
++ PRCM_PM_PWSTCTRL_DSP_PowerState_OFFSET;\
++ register u32 data = RD_MEM_32_VOLATILE((u32)(baseAddress)+offset);\
++ _DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32);\
++ data &= ~(PRCM_PM_PWSTCTRL_DSP_PowerState_MASK);\
++ data |= newValue;\
++ WR_MEM_32_VOLATILE((u32)(baseAddress)+offset, data);\
++}
++
++
++#define PRCMPM_PWSTST_DSPReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_PM_PWSTST_DSP_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2ReadRegister32),\
++ RD_MEM_32_VOLATILE(((u32)(baseAddress))+PRCM_PM_PWSTST_IVA2_OFFSET))
++
++
++#define PRCMPM_PWSTST_DSPInTransitionRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPInTransitionRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_PM_PWSTST_DSP_OFFSET)))) &\
++ PRCM_PM_PWSTST_DSP_InTransition_MASK) >>\
++ PRCM_PM_PWSTST_DSP_InTransition_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2InTransitionRead32(baseAddress)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2InTransitionRead32),\
++ (((RD_MEM_32_VOLATILE((((u32)(baseAddress))+\
++ (PRCM_PM_PWSTST_IVA2_OFFSET)))) &\
++ PRCM_PM_PWSTST_IVA2_InTransition_MASK) >>\
++ PRCM_PM_PWSTST_IVA2_InTransition_OFFSET))
++
++
++#define PRCMPM_PWSTST_DSPPowerStateStGet32(var)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_DSPPowerStateStGet32),\
++ (u32)((((u32)(var)) & PRCM_PM_PWSTST_DSP_PowerStateSt_MASK) >>\
++ PRCM_PM_PWSTST_DSP_PowerStateSt_OFFSET))
++
++
++#define PRCMPM_PWSTST_IVA2PowerStateStGet32(var)\
++ (_DEBUG_LEVEL_1_EASI(EASIL1_PRCMPM_PWSTST_IVA2PowerStateStGet32),\
++ (u32)((((u32)(var)) & PRCM_PM_PWSTST_IVA2_PowerStateSt_MASK) >>\
++ PRCM_PM_PWSTST_IVA2_PowerStateSt_OFFSET))
++
++
++#endif /* USE_LEVEL_1_MACROS */
++
++#endif /* _PRCM_REG_ACM_H */
+diff --git a/drivers/dsp/bridge/hw/hw_defs.h b/drivers/dsp/bridge/hw/hw_defs.h
+new file mode 100644
+index 0000000..a973f5c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_defs.h
+@@ -0,0 +1,73 @@
++/*
++ * hw_defs.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_defs.h ========
++ * Description:
++ * Global HW definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 19 Apr 2004 sb: Added generic page size, endianness and element size defns
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __HW_DEFS_H
++#define __HW_DEFS_H
++
++#include <GlobalTypes.h>
++
++/* Page size */
++#define HW_PAGE_SIZE_4KB 0x1000
++#define HW_PAGE_SIZE_64KB 0x10000
++#define HW_PAGE_SIZE_1MB 0x100000
++#define HW_PAGE_SIZE_16MB 0x1000000
++
++/* HW_STATUS: return type for HW API */
++typedef long HW_STATUS;
++
++/* HW_SetClear_t: Enumerated Type used to set and clear any bit */
++enum HW_SetClear_t {
++ HW_CLEAR,
++ HW_SET
++} ;
++
++/* HW_Endianism_t: Enumerated Type used to specify the endianism
++ * Do NOT change these values. They are used as bit fields. */
++enum HW_Endianism_t {
++ HW_LITTLE_ENDIAN,
++ HW_BIG_ENDIAN
++
++} ;
++
++/* HW_ElementSize_t: Enumerated Type used to specify the element size
++ * Do NOT change these values. They are used as bit fields. */
++enum HW_ElementSize_t {
++ HW_ELEM_SIZE_8BIT,
++ HW_ELEM_SIZE_16BIT,
++ HW_ELEM_SIZE_32BIT,
++ HW_ELEM_SIZE_64BIT
++
++} ;
++
++/* HW_IdleMode_t: Enumerated Type used to specify Idle modes */
++ enum HW_IdleMode_t {
++ HW_FORCE_IDLE,
++ HW_NO_IDLE,
++ HW_SMART_IDLE
++ } ;
++
++#endif /* __HW_DEFS_H */
+diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.c b/drivers/dsp/bridge/hw/hw_dspssC64P.c
+new file mode 100644
+index 0000000..a4b7c30
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_dspssC64P.c
+@@ -0,0 +1,55 @@
++/*
++ * hw_dspss64P.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_dspss64P.c ========
++ * Description:
++ * API definitions to configure DSP Subsystem modules like IPI
++ *
++ *! Revision History:
++ *! ================
++ *! 19 Apr 2004 sb: Implemented HW_DSPSS_IPIEndianismSet
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++/* PROJECT SPECIFIC INCLUDE FILES */
++#include <GlobalTypes.h>
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <IVA2RegAcM.h>
++#include <IPIAccInt.h>
++
++/* HW FUNCTIONS */
++HW_STATUS HW_DSPSS_BootModeSet(const u32 baseAddress,
++ enum HW_DSPSYSC_BootMode_t bootMode,
++ const u32 bootAddress)
++{
++ HW_STATUS status = RET_OK;
++ u32 offset = SYSC_IVA2BOOTMOD_OFFSET;
++ u32 alignedBootAddr;
++
++ /* if Boot mode it DIRECT BOOT, check that the bootAddress is
++ * aligned to atleast 1K :: TODO */
++ WR_MEM_32_VOLATILE((baseAddress) + offset, bootMode);
++
++ offset = SYSC_IVA2BOOTADDR_OFFSET;
++
++ alignedBootAddr = bootAddress & SYSC_IVA2BOOTADDR_MASK;
++
++ WR_MEM_32_VOLATILE((baseAddress) + offset, alignedBootAddr);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_dspssC64P.h b/drivers/dsp/bridge/hw/hw_dspssC64P.h
+new file mode 100644
+index 0000000..493effd
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_dspssC64P.h
+@@ -0,0 +1,48 @@
++/*
++ * hw_dspssC64P.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_dspss.h ========
++ * Description:
++ * DSP Subsystem API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb: Removed redundant argument from HW_DSPSS_IPIEndianismSet
++ *! Moved endianness and element size to generic hw_defs.h
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#ifndef __HW_DSPSS_H
++#define __HW_DSPSS_H
++#include <linux/types.h>
++
++ enum HW_DSPSYSC_BootMode_t {
++ HW_DSPSYSC_DIRECTBOOT = 0x0,
++ HW_DSPSYSC_IDLEBOOT = 0x1,
++ HW_DSPSYSC_SELFLOOPBOOT = 0x2,
++ HW_DSPSYSC_USRBOOTSTRAP = 0x3,
++ HW_DSPSYSC_DEFAULTRESTORE = 0x4
++ } ;
++
++#define HW_DSP_IDLEBOOT_ADDR 0x007E0000
++
++ extern HW_STATUS HW_DSPSS_BootModeSet(const u32 baseAddress,
++ enum HW_DSPSYSC_BootMode_t bootMode,
++ const u32 bootAddress);
++
++#endif /* __HW_DSPSS_H */
+diff --git a/drivers/dsp/bridge/hw/hw_mbox.c b/drivers/dsp/bridge/hw/hw_mbox.c
+new file mode 100644
+index 0000000..9f14f34
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mbox.c
+@@ -0,0 +1,244 @@
++/*
++ * hw_mbox.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_mbox.c ========
++ * Description:
++ * Mailbox messaging & configuration API definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "MLBRegAcM.h"
++#include <hw_defs.h>
++#include <hw_mbox.h>
++
++/* width in bits of MBOX Id */
++#define HW_MBOX_ID_WIDTH 2
++
++struct MAILBOX_CONTEXT mboxsetting = {0x4, 0x1, 0x1};
++
++/* Saves the mailbox context */
++HW_STATUS HW_MBOX_saveSettings(u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
++ /* Get current enable status */
++ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U0_ARM);
++ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U1_DSP1);
++ return status;
++}
++
++/* Restores the mailbox context */
++HW_STATUS HW_MBOX_restoreSettings(u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++ /* Restor IRQ enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U0_ARM,
++ mboxsetting.irqEnable0);
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, HW_MBOX_U1_DSP1,
++ mboxsetting.irqEnable1);
++ /* Restore Sysconfig register */
++ MLBMAILBOX_SYSCONFIGWriteRegister32(baseAddress, mboxsetting.sysconfig);
++ return status;
++}
++
++/* Reads a u32 from the sub module message box Specified. if there are no
++ * messages in the mailbox then and error is returned. */
++HW_STATUS HW_MBOX_MsgRead(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ u32 *const pReadValue)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_PARAM(pReadValue, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Read 32-bit message in mail box */
++ *pReadValue = MLBMAILBOX_MESSAGE___0_15ReadRegister32(baseAddress,
++ (u32)mailBoxId);
++
++ return status;
++}
++
++/* Writes a u32 from the sub module message box Specified. */
++HW_STATUS HW_MBOX_MsgWrite(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ const u32 writeValue)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Write 32-bit value to mailbox */
++ MLBMAILBOX_MESSAGE___0_15WriteRegister32(baseAddress, (u32)mailBoxId,
++ (u32)writeValue);
++
++ return status;
++}
++
++/* Gets number of messages in a specified mailbox. */
++HW_STATUS HW_MBOX_NumMsgGet(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ u32 *const pNumMsg)
++{
++ HW_STATUS status = RET_OK;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_PARAM(pNumMsg, NULL, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get number of messages available for MailBox */
++ *pNumMsg = MLBMAILBOX_MSGSTATUS___0_15NbOfMsgMBmRead32(baseAddress,
++ (u32)mailBoxId);
++
++ return status;
++}
++
++/* Enables the specified IRQ. */
++HW_STATUS HW_MBOX_EventEnable(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqEnableReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(enableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get current enable status */
++ irqEnableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
++ (u32)userId);
++
++ /* update enable value */
++ irqEnableReg |= ((u32)(events)) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH);
++
++ /* write new enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqEnableReg);
++
++ mboxsetting.sysconfig = MLBMAILBOX_SYSCONFIGReadRegister32(baseAddress);
++ /* Get current enable status */
++ mboxsetting.irqEnable0 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U0_ARM);
++ mboxsetting.irqEnable1 = MLBMAILBOX_IRQENABLE___0_3ReadRegister32
++ (baseAddress, HW_MBOX_U1_DSP1);
++ return status;
++}
++
++/* Disables the specified IRQ. */
++HW_STATUS HW_MBOX_EventDisable(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqDisableReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(disableIrq, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* Get current enable status */
++ irqDisableReg = MLBMAILBOX_IRQENABLE___0_3ReadRegister32(baseAddress,
++ (u32)userId);
++
++ /* update enable value */
++ irqDisableReg &= ~(((u32)(events)) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH));
++
++ /* write new enable status */
++ MLBMAILBOX_IRQENABLE___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqDisableReg);
++
++ return status;
++}
++
++/* Sets the status of the specified IRQ. */
++HW_STATUS HW_MBOX_EventAck(const u32 baseAddress, const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId, const u32 event)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqStatusReg;
++
++ /* Check input parameters */
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM, RES_MBOX_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ CHECK_INPUT_RANGE_MIN0(irqStatus, HW_MBOX_INT_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mailBoxId, HW_MBOX_ID_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(userId, HW_MBOX_USER_MAX, RET_INVALID_ID,
++ RES_MBOX_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* calculate status to write */
++ irqStatusReg = ((u32)event) << (((u32)(mailBoxId)) *
++ HW_MBOX_ID_WIDTH);
++
++ /* clear Irq Status for specified mailbox/User Id */
++ MLBMAILBOX_IRQSTATUS___0_3WriteRegister32(baseAddress, (u32)userId,
++ (u32)irqStatusReg);
++
++ /*
++ * FIXME: Replace all this custom register access with standard
++ * __raw_read/write().
++ *
++ * FIXME: Replace all interrupt handlers with standard linux style
++ * interrupt handlers.
++ *
++ * FIXME: Replace direct access to PRCM registers with omap standard
++ * PRCM register access.
++ *
++ * Flush posted write for the irq status to avoid spurious interrupts.
++ */
++ MLBMAILBOX_IRQSTATUS___0_3ReadRegister32(baseAddress, (u32)userId);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_mbox.h b/drivers/dsp/bridge/hw/hw_mbox.h
+new file mode 100644
+index 0000000..d2981d3
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mbox.h
+@@ -0,0 +1,323 @@
++/*
++ * hw_mbox.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_mbox.h ========
++ * Description:
++ * HW Mailbox API and types definitions
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __MBOX_H
++#define __MBOX_H
++
++/* Bitmasks for Mailbox interrupt sources */
++#define HW_MBOX_INT_NEW_MSG 0x1
++#define HW_MBOX_INT_NOT_FULL 0x2
++#define HW_MBOX_INT_ALL 0x3
++
++/* Maximum number of messages that mailbox can hald at a time. */
++#define HW_MBOX_MAX_NUM_MESSAGES 4
++
++/* HW_MBOX_Id_t: Enumerated Type used to specify Mailbox Sub Module Id Number */
++typedef enum HW_MBOX_Id_label {
++ HW_MBOX_ID_0,
++ HW_MBOX_ID_1,
++ HW_MBOX_ID_2,
++ HW_MBOX_ID_3,
++ HW_MBOX_ID_4,
++ HW_MBOX_ID_5
++
++} HW_MBOX_Id_t, *pHW_MBOX_Id_t;
++
++/* HW_MBOX_UserId_t: Enumerated Type used to specify Mail box User Id */
++typedef enum HW_MBOX_UserId_label {
++ HW_MBOX_U0_ARM,
++ HW_MBOX_U1_DSP1,
++ HW_MBOX_U2_DSP2,
++ HW_MBOX_U3_ARM
++
++} HW_MBOX_UserId_t, *pHW_MBOX_UserId_t;
++
++/* Mailbox context settings */
++struct MAILBOX_CONTEXT {
++ u32 sysconfig;
++ u32 irqEnable0;
++ u32 irqEnable1;
++};
++
++/*
++* FUNCTION : HW_MBOX_MsgRead
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to read
++*
++* OUTPUTS:
++*
++* Identifier : pReadValue
++* Type : u32 *const
++* Description : Value read from MailBox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/ptr Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function reads a u32 from the sub module message
++* box Specified. if there are no messages in the mailbox
++* then and error is returned.
++*/
++extern HW_STATUS HW_MBOX_MsgRead(const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ u32 *const pReadValue);
++
++/*
++* FUNCTION : HW_MBOX_MsgWrite
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to write
++*
++* Identifier : writeValue
++* Type : const u32
++* Description : Value to write to MailBox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function writes a u32 from the sub module message
++* box Specified.
++*/
++extern HW_STATUS HW_MBOX_MsgWrite(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const u32 writeValue
++ );
++
++/*
++* FUNCTION : HW_MBOX_NumMsgGet
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to get num messages
++*
++* OUTPUTS:
++*
++* Identifier : pNumMsg
++* Type : u32 *const
++* Description : Number of messages in mailbox
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Inavlid ID input at parameter
++*
++* PURPOSE: : this function gets number of messages in a specified mailbox.
++*/
++extern HW_STATUS HW_MBOX_NumMsgGet(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ u32 *const pNumMsg
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventEnable
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to enable
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to enable
++*
++* Identifier : enableIrq
++* Type : const u32
++* Description : Irq value to enable
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function enables the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventEnable(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventDisable
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to disable
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to disable
++*
++* Identifier : enableIrq
++* Type : const u32
++* Description : Irq value to disable
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM A Pointer Paramater was set to NULL
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function disables the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventDisable(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 events
++ );
++
++/*
++* FUNCTION : HW_MBOX_EventAck
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++* Identifier : mailBoxId
++* Type : const HW_MBOX_Id_t
++* Description : Mail Box Sub module Id to set
++*
++* Identifier : userId
++* Type : const HW_MBOX_UserId_t
++* Description : Mail box User Id to set
++*
++* Identifier : irqStatus
++* Type : const u32
++* Description : The value to write IRQ status
++*
++* OUTPUTS:
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address Paramater was set to 0
++* RET_INVALID_ID Invalid Id used
++*
++* PURPOSE: : this function sets the status of the specified IRQ.
++*/
++extern HW_STATUS HW_MBOX_EventAck(
++ const u32 baseAddress,
++ const HW_MBOX_Id_t mailBoxId,
++ const HW_MBOX_UserId_t userId,
++ const u32 event
++ );
++
++/*
++* FUNCTION : HW_MBOX_saveSettings
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function saves the context of mailbox
++*/
++extern HW_STATUS HW_MBOX_saveSettings(u32 baseAddres);
++
++/*
++* FUNCTION : HW_MBOX_restoreSettings
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of Mailbox module
++*
++*
++* RETURNS:
++*
++* Type : ReturnCode_t
++* Description : RET_OK No errors occured
++* RET_BAD_NULL_PARAM Address/pointer Paramater was set to 0/NULL
++* RET_INVALID_ID Invalid Id used
++* RET_EMPTY Mailbox empty
++*
++* PURPOSE: : this function restores the context of mailbox
++*/
++extern HW_STATUS HW_MBOX_restoreSettings(u32 baseAddres);
++
++#endif /* __MBOX_H */
+diff --git a/drivers/dsp/bridge/hw/hw_mmu.c b/drivers/dsp/bridge/hw/hw_mmu.c
+new file mode 100644
+index 0000000..ab65de0
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mmu.c
+@@ -0,0 +1,598 @@
++/*
++ * hw_mmu.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_mmu.c ========
++ * Description:
++ * API definitions to setup MMU TLB and PTE
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb TLBAdd and TLBFlush input the page size in bytes instead
++ of an enum. TLBAdd inputs mapping attributes struct instead
++ of individual arguments.
++ Removed MMU.h and other cosmetic updates.
++ *! 08-Mar-2004 sb Added the Page Table Management APIs
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "MMURegAcM.h"
++#include <hw_defs.h>
++#include <hw_mmu.h>
++#include <linux/types.h>
++
++#define MMU_BASE_VAL_MASK 0xFC00
++#define MMU_PAGE_MAX 3
++#define MMU_ELEMENTSIZE_MAX 3
++#define MMU_ADDR_MASK 0xFFFFF000
++#define MMU_TTB_MASK 0xFFFFC000
++#define MMU_SECTION_ADDR_MASK 0xFFF00000
++#define MMU_SSECTION_ADDR_MASK 0xFF000000
++#define MMU_PAGE_TABLE_MASK 0xFFFFFC00
++#define MMU_LARGE_PAGE_MASK 0xFFFF0000
++#define MMU_SMALL_PAGE_MASK 0xFFFFF000
++
++#define MMU_LOAD_TLB 0x00000001
++
++/* HW_MMUPageSize_t: Enumerated Type used to specify the MMU Page Size(SLSS) */
++enum HW_MMUPageSize_t {
++ HW_MMU_SECTION,
++ HW_MMU_LARGE_PAGE,
++ HW_MMU_SMALL_PAGE,
++ HW_MMU_SUPERSECTION
++} ;
++
++/*
++* FUNCTION : MMU_FlushEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of MMU module
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer
++* Paramater was set to NULL
++*
++* PURPOSE: : Flush the TLB entry pointed by the
++* lock counter register
++* even if this entry is set protected
++*
++* METHOD: : Check the Input parameter and Flush a
++* single entry in the TLB.
++*/
++static HW_STATUS MMU_FlushEntry(const u32 baseAddress);
++
++/*
++* FUNCTION : MMU_SetCAMEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* TypE : const u32
++* Description : Base Address of instance of MMU module
++*
++* Identifier : pageSize
++* TypE : const u32
++* Description : It indicates the page size
++*
++* Identifier : preservedBit
++* Type : const u32
++* Description : It indicates the TLB entry is preserved entry
++* or not
++*
++* Identifier : validBit
++* Type : const u32
++* Description : It indicates the TLB entry is valid entry or not
++*
++*
++* Identifier : virtualAddrTag
++* Type : const u32
++* Description : virtual Address
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer Paramater
++* was set to NULL
++* RET_PARAM_OUT_OF_RANGE -- Input Parameter out
++* of Range
++*
++* PURPOSE: : Set MMU_CAM reg
++*
++* METHOD: : Check the Input parameters and set the CAM entry.
++*/
++static HW_STATUS MMU_SetCAMEntry(const u32 baseAddress,
++ const u32 pageSize,
++ const u32 preservedBit,
++ const u32 validBit,
++ const u32 virtualAddrTag);
++
++/*
++* FUNCTION : MMU_SetRAMEntry
++*
++* INPUTS:
++*
++* Identifier : baseAddress
++* Type : const u32
++* Description : Base Address of instance of MMU module
++*
++* Identifier : physicalAddr
++* Type : const u32
++* Description : Physical Address to which the corresponding
++* virtual Address shouldpoint
++*
++* Identifier : endianism
++* Type : HW_Endianism_t
++* Description : endianism for the given page
++*
++* Identifier : elementSize
++* Type : HW_ElementSize_t
++* Description : The element size ( 8,16, 32 or 64 bit)
++*
++* Identifier : mixedSize
++* Type : HW_MMUMixedSize_t
++* Description : Element Size to follow CPU or TLB
++*
++* RETURNS:
++*
++* Type : HW_STATUS
++* Description : RET_OK -- No errors occured
++* RET_BAD_NULL_PARAM -- A Pointer Paramater
++* was set to NULL
++* RET_PARAM_OUT_OF_RANGE -- Input Parameter
++* out of Range
++*
++* PURPOSE: : Set MMU_CAM reg
++*
++* METHOD: : Check the Input parameters and set the RAM entry.
++*/
++static HW_STATUS MMU_SetRAMEntry(const u32 baseAddress,
++ const u32 physicalAddr,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elementSize,
++ enum HW_MMUMixedSize_t mixedSize);
++
++/* HW FUNCTIONS */
++
++HW_STATUS HW_MMU_Enable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_SET);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_Disable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLMMUEnableWrite32(baseAddress, HW_CLEAR);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_NumLockedSet(const u32 baseAddress,
++ u32 numLockedEntries)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_LOCKBaseValueWrite32(baseAddress, numLockedEntries);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_VictimNumSet(const u32 baseAddress,
++ u32 victimEntryNum)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_LOCKCurrentVictimWrite32(baseAddress, victimEntryNum);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventAck(const u32 baseAddress, u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_IRQSTATUSWriteRegister32(baseAddress, irqMask);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventDisable(const u32 baseAddress,
++ u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqReg;
++
++ irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
++
++ MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg & ~irqMask);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_EventEnable(const u32 baseAddress, u32 irqMask)
++{
++ HW_STATUS status = RET_OK;
++ u32 irqReg;
++
++ irqReg = MMUMMU_IRQENABLEReadRegister32(baseAddress);
++
++ MMUMMU_IRQENABLEWriteRegister32(baseAddress, irqReg | irqMask);
++
++ return status;
++}
++
++
++HW_STATUS HW_MMU_EventStatus(const u32 baseAddress, u32 *irqMask)
++{
++ HW_STATUS status = RET_OK;
++
++ *irqMask = MMUMMU_IRQSTATUSReadRegister32(baseAddress);
++
++ return status;
++}
++
++
++HW_STATUS HW_MMU_FaultAddrRead(const u32 baseAddress, u32 *addr)
++{
++ HW_STATUS status = RET_OK;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* read values from register */
++ *addr = MMUMMU_FAULT_ADReadRegister32(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TTBSet(const u32 baseAddress, u32 TTBPhysAddr)
++{
++ HW_STATUS status = RET_OK;
++ u32 loadTTB;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ loadTTB = TTBPhysAddr & ~0x7FUL;
++ /* write values to register */
++ MMUMMU_TTBWriteRegister32(baseAddress, loadTTB);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TWLEnable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_SET);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TWLDisable(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++
++ MMUMMU_CNTLTWLEnableWrite32(baseAddress, HW_CLEAR);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TLBFlush(const u32 baseAddress, u32 virtualAddr,
++ u32 pageSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 virtualAddrTag;
++ enum HW_MMUPageSize_t pgSizeBits;
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ pgSizeBits = HW_MMU_SMALL_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ pgSizeBits = HW_MMU_LARGE_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ pgSizeBits = HW_MMU_SECTION;
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ pgSizeBits = HW_MMU_SUPERSECTION;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ /* Generate the 20-bit tag from virtual address */
++ virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
++
++ MMU_SetCAMEntry(baseAddress, pgSizeBits, 0, 0, virtualAddrTag);
++
++ MMU_FlushEntry(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_TLBAdd(const u32 baseAddress,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ u32 entryNum,
++ struct HW_MMUMapAttrs_t *mapAttrs,
++ enum HW_SetClear_t preservedBit,
++ enum HW_SetClear_t validBit)
++{
++ HW_STATUS status = RET_OK;
++ u32 lockReg;
++ u32 virtualAddrTag;
++ enum HW_MMUPageSize_t mmuPgSize;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(pageSize, MMU_PAGE_MAX, RET_PARAM_OUT_OF_RANGE,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(mapAttrs->elementSize, MMU_ELEMENTSIZE_MAX,
++ RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ mmuPgSize = HW_MMU_SMALL_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ mmuPgSize = HW_MMU_LARGE_PAGE;
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ mmuPgSize = HW_MMU_SECTION;
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ mmuPgSize = HW_MMU_SUPERSECTION;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ lockReg = MMUMMU_LOCKReadRegister32(baseAddress);
++
++ /* Generate the 20-bit tag from virtual address */
++ virtualAddrTag = ((virtualAddr & MMU_ADDR_MASK) >> 12);
++
++ /* Write the fields in the CAM Entry Register */
++ MMU_SetCAMEntry(baseAddress, mmuPgSize, preservedBit, validBit,
++ virtualAddrTag);
++
++ /* Write the different fields of the RAM Entry Register */
++ /* endianism of the page,Element Size of the page (8, 16, 32, 64 bit)*/
++ MMU_SetRAMEntry(baseAddress, physicalAddr, mapAttrs->endianism,
++ mapAttrs->elementSize, mapAttrs->mixedSize);
++
++ /* Update the MMU Lock Register */
++ /* currentVictim between lockedBaseValue and (MMU_Entries_Number - 1)*/
++ MMUMMU_LOCKCurrentVictimWrite32(baseAddress, entryNum);
++
++ /* Enable loading of an entry in TLB by writing 1
++ into LD_TLB_REG register */
++ MMUMMU_LD_TLBWriteRegister32(baseAddress, MMU_LOAD_TLB);
++
++
++ MMUMMU_LOCKWriteRegister32(baseAddress, lockReg);
++
++ return status;
++}
++
++HW_STATUS HW_MMU_PteSet(const u32 pgTblVa,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ struct HW_MMUMapAttrs_t *mapAttrs)
++{
++ HW_STATUS status = RET_OK;
++ u32 pteAddr, pteVal;
++ s32 numEntries = 1;
++
++ switch (pageSize) {
++ case HW_PAGE_SIZE_4KB:
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_SMALL_PAGE_MASK);
++ pteVal = ((physicalAddr & MMU_SMALL_PAGE_MASK) |
++ (mapAttrs->endianism << 9) |
++ (mapAttrs->elementSize << 4) |
++ (mapAttrs->mixedSize << 11) | 2
++ );
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_LARGE_PAGE_MASK);
++ pteVal = ((physicalAddr & MMU_LARGE_PAGE_MASK) |
++ (mapAttrs->endianism << 9) |
++ (mapAttrs->elementSize << 4) |
++ (mapAttrs->mixedSize << 11) | 1
++ );
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ pteVal = ((((physicalAddr & MMU_SECTION_ADDR_MASK) |
++ (mapAttrs->endianism << 15) |
++ (mapAttrs->elementSize << 10) |
++ (mapAttrs->mixedSize << 17)) &
++ ~0x40000) | 0x2
++ );
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SSECTION_ADDR_MASK);
++ pteVal = (((physicalAddr & MMU_SSECTION_ADDR_MASK) |
++ (mapAttrs->endianism << 15) |
++ (mapAttrs->elementSize << 10) |
++ (mapAttrs->mixedSize << 17)
++ ) | 0x40000 | 0x2
++ );
++ break;
++
++ case HW_MMU_COARSE_PAGE_SIZE:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ pteVal = (physicalAddr & MMU_PAGE_TABLE_MASK) | 1;
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ while (--numEntries >= 0)
++ ((u32 *)pteAddr)[numEntries] = pteVal;
++
++ return status;
++}
++
++HW_STATUS HW_MMU_PteClear(const u32 pgTblVa,
++ u32 virtualAddr,
++ u32 pgSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 pteAddr;
++ s32 numEntries = 1;
++
++ switch (pgSize) {
++ case HW_PAGE_SIZE_4KB:
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_SMALL_PAGE_MASK);
++ break;
++
++ case HW_PAGE_SIZE_64KB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL2(pgTblVa,
++ virtualAddr & MMU_LARGE_PAGE_MASK);
++ break;
++
++ case HW_PAGE_SIZE_1MB:
++ case HW_MMU_COARSE_PAGE_SIZE:
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SECTION_ADDR_MASK);
++ break;
++
++ case HW_PAGE_SIZE_16MB:
++ numEntries = 16;
++ pteAddr = HW_MMU_PteAddrL1(pgTblVa,
++ virtualAddr & MMU_SSECTION_ADDR_MASK);
++ break;
++
++ default:
++ return RET_FAIL;
++ }
++
++ while (--numEntries >= 0)
++ ((u32 *)pteAddr)[numEntries] = 0;
++
++ return status;
++}
++
++/* MMU_FlushEntry */
++static HW_STATUS MMU_FlushEntry(const u32 baseAddress)
++{
++ HW_STATUS status = RET_OK;
++ u32 flushEntryData = 0x1;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ /* write values to register */
++ MMUMMU_FLUSH_ENTRYWriteRegister32(baseAddress, flushEntryData);
++
++ return status;
++}
++
++/* MMU_SetCAMEntry */
++static HW_STATUS MMU_SetCAMEntry(const u32 baseAddress,
++ const u32 pageSize,
++ const u32 preservedBit,
++ const u32 validBit,
++ const u32 virtualAddrTag)
++{
++ HW_STATUS status = RET_OK;
++ u32 mmuCamReg;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++
++ mmuCamReg = (virtualAddrTag << 12);
++ mmuCamReg = (mmuCamReg) | (pageSize) | (validBit << 2) |
++ (preservedBit << 3) ;
++
++ /* write values to register */
++ MMUMMU_CAMWriteRegister32(baseAddress, mmuCamReg);
++
++ return status;
++}
++
++/* MMU_SetRAMEntry */
++static HW_STATUS MMU_SetRAMEntry(const u32 baseAddress,
++ const u32 physicalAddr,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elementSize,
++ enum HW_MMUMixedSize_t mixedSize)
++{
++ HW_STATUS status = RET_OK;
++ u32 mmuRamReg;
++
++ /*Check the input Parameters*/
++ CHECK_INPUT_PARAM(baseAddress, 0, RET_BAD_NULL_PARAM,
++ RES_MMU_BASE + RES_INVALID_INPUT_PARAM);
++ CHECK_INPUT_RANGE_MIN0(elementSize, MMU_ELEMENTSIZE_MAX,
++ RET_PARAM_OUT_OF_RANGE, RES_MMU_BASE +
++ RES_INVALID_INPUT_PARAM);
++
++
++ mmuRamReg = (physicalAddr & MMU_ADDR_MASK);
++ mmuRamReg = (mmuRamReg) | ((endianism << 9) | (elementSize << 7) |
++ (mixedSize << 6));
++
++ /* write values to register */
++ MMUMMU_RAMWriteRegister32(baseAddress, mmuRamReg);
++
++ return status;
++
++}
+diff --git a/drivers/dsp/bridge/hw/hw_mmu.h b/drivers/dsp/bridge/hw/hw_mmu.h
+new file mode 100644
+index 0000000..a3dd2a8
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_mmu.h
+@@ -0,0 +1,177 @@
++/*
++ * hw_mmu.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== hw_mmu.h ========
++ * Description:
++ * MMU types and API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 19-Apr-2004 sb Moved & renamed endianness, page size, element size
++ TLBAdd takes in MMUMapAttrs instead of separate arguments
++ *! 08-Mar-2004 sb Added the Page Table management APIs
++ *! 16 Feb 2003 sb: Initial version
++ */
++#ifndef __HW_MMU_H
++#define __HW_MMU_H
++
++#include <linux/types.h>
++
++/* Bitmasks for interrupt sources */
++#define HW_MMU_TRANSLATION_FAULT 0x2
++#define HW_MMU_ALL_INTERRUPTS 0x1F
++
++#define HW_MMU_COARSE_PAGE_SIZE 0x400
++
++/* HW_MMUMixedSize_t: Enumerated Type used to specify whether to follow
++ CPU/TLB Element size */
++enum HW_MMUMixedSize_t {
++ HW_MMU_TLBES,
++ HW_MMU_CPUES
++
++} ;
++
++/* HW_MMUMapAttrs_t: Struct containing MMU mapping attributes */
++struct HW_MMUMapAttrs_t {
++ enum HW_Endianism_t endianism;
++ enum HW_ElementSize_t elementSize;
++ enum HW_MMUMixedSize_t mixedSize;
++ bool donotlockmpupage;
++} ;
++
++extern HW_STATUS HW_MMU_Enable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_Disable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_NumLockedSet(const u32 baseAddress,
++ u32 numLockedEntries);
++
++extern HW_STATUS HW_MMU_VictimNumSet(const u32 baseAddress,
++ u32 victimEntryNum);
++
++/* For MMU faults */
++extern HW_STATUS HW_MMU_EventAck(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventDisable(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventEnable(const u32 baseAddress,
++ u32 irqMask);
++
++extern HW_STATUS HW_MMU_EventStatus(const u32 baseAddress,
++ u32 *irqMask);
++
++extern HW_STATUS HW_MMU_FaultAddrRead(const u32 baseAddress,
++ u32 *addr);
++
++/* Set the TT base address */
++extern HW_STATUS HW_MMU_TTBSet(const u32 baseAddress,
++ u32 TTBPhysAddr);
++
++extern HW_STATUS HW_MMU_TWLEnable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_TWLDisable(const u32 baseAddress);
++
++extern HW_STATUS HW_MMU_TLBFlush(const u32 baseAddress,
++ u32 virtualAddr,
++ u32 pageSize);
++
++extern HW_STATUS HW_MMU_TLBAdd(const u32 baseAddress,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ u32 entryNum,
++ struct HW_MMUMapAttrs_t *mapAttrs,
++ enum HW_SetClear_t preservedBit,
++ enum HW_SetClear_t validBit);
++
++
++/* For PTEs */
++extern HW_STATUS HW_MMU_PteSet(const u32 pgTblVa,
++ u32 physicalAddr,
++ u32 virtualAddr,
++ u32 pageSize,
++ struct HW_MMUMapAttrs_t *mapAttrs);
++
++extern HW_STATUS HW_MMU_PteClear(const u32 pgTblVa,
++ u32 pgSize,
++ u32 virtualAddr);
++
++static inline u32 HW_MMU_PteAddrL1(u32 L1_base, u32 va)
++{
++ u32 pteAddr;
++ u32 VA_31_to_20;
++
++ VA_31_to_20 = va >> (20 - 2); /* Left-shift by 2 here itself */
++ VA_31_to_20 &= 0xFFFFFFFCUL;
++ pteAddr = L1_base + VA_31_to_20;
++
++ return pteAddr;
++}
++
++static inline u32 HW_MMU_PteAddrL2(u32 L2_base, u32 va)
++{
++ u32 pteAddr;
++
++ pteAddr = (L2_base & 0xFFFFFC00) | ((va >> 10) & 0x3FC);
++
++ return pteAddr;
++}
++
++static inline u32 HW_MMU_PteCoarseL1(u32 pteVal)
++{
++ u32 pteCoarse;
++
++ pteCoarse = pteVal & 0xFFFFFC00;
++
++ return pteCoarse;
++}
++
++static inline u32 HW_MMU_PteSizeL1(u32 pteVal)
++{
++ u32 pteSize = 0;
++
++ if ((pteVal & 0x3) == 0x1) {
++ /* Points to L2 PT */
++ pteSize = HW_MMU_COARSE_PAGE_SIZE;
++ }
++
++ if ((pteVal & 0x3) == 0x2) {
++ if (pteVal & (1 << 18))
++ pteSize = HW_PAGE_SIZE_16MB;
++ else
++ pteSize = HW_PAGE_SIZE_1MB;
++ }
++
++ return pteSize;
++}
++
++static inline u32 HW_MMU_PteSizeL2(u32 pteVal)
++{
++ u32 pteSize = 0;
++
++ if (pteVal & 0x2)
++ pteSize = HW_PAGE_SIZE_4KB;
++ else if (pteVal & 0x1)
++ pteSize = HW_PAGE_SIZE_64KB;
++
++ return pteSize;
++}
++
++#endif /* __HW_MMU_H */
+diff --git a/drivers/dsp/bridge/hw/hw_prcm.c b/drivers/dsp/bridge/hw/hw_prcm.c
+new file mode 100644
+index 0000000..61ff08f
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_prcm.c
+@@ -0,0 +1,167 @@
++/*
++ * hw_prcm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_prcm.c ========
++ * Description:
++ * API definitions to configure PRCM (Power, Reset & Clocks Manager)
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#include <GlobalTypes.h>
++#include "PRCMRegAcM.h"
++#include <hw_defs.h>
++#include <hw_prcm.h>
++
++static HW_STATUS HW_RST_WriteVal(const u32 baseAddress,
++ enum HW_RstModule_t r,
++ enum HW_SetClear_t val);
++
++HW_STATUS HW_RST_Reset(const u32 baseAddress, enum HW_RstModule_t r)
++{
++ return HW_RST_WriteVal(baseAddress, r, HW_SET);
++}
++
++HW_STATUS HW_RST_UnReset(const u32 baseAddress, enum HW_RstModule_t r)
++{
++ return HW_RST_WriteVal(baseAddress, r, HW_CLEAR);
++}
++
++static HW_STATUS HW_RST_WriteVal(const u32 baseAddress,
++ enum HW_RstModule_t r,
++ enum HW_SetClear_t val)
++{
++ HW_STATUS status = RET_OK;
++
++ switch (r) {
++ case HW_RST1_IVA2:
++ PRM_RSTCTRL_IVA2RST1_DSPWrite32(baseAddress, val);
++ break;
++ case HW_RST2_IVA2:
++ PRM_RSTCTRL_IVA2RST2_DSPWrite32(baseAddress, val);
++ break;
++ case HW_RST3_IVA2:
++ PRM_RSTCTRL_IVA2RST3_DSPWrite32(baseAddress, val);
++ break;
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ return status;
++}
++
++HW_STATUS HW_PWR_IVA2StateGet(const u32 baseAddress, enum HW_PwrModule_t p,
++ enum HW_PwrState_t *value)
++{
++ HW_STATUS status = RET_OK;
++ u32 temp;
++
++ switch (p) {
++ case HW_PWR_DOMAIN_DSP:
++ /* wait until Transition is complete */
++ do {
++ /* mdelay(1); */
++ temp = PRCMPM_PWSTST_IVA2InTransitionRead32
++ (baseAddress);
++
++ } while (temp);
++
++ temp = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
++ *value = PRCMPM_PWSTST_IVA2PowerStateStGet32(temp);
++ break;
++
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ return status;
++}
++
++HW_STATUS HW_PWRST_IVA2RegGet(const u32 baseAddress, u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMPM_PWSTST_IVA2ReadRegister32(baseAddress);
++
++ return status;
++}
++
++
++HW_STATUS HW_PWR_IVA2PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value)
++{
++ HW_STATUS status = RET_OK;
++
++ switch (p) {
++ case HW_PWR_DOMAIN_DSP:
++ switch (value) {
++ case HW_PWR_STATE_ON:
++ PRCMPM_PWSTCTRL_IVA2PowerStateWriteON32(baseAddress);
++ break;
++ case HW_PWR_STATE_RET:
++ PRCMPM_PWSTCTRL_DSPPowerStateWriteRET32(baseAddress);
++ break;
++ case HW_PWR_STATE_OFF:
++ PRCMPM_PWSTCTRL_IVA2PowerStateWriteOFF32(baseAddress);
++ break;
++ default:
++ status = RET_FAIL;
++ break;
++ }
++ break;
++
++ default:
++ status = RET_FAIL;
++ break;
++ }
++
++ return status;
++}
++
++HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const u32 baseAddress,
++ enum HW_TransitionState_t val)
++{
++ HW_STATUS status = RET_OK;
++
++ PRCMCM_CLKSTCTRL_IVA2WriteRegister32(baseAddress, val);
++
++ return status;
++
++}
++
++HW_STATUS HW_RSTST_RegGet(const u32 baseAddress, enum HW_RstModule_t m,
++ u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMRM_RSTST_DSPReadRegister32(baseAddress);
++
++ return status;
++}
++
++HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress, enum HW_RstModule_t m,
++ u32 *value)
++{
++ HW_STATUS status = RET_OK;
++
++ *value = PRCMRM_RSTCTRL_DSPReadRegister32(baseAddress);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/hw/hw_prcm.h b/drivers/dsp/bridge/hw/hw_prcm.h
+new file mode 100644
+index 0000000..928486c
+--- /dev/null
++++ b/drivers/dsp/bridge/hw/hw_prcm.h
+@@ -0,0 +1,168 @@
++/*
++ * hw_prcm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== hw_prcm.h ========
++ * Description:
++ * PRCM types and API declarations
++ *
++ *! Revision History:
++ *! ================
++ *! 16 Feb 2003 sb: Initial version
++ */
++
++#ifndef __HW_PRCM_H
++#define __HW_PRCM_H
++
++/* HW_ClkModule: Enumerated Type used to specify the clock domain */
++
++enum HW_ClkModule_t {
++/* DSP Domain */
++ HW_CLK_DSP_CPU,
++ HW_CLK_DSP_IPI_MMU,
++ HW_CLK_IVA_ARM,
++ HW_CLK_IVA_COP, /* IVA Coprocessor */
++
++/* Core Domain */
++ HW_CLK_FN_WDT4, /* Functional Clock */
++ HW_CLK_FN_WDT3,
++ HW_CLK_FN_UART2,
++ HW_CLK_FN_UART1,
++ HW_CLK_GPT5,
++ HW_CLK_GPT6,
++ HW_CLK_GPT7,
++ HW_CLK_GPT8,
++
++ HW_CLK_IF_WDT4, /* Interface Clock */
++ HW_CLK_IF_WDT3,
++ HW_CLK_IF_UART2,
++ HW_CLK_IF_UART1,
++ HW_CLK_IF_MBOX
++
++} ;
++
++enum HW_ClkSubsys_t {
++ HW_CLK_DSPSS,
++ HW_CLK_IVASS
++} ;
++
++/* HW_GPtimers: General purpose timers */
++enum HW_GPtimer_t {
++ HW_GPT5 = 5,
++ HW_GPT6 = 6,
++ HW_GPT7 = 7,
++ HW_GPT8 = 8
++} ;
++
++
++/* GP timers Input clock type: General purpose timers */
++enum HW_Clocktype_t {
++ HW_CLK_32KHz = 0,
++ HW_CLK_SYS = 1,
++ HW_CLK_EXT = 2
++} ;
++
++/* HW_ClkDiv: Clock divisors */
++enum HW_ClkDiv_t {
++ HW_CLK_DIV_1 = 0x1,
++ HW_CLK_DIV_2 = 0x2,
++ HW_CLK_DIV_3 = 0x3,
++ HW_CLK_DIV_4 = 0x4,
++ HW_CLK_DIV_6 = 0x6,
++ HW_CLK_DIV_8 = 0x8,
++ HW_CLK_DIV_12 = 0xC
++} ;
++
++/* HW_RstModule: Enumerated Type used to specify the module to be reset */
++enum HW_RstModule_t {
++ HW_RST1_IVA2, /* Reset the DSP */
++ HW_RST2_IVA2, /* Reset MMU and LEON HWa */
++ HW_RST3_IVA2 /* Reset LEON sequencer */
++} ;
++
++/* HW_PwrModule: Enumerated Type used to specify the power domain */
++enum HW_PwrModule_t {
++/* Domains */
++ HW_PWR_DOMAIN_CORE,
++ HW_PWR_DOMAIN_MPU,
++ HW_PWR_DOMAIN_WAKEUP,
++ HW_PWR_DOMAIN_DSP,
++
++/* Sub-domains */
++ HW_PWR_DSP_IPI, /* IPI = Intrusive Port Interface */
++ HW_PWR_IVA_ISP /* ISP = Intrusive Slave Port */
++} ;
++
++enum HW_PwrState_t {
++ HW_PWR_STATE_OFF,
++ HW_PWR_STATE_RET,
++ HW_PWR_STATE_INACT,
++ HW_PWR_STATE_ON = 3
++} ;
++
++enum HW_ForceState_t {
++ HW_FORCE_OFF,
++ HW_FORCE_ON
++} ;
++
++enum HW_IdleState_t {
++ HW_ACTIVE,
++ HW_STANDBY
++
++} ;
++
++enum HW_TransitionState_t {
++ HW_AUTOTRANS_DIS,
++ HW_SW_SUP_SLEEP,
++ HW_SW_SUP_WAKEUP,
++ HW_AUTOTRANS_EN
++} ;
++
++
++extern HW_STATUS HW_RST_Reset(const u32 baseAddress,
++ enum HW_RstModule_t r);
++
++extern HW_STATUS HW_RST_UnReset(const u32 baseAddress,
++ enum HW_RstModule_t r);
++
++extern HW_STATUS HW_RSTCTRL_RegGet(const u32 baseAddress,
++ enum HW_RstModule_t p,
++ u32 *value);
++extern HW_STATUS HW_RSTST_RegGet(const u32 baseAddress,
++ enum HW_RstModule_t p, u32 *value);
++
++extern HW_STATUS HW_PWR_PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value);
++
++extern HW_STATUS HW_CLK_SetInputClock(const u32 baseAddress,
++ enum HW_GPtimer_t gpt,
++ enum HW_Clocktype_t c);
++
++extern HW_STATUS HW_PWR_IVA2StateGet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t *value);
++
++extern HW_STATUS HW_PWRST_IVA2RegGet(const u32 baseAddress, u32 *value);
++
++extern HW_STATUS HW_PWR_IVA2PowerStateSet(const u32 baseAddress,
++ enum HW_PwrModule_t p,
++ enum HW_PwrState_t value);
++
++extern HW_STATUS HW_PWR_CLKCTRL_IVA2RegSet(const u32 baseAddress,
++ enum HW_TransitionState_t val);
++
++#endif /* __HW_PRCM_H */
+diff --git a/drivers/dsp/bridge/pmgr/chnl.c b/drivers/dsp/bridge/pmgr/chnl.c
+new file mode 100644
+index 0000000..6b5a0d9
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/chnl.c
+@@ -0,0 +1,260 @@
++/*
++ * chnl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl.c ========
++ * Description:
++ * WCD channel interface: multiplexes data streams through the single
++ * physical link managed by a 'Bridge mini-driver.
++ *
++ * Public Functions:
++ * CHNL_Close
++ * CHNL_CloseOrphans
++ * CHNL_Create
++ * CHNL_Destroy
++ * CHNL_Exit
++ * CHNL_GetHandle
++ * CHNL_GetProcessHandle
++ * CHNL_Init
++ * CHNL_Open
++ *
++ * Notes:
++ * This interface is basically a pass through to the WMD CHNL functions,
++ * except for the CHNL_Get() accessor functions which call
++ * WMD_CHNL_GetInfo().
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 07-Jan-2002 ag CHNL_CloseOrphans() now closes supported # of channels.
++ *! 17-Nov-2000 jeh Removed IRQ, shared memory stuff from CHNL_Create.
++ *! 28-Feb-2000 rr: New GT USage Implementation
++ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
++ *! SERVICES)
++ *! 21-Jan-2000 ag: Added code review comments.
++ *! 13-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! 08-Dec-1999 ag: CHNL_[Alloc|Free]Buffer bufs taken from client process heap.
++ *! 02-Dec-1999 ag: Implemented CHNL_GetEventHandle().
++ *! 17-Nov-1999 ag: CHNL_AllocBuffer() allocs extra word for process mapping.
++ *! 28-Oct-1999 ag: WinCE port. Search for "WinCE" for changes(TBR).
++ *! 07-Jan-1998 gp: CHNL_[Alloc|Free]Buffer now call MEM_UMB functions.
++ *! 22-Oct-1997 gp: Removed requirement in CHNL_Open that hReserved1 != NULL.
++ *! 30-Aug-1997 cr: Renamed cfg.h wbwcd.h b/c of WINNT file name collision.
++ *! 10-Mar-1997 gp: Added GT trace.
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 03-Jan-1997 gp: Moved CHNL_AllocBuffer/CHNL_FreeBuffer code from udspsys.
++ *! 14-Dec-1996 gp: Added uChnlId parameter to CHNL_Open().
++ *! 09-Sep-1996 gp: Added CHNL_GetProcessHandle().
++ *! 15-Jul-1996 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/proc.h>
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/chnlpriv.h>
++#include <chnlobj.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/chnl.h>
++
++/* ----------------------------------- Globals */
++static u32 cRefs;
++#if GT_TRACE
++static struct GT_Mask CHNL_DebugMask = { NULL, NULL }; /* WCD CHNL Mask */
++#endif
++
++
++
++/*
++ * ======== CHNL_Create ========
++ * Purpose:
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given 'Bridge board.
++ */
++DSP_STATUS CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
++{
++ DSP_STATUS status;
++ struct CHNL_MGR *hChnlMgr;
++ struct CHNL_MGR_ *pChnlMgr = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phChnlMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++
++ GT_3trace(CHNL_DebugMask, GT_ENTER,
++ "Entered CHNL_Create: phChnlMgr: 0x%x\t"
++ "hDevObject: 0x%x\tpMgrAttrs:0x%x\n",
++ phChnlMgr, hDevObject, pMgrAttrs);
++
++ *phChnlMgr = NULL;
++
++ /* Validate args: */
++ if ((0 < pMgrAttrs->cChannels) &&
++ (pMgrAttrs->cChannels <= CHNL_MAXCHANNELS)) {
++ status = DSP_SOK;
++ } else if (pMgrAttrs->cChannels == 0) {
++ status = DSP_EINVALIDARG;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Invalid Args\n");
++ } else {
++ status = CHNL_E_MAXCHANNELS;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Error Max Channels\n");
++ }
++ if (pMgrAttrs->uWordSize == 0) {
++ status = CHNL_E_INVALIDWORDSIZE;
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Create:Invalid Word size\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ if (DSP_SUCCEEDED(status) && hChnlMgr != NULL)
++ status = CHNL_E_MGREXISTS;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++ /* Let WMD channel module finish the create: */
++ status = (*pIntfFxns->pfnChnlCreate)(&hChnlMgr, hDevObject,
++ pMgrAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in WCD channel module's fields of the
++ * CHNL_MGR structure */
++ pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
++ pChnlMgr->pIntfFxns = pIntfFxns;
++ /* Finally, return the new channel manager handle: */
++ *phChnlMgr = hChnlMgr;
++ GT_1trace(CHNL_DebugMask, GT_1CLASS,
++ "CHNL_Create: Success pChnlMgr:"
++ "0x%x\n", pChnlMgr);
++ }
++ }
++
++ GT_2trace(CHNL_DebugMask, GT_ENTER,
++ "Exiting CHNL_Create: pChnlMgr: 0x%x,"
++ "status: 0x%x\n", pChnlMgr, status);
++ DBC_Ensure(DSP_FAILED(status) || CHNL_IsValidMgr(pChnlMgr));
++
++ return status;
++}
++
++/*
++ * ======== CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ */
++DSP_STATUS CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
++{
++ struct CHNL_MGR_ *pChnlMgr = (struct CHNL_MGR_ *)hChnlMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(CHNL_DebugMask, GT_ENTER,
++ "Entered CHNL_Destroy: hChnlMgr: 0x%x\n", hChnlMgr);
++ if (CHNL_IsValidMgr(pChnlMgr)) {
++ pIntfFxns = pChnlMgr->pIntfFxns;
++ /* Let WMD channel module destroy the CHNL_MGR: */
++ status = (*pIntfFxns->pfnChnlDestroy)(hChnlMgr);
++ } else {
++ GT_0trace(CHNL_DebugMask, GT_7CLASS,
++ "CHNL_Destroy:Invalid Handle\n");
++ status = DSP_EHANDLE;
++ }
++
++ GT_2trace(CHNL_DebugMask, GT_ENTER,
++ "Exiting CHNL_Destroy: pChnlMgr: 0x%x,"
++ " status:0x%x\n", pChnlMgr, status);
++ DBC_Ensure(DSP_FAILED(status) || !CHNL_IsValidMgr(pChnlMgr));
++
++ return status;
++}
++
++/*
++ * ======== CHNL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CHNL module.
++ */
++void CHNL_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(CHNL_DebugMask, GT_5CLASS,
++ "Entered CHNL_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++
++/*
++ * ======== CHNL_Init ========
++ * Purpose:
++ * Initialize the CHNL module's private state.
++ */
++bool CHNL_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!CHNL_DebugMask.flags);
++ GT_create(&CHNL_DebugMask, "CH"); /* "CH" for CHannel */
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(CHNL_DebugMask, GT_5CLASS,
++ "Entered CHNL_Init, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++
+diff --git a/drivers/dsp/bridge/pmgr/chnlobj.h b/drivers/dsp/bridge/pmgr/chnlobj.h
+new file mode 100644
+index 0000000..da74c96
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/chnlobj.h
+@@ -0,0 +1,71 @@
++/*
++ * chnlobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnlobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library channel objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 17-Nov-2000 jeh Removed some fields from CHNL_MGR_ to match CHNL_MGR
++ *! structure defined in _chnl_sm.h.
++ *! 16-Jan-1997 gp: Created from chnlpriv.h
++ */
++
++#ifndef CHNLOBJ_
++#define CHNLOBJ_
++
++#include <dspbridge/chnldefs.h>
++#include <dspbridge/wmd.h>
++
++/* Object validateion macros: */
++#define CHNL_IsValidMgr(h) \
++ ((h != NULL) && ((h)->dwSignature == CHNL_MGRSIGNATURE))
++
++#define CHNL_IsValidChnl(h)\
++ ((h != NULL) && ((h)->dwSignature == CHNL_SIGNATURE))
++
++/*
++ * This struct is the first field in a CHNL_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct CHNL_MGR_ {
++ /* These must be the first fields in a CHNL_MGR struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++} ;
++
++/*
++ * This struct is the first field in a CHNL_OBJECT struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct CHNL_OBJECT_ {
++ /* These must be the first fields in a CHNL_OBJECT struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct CHNL_MGR_ *pChnlMgr; /* Pointer back to channel manager. */
++} ;
++
++#endif /* CHNLOBJ_ */
++
+diff --git a/drivers/dsp/bridge/pmgr/cmm.c b/drivers/dsp/bridge/pmgr/cmm.c
+new file mode 100644
+index 0000000..99a2432
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/cmm.c
+@@ -0,0 +1,1291 @@
++/*
++ * cmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cmm.c ========
++ * Purpose:
++ * The Communication(Shared) Memory Management(CMM) module provides
++ * shared memory management services for DSP/BIOS Bridge data streaming
++ * and messaging.
++ *
++ * Multiple shared memory segments can be registered with CMM.
++ * Each registered SM segment is represented by a SM "allocator" that
++ * describes a block of physically contiguous shared memory used for
++ * future allocations by CMM.
++ *
++ * Memory is coelesced back to the appropriate heap when a buffer is
++ * freed.
++ *
++ * Public Functions:
++ * CMM_CallocBuf
++ * CMM_Create
++ * CMM_Destroy
++ * CMM_Exit
++ * CMM_FreeBuf
++ * CMM_GetHandle
++ * CMM_GetInfo
++ * CMM_Init
++ * CMM_RegisterGPPSMSeg
++ * CMM_UnRegisterGPPSMSeg
++ *
++ * The CMM_Xlator[xxx] routines below are used by Node and Stream
++ * to perform SM address translation to the client process address space.
++ * A "translator" object is created by a node/stream for each SM seg used.
++ *
++ * Translator Routines:
++ * CMM_XlatorAllocBuf
++ * CMM_XlatorCreate
++ * CMM_XlatorDelete
++ * CMM_XlatorFreeBuf
++ * CMM_XlatorInfo
++ * CMM_XlatorTranslate
++ *
++ * Private Functions:
++ * AddToFreeList
++ * GetAllocator
++ * GetFreeBlock
++ * GetNode
++ * GetSlot
++ * UnRegisterGPPSMSeg
++ *
++ * Notes:
++ * Va: Virtual address.
++ * Pa: Physical or kernel system address.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 16-Feb-2002 ag Code review cleanup.
++ *! PreOMAP address translation no longner supported.
++ *! 30-Jan-2002 ag Updates to CMM_XlatorTranslate() per TII, ANSI C++
++ *! warnings.
++ *! 27-Jan-2002 ag Removed unused CMM_[Alloc][Free]Desc() & #ifdef USELOOKUP,
++ *! & unused VALIDATECMM and VaPaConvert().
++ *! Removed bFastXlate from CMM_XLATOR. Always fast lookup.
++ *! 03-Jan-2002 ag Clear SM in CMM_AllocBuf(). Renamed to CMM_CallocBuf().
++ *! 13-Nov-2001 ag Now delete pNodeFreeListHead and nodes in CMM_Destroy().
++ *! 28-Aug-2001 ag CMM_GetHandle() returns CMM Mgr hndle given HPROCESSOR.
++ *! Removed unused CMM_[Un]RegisterDSPSMSeg() &
++ * CMM_[Un}ReserveVirtSpace fxns. Some cleanup.
++ *! 12-Aug-2001 ag Exposed CMM_UnRegisterGPP[DSP]SMSeg.
++ *! 13-Feb-2001 kc DSP/BIOS Bridge name update.
++ *! 21-Dec-2000 rr GetFreeBlock checks for pAllocator.
++ *! 09-Dec-2000 ag Added GPPPA2DSPPA, DSPPA2GPPPA macros.
++ *! 05-Dec-2000 ag CMM_XlatorDelete() optionally frees SM bufs and descriptors.
++ *! 30-Oct-2000 ag Buf size bug fixed in CMM_AllocBuf() causing leak.
++ *! Revamped XlatorTranslate() routine.
++ *! 10-Oct-2000 ag Added CMM_Xlator[xxx] functions.
++ *! 02-Aug-2000 ag Created.
++ *!
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/proc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++/* Object signatures */
++#define CMMSIGNATURE 0x004d4d43 /* "CMM" (in reverse) */
++#define SMEMSIGNATURE 0x4D454D53 /* "SMEM" SM space */
++#define CMMXLATESIGNATURE 0x584d4d43 /* "CMMX" CMM Xlator */
++
++#define NEXT_PA(pNode) (pNode->dwPA + pNode->ulSize)
++
++/* Other bus/platform translations */
++#define DSPPA2GPPPA(base, x, y) ((x)+(y))
++#define GPPPA2DSPPA(base, x, y) ((x)-(y))
++
++/*
++ * Allocators define a block of contiguous memory used for future allocations.
++ *
++ * sma - shared memory allocator.
++ * vma - virtual memory allocator.(not used).
++ */
++struct CMM_ALLOCATOR { /* sma */
++ u32 dwSignature; /* SMA allocator signature SMEMSIGNATURE */
++ unsigned int dwSmBase; /* Start of physical SM block */
++ u32 ulSmSize; /* Size of SM block in bytes */
++ unsigned int dwVmBase; /* Start of VM block. (Dev driver
++ * context for 'sma') */
++ u32 dwDSPPhysAddrOffset; /* DSP PA to GPP PA offset for this
++ * SM space */
++ /* CMM_ADDTO[SUBFROM]DSPPA, _POMAPEMIF2DSPBUS */
++ enum CMM_CNVTTYPE cFactor;
++ unsigned int dwDSPBase; /* DSP virt base byte address */
++ u32 ulDSPSize; /* DSP seg size in bytes */
++ struct CMM_OBJECT *hCmmMgr; /* back ref to parent mgr */
++ struct LST_LIST *pFreeListHead; /* node list of available memory */
++ struct LST_LIST *pInUseListHead; /* node list of memory in use */
++} ;
++
++struct CMM_XLATOR { /* Pa<->Va translator object */
++ u32 dwSignature; /* "CMMX" */
++ struct CMM_OBJECT *hCmmMgr; /* CMM object this translator associated */
++ /*
++ * Client process virtual base address that corresponds to phys SM
++ * base address for translator's ulSegId.
++ * Only 1 segment ID currently supported.
++ */
++ unsigned int dwVirtBase; /* virtual base address */
++ u32 ulVirtSize; /* size of virt space in bytes */
++ u32 ulSegId; /* Segment Id */
++} ;
++
++/* CMM Mgr */
++struct CMM_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /*
++ * Cmm Lock is used to serialize access mem manager for multi-threads.
++ */
++ struct SYNC_CSOBJECT *hCmmLock; /* Lock to access cmm mgr */
++ struct LST_LIST *pNodeFreeListHead; /* Free list of memory nodes */
++ u32 ulMinBlockSize; /* Min SM block; default 16 bytes */
++ u32 dwPageSize; /* Memory Page size (1k/4k) */
++ /* GPP SM segment ptrs */
++ struct CMM_ALLOCATOR *paGPPSMSegTab[CMM_MAXGPPSEGS];
++} ;
++
++/* Default CMM Mgr attributes */
++static struct CMM_MGRATTRS CMM_DFLTMGRATTRS = {
++ 16 /* ulMinBlockSize, min block size(bytes) allocated by cmm mgr */
++};
++
++/* Default allocation attributes */
++static struct CMM_ATTRS CMM_DFLTALCTATTRS = {
++ 1 /* ulSegId, default segment Id for allocator */
++};
++
++/* Address translator default attrs */
++static struct CMM_XLATORATTRS CMM_DFLTXLATORATTRS = {
++ 1, /* ulSegId, does not have to match CMM_DFLTALCTATTRS ulSegId */
++ 0, /* dwDSPBufs */
++ 0, /* dwDSPBufSize */
++ NULL, /* pVmBase */
++ 0, /* dwVmSize */
++};
++
++/* SM node representing a block of memory. */
++struct CMM_MNODE {
++ struct LST_ELEM link; /* must be 1st element */
++ u32 dwPA; /* Phys addr */
++ u32 dwVA; /* Virtual address in device process context */
++ u32 ulSize; /* SM block size in bytes */
++ u32 hClientProc; /* Process that allocated this mem block */
++} ;
++
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* ----------------------------------- Function Prototypes */
++static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
++ struct CMM_MNODE *pNode);
++static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
++ u32 ulSegId);
++static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
++ u32 uSize);
++static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
++ u32 dwVA, u32 ulSize);
++/* get available slot for new allocator */
++static s32 GetSlot(struct CMM_OBJECT *hCmmMgr);
++static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA);
++
++/*
++ * ======== CMM_CallocBuf ========
++ * Purpose:
++ * Allocate a SM buffer, zero contents, and return the physical address
++ * and optional driver context virtual address(ppBufVA).
++ *
++ * The freelist is sorted in increasing size order. Get the first
++ * block that satifies the request and sort the remaining back on
++ * the freelist; if large enough. The kept block is placed on the
++ * inUseList.
++ */
++void *CMM_CallocBuf(struct CMM_OBJECT *hCmmMgr, u32 uSize,
++ struct CMM_ATTRS *pAttrs, OUT void **ppBufVA)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ void *pBufPA = NULL;
++ struct CMM_MNODE *pNode = NULL;
++ struct CMM_MNODE *pNewNode = NULL;
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++ u32 uDeltaSize;
++ u8 *pByte = NULL;
++ s32 cnt;
++
++ if (pAttrs == NULL)
++ pAttrs = &CMM_DFLTALCTATTRS;
++
++ if (ppBufVA != NULL)
++ *ppBufVA = NULL;
++
++ if ((MEM_IsValidHandle(pCmmMgr, CMMSIGNATURE)) && (uSize != 0)) {
++ if (pAttrs->ulSegId > 0) {
++ /* SegId > 0 is SM */
++ /* get the allocator object for this segment id */
++ pAllocator = GetAllocator(pCmmMgr, pAttrs->ulSegId);
++ /* keep block size a multiple of ulMinBlockSize */
++ uSize = ((uSize - 1) & ~(pCmmMgr->ulMinBlockSize - 1))
++ + pCmmMgr->ulMinBlockSize;
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pNode = GetFreeBlock(pAllocator, uSize);
++ }
++ if (pNode) {
++ uDeltaSize = (pNode->ulSize - uSize);
++ if (uDeltaSize >= pCmmMgr->ulMinBlockSize) {
++ /* create a new block with the leftovers and
++ * add to freelist */
++ pNewNode = GetNode(pCmmMgr, pNode->dwPA + uSize,
++ pNode->dwVA + uSize,
++ (u32)uDeltaSize);
++ /* leftovers go free */
++ AddToFreeList(pAllocator, pNewNode);
++ /* adjust our node's size */
++ pNode->ulSize = uSize;
++ }
++ /* Tag node with client process requesting allocation
++ * We'll need to free up a process's alloc'd SM if the
++ * client process goes away.
++ */
++ /* Return PID instead of process handle */
++ pNode->hClientProc = current->pid;
++
++ /* put our node on InUse list */
++ LST_PutTail(pAllocator->pInUseListHead,
++ (struct LST_ELEM *)pNode);
++ pBufPA = (void *)pNode->dwPA; /* physical address */
++ /* clear mem */
++ pByte = (u8 *)pNode->dwVA;
++ for (cnt = 0; cnt < (s32) uSize; cnt++, pByte++)
++ *pByte = 0;
++
++ if (ppBufVA != NULL) {
++ /* Virtual address */
++ *ppBufVA = (void *)pNode->dwVA;
++ }
++ }
++ GT_3trace(CMM_debugMask, GT_3CLASS,
++ "CMM_CallocBuf dwPA %x, dwVA %x uSize"
++ "%x\n", pNode->dwPA, pNode->dwVA, uSize);
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ }
++ return pBufPA;
++}
++
++/*
++ * ======== CMM_Create ========
++ * Purpose:
++ * Create a communication memory manager object.
++ */
++DSP_STATUS CMM_Create(OUT struct CMM_OBJECT **phCmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CMM_MGRATTRS *pMgrAttrs)
++{
++ struct CMM_OBJECT *pCmmObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct UTIL_SYSINFO sysInfo;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCmmMgr != NULL);
++
++ GT_3trace(CMM_debugMask, GT_ENTER,
++ "CMM_Create: phCmmMgr: 0x%x\thDevObject: "
++ "0x%x\tpMgrAttrs: 0x%x\n", phCmmMgr, hDevObject, pMgrAttrs);
++ *phCmmMgr = NULL;
++ /* create, zero, and tag a cmm mgr object */
++ MEM_AllocObject(pCmmObject, struct CMM_OBJECT, CMMSIGNATURE);
++ if (pCmmObject != NULL) {
++ if (pMgrAttrs == NULL)
++ pMgrAttrs = &CMM_DFLTMGRATTRS; /* set defaults */
++
++ /* 4 bytes minimum */
++ DBC_Assert(pMgrAttrs->ulMinBlockSize >= 4);
++ /* save away smallest block allocation for this cmm mgr */
++ pCmmObject->ulMinBlockSize = pMgrAttrs->ulMinBlockSize;
++ /* save away the systems memory page size */
++ sysInfo.dwPageSize = PAGE_SIZE;
++ sysInfo.dwAllocationGranularity = PAGE_SIZE;
++ sysInfo.dwNumberOfProcessors = 1;
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CMM_debugMask, GT_5CLASS,
++ "CMM_Create: Got system page size"
++ "= 0x%x\t\n", sysInfo.dwPageSize);
++ pCmmObject->dwPageSize = sysInfo.dwPageSize;
++ } else {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_Create: failed to get system"
++ "page size\n");
++ pCmmObject->dwPageSize = 0;
++ status = DSP_EFAIL;
++ }
++ /* Note: DSP SM seg table(aDSPSMSegTab[]) zero'd by
++ * MEM_AllocObject */
++ if (DSP_SUCCEEDED(status)) {
++ /* create node free list */
++ pCmmObject->pNodeFreeListHead = LST_Create();
++ if (pCmmObject->pNodeFreeListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_Create: LST_Create() "
++ "failed \n");
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pCmmObject->hCmmLock);
++
++ if (DSP_SUCCEEDED(status))
++ *phCmmMgr = pCmmObject;
++ else
++ CMM_Destroy(pCmmObject, true);
++
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_Create: Object Allocation "
++ "Failure(CMM Object)\n");
++ status = DSP_EMEMORY;
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_Destroy ========
++ * Purpose:
++ * Release the communication memory manager resources.
++ */
++DSP_STATUS CMM_Destroy(struct CMM_OBJECT *hCmmMgr, bool bForce)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ struct CMM_INFO tempInfo;
++ DSP_STATUS status = DSP_SOK;
++ s32 nSlot;
++ struct CMM_MNODE *pNode;
++
++ DBC_Require(cRefs > 0);
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ /* If not force then fail if outstanding allocations exist */
++ if (!bForce) {
++ /* Check for outstanding memory allocations */
++ status = CMM_GetInfo(hCmmMgr, &tempInfo);
++ if (DSP_SUCCEEDED(status)) {
++ if (tempInfo.ulTotalInUseCnt > 0) {
++ /* outstanding allocations */
++ status = DSP_EFAIL;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* UnRegister SM allocator */
++ for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
++ if (pCmmMgr->paGPPSMSegTab[nSlot] != NULL) {
++ UnRegisterGPPSMSeg(pCmmMgr->
++ paGPPSMSegTab[nSlot]);
++ /* Set slot to NULL for future reuse */
++ pCmmMgr->paGPPSMSegTab[nSlot] = NULL;
++ }
++ }
++ }
++ if (pCmmMgr->pNodeFreeListHead != NULL) {
++ /* Free the free nodes */
++ while (!LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
++ /* (struct LST_ELEM*) pNode =
++ * LST_GetHead(pCmmMgr->pNodeFreeListHead);*/
++ pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
++ pNodeFreeListHead);
++ MEM_Free(pNode);
++ }
++ /* delete NodeFreeList list */
++ LST_Delete(pCmmMgr->pNodeFreeListHead);
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ if (DSP_SUCCEEDED(status)) {
++ /* delete CS & cmm mgr object */
++ SYNC_DeleteCS(pCmmMgr->hCmmLock);
++ MEM_FreeObject(pCmmMgr);
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void CMM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(CMM_debugMask, GT_ENTER,
++ "exiting CMM_Exit,ref count:0x%x\n", cRefs);
++}
++
++/*
++ * ======== CMM_FreeBuf ========
++ * Purpose:
++ * Free the given buffer.
++ */
++DSP_STATUS CMM_FreeBuf(struct CMM_OBJECT *hCmmMgr, void *pBufPA, u32 ulSegId)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ DSP_STATUS status = DSP_EPOINTER;
++ struct CMM_MNODE *pCurNode = NULL;
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++ struct CMM_ATTRS *pAttrs;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufPA != NULL);
++ GT_1trace(CMM_debugMask, GT_ENTER, "CMM_FreeBuf pBufPA %x\n", pBufPA);
++ if (ulSegId == 0) {
++ pAttrs = &CMM_DFLTALCTATTRS;
++ ulSegId = pAttrs->ulSegId;
++ }
++ if (!(MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) || !(ulSegId > 0)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ /* get the allocator for this segment id */
++ pAllocator = GetAllocator(pCmmMgr, ulSegId);
++ if (pAllocator != NULL) {
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->
++ pInUseListHead);
++ while (pCurNode) {
++ if ((u32)pBufPA == pCurNode->dwPA) {
++ /* Found it */
++ LST_RemoveElem(pAllocator->pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ /* back to freelist */
++ AddToFreeList(pAllocator, pCurNode);
++ status = DSP_SOK; /* all right! */
++ break;
++ }
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pInUseListHead, (struct LST_ELEM *)pCurNode);
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_GetHandle ========
++ * Purpose:
++ * Return the communication memory manager object for this device.
++ * This is typically called from the client process.
++ */
++DSP_STATUS CMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct CMM_OBJECT **phCmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCmmMgr != NULL);
++ if (hProcessor != NULL)
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ else
++ hDevObject = DEV_GetFirst(); /* default */
++
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetCmmMgr(hDevObject, phCmmMgr);
++
++ return status;
++}
++
++/*
++ * ======== CMM_GetInfo ========
++ * Purpose:
++ * Return the current memory utilization information.
++ */
++DSP_STATUS CMM_GetInfo(struct CMM_OBJECT *hCmmMgr,
++ OUT struct CMM_INFO *pCmmInfo)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ u32 ulSeg;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_ALLOCATOR *pAltr;
++ struct CMM_MNODE *pCurNode = NULL;
++
++ DBC_Require(pCmmInfo != NULL);
++
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ pCmmInfo->ulNumGPPSMSegs = 0; /* # of SM segments */
++ pCmmInfo->ulTotalInUseCnt = 0; /* Total # of outstanding alloc */
++ pCmmInfo->ulMinBlockSize = pCmmMgr->ulMinBlockSize; /* min block size */
++ /* check SM memory segments */
++ for (ulSeg = 1; ulSeg <= CMM_MAXGPPSEGS; ulSeg++) {
++ /* get the allocator object for this segment id */
++ pAltr = GetAllocator(pCmmMgr, ulSeg);
++ if (pAltr != NULL) {
++ pCmmInfo->ulNumGPPSMSegs++;
++ pCmmInfo->segInfo[ulSeg - 1].dwSegBasePa =
++ pAltr->dwSmBase - pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].ulTotalSegSize =
++ pAltr->ulDSPSize + pAltr->ulSmSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwGPPBasePA =
++ pAltr->dwSmBase;
++ pCmmInfo->segInfo[ulSeg - 1].ulGPPSize =
++ pAltr->ulSmSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwDSPBaseVA =
++ pAltr->dwDSPBase;
++ pCmmInfo->segInfo[ulSeg - 1].ulDSPSize =
++ pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].dwSegBaseVa =
++ pAltr->dwVmBase - pAltr->ulDSPSize;
++ pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt = 0;
++ pCurNode = (struct CMM_MNODE *)LST_First(pAltr->
++ pInUseListHead);
++ /* Count inUse blocks */
++ while (pCurNode) {
++ pCmmInfo->ulTotalInUseCnt++;
++ pCmmInfo->segInfo[ulSeg - 1].ulInUseCnt++;
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAltr->
++ pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ }
++ }
++ } /* end for */
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ return status;
++}
++
++/*
++ * ======== CMM_Init ========
++ * Purpose:
++ * Initializes private state of CMM module.
++ */
++bool CMM_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ /* "CM" for Comm Memory manager */
++ GT_create(&CMM_debugMask, "CM");
++ }
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(CMM_debugMask, GT_ENTER,
++ "Entered CMM_Init,ref count:0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== CMM_RegisterGPPSMSeg ========
++ * Purpose:
++ * Register a block of SM with the CMM to be used for later GPP SM
++ * allocations.
++ */
++DSP_STATUS CMM_RegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 dwGPPBasePA,
++ u32 ulSize, u32 dwDSPAddrOffset,
++ enum CMM_CNVTTYPE cFactor, u32 dwDSPBase,
++ u32 ulDSPSize, u32 *pulSegId,
++ u32 dwGPPBaseVA)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ struct CMM_ALLOCATOR *pSMA = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_MNODE *pNewNode;
++ s32 nSlot;
++
++ DBC_Require(ulSize > 0);
++ DBC_Require(pulSegId != NULL);
++ DBC_Require(dwGPPBasePA != 0);
++ DBC_Require(dwGPPBaseVA != 0);
++ DBC_Require((cFactor <= CMM_ADDTODSPPA) &&
++ (cFactor >= CMM_SUBFROMDSPPA));
++ GT_6trace(CMM_debugMask, GT_ENTER,
++ "CMM_RegisterGPPSMSeg dwGPPBasePA %x "
++ "ulSize %x dwDSPAddrOffset %x dwDSPBase %x ulDSPSize %x "
++ "dwGPPBaseVA %x\n", dwGPPBasePA, ulSize, dwDSPAddrOffset,
++ dwDSPBase, ulDSPSize, dwGPPBaseVA);
++ if (!MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ /* make sure we have room for another allocator */
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ nSlot = GetSlot(pCmmMgr);
++ if (nSlot < 0) {
++ /* get a slot number */
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ /* Check if input ulSize is big enough to alloc at least one block */
++ if (DSP_SUCCEEDED(status)) {
++ if (ulSize < pCmmMgr->ulMinBlockSize) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "ulSize too small\n");
++ status = DSP_EINVALIDARG;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* create, zero, and tag an SM allocator object */
++ MEM_AllocObject(pSMA, struct CMM_ALLOCATOR, SMEMSIGNATURE);
++ }
++ if (pSMA != NULL) {
++ pSMA->hCmmMgr = hCmmMgr; /* ref to parent */
++ pSMA->dwSmBase = dwGPPBasePA; /* SM Base phys */
++ pSMA->ulSmSize = ulSize; /* SM segment size in bytes */
++ pSMA->dwVmBase = dwGPPBaseVA;
++ pSMA->dwDSPPhysAddrOffset = dwDSPAddrOffset;
++ pSMA->cFactor = cFactor;
++ pSMA->dwDSPBase = dwDSPBase;
++ pSMA->ulDSPSize = ulDSPSize;
++ if (pSMA->dwVmBase == 0) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: Error"
++ "MEM_LinearAddress()\n");
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* return the actual segment identifier */
++ *pulSegId = (u32) nSlot + 1;
++ /* create memory free list */
++ pSMA->pFreeListHead = LST_Create();
++ if (pSMA->pFreeListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "Out Of Memory \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* create memory in-use list */
++ pSMA->pInUseListHead = LST_Create();
++ if (pSMA->pInUseListHead == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: "
++ "LST_Create failed\n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get a mem node for this hunk-o-memory */
++ pNewNode = GetNode(pCmmMgr, dwGPPBasePA,
++ pSMA->dwVmBase, ulSize);
++ /* Place node on the SM allocator's free list */
++ if (pNewNode) {
++ LST_PutTail(pSMA->pFreeListHead,
++ (struct LST_ELEM *)pNewNode);
++ } else {
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* Cleanup allocator */
++ UnRegisterGPPSMSeg(pSMA);
++ }
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_RegisterGPPSMSeg: SMA Object "
++ "Allocation Failure\n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ /* make entry */
++ if (DSP_SUCCEEDED(status))
++ pCmmMgr->paGPPSMSegTab[nSlot] = pSMA;
++
++func_end:
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ return status;
++}
++
++/*
++ * ======== CMM_UnRegisterGPPSMSeg ========
++ * Purpose:
++ * UnRegister GPP SM segments with the CMM.
++ */
++DSP_STATUS CMM_UnRegisterGPPSMSeg(struct CMM_OBJECT *hCmmMgr, u32 ulSegId)
++{
++ struct CMM_OBJECT *pCmmMgr = (struct CMM_OBJECT *)hCmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_ALLOCATOR *pSMA;
++ u32 ulId = ulSegId;
++
++ DBC_Require(ulSegId > 0);
++ if (MEM_IsValidHandle(hCmmMgr, CMMSIGNATURE)) {
++ if (ulSegId == CMM_ALLSEGMENTS)
++ ulId = 1;
++
++ if ((ulId > 0) && (ulId <= CMM_MAXGPPSEGS)) {
++ while (ulId <= CMM_MAXGPPSEGS) {
++ SYNC_EnterCS(pCmmMgr->hCmmLock);
++ /* slot = segId-1 */
++ pSMA = pCmmMgr->paGPPSMSegTab[ulId - 1];
++ if (pSMA != NULL) {
++ UnRegisterGPPSMSeg(pSMA);
++ /* Set alctr ptr to NULL for future
++ * reuse */
++ pCmmMgr->paGPPSMSegTab[ulId - 1] = NULL;
++ } else if (ulSegId != CMM_ALLSEGMENTS) {
++ status = DSP_EFAIL;
++ }
++ SYNC_LeaveCS(pCmmMgr->hCmmLock);
++ if (ulSegId != CMM_ALLSEGMENTS)
++ break;
++
++ ulId++;
++ } /* end while */
++ } else {
++ status = DSP_EINVALIDARG;
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_UnRegisterGPPSMSeg: Bad "
++ "segment Id\n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== UnRegisterGPPSMSeg ========
++ * Purpose:
++ * UnRegister the SM allocator by freeing all its resources and
++ * nulling cmm mgr table entry.
++ * Note:
++ * This routine is always called within cmm lock crit sect.
++ */
++static void UnRegisterGPPSMSeg(struct CMM_ALLOCATOR *pSMA)
++{
++ struct CMM_MNODE *pCurNode = NULL;
++ struct CMM_MNODE *pNextNode = NULL;
++
++ DBC_Require(pSMA != NULL);
++ if (pSMA->pFreeListHead != NULL) {
++ /* free nodes on free list */
++ pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pFreeListHead);
++ while (pCurNode) {
++ pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
++ pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ LST_RemoveElem(pSMA->pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ MEM_Free((void *) pCurNode);
++ /* next node. */
++ pCurNode = pNextNode;
++ }
++ LST_Delete(pSMA->pFreeListHead); /* delete freelist */
++ /* free nodes on InUse list */
++ pCurNode = (struct CMM_MNODE *)LST_First(pSMA->pInUseListHead);
++ while (pCurNode) {
++ pNextNode = (struct CMM_MNODE *)LST_Next(pSMA->
++ pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ LST_RemoveElem(pSMA->pInUseListHead,
++ (struct LST_ELEM *)pCurNode);
++ MEM_Free((void *) pCurNode);
++ /* next node. */
++ pCurNode = pNextNode;
++ }
++ LST_Delete(pSMA->pInUseListHead); /* delete InUse list */
++ }
++ if ((void *) pSMA->dwVmBase != NULL)
++ MEM_UnmapLinearAddress((void *) pSMA->dwVmBase);
++
++ /* Free allocator itself */
++ MEM_FreeObject(pSMA);
++}
++
++/*
++ * ======== GetSlot ========
++ * Purpose:
++ * An available slot # is returned. Returns negative on failure.
++ */
++static s32 GetSlot(struct CMM_OBJECT *pCmmMgr)
++{
++ s32 nSlot = -1; /* neg on failure */
++ DBC_Require(pCmmMgr != NULL);
++ /* get first available slot in cmm mgr SMSegTab[] */
++ for (nSlot = 0; nSlot < CMM_MAXGPPSEGS; nSlot++) {
++ if (pCmmMgr->paGPPSMSegTab[nSlot] == NULL)
++ break;
++
++ }
++ if (nSlot == CMM_MAXGPPSEGS) {
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_RegisterGPPSMSeg: Allocator "
++ "entry failure, max exceeded\n");
++ nSlot = -1; /* failed */
++ }
++ return nSlot;
++}
++
++/*
++ * ======== GetNode ========
++ * Purpose:
++ * Get a memory node from freelist or create a new one.
++ */
++static struct CMM_MNODE *GetNode(struct CMM_OBJECT *pCmmMgr, u32 dwPA,
++ u32 dwVA, u32 ulSize)
++{
++ struct CMM_MNODE *pNode = NULL;
++
++ DBC_Require(pCmmMgr != NULL);
++ DBC_Require(dwPA != 0);
++ DBC_Require(dwVA != 0);
++ DBC_Require(ulSize != 0);
++ /* Check cmm mgr's node freelist */
++ if (LST_IsEmpty(pCmmMgr->pNodeFreeListHead)) {
++ pNode = (struct CMM_MNODE *)MEM_Calloc(sizeof(struct CMM_MNODE),
++ MEM_PAGED);
++ } else {
++ /* surely a valid element */
++ /* (struct LST_ELEM*) pNode = LST_GetHead(pCmmMgr->
++ * pNodeFreeListHead);*/
++ pNode = (struct CMM_MNODE *)LST_GetHead(pCmmMgr->
++ pNodeFreeListHead);
++ }
++ if (pNode == NULL) {
++ GT_0trace(CMM_debugMask, GT_7CLASS, "GetNode: Out Of Memory\n");
++ } else {
++ LST_InitElem((struct LST_ELEM *) pNode); /* set self */
++ pNode->dwPA = dwPA; /* Physical addr of start of block */
++ pNode->dwVA = dwVA; /* Virtual " " */
++ pNode->ulSize = ulSize; /* Size of block */
++ }
++ return pNode;
++}
++
++/*
++ * ======== DeleteNode ========
++ * Purpose:
++ * Put a memory node on the cmm nodelist for later use.
++ * Doesn't actually delete the node. Heap thrashing friendly.
++ */
++static void DeleteNode(struct CMM_OBJECT *pCmmMgr, struct CMM_MNODE *pNode)
++{
++ DBC_Require(pNode != NULL);
++ LST_InitElem((struct LST_ELEM *) pNode); /* init .self ptr */
++ LST_PutTail(pCmmMgr->pNodeFreeListHead, (struct LST_ELEM *) pNode);
++}
++
++/*
++ * ====== GetFreeBlock ========
++ * Purpose:
++ * Scan the free block list and return the first block that satisfies
++ * the size.
++ */
++static struct CMM_MNODE *GetFreeBlock(struct CMM_ALLOCATOR *pAllocator,
++ u32 uSize)
++{
++ if (pAllocator) {
++ struct CMM_MNODE *pCurNode = (struct CMM_MNODE *)
++ LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (uSize <= (u32) pCurNode->ulSize) {
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pCurNode);
++ return pCurNode;
++ }
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ }
++ }
++ return NULL;
++}
++
++/*
++ * ======== AddToFreeList ========
++ * Purpose:
++ * Coelesce node into the freelist in ascending size order.
++ */
++static void AddToFreeList(struct CMM_ALLOCATOR *pAllocator,
++ struct CMM_MNODE *pNode)
++{
++ struct CMM_MNODE *pNodePrev = NULL;
++ struct CMM_MNODE *pNodeNext = NULL;
++ struct CMM_MNODE *pCurNode;
++ u32 dwThisPA;
++ u32 dwNextPA;
++
++ DBC_Require(pNode != NULL);
++ DBC_Require(pAllocator != NULL);
++ dwThisPA = pNode->dwPA;
++ dwNextPA = NEXT_PA(pNode);
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (dwThisPA == NEXT_PA(pCurNode)) {
++ /* found the block ahead of this one */
++ pNodePrev = pCurNode;
++ } else if (dwNextPA == pCurNode->dwPA) {
++ pNodeNext = pCurNode;
++ }
++ if ((pNodePrev == NULL) || (pNodeNext == NULL)) {
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ } else {
++ /* got 'em */
++ break;
++ }
++ } /* while */
++ if (pNodePrev != NULL) {
++ /* combine with previous block */
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNodePrev);
++ /* grow node to hold both */
++ pNode->ulSize += pNodePrev->ulSize;
++ pNode->dwPA = pNodePrev->dwPA;
++ pNode->dwVA = pNodePrev->dwVA;
++ /* place node on mgr nodeFreeList */
++ DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodePrev);
++ }
++ if (pNodeNext != NULL) {
++ /* combine with next block */
++ LST_RemoveElem(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNodeNext);
++ /* grow da node */
++ pNode->ulSize += pNodeNext->ulSize;
++ /* place node on mgr nodeFreeList */
++ DeleteNode((struct CMM_OBJECT *)pAllocator->hCmmMgr, pNodeNext);
++ }
++ /* Now, let's add to freelist in increasing size order */
++ pCurNode = (struct CMM_MNODE *)LST_First(pAllocator->pFreeListHead);
++ while (pCurNode) {
++ if (pNode->ulSize <= pCurNode->ulSize)
++ break;
++
++ /* next node. */
++ pCurNode = (struct CMM_MNODE *)LST_Next(pAllocator->
++ pFreeListHead, (struct LST_ELEM *)pCurNode);
++ }
++ /* if pCurNode is NULL then add our pNode to the end of the freelist */
++ if (pCurNode == NULL) {
++ LST_PutTail(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNode);
++ } else {
++ /* insert our node before the current traversed node */
++ LST_InsertBefore(pAllocator->pFreeListHead,
++ (struct LST_ELEM *)pNode,
++ (struct LST_ELEM *)pCurNode);
++ }
++}
++
++/*
++ * ======== GetAllocator ========
++ * Purpose:
++ * Return the allocator for the given SM Segid.
++ * SegIds: 1,2,3..max.
++ */
++static struct CMM_ALLOCATOR *GetAllocator(struct CMM_OBJECT *pCmmMgr,
++ u32 ulSegId)
++{
++ struct CMM_ALLOCATOR *pAllocator = NULL;
++
++ DBC_Require(pCmmMgr != NULL);
++ DBC_Require((ulSegId > 0) && (ulSegId <= CMM_MAXGPPSEGS));
++ pAllocator = pCmmMgr->paGPPSMSegTab[ulSegId - 1];
++ if (pAllocator != NULL) {
++ /* make sure it's for real */
++ if (!MEM_IsValidHandle(pAllocator, SMEMSIGNATURE)) {
++ pAllocator = NULL;
++ DBC_Assert(false);
++ }
++ }
++ return pAllocator;
++}
++
++/*
++ * ======== CMM_XlatorCreate ========
++ * Purpose:
++ * Create an address translator object.
++ */
++DSP_STATUS CMM_XlatorCreate(OUT struct CMM_XLATOROBJECT **phXlator,
++ struct CMM_OBJECT *hCmmMgr,
++ struct CMM_XLATORATTRS *pXlatorAttrs)
++{
++ struct CMM_XLATOR *pXlatorObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phXlator != NULL);
++ DBC_Require(hCmmMgr != NULL);
++ GT_3trace(CMM_debugMask, GT_ENTER,
++ "CMM_XlatorCreate: phXlator: 0x%x\t"
++ "phCmmMgr: 0x%x\tpXlAttrs: 0x%x\n", phXlator,
++ hCmmMgr, pXlatorAttrs);
++ *phXlator = NULL;
++ if (pXlatorAttrs == NULL)
++ pXlatorAttrs = &CMM_DFLTXLATORATTRS; /* set defaults */
++
++ MEM_AllocObject(pXlatorObject, struct CMM_XLATOR, CMMXLATESIGNATURE);
++ if (pXlatorObject != NULL) {
++ pXlatorObject->hCmmMgr = hCmmMgr; /* ref back to CMM */
++ pXlatorObject->ulSegId = pXlatorAttrs->ulSegId; /* SM segId */
++ } else {
++ GT_0trace(CMM_debugMask, GT_6CLASS,
++ "CMM_XlatorCreate: Object Allocation"
++ "Failure(CMM Xlator)\n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status))
++ *phXlator = (struct CMM_XLATOROBJECT *) pXlatorObject;
++
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorDelete ========
++ * Purpose:
++ * Free the Xlator resources.
++ * VM gets freed later.
++ */
++DSP_STATUS CMM_XlatorDelete(struct CMM_XLATOROBJECT *hXlator, bool bForce)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ MEM_FreeObject(pXlator);
++ } else {
++ status = DSP_EHANDLE;
++ }
++
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorAllocBuf ========
++ */
++void *CMM_XlatorAllocBuf(struct CMM_XLATOROBJECT *hXlator, void *pVaBuf,
++ u32 uPaSize)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ void *pBuf = NULL;
++ struct CMM_ATTRS attrs;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hXlator != NULL);
++ DBC_Require(pXlator->hCmmMgr != NULL);
++ DBC_Require(pVaBuf != NULL);
++ DBC_Require(uPaSize > 0);
++ DBC_Require(pXlator->ulSegId > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ attrs.ulSegId = pXlator->ulSegId;
++ *(volatile u32 *)pVaBuf = 0;
++ /* Alloc SM */
++ pBuf = CMM_CallocBuf(pXlator->hCmmMgr, uPaSize, &attrs, NULL);
++ if (pBuf) {
++ /* convert to translator(node/strm) process Virtual
++ * address */
++ *(volatile u32 **)pVaBuf =
++ (u32 *)CMM_XlatorTranslate(hXlator,
++ pBuf, CMM_PA2VA);
++ }
++ }
++ return pBuf;
++}
++
++/*
++ * ======== CMM_XlatorFreeBuf ========
++ * Purpose:
++ * Free the given SM buffer and descriptor.
++ * Does not free virtual memory.
++ */
++DSP_STATUS CMM_XlatorFreeBuf(struct CMM_XLATOROBJECT *hXlator, void *pBufVa)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_EFAIL;
++ void *pBufPa = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufVa != NULL);
++ DBC_Require(pXlator->ulSegId > 0);
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ /* convert Va to Pa so we can free it. */
++ pBufPa = CMM_XlatorTranslate(hXlator, pBufVa, CMM_VA2PA);
++ if (pBufPa) {
++ status = CMM_FreeBuf(pXlator->hCmmMgr, pBufPa,
++ pXlator->ulSegId);
++ if (DSP_FAILED(status)) {
++ /* Uh oh, this shouldn't happen. Descriptor
++ * gone! */
++ GT_2trace(CMM_debugMask, GT_7CLASS,
++ "Cannot free DMA/ZCPY buffer"
++ "not allocated by MPU. PA %x, VA %x\n",
++ pBufPa, pBufVa);
++ DBC_Assert(false); /* CMM is leaking mem! */
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorInfo ========
++ * Purpose:
++ * Set/Get translator info.
++ */
++DSP_STATUS CMM_XlatorInfo(struct CMM_XLATOROBJECT *hXlator, IN OUT u8 **pAddr,
++ u32 ulSize, u32 uSegId, bool bSetInfo)
++{
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAddr != NULL);
++ DBC_Require((uSegId > 0) && (uSegId <= CMM_MAXGPPSEGS));
++
++ if (MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE)) {
++ if (bSetInfo) {
++ /* set translators virtual address range */
++ pXlator->dwVirtBase = (u32)*pAddr;
++ pXlator->ulVirtSize = ulSize;
++ GT_2trace(CMM_debugMask, GT_3CLASS,
++ "pXlator->dwVirtBase %x, "
++ "ulVirtSize %x\n", pXlator->dwVirtBase,
++ pXlator->ulVirtSize);
++ } else { /* return virt base address */
++ *pAddr = (u8 *)pXlator->dwVirtBase;
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== CMM_XlatorTranslate ========
++ */
++void *CMM_XlatorTranslate(struct CMM_XLATOROBJECT *hXlator, void *pAddr,
++ enum CMM_XLATETYPE xType)
++{
++ u32 dwAddrXlate = 0;
++ struct CMM_XLATOR *pXlator = (struct CMM_XLATOR *)hXlator;
++ struct CMM_OBJECT *pCmmMgr = NULL;
++ struct CMM_ALLOCATOR *pAlctr = NULL;
++ u32 dwOffset = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAddr != NULL);
++ DBC_Require((xType >= CMM_VA2PA) && (xType <= CMM_DSPPA2PA));
++
++ if (!MEM_IsValidHandle(pXlator, CMMXLATESIGNATURE))
++ goto loop_cont;
++
++ pCmmMgr = (struct CMM_OBJECT *)pXlator->hCmmMgr;
++ /* get this translator's default SM allocator */
++ DBC_Assert(pXlator->ulSegId > 0);
++ pAlctr = pCmmMgr->paGPPSMSegTab[pXlator->ulSegId - 1];
++ if (!MEM_IsValidHandle(pAlctr, SMEMSIGNATURE))
++ goto loop_cont;
++
++ if ((xType == CMM_VA2DSPPA) || (xType == CMM_VA2PA) ||
++ (xType == CMM_PA2VA)) {
++ if (xType == CMM_PA2VA) {
++ /* Gpp Va = Va Base + offset */
++ dwOffset = (u8 *)pAddr - (u8 *)(pAlctr->dwSmBase -
++ pAlctr->ulDSPSize);
++ dwAddrXlate = pXlator->dwVirtBase + dwOffset;
++ /* Check if translated Va base is in range */
++ if ((dwAddrXlate < pXlator->dwVirtBase) ||
++ (dwAddrXlate >=
++ (pXlator->dwVirtBase + pXlator->ulVirtSize))) {
++ dwAddrXlate = 0; /* bad address */
++ GT_0trace(CMM_debugMask, GT_7CLASS,
++ "CMM_XlatorTranslate: "
++ "Virt addr out of range\n");
++ }
++ } else {
++ /* Gpp PA = Gpp Base + offset */
++ dwOffset = (u8 *)pAddr - (u8 *)pXlator->dwVirtBase;
++ dwAddrXlate = pAlctr->dwSmBase - pAlctr->ulDSPSize +
++ dwOffset;
++ }
++ } else {
++ dwAddrXlate = (u32)pAddr;
++ }
++ /*Now convert address to proper target physical address if needed*/
++ if ((xType == CMM_VA2DSPPA) || (xType == CMM_PA2DSPPA)) {
++ /* Got Gpp Pa now, convert to DSP Pa */
++ dwAddrXlate = GPPPA2DSPPA((pAlctr->dwSmBase - pAlctr->
++ ulDSPSize), dwAddrXlate,
++ pAlctr->dwDSPPhysAddrOffset *
++ pAlctr->cFactor);
++ } else if (xType == CMM_DSPPA2PA) {
++ /* Got DSP Pa, convert to GPP Pa */
++ dwAddrXlate = DSPPA2GPPPA(pAlctr->dwSmBase - pAlctr->ulDSPSize,
++ dwAddrXlate,
++ pAlctr->dwDSPPhysAddrOffset *
++ pAlctr->cFactor);
++ }
++loop_cont:
++ if (!dwAddrXlate) {
++ GT_2trace(CMM_debugMask, GT_7CLASS,
++ "CMM_XlatorTranslate: Can't translate"
++ " address: 0x%x xType %x\n", pAddr, xType);
++ } else {
++ GT_3trace(CMM_debugMask, GT_3CLASS,
++ "CMM_XlatorTranslate: pAddr %x, xType"
++ " %x, dwAddrXlate %x\n", pAddr, xType, dwAddrXlate);
++ }
++ return (void *)dwAddrXlate;
++}
+diff --git a/drivers/dsp/bridge/pmgr/cod.c b/drivers/dsp/bridge/pmgr/cod.c
+new file mode 100644
+index 0000000..6363f1e
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/cod.c
+@@ -0,0 +1,683 @@
++/*
++ * cod.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cod.c ========
++ * This module implements DSP code management for the DSP/BIOS Bridge
++ * environment. It is mostly a thin wrapper.
++ *
++ * This module provides an interface for loading both static and
++ * dynamic code objects onto DSP systems.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Apr-2003 map: Consolidated DBL to DBLL loader name
++ *! 24-Feb-2003 swa: PMGR Code review comments incorporated.
++ *! 18-Apr-2002 jeh: Added DBL function tables.
++ *! 20-Nov-2001 jeh: Removed call to ZL_loadArgs function.
++ *! 19-Oct-2001 jeh: Access DBL as a static library. Added COD_GetBaseLib,
++ *! COD_GetLoader, removed COD_LoadSection, COD_UnloadSection.
++ *! 07-Sep-2001 jeh: Added COD_LoadSection(), COD_UnloadSection().
++ *! 07-Aug-2001 rr: hMgr->baseLib is updated after zlopen in COD_LoadBase.
++ *! 18-Apr-2001 jeh: Check for fLoaded flag before ZL_unload, to allow
++ *! COD_OpenBase to be used.
++ *! 11-Jan-2001 jeh: Added COD_OpenBase (not used yet, since there is an
++ *! occasional crash).
++ *! 02-Aug-2000 kc: Added COD_ReadSection to COD module. Incorporates use
++ *! of ZL_readSect (new function in ZL module).
++ *! 28-Feb-2000 rr: New GT Usage Implementation
++ *! 08-Dec-1999 ag: Removed x86 specific __asm int 3.
++ *! 02-Oct-1999 ag: Added #ifdef DEBUGINT3COD for debug.
++ *! 20-Sep-1999 ag: Removed call to GT_set().
++ *! 04-Jun-1997 cr: Added validation of argc/argv pair in COD_LoadBase, as it
++ *! is a requirement to ZL_loadArgs.
++ *! 31-May-1997 cr: Changed COD_LoadBase argc value from u32 to int, added
++ *! DSP_ENOTIMPL return value to COD_Create when attrs != NULL.
++ *! 29-May-1997 cr: Added debugging support.
++ *! 24-Oct-1996 gp: Added COD_GetSection().
++ *! 18-Jun-1996 gp: Updated GetSymValue() to check for lib; updated E_ codes.
++ *! 12-Jun-1996 gp: Imported CSL_ services for strcpyn(); Added ref counting.
++ *! 20-May-1996 mg: Adapted for new MEM and LDR modules.
++ *! 08-May-1996 mg: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/kfile.h>
++#include <dspbridge/ldr.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Platform Manager */
++/* Include appropriate loader header file */
++#include <dspbridge/dbll.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cod.h>
++
++/* magic number for handle validation */
++#define MAGIC 0xc001beef
++
++/* macro to validate COD manager handles */
++#define IsValid(h) ((h) != NULL && (h)->ulMagic == MAGIC)
++
++/*
++ * ======== COD_MANAGER ========
++ */
++struct COD_MANAGER {
++ struct DBLL_TarObj *target;
++ struct DBLL_LibraryObj *baseLib;
++ bool fLoaded; /* Base library loaded? */
++ u32 ulEntry;
++ struct LDR_MODULE *hDll;
++ struct DBLL_Fxns fxns;
++ struct DBLL_Attrs attrs;
++ char szZLFile[COD_MAXPATHLENGTH];
++ u32 ulMagic;
++} ;
++
++/*
++ * ======== COD_LIBRARYOBJ ========
++ */
++struct COD_LIBRARYOBJ {
++ struct DBLL_LibraryObj *dbllLib;
++ struct COD_MANAGER *hCodMgr;
++} ;
++
++static u32 cRefs = 0L;
++
++#if GT_TRACE
++static struct GT_Mask COD_debugMask = { NULL, NULL };
++#endif
++
++static struct DBLL_Fxns dbllFxns = {
++ (DBLL_CloseFxn) DBLL_close,
++ (DBLL_CreateFxn) DBLL_create,
++ (DBLL_DeleteFxn) DBLL_delete,
++ (DBLL_ExitFxn) DBLL_exit,
++ (DBLL_GetAttrsFxn) DBLL_getAttrs,
++ (DBLL_GetAddrFxn) DBLL_getAddr,
++ (DBLL_GetCAddrFxn) DBLL_getCAddr,
++ (DBLL_GetSectFxn) DBLL_getSect,
++ (DBLL_InitFxn) DBLL_init,
++ (DBLL_LoadFxn) DBLL_load,
++ (DBLL_LoadSectFxn) DBLL_loadSect,
++ (DBLL_OpenFxn) DBLL_open,
++ (DBLL_ReadSectFxn) DBLL_readSect,
++ (DBLL_SetAttrsFxn) DBLL_setAttrs,
++ (DBLL_UnloadFxn) DBLL_unload,
++ (DBLL_UnloadSectFxn) DBLL_unloadSect,
++};
++
++static bool NoOp(void);
++
++/*
++ * ======== COD_Close ========
++ */
++void COD_Close(struct COD_LIBRARYOBJ *lib)
++{
++ struct COD_MANAGER *hMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(((struct COD_LIBRARYOBJ *)lib)->hCodMgr));
++
++ hMgr = lib->hCodMgr;
++ hMgr->fxns.closeFxn(lib->dbllLib);
++
++ MEM_Free(lib);
++}
++
++/*
++ * ======== COD_Create ========
++ * Purpose:
++ * Create an object to manage code on a DSP system.
++ * This object can be used to load an initial program image with
++ * arguments that can later be expanded with
++ * dynamically loaded object files.
++ *
++ */
++DSP_STATUS COD_Create(OUT struct COD_MANAGER **phMgr, char *pstrDummyFile,
++ IN OPTIONAL CONST struct COD_ATTRS *attrs)
++{
++ struct COD_MANAGER *hMgrNew;
++ struct DBLL_Attrs zlAttrs;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_3trace(COD_debugMask, GT_ENTER,
++ "Entered COD_Create, Args: \t\nphMgr: "
++ "0x%x\t\npstrDummyFile: 0x%x\t\nattr: 0x%x\n",
++ phMgr, pstrDummyFile, attrs);
++ /* assume failure */
++ *phMgr = NULL;
++
++ /* we don't support non-default attrs yet */
++ if (attrs != NULL)
++ return DSP_ENOTIMPL;
++
++ hMgrNew = MEM_Calloc(sizeof(struct COD_MANAGER), MEM_NONPAGED);
++ if (hMgrNew == NULL) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_Create: Out Of Memory\n");
++ return DSP_EMEMORY;
++ }
++
++ hMgrNew->ulMagic = MAGIC;
++
++ /* Set up loader functions */
++ hMgrNew->fxns = dbllFxns;
++
++ /* initialize the ZL module */
++ hMgrNew->fxns.initFxn();
++
++ zlAttrs.alloc = (DBLL_AllocFxn)NoOp;
++ zlAttrs.free = (DBLL_FreeFxn)NoOp;
++ zlAttrs.fread = (DBLL_ReadFxn)KFILE_Read;
++ zlAttrs.fseek = (DBLL_SeekFxn)KFILE_Seek;
++ zlAttrs.ftell = (DBLL_TellFxn)KFILE_Tell;
++ zlAttrs.fclose = (DBLL_FCloseFxn)KFILE_Close;
++ zlAttrs.fopen = (DBLL_FOpenFxn)KFILE_Open;
++ zlAttrs.symLookup = NULL;
++ zlAttrs.baseImage = true;
++ zlAttrs.logWrite = NULL;
++ zlAttrs.logWriteHandle = NULL;
++ zlAttrs.write = NULL;
++ zlAttrs.rmmHandle = NULL;
++ zlAttrs.wHandle = NULL;
++ zlAttrs.symHandle = NULL;
++ zlAttrs.symArg = NULL;
++
++ hMgrNew->attrs = zlAttrs;
++
++ status = hMgrNew->fxns.createFxn(&hMgrNew->target, &zlAttrs);
++
++ if (DSP_FAILED(status)) {
++ COD_Delete(hMgrNew);
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_Create:ZL Create Failed: 0x%x\n", status);
++ return COD_E_ZLCREATEFAILED;
++ }
++
++ /* return the new manager */
++ *phMgr = hMgrNew;
++ GT_1trace(COD_debugMask, GT_1CLASS,
++ "COD_Create: Success CodMgr: 0x%x\n", *phMgr);
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_Delete ========
++ * Purpose:
++ * Delete a code manager object.
++ */
++void COD_Delete(struct COD_MANAGER *hMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++
++ GT_1trace(COD_debugMask, GT_ENTER, "COD_Delete:hMgr 0x%x\n", hMgr);
++ if (hMgr->baseLib) {
++ if (hMgr->fLoaded)
++ hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
++
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ }
++ if (hMgr->target) {
++ hMgr->fxns.deleteFxn(hMgr->target);
++ hMgr->fxns.exitFxn();
++ }
++ hMgr->ulMagic = ~MAGIC;
++ MEM_Free(hMgr);
++}
++
++/*
++ * ======== COD_Exit ========
++ * Purpose:
++ * Discontinue usage of the COD module.
++ *
++ */
++void COD_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(COD_debugMask, GT_ENTER,
++ "Entered COD_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== COD_GetBaseLib ========
++ * Purpose:
++ * Get handle to the base image DBL library.
++ */
++DSP_STATUS COD_GetBaseLib(struct COD_MANAGER *hManager,
++ struct DBLL_LibraryObj **plib)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(plib != NULL);
++
++ *plib = (struct DBLL_LibraryObj *) hManager->baseLib;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetBaseName ========
++ */
++DSP_STATUS COD_GetBaseName(struct COD_MANAGER *hManager, char *pszName,
++ u32 uSize)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(pszName != NULL);
++
++ if (uSize <= COD_MAXPATHLENGTH)
++ strncpy(pszName, hManager->szZLFile, uSize);
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetEntry ========
++ * Purpose:
++ * Retrieve the entry point of a loaded DSP program image
++ *
++ */
++DSP_STATUS COD_GetEntry(struct COD_MANAGER *hManager, u32 *pulEntry)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(pulEntry != NULL);
++
++ *pulEntry = hManager->ulEntry;
++
++ GT_1trace(COD_debugMask, GT_ENTER, "COD_GetEntry:ulEntr 0x%x\n",
++ *pulEntry);
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_GetLoader ========
++ * Purpose:
++ * Get handle to the DBLL loader.
++ */
++DSP_STATUS COD_GetLoader(struct COD_MANAGER *hManager,
++ struct DBLL_TarObj **phLoader)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hManager));
++ DBC_Require(phLoader != NULL);
++
++ *phLoader = (struct DBLL_TarObj *)hManager->target;
++
++ return status;
++}
++
++/*
++ * ======== COD_GetSection ========
++ * Purpose:
++ * Retrieve the starting address and length of a section in the COFF file
++ * given the section name.
++ */
++DSP_STATUS COD_GetSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
++ OUT u32 *puAddr, OUT u32 *puLen)
++{
++ struct COD_MANAGER *hManager;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(lib->hCodMgr));
++ DBC_Require(pstrSect != NULL);
++ DBC_Require(puAddr != NULL);
++ DBC_Require(puLen != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER,
++ "Entered COD_GetSection Args \t\n lib: "
++ "0x%x\t\npstrsect: 0x%x\t\npuAddr: 0x%x\t\npuLen: 0x%x\n",
++ lib, pstrSect, puAddr, puLen);
++ *puAddr = 0;
++ *puLen = 0;
++ if (lib != NULL) {
++ hManager = lib->hCodMgr;
++ status = hManager->fxns.getSectFxn(lib->dbllLib, pstrSect,
++ puAddr, puLen);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSection: Section %s not"
++ "found\n", pstrSect);
++ }
++ } else {
++ status = COD_E_NOSYMBOLSLOADED;
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSection:No Symbols loaded\n");
++ }
++
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((*puAddr == 0) && (*puLen == 0)));
++
++ return status;
++}
++
++/*
++ * ======== COD_GetSymValue ========
++ * Purpose:
++ * Retrieve the value for the specified symbol. The symbol is first
++ * searched for literally and then, if not found, searched for as a
++ * C symbol.
++ *
++ */
++DSP_STATUS COD_GetSymValue(struct COD_MANAGER *hMgr, char *pstrSym,
++ u32 *pulValue)
++{
++ struct DBLL_Symbol *pSym;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pstrSym != NULL);
++ DBC_Require(pulValue != NULL);
++
++ GT_3trace(COD_debugMask, GT_ENTER, "Entered COD_GetSymValue Args \t\n"
++ "hMgr: 0x%x\t\npstrSym: 0x%x\t\npulValue: 0x%x\n",
++ hMgr, pstrSym, pulValue);
++ if (hMgr->baseLib) {
++ if (!hMgr->fxns.getAddrFxn(hMgr->baseLib, pstrSym, &pSym)) {
++ if (!hMgr->fxns.getCAddrFxn(hMgr->baseLib, pstrSym,
++ &pSym)) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_GetSymValue: "
++ "Symbols not found\n");
++ return COD_E_SYMBOLNOTFOUND;
++ }
++ }
++ } else {
++ GT_0trace(COD_debugMask, GT_7CLASS, "COD_GetSymValue: "
++ "No Symbols loaded\n");
++ return COD_E_NOSYMBOLSLOADED;
++ }
++
++ *pulValue = pSym->value;
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== COD_Init ========
++ * Purpose:
++ * Initialize the COD module's private state.
++ *
++ */
++bool COD_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!COD_debugMask.flags);
++ GT_create(&COD_debugMask, "CO");
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++
++ GT_1trace(COD_debugMask, GT_1CLASS,
++ "Entered COD_Init, ref count: 0x%x\n", cRefs);
++ DBC_Ensure((fRetVal && cRefs > 0) || (!fRetVal && cRefs >= 0));
++ return fRetVal;
++}
++
++/*
++ * ======== COD_LoadBase ========
++ * Purpose:
++ * Load the initial program image, optionally with command-line arguments,
++ * on the DSP system managed by the supplied handle. The program to be
++ * loaded must be the first element of the args array and must be a fully
++ * qualified pathname.
++ * Details:
++ * if nArgc doesn't match the number of arguments in the aArgs array, the
++ * aArgs array is searched for a NULL terminating entry, and argc is
++ * recalculated to reflect this. In this way, we can support NULL
++ * terminating aArgs arrays, if nArgc is very large.
++ */
++DSP_STATUS COD_LoadBase(struct COD_MANAGER *hMgr, u32 nArgc, char *aArgs[],
++ COD_WRITEFXN pfnWrite, void *pArb, char *envp[])
++{
++ DBLL_Flags flags;
++ struct DBLL_Attrs saveAttrs;
++ struct DBLL_Attrs newAttrs;
++ DSP_STATUS status;
++ u32 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(nArgc > 0);
++ DBC_Require(aArgs != NULL);
++ DBC_Require(aArgs[0] != NULL);
++ DBC_Require(pfnWrite != NULL);
++ DBC_Require(hMgr->baseLib != NULL);
++
++ GT_6trace(COD_debugMask, GT_ENTER,
++ "Entered COD_LoadBase, hMgr: 0x%x\n \t"
++ "nArgc: 0x%x\n\taArgs: 0x%x\n\tpfnWrite: 0x%x\n\tpArb:"
++ " 0x%x\n \tenvp: 0x%x\n", hMgr, nArgc, aArgs, pfnWrite,
++ pArb, envp);
++ /*
++ * Make sure every argv[] stated in argc has a value, or change argc to
++ * reflect true number in NULL terminated argv array.
++ */
++ for (i = 0; i < nArgc; i++) {
++ if (aArgs[i] == NULL) {
++ nArgc = i;
++ break;
++ }
++ }
++
++ /* set the write function for this operation */
++ hMgr->fxns.getAttrsFxn(hMgr->target, &saveAttrs);
++
++ newAttrs = saveAttrs;
++ newAttrs.write = (DBLL_WriteFxn)pfnWrite;
++ newAttrs.wHandle = pArb;
++ newAttrs.alloc = (DBLL_AllocFxn)NoOp;
++ newAttrs.free = (DBLL_FreeFxn)NoOp;
++ newAttrs.logWrite = NULL;
++ newAttrs.logWriteHandle = NULL;
++
++ /* Load the image */
++ flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
++ status = hMgr->fxns.loadFxn(hMgr->baseLib, flags, &newAttrs,
++ &hMgr->ulEntry);
++ if (DSP_FAILED(status)) {
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_LoadBase: COD Load failed: "
++ "0x%x\n", status);
++ }
++ if (DSP_SUCCEEDED(status))
++ hMgr->fLoaded = true;
++ else
++ hMgr->baseLib = NULL;
++
++ return status;
++}
++
++/*
++ * ======== COD_Open ========
++ * Open library for reading sections.
++ */
++DSP_STATUS COD_Open(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ COD_FLAGS flags, struct COD_LIBRARYOBJ **pLib)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct COD_LIBRARYOBJ *lib = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pszCoffPath != NULL);
++ DBC_Require(flags == COD_NOLOAD || flags == COD_SYMB);
++ DBC_Require(pLib != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_Open, hMgr: 0x%x\n\t "
++ "pszCoffPath: 0x%x\tflags: 0x%x\tlib: 0x%x\n", hMgr,
++ pszCoffPath, flags, pLib);
++
++ *pLib = NULL;
++
++ lib = MEM_Calloc(sizeof(struct COD_LIBRARYOBJ), MEM_NONPAGED);
++ if (lib == NULL) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_Open: Out Of Memory\n");
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ lib->hCodMgr = hMgr;
++ status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags,
++ &lib->dbllLib);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_Open failed: 0x%x\n", status);
++ } else {
++ *pLib = lib;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== COD_OpenBase ========
++ * Purpose:
++ * Open base image for reading sections.
++ */
++DSP_STATUS COD_OpenBase(struct COD_MANAGER *hMgr, IN char *pszCoffPath,
++ DBLL_Flags flags)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValid(hMgr));
++ DBC_Require(pszCoffPath != NULL);
++
++ GT_2trace(COD_debugMask, GT_ENTER,
++ "Entered COD_OpenBase, hMgr: 0x%x\n\t"
++ "pszCoffPath: 0x%x\n", hMgr, pszCoffPath);
++
++ /* if we previously opened a base image, close it now */
++ if (hMgr->baseLib) {
++ if (hMgr->fLoaded) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "Base Image is already loaded. "
++ "Unloading it...\n");
++ hMgr->fxns.unloadFxn(hMgr->baseLib, &hMgr->attrs);
++ hMgr->fLoaded = false;
++ }
++ hMgr->fxns.closeFxn(hMgr->baseLib);
++ hMgr->baseLib = NULL;
++ } else {
++ GT_0trace(COD_debugMask, GT_1CLASS,
++ "COD_OpenBase: Opening the base image ...\n");
++ }
++ status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags, &lib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_OpenBase: COD Open failed\n");
++ } else {
++ /* hang onto the library for subsequent sym table usage */
++ hMgr->baseLib = lib;
++ strncpy(hMgr->szZLFile, pszCoffPath, COD_MAXPATHLENGTH);
++ }
++
++ return status;
++}
++
++/*
++ * ======== COD_ReadSection ========
++ * Purpose:
++ * Retrieve the content of a code section given the section name.
++ */
++DSP_STATUS COD_ReadSection(struct COD_LIBRARYOBJ *lib, IN char *pstrSect,
++ OUT char *pstrContent, IN u32 cContentSize)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(lib != NULL);
++ DBC_Require(IsValid(lib->hCodMgr));
++ DBC_Require(pstrSect != NULL);
++ DBC_Require(pstrContent != NULL);
++
++ GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_ReadSection Args: 0x%x,"
++ " 0x%x, 0x%x, 0x%x\n", lib, pstrSect, pstrContent,
++ cContentSize);
++
++ if (lib != NULL) {
++ status = lib->hCodMgr->fxns.readSectFxn(lib->dbllLib, pstrSect,
++ pstrContent,
++ cContentSize);
++ if (DSP_FAILED(status)) {
++ GT_1trace(COD_debugMask, GT_7CLASS,
++ "COD_ReadSection failed: 0x%lx\n", status);
++ }
++ } else {
++ status = COD_E_NOSYMBOLSLOADED;
++ GT_0trace(COD_debugMask, GT_7CLASS,
++ "COD_ReadSection: No Symbols loaded\n");
++ }
++ return status;
++}
++
++/*
++ * ======== NoOp ========
++ * Purpose:
++ * No Operation.
++ *
++ */
++static bool NoOp(void)
++{
++ return true;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dbl.c b/drivers/dsp/bridge/pmgr/dbl.c
+new file mode 100644
+index 0000000..641b011
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dbl.c
+@@ -0,0 +1,1385 @@
++/*
++ * dbl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbl.c ========
++ * Dynamic BOF Loader library. Contains functions related to
++ * loading and unloading symbols/code/data on DSP.
++ * Also contains other support functions.
++ *
++ *! Revision History
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 24-May-2002 jeh Free DCD sects in DBL_close().
++ *! 19-Mar-2002 jeh Changes made to match dynamic loader (dbll.c): Pass
++ *! DBL_Library to DBL_getAddr() instead of DBL_Target,
++ *! eliminate scope param, use DBL_Symbol. Pass attrs to
++ *! DBL_load(), DBL_unload().
++ *! 20-Nov-2001 jeh Removed DBL_loadArgs().
++ *! 07-Sep-2001 jeh Added overlay support.
++ *! 31-Jul-2001 jeh Include windows.h.
++ *! 06-Jun-2001 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/kfile.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbof.h>
++#include <dspbridge/dbl.h>
++
++#define DBL_TARGSIGNATURE 0x544c4244 /* "TLBD" */
++#define DBL_LIBSIGNATURE 0x4c4c4244 /* "LLBD" */
++
++#define C54TARG 0
++#define C55TARG 1
++#define NUMTARGS 2
++
++#define C54MAGIC 0x98 /* Magic number for TI C54 COF */
++#define C55MAGIC 0x9c /* Magic number for LEAD3 (C55) COF */
++
++/* Three task phases */
++#define CREATEPHASE 0
++#define DELETEPHASE 1
++#define EXECUTEPHASE 2
++#define NONE 3 /* For overlay section with phase not specified */
++
++/* Default load buffer size */
++#define LOADBUFSIZE 0x800
++
++#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
++ (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
++
++#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
++
++/*
++ * Macros for accessing the following types of overlay data within a
++ * structure of type OvlyData:
++ * - Overlay data not associated with a particular phase
++ * - Create phase overlay data
++ * - Delete phase overlay data
++ * - Execute phase overlay data
++ */
++#define numOtherSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numOtherSects)
++#define numCreateSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numCreateSects)
++#define numDeleteSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numDeleteSects)
++#define numExecuteSects(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numExecuteSects)
++#define otherOffset(pOvlyData) 0
++#define createOffset(pOvlyData) ((pOvlyData)->hdr.dbofHdr.numOtherSects)
++#define deleteOffset(pOvlyData) (createOffset(pOvlyData) + \
++ (pOvlyData->hdr.dbofHdr.numCreateSects))
++#define executeOffset(pOvlyData) (deleteOffset(pOvlyData) + \
++ (pOvlyData->hdr.dbofHdr.numDeleteSects))
++/*
++ * ======== OvlyHdr ========
++ */
++struct OvlyHdr {
++ struct DBOF_OvlySectHdr dbofHdr;
++ char *pName; /* Name of overlay section */
++ u16 createRef; /* Reference count for create phase */
++ u16 deleteRef; /* Reference count for delete phase */
++ u16 executeRef; /* Execute phase ref count */
++ u16 otherRef; /* Unspecified phase ref count */
++} ;
++
++/*
++ * ======== OvlyData ========
++ */
++struct OvlyData {
++ struct OvlyHdr hdr;
++ struct DBOF_OvlySectData data[1];
++} ;
++
++/*
++ * ======== Symbol ========
++ */
++struct Symbol {
++ struct DBL_Symbol sym;
++ char *pSymName;
++};
++
++/*
++ * ======== DCDSect ========
++ */
++struct DCDSect {
++ struct DBOF_DCDSectHdr sectHdr;
++ char *pData;
++} ;
++
++/*
++ * ======== DBL_TargetObj ========
++ */
++struct DBL_TargetObj {
++ u32 dwSignature; /* For object validation */
++ struct DBL_Attrs dblAttrs; /* file read, write, etc. functions */
++ char *pBuf; /* Load buffer */
++};
++
++/*
++ * ======== TargetInfo ========
++ */
++struct TargetInfo {
++ u16 dspType; /* eg, C54TARG, C55TARG */
++ u32 magic; /* COFF magic number, identifies target type */
++ u16 wordSize; /* Size of a DSP word */
++ u16 mauSize; /* Size of minimum addressable unit */
++ u16 charSize; /* For C55x, mausize = 1, but charsize = 2 */
++} ;
++
++/*
++ * ======== DBL_LibraryObj ========
++ * Represents a library loaded on a target.
++ */
++struct DBL_LibraryObj {
++ u32 dwSignature; /* For object validation */
++ struct DBL_TargetObj *pTarget; /* Target for this library */
++ struct KFILE_FileObj *file; /* DBOF file handle */
++ bool byteSwapped; /* Are bytes swapped? */
++ struct DBOF_FileHdr fileHdr; /* Header of DBOF file */
++ u16 nSymbols; /* Number of DSP/Bridge symbols */
++ struct Symbol *symbols; /* Table of DSP/Bridge symbols */
++ u16 nDCDSects; /* Number of DCD sections */
++ u16 nOvlySects; /* Number of overlay nodes */
++ struct DCDSect *dcdSects; /* DCD section data */
++ struct OvlyData **ppOvlyData; /* Array of overlay section data */
++ struct TargetInfo *pTargetInfo; /* Entry in targetTab[] below */
++} ;
++
++#if GT_TRACE
++static struct GT_Mask DBL_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static u32 magicTab[NUMTARGS] = { C54MAGIC, C55MAGIC };
++
++static struct TargetInfo targetTab[] = {
++ /* targ magic wordsize mausize charsize */
++ {C54TARG, C54MAGIC, 2, 2, 2}, /* C54 */
++ {C55TARG, C55MAGIC, 2, 1, 2}, /* C55 */
++};
++
++static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
++ s32 offset, s32 nSects);
++static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib);
++
++/*
++ * ======== DBL_close ========
++ * Purpose:
++ * Close library opened with DBL_open.
++ */
++void DBL_close(struct DBL_LibraryObj *lib)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER, "DBL_close: lib: 0x%x\n", lib);
++
++ /* Free symbols */
++ if (pdblLib->symbols) {
++ for (i = 0; i < pdblLib->nSymbols; i++) {
++ if (pdblLib->symbols[i].pSymName)
++ MEM_Free(pdblLib->symbols[i].pSymName);
++
++ }
++ MEM_Free(pdblLib->symbols);
++ }
++
++ /* Free DCD sects */
++ if (pdblLib->dcdSects) {
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (pdblLib->dcdSects[i].pData)
++ MEM_Free(pdblLib->dcdSects[i].pData);
++
++ }
++ MEM_Free(pdblLib->dcdSects);
++ }
++
++ /* Free overlay sects */
++ if (pdblLib->ppOvlyData) {
++ for (i = 0; i < pdblLib->nOvlySects; i++) {
++ if (pdblLib->ppOvlyData[i]) {
++ if (pdblLib->ppOvlyData[i]->hdr.pName) {
++ MEM_Free(pdblLib->ppOvlyData[i]->
++ hdr.pName);
++ }
++ MEM_Free(pdblLib->ppOvlyData[i]);
++ }
++ }
++ MEM_Free(pdblLib->ppOvlyData);
++ }
++
++ /* Close the file */
++ if (pdblLib->file)
++ (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
++
++
++ MEM_FreeObject(pdblLib);
++}
++
++/*
++ * ======== DBL_create ========
++ * Purpose:
++ * Create a target object by specifying the alloc, free, and
++ * write functions for the target.
++ */
++DSP_STATUS DBL_create(struct DBL_TargetObj **pTarget, struct DBL_Attrs *pAttrs)
++{
++ struct DBL_TargetObj *pdblTarget = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pTarget != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_create: pTarget: 0x%x pAttrs: 0x%x\n",
++ pTarget, pAttrs);
++ /* Allocate DBL target object */
++ MEM_AllocObject(pdblTarget, struct DBL_TargetObj, DBL_TARGSIGNATURE);
++ if (pdblTarget == NULL) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ pdblTarget->dblAttrs = *pAttrs;
++ /* Allocate buffer for loading target */
++ pdblTarget->pBuf = MEM_Calloc(LOADBUFSIZE, MEM_PAGED);
++ if (pdblTarget->pBuf == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *pTarget = pdblTarget;
++ } else {
++ *pTarget = NULL;
++ if (pdblTarget)
++ DBL_delete(pdblTarget);
++
++ }
++ DBC_Ensure(DSP_SUCCEEDED(status) &&
++ ((MEM_IsValidHandle((*pTarget), DBL_TARGSIGNATURE)) ||
++ (DSP_FAILED(status) && *pTarget == NULL)));
++ return status;
++}
++
++/*
++ * ======== DBL_delete ========
++ * Purpose:
++ * Delete target object and free resources for any loaded libraries.
++ */
++void DBL_delete(struct DBL_TargetObj *target)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "DBL_delete: target: 0x%x\n", target);
++
++ if (target->pBuf)
++ MEM_Free(target->pBuf);
++
++ MEM_FreeObject(target);
++}
++
++/*
++ * ======== DBL_exit ========
++ * Purpose
++ * Discontinue usage of DBL module.
++ */
++void DBL_exit()
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ GT_1trace(DBL_debugMask, GT_5CLASS,
++ "DBL_exit() ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DBL_getAddr ========
++ * Purpose:
++ * Get address of name in the specified library.
++ */
++bool DBL_getAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym)
++{
++ bool retVal = false;
++ struct Symbol *symbol;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_getAddr: libt: 0x%x name: %s pAddr: "
++ "0x%x\n", lib, name, ppSym);
++ for (i = 0; i < lib->nSymbols; i++) {
++ symbol = &lib->symbols[i];
++ if (CSL_Strcmp(name, symbol->pSymName) == 0) {
++ /* Found it */
++ *ppSym = &lib->symbols[i].sym;
++ retVal = true;
++ break;
++ }
++ }
++ return retVal;
++}
++
++/*
++ * ======== DBL_getAttrs ========
++ * Purpose:
++ * Retrieve the attributes of the target.
++ */
++void DBL_getAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++ GT_2trace(DBL_debugMask, GT_ENTER, "DBL_getAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++ *pAttrs = target->dblAttrs;
++}
++
++/*
++ * ======== DBL_getCAddr ========
++ * Purpose:
++ * Get address of "C" name in the specified library.
++ */
++bool DBL_getCAddr(struct DBL_LibraryObj *lib, char *name,
++ struct DBL_Symbol **ppSym)
++{
++ bool retVal = false;
++ struct Symbol *symbol;
++ u16 i;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_getCAddr: target: 0x%x name:%s pAddr:"
++ " 0x%x\n", lib, name, ppSym);
++ for (i = 0; i < lib->nSymbols; i++) {
++ symbol = &lib->symbols[i];
++ if ((CSL_Strcmp(name, symbol->pSymName) == 0) ||
++ (CSL_Strcmp(name, symbol->pSymName + 1) == 0 &&
++ symbol->pSymName[0] == '_')) {
++ /* Found it */
++ *ppSym = &lib->symbols[i].sym;
++ retVal = true;
++ break;
++ }
++ }
++ return retVal;
++}
++
++/*
++ * ======== DBL_getEntry ========
++ * Purpose:
++ * Get program entry point.
++ *
++ */
++bool DBL_getEntry(struct DBL_LibraryObj *lib, u32 *pEntry)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_getEntry: lib: 0x%x pEntry: 0x%x\n", lib, pEntry);
++ *pEntry = pdblLib->fileHdr.entry;
++
++ return true;
++}
++
++/*
++ * ======== DBL_getSect ========
++ * Purpose:
++ * Get address and size of a named section.
++ */
++DSP_STATUS DBL_getSect(struct DBL_LibraryObj *lib, char *name, u32 *pAddr,
++ u32 *pSize)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(name != NULL);
++ DBC_Require(pAddr != NULL);
++ DBC_Require(pSize != NULL);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++
++ GT_4trace(DBL_debugMask, GT_ENTER,
++ "DBL_getSect: lib: 0x%x name: %s pAddr:"
++ " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
++
++ /*
++ * Check for DCD and overlay sections. Overlay loader uses DBL_getSect
++ * to determine whether or not a node has overlay sections.
++ * DCD section names begin with '.'
++ */
++ if (name[0] == '.') {
++ /* Get DCD section size (address is 0, since it's a NOLOAD). */
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name,
++ name) == 0) {
++ *pAddr = 0;
++ *pSize = pdblLib->dcdSects[i].sectHdr.size *
++ pdblLib->pTargetInfo->mauSize;
++ status = DSP_SOK;
++ break;
++ }
++ }
++ } else {
++ /* Check for overlay section */
++ for (i = 0; i < pdblLib->nOvlySects; i++) {
++ if (CSL_Strcmp(pdblLib->ppOvlyData[i]->hdr.pName,
++ name) == 0) {
++ /* Address and size are meaningless */
++ *pAddr = 0;
++ *pSize = 0;
++ status = DSP_SOK;
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBL_init ========
++ * Purpose:
++ * Initialize DBL module.
++ */
++bool DBL_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DBL_debugMask.flags);
++ GT_create(&DBL_debugMask, "BL"); /* "BL" for dBL */
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++
++ GT_1trace(DBL_debugMask, GT_5CLASS, "DBL_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== DBL_load ========
++ * Purpose:
++ * Add symbols/code/data defined in file to that already present
++ * on the target.
++ */
++DSP_STATUS DBL_load(struct DBL_LibraryObj *lib, DBL_Flags flags,
++ struct DBL_Attrs *attrs, u32 *pEntry)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ struct DBL_TargetObj *dbl;
++ u16 i;
++ u16 nSects;
++ DSP_STATUS status = DSP_EFAIL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++ DBC_Require(attrs != NULL);
++
++ GT_4trace(DBL_debugMask, GT_ENTER, "DBL_load: lib: 0x%x flags: "
++ "0x%x attrs: 0x%x pEntry: 0x%x\n", lib, flags, attrs, pEntry);
++
++ dbl = pdblLib->pTarget;
++ *pEntry = pdblLib->fileHdr.entry;
++ nSects = pdblLib->fileHdr.numSects;
++ dbl->dblAttrs = *attrs;
++
++ for (i = 0; i < nSects; i++) {
++ /* Load the section at the current file offset */
++ status = loadSect(dbl, lib);
++ if (DSP_FAILED(status))
++ break;
++
++ }
++
++ /* Done with file, we can close it */
++ if (pdblLib->file) {
++ (*pdblLib->pTarget->dblAttrs.fclose) (pdblLib->file);
++ pdblLib->file = NULL;
++ }
++ return status;
++}
++
++/*
++ * ======== DBL_loadSect ========
++ * Purpose:
++ * Load a named section from an library (for overlay support).
++ */
++DSP_STATUS DBL_loadSect(struct DBL_LibraryObj *lib, char *sectName,
++ struct DBL_Attrs *attrs)
++{
++ struct DBL_TargetObj *dbl;
++ s32 i;
++ s32 phase;
++ s32 offset = -1;
++ s32 nSects = -1;
++ s32 allocdSects = 0;
++ u32 loadAddr;
++ u32 runAddr;
++ u32 size;
++ u32 space;
++ u32 ulBytes;
++ u16 mauSize;
++ u16 wordSize;
++ u16 *phaseRef = NULL;
++ u16 *otherRef = NULL;
++ char *name = NULL;
++ struct OvlyData *pOvlyData;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(sectName != NULL);
++ DBC_Require(attrs != NULL);
++ DBC_Require(attrs->write != NULL);
++ GT_3trace(DBL_debugMask, GT_ENTER,
++ "DBL_loadSect: lib: 0x%x sectName: %s "
++ "attrs: 0x%x\n", lib, sectName, attrs);
++ dbl = lib->pTarget;
++ mauSize = lib->pTargetInfo->mauSize;
++ wordSize = lib->pTargetInfo->wordSize;
++ /* Check for match of sect name in overlay table */
++ for (i = 0; i < lib->nOvlySects; i++) {
++ name = lib->ppOvlyData[i]->hdr.pName;
++ if (!CSL_Strncmp(name, sectName, CSL_Strlen(name))) {
++ /* Match found */
++ status = DSP_SOK;
++ break;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(i < lib->nOvlySects);
++ pOvlyData = lib->ppOvlyData[i];
++ /*
++ * If node overlay, phase will be encoded in name. If not node
++ * overlay, set phase to NONE.
++ */
++ phase = (CSL_Strcmp(name, sectName)) ?
++ CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
++ /* Get reference count of node phase to be loaded, offset into
++ * overlay data array, and number of sections to overlay. */
++ switch (phase) {
++ case NONE:
++ /* Not a node overlay */
++ phaseRef = &pOvlyData->hdr.otherRef;
++ nSects = numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ break;
++ case CREATEPHASE:
++ phaseRef = &pOvlyData->hdr.createRef;
++ otherRef = &pOvlyData->hdr.otherRef;
++ if (*otherRef) {
++ /* The overlay sections where node phase was
++ * not specified, have already been loaded. */
++ nSects = numCreateSects(pOvlyData);
++ offset = createOffset(pOvlyData);
++ } else {
++ /* Overlay sections where node phase was not
++ * specified get loaded at create time, along
++ * with create sects. */
++ nSects = numCreateSects(pOvlyData) +
++ numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ }
++ break;
++ case DELETEPHASE:
++ phaseRef = &pOvlyData->hdr.deleteRef;
++ nSects = numDeleteSects(pOvlyData);
++ offset = deleteOffset(pOvlyData);
++ break;
++ case EXECUTEPHASE:
++ phaseRef = &pOvlyData->hdr.executeRef;
++ nSects = numExecuteSects(pOvlyData);
++ offset = executeOffset(pOvlyData);
++ break;
++ default:
++ /* ERROR */
++ DBC_Assert(false);
++ break;
++ }
++ /* Do overlay if reference count is 0 */
++ if (!(*phaseRef)) {
++ /* "Allocate" all sections */
++ for (i = 0; i < nSects; i++) {
++ runAddr = pOvlyData->data[offset + i].runAddr;
++ size = pOvlyData->data[offset + i].size;
++ space = pOvlyData->data[offset + i].page;
++ status = (dbl->dblAttrs.alloc)(dbl->dblAttrs.
++ rmmHandle, space, size, 0,
++ &runAddr, true);
++ if (DSP_FAILED(status))
++ break;
++
++ allocdSects++;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Load sections */
++ for (i = 0; i < nSects; i++) {
++ loadAddr = pOvlyData->data[offset + i].
++ loadAddr;
++ runAddr = pOvlyData->data[offset + i].
++ runAddr;
++ size = pOvlyData->data[offset + i].
++ size;
++ space = pOvlyData->data[offset + i].
++ page;
++ /* Convert to word address, call
++ * write function */
++ loadAddr /= (wordSize / mauSize);
++ runAddr /= (wordSize / mauSize);
++ ulBytes = size * mauSize;
++ if ((*attrs->write)(attrs->wHandle,
++ runAddr, (void *)loadAddr, ulBytes,
++ space) != ulBytes) {
++ GT_0trace(DBL_debugMask,
++ GT_6CLASS,
++ "DBL_loadSect: write"
++ " failed\n");
++ status = DSP_EFWRITE;
++ break;
++ }
++ }
++ }
++ /* Free sections on failure */
++ if (DSP_FAILED(status))
++ freeSects(dbl, pOvlyData, offset, allocdSects);
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Increment reference counts */
++ if (otherRef)
++ *otherRef = *otherRef + 1;
++
++ *phaseRef = *phaseRef + 1;
++ }
++ return status;
++}
++
++/*
++ * ======== DBL_open ========
++ * Purpose:
++ * DBL_open() returns a library handle that can be used to
++ * load/unload the symbols/code/data via DBL_load()/DBL_unload().
++ */
++DSP_STATUS DBL_open(struct DBL_TargetObj *target, char *file, DBL_Flags flags,
++ struct DBL_LibraryObj **pLib)
++{
++ struct DBL_LibraryObj *pdblLib = NULL;
++ u16 nSymbols;
++ u16 nDCDSects;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(target->dblAttrs.fopen != NULL);
++ DBC_Require(file != NULL);
++ DBC_Require(pLib != NULL);
++
++ GT_3trace(DBL_debugMask, GT_ENTER, "DBL_open: target: 0x%x file: %s "
++ "pLib: 0x%x\n", target, file, pLib);
++ /* Allocate DBL library object */
++ MEM_AllocObject(pdblLib, struct DBL_LibraryObj, DBL_LIBSIGNATURE);
++ if (pdblLib == NULL)
++ status = DSP_EMEMORY;
++
++ /* Open the file */
++ if (DSP_SUCCEEDED(status)) {
++ pdblLib->pTarget = target;
++ pdblLib->file = (*target->dblAttrs.fopen)(file, "rb");
++ if (pdblLib->file == NULL)
++ status = DSP_EFOPEN;
++
++ }
++ /* Read file header */
++ if (DSP_SUCCEEDED(status)) {
++ status = readHeader(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read file header\n");
++ }
++ }
++ /* Allocate symbol table */
++ if (DSP_SUCCEEDED(status)) {
++ nSymbols = pdblLib->nSymbols = pdblLib->fileHdr.numSymbols;
++ pdblLib->symbols = MEM_Calloc(nSymbols * sizeof(struct Symbol),
++ MEM_PAGED);
++ if (pdblLib->symbols == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /* Read all the symbols */
++ if (DSP_SUCCEEDED(status)) {
++ status = readSymbols(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read symbols\n");
++ }
++ }
++ /* Allocate DCD sect table */
++ if (DSP_SUCCEEDED(status)) {
++ nDCDSects = pdblLib->nDCDSects = pdblLib->fileHdr.numDCDSects;
++ pdblLib->dcdSects = MEM_Calloc(nDCDSects *
++ sizeof(struct DCDSect), MEM_PAGED);
++ if (pdblLib->dcdSects == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /* Read DCD sections */
++ if (DSP_SUCCEEDED(status)) {
++ status = readDCDSects(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read DCD sections\n");
++ }
++ }
++ /* Read overlay sections */
++ if (DSP_SUCCEEDED(status)) {
++ status = readOvlySects(target, pdblLib);
++ if (DSP_FAILED(status)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "DBL_open(): Failed to read "
++ "overlay sections\n");
++ }
++ }
++ if (DSP_FAILED(status)) {
++ *pLib = NULL;
++ if (pdblLib != NULL)
++ DBL_close((struct DBL_LibraryObj *) pdblLib);
++
++ } else {
++ *pLib = pdblLib;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ (MEM_IsValidHandle((*pLib), DBL_LIBSIGNATURE))) ||
++ (DSP_FAILED(status) && *pLib == NULL));
++ return status;
++}
++
++/*
++ * ======== DBL_readSect ========
++ * Purpose:
++ * Read COFF section into a character buffer.
++ */
++DSP_STATUS DBL_readSect(struct DBL_LibraryObj *lib, char *name, char *pContent,
++ u32 size)
++{
++ struct DBL_LibraryObj *pdblLib = (struct DBL_LibraryObj *)lib;
++ u16 i;
++ u32 mauSize;
++ u32 max;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pdblLib, DBL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(pContent != NULL);
++ DBC_Require(size != 0);
++ GT_4trace(DBL_debugMask, GT_ENTER, "DBL_readSect: lib: 0x%x name: %s "
++ "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
++
++ mauSize = pdblLib->pTargetInfo->mauSize;
++
++ /* Attempt to find match with DCD section names. */
++ for (i = 0; i < pdblLib->nDCDSects; i++) {
++ if (CSL_Strcmp(pdblLib->dcdSects[i].sectHdr.name, name) == 0) {
++ /* Match found */
++ max = pdblLib->dcdSects[i].sectHdr.size * mauSize;
++ max = (max > size) ? size : max;
++ memcpy(pContent, pdblLib->dcdSects[i].pData, max);
++ status = DSP_SOK;
++ break;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBL_setAttrs ========
++ * Purpose:
++ * Set the attributes of the target.
++ */
++void DBL_setAttrs(struct DBL_TargetObj *target, struct DBL_Attrs *pAttrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(target, DBL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER, "DBL_setAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++
++ target->dblAttrs = *pAttrs;
++}
++
++/*
++ * ======== DBL_unload ========
++ * Purpose:
++ * Remove the symbols/code/data corresponding to the library lib.
++ */
++void DBL_unload(struct DBL_LibraryObj *lib, struct DBL_Attrs *attrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++
++ GT_1trace(DBL_debugMask, GT_ENTER, "DBL_unload: lib: 0x%x\n", lib);
++
++ /* Nothing to do for static loading */
++}
++
++/*
++ * ======== DBL_unloadSect ========
++ * Purpose:
++ * Unload a named section from an library (for overlay support).
++ */
++DSP_STATUS DBL_unloadSect(struct DBL_LibraryObj *lib, char *sectName,
++ struct DBL_Attrs *attrs)
++{
++ struct DBL_TargetObj *dbl;
++ s32 i;
++ s32 phase;
++ s32 offset = -1;
++ s32 nSects = -1;
++ u16 *phaseRef = NULL;
++ u16 *otherRef = NULL;
++ char *pName = NULL;
++ struct OvlyData *pOvlyData;
++ DSP_STATUS status = DSP_ENOSECT;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(lib, DBL_LIBSIGNATURE));
++ DBC_Require(sectName != NULL);
++
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "DBL_unloadSect: lib: 0x%x sectName: %s\n", lib, sectName);
++ dbl = lib->pTarget;
++ /* Check for match of sect name in overlay table */
++ for (i = 0; i < lib->nOvlySects; i++) {
++ pName = lib->ppOvlyData[i]->hdr.pName;
++ if (!CSL_Strncmp(pName, sectName, CSL_Strlen(pName))) {
++ /* Match found */
++ status = DSP_SOK;
++ break;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(i < lib->nOvlySects);
++ pOvlyData = lib->ppOvlyData[i];
++ /* If node overlay, phase will be encoded in name. */
++ phase = (CSL_Strcmp(pName, sectName)) ?
++ CSL_Atoi(sectName + CSL_Strlen(sectName) - 1) : NONE;
++ switch (phase) {
++ case NONE:
++ nSects = numOtherSects(pOvlyData);
++ phaseRef = &pOvlyData->hdr.otherRef;
++ offset = otherOffset(pOvlyData);
++ break;
++ case CREATEPHASE:
++ nSects = numCreateSects(pOvlyData);
++ offset = createOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.createRef;
++ break;
++ case DELETEPHASE:
++ nSects = numDeleteSects(pOvlyData);
++ offset = deleteOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.deleteRef;
++ otherRef = &pOvlyData->hdr.otherRef;
++ break;
++ case EXECUTEPHASE:
++ nSects = numExecuteSects(pOvlyData);
++ offset = executeOffset(pOvlyData);
++ phaseRef = &pOvlyData->hdr.executeRef;
++ break;
++ default:
++ /* ERROR */
++ DBC_Assert(false);
++ break;
++ }
++ if (*phaseRef) {
++ *phaseRef = *phaseRef - 1;
++ if (*phaseRef == 0) {
++ /* Unload overlay sections for phase */
++ freeSects(dbl, pOvlyData, offset, nSects);
++ }
++ if (phase == DELETEPHASE) {
++ DBC_Assert(*otherRef);
++ *otherRef = *otherRef - 1;
++ if (*otherRef == 0) {
++ /* Unload other overlay sections */
++ nSects = numOtherSects(pOvlyData);
++ offset = otherOffset(pOvlyData);
++ freeSects(dbl, pOvlyData, offset,
++ nSects);
++ }
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== freeSects ========
++ * Purpose:
++ * Free section
++ */
++static void freeSects(struct DBL_TargetObj *dbl, struct OvlyData *pOvlyData,
++ s32 offset, s32 nSects)
++{
++ u32 runAddr;
++ u32 size;
++ u32 space;
++ s32 i;
++
++ for (i = 0; i < nSects; i++) {
++ runAddr = pOvlyData->data[offset + i].runAddr;
++ size = pOvlyData->data[offset + i].size;
++ space = pOvlyData->data[offset + i].page;
++ if (!(dbl->dblAttrs.free)
++ (dbl->dblAttrs.rmmHandle, space, runAddr, size, true)) {
++ /*
++ * Free function will not fail for overlay, unless
++ * address passed in is bad.
++ */
++ DBC_Assert(false);
++ }
++ }
++}
++
++/*
++ * ======== loadSect ========
++ * Purpose:
++ * Load section to target
++ */
++static DSP_STATUS loadSect(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_SectHdr sectHdr;
++ char *pBuf;
++ struct KFILE_FileObj *file;
++ u32 space;
++ u32 addr;
++ u32 total;
++ u32 nWords = 0;
++ u32 nBytes = 0;
++ u16 mauSize;
++ u32 bufSize;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++ mauSize = pdblLib->pTargetInfo->mauSize;
++ bufSize = LOADBUFSIZE / mauSize;
++ pBuf = dbl->pBuf;
++
++ /* Read the section header */
++ if ((*dbl->dblAttrs.fread)(&sectHdr, sizeof(struct DBOF_SectHdr),
++ 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ } else {
++ if (pdblLib->byteSwapped) {
++ sectHdr.size = SWAPLONG(sectHdr.size);
++ sectHdr.addr = SWAPLONG(sectHdr.addr);
++ sectHdr.page = SWAPWORD(sectHdr.page);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ addr = sectHdr.addr;
++ space = sectHdr.page;
++ for (total = sectHdr.size; total > 0; total -= nWords) {
++ nWords = min(total, bufSize);
++ nBytes = nWords * mauSize;
++ /* Read section data */
++ if ((*dbl->dblAttrs.fread)(pBuf, nBytes, 1,
++ file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Write section to target */
++ if (!(*dbl->dblAttrs.write)(dbl->dblAttrs.wHandle,
++ addr, pBuf, nBytes, space)) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to write section data\n");
++ status = DSP_EFWRITE;
++ break;
++ }
++ addr += nWords;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readDCDSects ========
++ * Purpose:
++ * Read DCD sections.
++ */
++static DSP_STATUS readDCDSects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_DCDSectHdr *pSectHdr;
++ struct DCDSect *pSect;
++ struct KFILE_FileObj *file;
++ u16 nSects;
++ u16 i;
++ u16 mauSize;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++ mauSize = pdblLib->pTargetInfo->mauSize;
++ nSects = pdblLib->fileHdr.numDCDSects;
++ for (i = 0; i < nSects; i++) {
++ pSect = &pdblLib->dcdSects[i];
++ pSectHdr = &pdblLib->dcdSects[i].sectHdr;
++ /* Read sect header */
++ if ((*dbl->dblAttrs.fread)(pSectHdr,
++ sizeof(struct DBOF_DCDSectHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped)
++ pSectHdr->size = SWAPLONG(pSectHdr->size);
++
++ pSect->pData = (char *)MEM_Calloc(pSectHdr->size *
++ mauSize, MEM_PAGED);
++ if (pSect->pData == NULL) {
++ GT_2trace(DBL_debugMask, GT_6CLASS,
++ "Memory allocation for sect %s "
++ "data failed: Size: 0x%lx\n", pSectHdr->name,
++ pSectHdr->size);
++ status = DSP_EMEMORY;
++ break;
++ }
++ /* Read DCD sect data */
++ if ((*dbl->dblAttrs.fread)(pSect->pData, mauSize,
++ pSectHdr->size, file) != pSectHdr->size) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read DCD sect data\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== readHeader ========
++ * Purpose:
++ * Read Header.
++ */
++static DSP_STATUS readHeader(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct KFILE_FileObj *file;
++ s32 i;
++ struct DBOF_FileHdr *pHdr;
++ u32 swapMagic;
++ DSP_STATUS status = DSP_SOK;
++
++ pdblLib->byteSwapped = false;
++ file = pdblLib->file;
++ pHdr = &pdblLib->fileHdr;
++ if ((*dbl->dblAttrs.fread)(pHdr, sizeof(struct DBOF_FileHdr), 1,
++ file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "readHeader: Failed to read file header\n");
++ status = DSP_EFREAD;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Determine if byte swapped */
++ for (i = 0; i < NUMTARGS; i++) {
++ swapMagic = SWAPLONG(pHdr->magic);
++ if (pHdr->magic == magicTab[i] || swapMagic ==
++ magicTab[i]) {
++ if (swapMagic == magicTab[i]) {
++ pdblLib->byteSwapped = true;
++ pHdr->magic = SWAPLONG(pHdr->magic);
++ pHdr->entry = SWAPLONG(pHdr->entry);
++ pHdr->symOffset = SWAPLONG(pHdr->
++ symOffset);
++ pHdr->dcdSectOffset = SWAPLONG(pHdr->
++ dcdSectOffset);
++ pHdr->loadSectOffset = SWAPLONG(pHdr->
++ loadSectOffset);
++ pHdr->ovlySectOffset = SWAPLONG(pHdr->
++ ovlySectOffset);
++ pHdr->numSymbols = SWAPWORD(pHdr->
++ numSymbols);
++ pHdr->numDCDSects = SWAPWORD(pHdr->
++ numDCDSects);
++ pHdr->numSects = SWAPWORD(pHdr->
++ numSects);
++ pHdr->numOvlySects = SWAPWORD(pHdr->
++ numOvlySects);
++ }
++ break;
++ }
++ }
++ if (i == NUMTARGS) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "readHeader: Failed to determine"
++ " target type\n");
++ status = DSP_ECORRUPTFILE;
++ } else {
++ pdblLib->pTargetInfo = &targetTab[i];
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "COF type: 0x%lx\n", pHdr->magic);
++ GT_1trace(DBL_debugMask, GT_ENTER,
++ "Entry point:0x%lx\n", pHdr->entry);
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readOvlySects ========
++ * Purpose:
++ * Read Overlay Sections
++ */
++static DSP_STATUS readOvlySects(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_OvlySectHdr hdr;
++ struct DBOF_OvlySectData *pData;
++ struct OvlyData *pOvlyData;
++ char *pName;
++ struct KFILE_FileObj *file;
++ u16 i, j;
++ u16 nSects;
++ u16 n;
++ DSP_STATUS status = DSP_SOK;
++
++ pdblLib->nOvlySects = nSects = pdblLib->fileHdr.numOvlySects;
++ file = pdblLib->file;
++ if (nSects > 0) {
++ pdblLib->ppOvlyData = MEM_Calloc(nSects * sizeof(OvlyData *),
++ MEM_PAGED);
++ if (pdblLib->ppOvlyData == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate overlay "
++ "data memory\n");
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Read overlay data for each node */
++ for (i = 0; i < nSects; i++) {
++ /* Read overlay section header */
++ if ((*dbl->dblAttrs.fread)(&hdr,
++ sizeof(struct DBOF_OvlySectHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read overlay sect"
++ " header\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped) {
++ hdr.nameLen = SWAPWORD(hdr.nameLen);
++ hdr.numCreateSects =
++ SWAPWORD(hdr.numCreateSects);
++ hdr.numDeleteSects =
++ SWAPWORD(hdr.numDeleteSects);
++ hdr.numExecuteSects =
++ SWAPWORD(hdr.numExecuteSects);
++ hdr.numOtherSects =
++ SWAPWORD(hdr.numOtherSects);
++ hdr.resvd = SWAPWORD(hdr.resvd);
++ }
++ n = hdr.numCreateSects + hdr.numDeleteSects +
++ hdr.numExecuteSects + hdr.numOtherSects;
++
++ /* Allocate memory for node's overlay data */
++ pOvlyData = (struct OvlyData *)MEM_Calloc
++ (sizeof(struct OvlyHdr) +
++ n * sizeof(struct DBOF_OvlySectData),
++ MEM_PAGED);
++ if (pOvlyData == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate ovlyay"
++ " data memory\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pOvlyData->hdr.dbofHdr = hdr;
++ pdblLib->ppOvlyData[i] = pOvlyData;
++ /* Allocate memory for section name */
++ pName = (char *)MEM_Calloc(hdr.nameLen + 1, MEM_PAGED);
++ if (pName == NULL) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "Failed to allocatate ovlyay"
++ " section name\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pOvlyData->hdr.pName = pName;
++ /* Read the overlay section name */
++ if ((*dbl->dblAttrs.fread)(pName, sizeof(char),
++ hdr.nameLen, file) != hdr.nameLen) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "readOvlySects: Unable to "
++ "read overlay name.\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Read the overlay section data */
++ pData = pOvlyData->data;
++ if ((*dbl->dblAttrs.fread)(pData,
++ sizeof(struct DBOF_OvlySectData), n, file) != n) {
++ GT_0trace(DBL_debugMask, GT_7CLASS,
++ "readOvlySects: Unable to "
++ "read overlay data.\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ /* Swap overlay data, if necessary */
++ if (pdblLib->byteSwapped) {
++ for (j = 0; j < n; j++) {
++ pData[j].loadAddr =
++ SWAPLONG(pData[j].loadAddr);
++ pData[j].runAddr =
++ SWAPLONG(pData[j].runAddr);
++ pData[j].size =
++ SWAPLONG(pData[j].size);
++ pData[j].page =
++ SWAPWORD(pData[j].page);
++ }
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== readSymbols ========
++ * Purpose:
++ * Read Symbols
++ */
++static DSP_STATUS readSymbols(struct DBL_TargetObj *dbl,
++ struct DBL_LibraryObj *pdblLib)
++{
++ struct DBOF_SymbolHdr symHdr;
++ struct KFILE_FileObj *file;
++ u16 i;
++ u16 nSymbols;
++ u16 len;
++ char *pName = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ file = pdblLib->file;
++
++ nSymbols = pdblLib->fileHdr.numSymbols;
++
++ for (i = 0; i < nSymbols; i++) {
++ /* Read symbol value */
++ if ((*dbl->dblAttrs.fread)(&symHdr,
++ sizeof(struct DBOF_SymbolHdr), 1, file) != 1) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read symbol value\n");
++ status = DSP_EFREAD;
++ break;
++ }
++ if (pdblLib->byteSwapped) {
++ symHdr.nameLen = SWAPWORD(symHdr.nameLen);
++ symHdr.value = SWAPLONG(symHdr.value);
++ }
++ /* Allocate buffer for symbol name */
++ len = symHdr.nameLen;
++ pName = (char *)MEM_Calloc(len + 1, MEM_PAGED);
++ if (pName == NULL) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ pdblLib->symbols[i].pSymName = pName;
++ pdblLib->symbols[i].sym.value = symHdr.value;
++ /* Read symbol name */
++ if ((*dbl->dblAttrs.fread) (pName, sizeof(char), len, file) !=
++ len) {
++ GT_0trace(DBL_debugMask, GT_6CLASS,
++ "Failed to read symbol value\n");
++ status = DSP_EFREAD;
++ break;
++ } else {
++ pName[len] = '\0';
++ GT_2trace(DBL_debugMask, GT_ENTER,
++ "Symbol: %s Value: 0x%lx\n",
++ pName, symHdr.value);
++ }
++ }
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dbll.c b/drivers/dsp/bridge/pmgr/dbll.c
+new file mode 100644
+index 0000000..82430a3
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dbll.c
+@@ -0,0 +1,1564 @@
++/*
++ * dbll.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dbll.c ========
++ *
++ *! Revision History
++ *! ================
++ *! 25-Apr-2030 map: Fixed symbol redefinition bug + unload and return error
++ *! 08-Apr-2003 map: Consolidated DBL with DBLL loader name
++ *! 24-Mar-2003 map: Updated findSymbol to support dllview update
++ *! 23-Jan-2003 map: Updated rmmAlloc to support memory granularity
++ *! 21-Nov-2002 map: Combine fopen and DLOAD_module_open to increase
++ *! performance on start.
++ *! 04-Oct-2002 map: Integrated new TIP dynamic loader w/ DOF api.
++ *! 27-Sep-2002 map: Changed handle passed to RemoteFree, instead of
++ *! RMM_free; added GT_trace to rmmDealloc
++ *! 20-Sep-2002 map: Updated from Code Review
++ *! 08-Aug-2002 jeh: Updated to support overlays.
++ *! 25-Jun-2002 jeh: Pass RMM_Addr object to alloc function in rmmAlloc().
++ *! 20-Mar-2002 jeh: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++#include <dspbridge/gh.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* Dynamic loader library interface */
++#include <dspbridge/dynamic_loader.h>
++#include <dspbridge/getsection.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbll.h>
++#include <dspbridge/rmm.h>
++
++#define DBLL_TARGSIGNATURE 0x544c4c44 /* "TLLD" */
++#define DBLL_LIBSIGNATURE 0x4c4c4c44 /* "LLLD" */
++
++/* Number of buckets for symbol hash table */
++#define MAXBUCKETS 211
++
++/* Max buffer length */
++#define MAXEXPR 128
++
++#ifndef UINT32_C
++#define UINT32_C(zzz) ((uint32_t)zzz)
++#endif
++#define DOFF_ALIGN(x) (((x) + 3) & ~UINT32_C(3))
++
++/*
++ * ======== struct DBLL_TarObj* ========
++ * A target may have one or more libraries of symbols/code/data loaded
++ * onto it, where a library is simply the symbols/code/data contained
++ * in a DOFF file.
++ */
++/*
++ * ======== DBLL_TarObj ========
++ */
++struct DBLL_TarObj {
++ u32 dwSignature; /* For object validation */
++ struct DBLL_Attrs attrs;
++ struct DBLL_LibraryObj *head; /* List of all opened libraries */
++} ;
++
++/*
++ * The following 4 typedefs are "super classes" of the dynamic loader
++ * library types used in dynamic loader functions (dynamic_loader.h).
++ */
++/*
++ * ======== DBLLStream ========
++ * Contains Dynamic_Loader_Stream
++ */
++struct DBLLStream {
++ struct Dynamic_Loader_Stream dlStream;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLSymbol ========
++ */
++struct DBLLSymbol {
++ struct Dynamic_Loader_Sym dlSymbol;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLAlloc ========
++ */
++ struct DBLLAlloc {
++ struct Dynamic_Loader_Allocate dlAlloc;
++ struct DBLL_LibraryObj *lib;
++} ;
++
++/*
++ * ======== DBLLInit ========
++ */
++struct DBLLInit {
++ struct Dynamic_Loader_Initialize dlInit;
++ struct DBLL_LibraryObj *lib;
++};
++
++/*
++ * ======== DBLL_Library ========
++ * A library handle is returned by DBLL_Open() and is passed to DBLL_load()
++ * to load symbols/code/data, and to DBLL_unload(), to remove the
++ * symbols/code/data loaded by DBLL_load().
++ */
++
++/*
++ * ======== DBLL_LibraryObj ========
++ */
++ struct DBLL_LibraryObj {
++ u32 dwSignature; /* For object validation */
++ struct DBLL_LibraryObj *next; /* Next library in target's list */
++ struct DBLL_LibraryObj *prev; /* Previous in the list */
++ struct DBLL_TarObj *pTarget; /* target for this library */
++
++ /* Objects needed by dynamic loader */
++ struct DBLLStream stream;
++ struct DBLLSymbol symbol;
++ struct DBLLAlloc allocate;
++ struct DBLLInit init;
++ DLOAD_mhandle mHandle;
++
++ char *fileName; /* COFF file name */
++ void *fp; /* Opaque file handle */
++ u32 entry; /* Entry point */
++ DLOAD_mhandle desc; /* desc of DOFF file loaded */
++ u32 openRef; /* Number of times opened */
++ u32 loadRef; /* Number of times loaded */
++ struct GH_THashTab *symTab; /* Hash table of symbols */
++ u32 ulPos;
++} ;
++
++/*
++ * ======== Symbol ========
++ */
++struct Symbol {
++ struct DBLL_Symbol value;
++ char *name;
++} ;
++extern bool bSymbolsReloaded;
++
++static void dofClose(struct DBLL_LibraryObj *zlLib);
++static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib);
++static s32 NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsiz);
++
++/*
++ * Functions called by dynamic loader
++ *
++ */
++/* Dynamic_Loader_Stream */
++static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
++ unsigned bufsize);
++static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos);
++/* Dynamic_Loader_Sym */
++static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
++ const char *name);
++static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleId);
++static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleid);
++static void purgeSymbolTable(struct Dynamic_Loader_Sym *this,
++ unsigned moduleId);
++static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize);
++static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr);
++static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
++ va_list args);
++/* Dynamic_Loader_Allocate */
++static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info, unsigned align);
++static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info);
++
++/* Dynamic_Loader_Initialize */
++static int connect(struct Dynamic_Loader_Initialize *this);
++static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes);
++static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes);
++static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
++ struct LDR_SECTION_INFO *info, unsigned nbytes,
++ unsigned val);
++static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start);
++static void release(struct Dynamic_Loader_Initialize *this);
++
++/* symbol table hash functions */
++static u16 nameHash(void *name, u16 maxBucket);
++static bool nameMatch(void *name, void *sp);
++static void symDelete(void *sp);
++
++#if GT_TRACE
++static struct GT_Mask DBLL_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* Symbol Redefinition */
++static int bRedefinedSymbol;
++static int bGblSearch = 1;
++
++/*
++ * ======== DBLL_close ========
++ */
++void DBLL_close(struct DBLL_LibraryObj *zlLib)
++{
++ struct DBLL_TarObj *zlTarget;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(zlLib->openRef > 0);
++ zlTarget = zlLib->pTarget;
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_close: lib: 0x%x\n", zlLib);
++ zlLib->openRef--;
++ if (zlLib->openRef == 0) {
++ /* Remove library from list */
++ if (zlTarget->head == zlLib)
++ zlTarget->head = zlLib->next;
++
++ if (zlLib->prev)
++ (zlLib->prev)->next = zlLib->next;
++
++ if (zlLib->next)
++ (zlLib->next)->prev = zlLib->prev;
++
++ /* Free DOF resources */
++ dofClose(zlLib);
++ if (zlLib->fileName)
++ MEM_Free(zlLib->fileName);
++
++ /* remove symbols from symbol table */
++ if (zlLib->symTab)
++ GH_delete(zlLib->symTab);
++
++ /* remove the library object itself */
++ MEM_FreeObject(zlLib);
++ zlLib = NULL;
++ }
++}
++
++/*
++ * ======== DBLL_create ========
++ */
++DSP_STATUS DBLL_create(struct DBLL_TarObj **pTarget, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *pzlTarget;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pTarget != NULL);
++
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_create: pTarget: 0x%x pAttrs: "
++ "0x%x\n", pTarget, pAttrs);
++ /* Allocate DBL target object */
++ MEM_AllocObject(pzlTarget, struct DBLL_TarObj, DBLL_TARGSIGNATURE);
++ if (pTarget != NULL) {
++ if (pzlTarget == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_create: Memory allocation"
++ " failed\n");
++ *pTarget = NULL;
++ status = DSP_EMEMORY;
++ } else {
++ pzlTarget->attrs = *pAttrs;
++ *pTarget = (struct DBLL_TarObj *)pzlTarget;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct DBLL_TarObj *)(*pTarget)),
++ DBLL_TARGSIGNATURE)) || (DSP_FAILED(status) &&
++ *pTarget == NULL));
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_delete ========
++ */
++void DBLL_delete(struct DBLL_TarObj *target)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_delete: target: 0x%x\n",
++ target);
++
++ if (zlTarget != NULL)
++ MEM_FreeObject(zlTarget);
++
++}
++
++/*
++ * ======== DBLL_exit ========
++ * Discontinue usage of DBL module.
++ */
++void DBLL_exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_exit() ref count: 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0) {
++ MEM_Exit();
++ CSL_Exit();
++ GH_exit();
++#if GT_TRACE
++ DBLL_debugMask.flags = NULL;
++#endif
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DBLL_getAddr ========
++ * Get address of name in the specified library.
++ */
++bool DBLL_getAddr(struct DBLL_LibraryObj *zlLib, char *name,
++ struct DBLL_Symbol **ppSym)
++{
++ struct Symbol *sym;
++ bool status = false;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(ppSym != NULL);
++ DBC_Require(zlLib->symTab != NULL);
++
++ GT_3trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_getAddr: lib: 0x%x name: %s pAddr:"
++ " 0x%x\n", zlLib, name, ppSym);
++ sym = (struct Symbol *)GH_find(zlLib->symTab, name);
++ if (sym != NULL) {
++ *ppSym = &sym->value;
++ status = true;
++ }
++ return status;
++}
++
++/*
++ * ======== DBLL_getAttrs ========
++ * Retrieve the attributes of the target.
++ */
++void DBLL_getAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++
++ if ((pAttrs != NULL) && (zlTarget != NULL))
++ *pAttrs = zlTarget->attrs;
++
++}
++
++/*
++ * ======== DBLL_getCAddr ========
++ * Get address of a "C" name in the specified library.
++ */
++bool DBLL_getCAddr(struct DBLL_LibraryObj *zlLib, char *name,
++ struct DBLL_Symbol **ppSym)
++{
++ struct Symbol *sym;
++ char cname[MAXEXPR + 1];
++ bool status = false;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(ppSym != NULL);
++ DBC_Require(zlLib->symTab != NULL);
++ DBC_Require(name != NULL);
++
++ cname[0] = '_';
++
++ strncpy(cname + 1, name, sizeof(cname) - 2);
++ cname[MAXEXPR] = '\0'; /* insure '\0' string termination */
++
++ /* Check for C name, if not found */
++ sym = (struct Symbol *)GH_find(zlLib->symTab, cname);
++
++ if (sym != NULL) {
++ *ppSym = &sym->value;
++ status = true;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_getSect ========
++ * Get the base address and size (in bytes) of a COFF section.
++ */
++DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name, u32 *pAddr,
++ u32 *pSize)
++{
++ u32 uByteSize;
++ bool fOpenedDoff = false;
++ const struct LDR_SECTION_INFO *sect = NULL;
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(name != NULL);
++ DBC_Require(pAddr != NULL);
++ DBC_Require(pSize != NULL);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_getSect: lib: 0x%x name: %s pAddr:"
++ " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize);
++ /* If DOFF file is not open, we open it. */
++ if (zlLib != NULL) {
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ } else {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
++ zlLib->ulPos, SEEK_SET);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ uByteSize = 1;
++ if (DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
++ *pAddr = sect->load_addr;
++ *pSize = sect->size * uByteSize;
++ /* Make sure size is even for good swap */
++ if (*pSize % 2)
++ (*pSize)++;
++
++ /* Align size */
++ *pSize = DOFF_ALIGN(*pSize);
++ } else {
++ status = DSP_ENOSECT;
++ }
++ }
++ if (fOpenedDoff) {
++ dofClose(zlLib);
++ fOpenedDoff = false;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DBLL_init ========
++ */
++bool DBLL_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DBLL_debugMask.flags);
++ GT_create(&DBLL_debugMask, "DL"); /* "DL" for dbDL */
++ GH_init();
++ CSL_Init();
++ retVal = MEM_Init();
++ if (!retVal)
++ MEM_Exit();
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== DBLL_load ========
++ */
++DSP_STATUS DBLL_load(struct DBLL_LibraryObj *lib, DBLL_Flags flags,
++ struct DBLL_Attrs *attrs, u32 *pEntry)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ struct DBLL_TarObj *dbzl;
++ bool gotSymbols = true;
++ s32 err;
++ DSP_STATUS status = DSP_SOK;
++ bool fOpenedDoff = false;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(pEntry != NULL);
++ DBC_Require(attrs != NULL);
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_load: lib: 0x%x flags: 0x%x pEntry:"
++ " 0x%x\n", lib, flags, attrs, pEntry);
++ /*
++ * Load if not already loaded.
++ */
++ if (zlLib->loadRef == 0 || !(flags & DBLL_DYNAMIC)) {
++ dbzl = zlLib->pTarget;
++ dbzl->attrs = *attrs;
++ /* Create a hash table for symbols if not already created */
++ if (zlLib->symTab == NULL) {
++ gotSymbols = false;
++ zlLib->symTab = GH_create(MAXBUCKETS,
++ sizeof(struct Symbol),
++ nameHash,
++ nameMatch, symDelete);
++ if (zlLib->symTab == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ /*
++ * Set up objects needed by the dynamic loader
++ */
++ /* Stream */
++ zlLib->stream.dlStream.read_buffer = readBuffer;
++ zlLib->stream.dlStream.set_file_posn = setFilePosn;
++ zlLib->stream.lib = zlLib;
++ /* Symbol */
++ zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
++ if (gotSymbols) {
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
++ findInSymbolTable;
++ } else {
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table =
++ addToSymbolTable;
++ }
++ zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
++ zlLib->symbol.dlSymbol.Allocate = allocate;
++ zlLib->symbol.dlSymbol.Deallocate = deallocate;
++ zlLib->symbol.dlSymbol.Error_Report = errorReport;
++ zlLib->symbol.lib = zlLib;
++ /* Allocate */
++ zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
++ zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
++ zlLib->allocate.lib = zlLib;
++ /* Init */
++ zlLib->init.dlInit.connect = connect;
++ zlLib->init.dlInit.readmem = readMem;
++ zlLib->init.dlInit.writemem = writeMem;
++ zlLib->init.dlInit.fillmem = fillMem;
++ zlLib->init.dlInit.execute = execute;
++ zlLib->init.dlInit.release = release;
++ zlLib->init.lib = zlLib;
++ /* If COFF file is not open, we open it. */
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell))
++ (zlLib->fp);
++ /* Reset file cursor */
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0,
++ SEEK_SET);
++ bSymbolsReloaded = true;
++ /* The 5th argument, DLOAD_INITBSS, tells the DLL
++ * module to zero-init all BSS sections. In general,
++ * this is not necessary and also increases load time.
++ * We may want to make this configurable by the user */
++ err = Dynamic_Load_Module(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol, &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit, DLOAD_INITBSS,
++ &zlLib->mHandle);
++
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_load: "
++ "Dynamic_Load_Module failed: 0x%lx\n",
++ err);
++ status = DSP_EDYNLOAD;
++ } else if (bRedefinedSymbol) {
++ zlLib->loadRef++;
++ DBLL_unload(zlLib, (struct DBLL_Attrs *) attrs);
++ bRedefinedSymbol = false;
++ status = DSP_EDYNLOAD;
++ } else {
++ *pEntry = zlLib->entry;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ zlLib->loadRef++;
++
++ /* Clean up DOFF resources */
++ if (fOpenedDoff)
++ dofClose(zlLib);
++
++ DBC_Ensure(DSP_FAILED(status) || zlLib->loadRef > 0);
++ return status;
++}
++
++/*
++ * ======== DBLL_loadSect ========
++ * Not supported for COFF.
++ */
++DSP_STATUS DBLL_loadSect(struct DBLL_LibraryObj *zlLib, char *sectName,
++ struct DBLL_Attrs *attrs)
++{
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== DBLL_open ========
++ */
++DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file, DBLL_Flags flags,
++ struct DBLL_LibraryObj **pLib)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++ struct DBLL_LibraryObj *zlLib = NULL;
++ s32 err;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(zlTarget->attrs.fopen != NULL);
++ DBC_Require(file != NULL);
++ DBC_Require(pLib != NULL);
++
++ GT_3trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_open: target: 0x%x file: %s pLib:"
++ " 0x%x\n", target, file, pLib);
++ zlLib = zlTarget->head;
++ while (zlLib != NULL) {
++ if (strcmp(zlLib->fileName, file) == 0) {
++ /* Library is already opened */
++ zlLib->openRef++;
++ break;
++ }
++ zlLib = zlLib->next;
++ }
++ if (zlLib == NULL) {
++ /* Allocate DBL library object */
++ MEM_AllocObject(zlLib, struct DBLL_LibraryObj,
++ DBLL_LIBSIGNATURE);
++ if (zlLib == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ zlLib->ulPos = 0;
++ /* Increment ref count to allow close on failure
++ * later on */
++ zlLib->openRef++;
++ zlLib->pTarget = zlTarget;
++ /* Keep a copy of the file name */
++ zlLib->fileName = MEM_Calloc(strlen(file) + 1,
++ MEM_PAGED);
++ if (zlLib->fileName == NULL) {
++ GT_0trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(zlLib->fileName, file,
++ strlen(file) + 1);
++ }
++ zlLib->symTab = NULL;
++ }
++ }
++ /*
++ * Set up objects needed by the dynamic loader
++ */
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Stream */
++ zlLib->stream.dlStream.read_buffer = readBuffer;
++ zlLib->stream.dlStream.set_file_posn = setFilePosn;
++ zlLib->stream.lib = zlLib;
++ /* Symbol */
++ zlLib->symbol.dlSymbol.Add_To_Symbol_Table = addToSymbolTable;
++ zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol;
++ zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable;
++ zlLib->symbol.dlSymbol.Allocate = allocate;
++ zlLib->symbol.dlSymbol.Deallocate = deallocate;
++ zlLib->symbol.dlSymbol.Error_Report = errorReport;
++ zlLib->symbol.lib = zlLib;
++ /* Allocate */
++ zlLib->allocate.dlAlloc.Allocate = rmmAlloc;
++ zlLib->allocate.dlAlloc.Deallocate = rmmDealloc;
++ zlLib->allocate.lib = zlLib;
++ /* Init */
++ zlLib->init.dlInit.connect = connect;
++ zlLib->init.dlInit.readmem = readMem;
++ zlLib->init.dlInit.writemem = writeMem;
++ zlLib->init.dlInit.fillmem = fillMem;
++ zlLib->init.dlInit.execute = execute;
++ zlLib->init.dlInit.release = release;
++ zlLib->init.lib = zlLib;
++ if (DSP_SUCCEEDED(status) && zlLib->fp == NULL)
++ status = dofOpen(zlLib);
++
++ zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell)) (zlLib->fp);
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long) 0, SEEK_SET);
++ /* Create a hash table for symbols if flag is set */
++ if (zlLib->symTab != NULL || !(flags & DBLL_SYMB))
++ goto func_cont;
++
++ zlLib->symTab = GH_create(MAXBUCKETS, sizeof(struct Symbol), nameHash,
++ nameMatch, symDelete);
++ if (zlLib->symTab == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Do a fake load to get symbols - set write function to NoOp */
++ zlLib->init.dlInit.writemem = NoOp;
++ err = Dynamic_Open_Module(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit, 0,
++ &zlLib->mHandle);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: "
++ "Dynamic_Load_Module failed: 0x%lx\n", err);
++ status = DSP_EDYNLOAD;
++ } else {
++ /* Now that we have the symbol table, we can unload */
++ err = Dynamic_Unload_Module(zlLib->mHandle,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc,
++ &zlLib->init.dlInit);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "DBLL_open: "
++ "Dynamic_Unload_Module failed: 0x%lx\n",
++ err);
++ status = DSP_EDYNLOAD;
++ }
++ zlLib->mHandle = NULL;
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ if (zlLib->openRef == 1) {
++ /* First time opened - insert in list */
++ if (zlTarget->head)
++ (zlTarget->head)->prev = zlLib;
++
++ zlLib->prev = NULL;
++ zlLib->next = zlTarget->head;
++ zlTarget->head = zlLib;
++ }
++ *pLib = (struct DBLL_LibraryObj *)zlLib;
++ } else {
++ *pLib = NULL;
++ if (zlLib != NULL)
++ DBLL_close((struct DBLL_LibraryObj *)zlLib);
++
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && (zlLib->openRef > 0) &&
++ MEM_IsValidHandle(((struct DBLL_LibraryObj *)(*pLib)),
++ DBLL_LIBSIGNATURE)) || (DSP_FAILED(status) && *pLib == NULL));
++ return status;
++}
++
++/*
++ * ======== DBLL_readSect ========
++ * Get the content of a COFF section.
++ */
++DSP_STATUS DBLL_readSect(struct DBLL_LibraryObj *lib, char *name,
++ char *pContent, u32 size)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ bool fOpenedDoff = false;
++ u32 uByteSize; /* size of bytes */
++ u32 ulSectSize; /* size of section */
++ const struct LDR_SECTION_INFO *sect = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(name != NULL);
++ DBC_Require(pContent != NULL);
++ DBC_Require(size != 0);
++
++ GT_4trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_readSect: lib: 0x%x name: %s "
++ "pContent: 0x%x size: 0x%x\n", lib, name, pContent, size);
++ /* If DOFF file is not open, we open it. */
++ if (zlLib != NULL) {
++ if (zlLib->fp == NULL) {
++ status = dofOpen(zlLib);
++ if (DSP_SUCCEEDED(status))
++ fOpenedDoff = true;
++
++ } else {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp,
++ zlLib->ulPos, SEEK_SET);
++ }
++ }
++
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ uByteSize = 1;
++ if (!DLOAD_GetSectionInfo(zlLib->desc, name, &sect)) {
++ status = DSP_ENOSECT;
++ goto func_cont;
++ }
++ /*
++ * Ensure the supplied buffer size is sufficient to store
++ * the section content to be read.
++ */
++ ulSectSize = sect->size * uByteSize;
++ /* Make sure size is even for good swap */
++ if (ulSectSize % 2)
++ ulSectSize++;
++
++ /* Align size */
++ ulSectSize = DOFF_ALIGN(ulSectSize);
++ if (ulSectSize > size) {
++ status = DSP_EFAIL;
++ } else {
++ if (!DLOAD_GetSection(zlLib->desc, sect, pContent))
++ status = DSP_EFREAD;
++
++ }
++func_cont:
++ if (fOpenedDoff) {
++ dofClose(zlLib);
++ fOpenedDoff = false;
++ }
++ return status;
++}
++
++/*
++ * ======== DBLL_setAttrs ========
++ * Set the attributes of the target.
++ */
++void DBLL_setAttrs(struct DBLL_TarObj *target, struct DBLL_Attrs *pAttrs)
++{
++ struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE));
++ DBC_Require(pAttrs != NULL);
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_setAttrs: target: 0x%x pAttrs: "
++ "0x%x\n", target, pAttrs);
++ if ((pAttrs != NULL) && (zlTarget != NULL))
++ zlTarget->attrs = *pAttrs;
++
++}
++
++/*
++ * ======== DBLL_unload ========
++ */
++void DBLL_unload(struct DBLL_LibraryObj *lib, struct DBLL_Attrs *attrs)
++{
++ struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib;
++ s32 err = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE));
++ DBC_Require(zlLib->loadRef > 0);
++ GT_1trace(DBLL_debugMask, GT_ENTER, "DBLL_unload: lib: 0x%x\n", lib);
++ zlLib->loadRef--;
++ /* Unload only if reference count is 0 */
++ if (zlLib->loadRef != 0)
++ goto func_end;
++
++ zlLib->pTarget->attrs = *attrs;
++ if (zlLib != NULL) {
++ if (zlLib->mHandle) {
++ err = Dynamic_Unload_Module(zlLib->mHandle,
++ &zlLib->symbol.dlSymbol,
++ &zlLib->allocate.dlAlloc, &zlLib->init.dlInit);
++ if (err != 0) {
++ GT_1trace(DBLL_debugMask, GT_5CLASS,
++ "Dynamic_Unload_Module "
++ "failed: 0x%x\n", err);
++ }
++ }
++ /* remove symbols from symbol table */
++ if (zlLib->symTab != NULL) {
++ GH_delete(zlLib->symTab);
++ zlLib->symTab = NULL;
++ }
++ /* delete DOFF desc since it holds *lots* of host OS
++ * resources */
++ dofClose(zlLib);
++ }
++func_end:
++ DBC_Ensure(zlLib->loadRef >= 0);
++}
++
++/*
++ * ======== DBLL_unloadSect ========
++ * Not supported for COFF.
++ */
++DSP_STATUS DBLL_unloadSect(struct DBLL_LibraryObj *lib, char *sectName,
++ struct DBLL_Attrs *attrs)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(sectName != NULL);
++ GT_2trace(DBLL_debugMask, GT_ENTER,
++ "DBLL_unloadSect: lib: 0x%x sectName: "
++ "%s\n", lib, sectName);
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== dofClose ========
++ */
++static void dofClose(struct DBLL_LibraryObj *zlLib)
++{
++ if (zlLib->desc) {
++ DLOAD_module_close(zlLib->desc);
++ zlLib->desc = NULL;
++ }
++ /* close file */
++ if (zlLib->fp) {
++ (zlLib->pTarget->attrs.fclose) (zlLib->fp);
++ zlLib->fp = NULL;
++ }
++}
++
++/*
++ * ======== dofOpen ========
++ */
++static DSP_STATUS dofOpen(struct DBLL_LibraryObj *zlLib)
++{
++ void *open = *(zlLib->pTarget->attrs.fopen);
++ DSP_STATUS status = DSP_SOK;
++
++ /* First open the file for the dynamic loader, then open COF */
++ zlLib->fp = (void *)((DBLL_FOpenFxn)(open))(zlLib->fileName, "rb");
++
++ /* Open DOFF module */
++ if (zlLib->fp && zlLib->desc == NULL) {
++ (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long)0, SEEK_SET);
++ zlLib->desc = DLOAD_module_open(&zlLib->stream.dlStream,
++ &zlLib->symbol.dlSymbol);
++ if (zlLib->desc == NULL) {
++ (zlLib->pTarget->attrs.fclose)(zlLib->fp);
++ zlLib->fp = NULL;
++ status = DSP_EFOPEN;
++ }
++ } else {
++ status = DSP_EFOPEN;
++ }
++
++ return status;
++}
++
++/*
++ * ======== nameHash ========
++ */
++static u16 nameHash(void *key, u16 maxBucket)
++{
++ u16 ret;
++ u16 hash;
++ char *name = (char *)key;
++
++ DBC_Require(name != NULL);
++
++ hash = 0;
++
++ while (*name) {
++ hash <<= 1;
++ hash ^= *name++;
++ }
++
++ ret = hash % maxBucket;
++
++ return ret;
++}
++
++/*
++ * ======== nameMatch ========
++ */
++static bool nameMatch(void *key, void *value)
++{
++ DBC_Require(key != NULL);
++ DBC_Require(value != NULL);
++
++ if ((key != NULL) && (value != NULL)) {
++ if (strcmp((char *)key, ((struct Symbol *)value)->name) == 0)
++ return true;
++ }
++ return false;
++}
++
++/*
++ * ======== NoOp ========
++ */
++static int NoOp(struct Dynamic_Loader_Initialize *thisptr, void *bufr,
++ LDR_ADDR locn, struct LDR_SECTION_INFO *info, unsigned bytsize)
++{
++ return 1;
++}
++
++/*
++ * ======== symDelete ========
++ */
++static void symDelete(void *value)
++{
++ struct Symbol *sp = (struct Symbol *)value;
++
++ MEM_Free(sp->name);
++}
++
++/*
++ * Dynamic Loader Functions
++ */
++
++/* Dynamic_Loader_Stream */
++/*
++ * ======== readBuffer ========
++ */
++static int readBuffer(struct Dynamic_Loader_Stream *this, void *buffer,
++ unsigned bufsize)
++{
++ struct DBLLStream *pStream = (struct DBLLStream *)this;
++ struct DBLL_LibraryObj *lib;
++ int bytesRead = 0;
++
++ DBC_Require(this != NULL);
++ lib = pStream->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ bytesRead = (*(lib->pTarget->attrs.fread))(buffer, 1, bufsize,
++ lib->fp);
++ }
++ return bytesRead;
++}
++
++/*
++ * ======== setFilePosn ========
++ */
++static int setFilePosn(struct Dynamic_Loader_Stream *this, unsigned int pos)
++{
++ struct DBLLStream *pStream = (struct DBLLStream *)this;
++ struct DBLL_LibraryObj *lib;
++ int status = 0; /* Success */
++
++ DBC_Require(this != NULL);
++ lib = pStream->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ status = (*(lib->pTarget->attrs.fseek))(lib->fp, (long)pos,
++ SEEK_SET);
++ }
++
++ return status;
++}
++
++/* Dynamic_Loader_Sym */
++
++/*
++ * ======== findSymbol ========
++ */
++static struct dynload_symbol *findSymbol(struct Dynamic_Loader_Sym *this,
++ const char *name)
++{
++ struct dynload_symbol *retSym;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct DBLL_Symbol *pSym = NULL;
++ bool status = false; /* Symbol not found yet */
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ if (lib != NULL) {
++ if (lib->pTarget->attrs.symLookup) {
++ /* Check current lib + base lib + dep lib +
++ * persistent lib */
++ status = (*(lib->pTarget->attrs.symLookup))
++ (lib->pTarget->attrs.symHandle,
++ lib->pTarget->attrs.symArg,
++ lib->pTarget->attrs.rmmHandle, name, &pSym);
++ } else {
++ /* Just check current lib for symbol */
++ status = DBLL_getAddr((struct DBLL_LibraryObj *)lib,
++ (char *)name, &pSym);
++ if (!status) {
++ status =
++ DBLL_getCAddr((struct DBLL_LibraryObj *)lib,
++ (char *)name, &pSym);
++ }
++ }
++ }
++
++ if (!status && bGblSearch) {
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "findSymbol: Symbol not found: %s\n", name);
++ }
++
++ DBC_Assert((status && (pSym != NULL)) || (!status && (pSym == NULL)));
++
++ retSym = (struct dynload_symbol *)pSym;
++ return retSym;
++}
++
++/*
++ * ======== findInSymbolTable ========
++ */
++static struct dynload_symbol *findInSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleid)
++{
++ struct dynload_symbol *retSym;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct Symbol *sym;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ DBC_Require(lib->symTab != NULL);
++
++ sym = (struct Symbol *)GH_find(lib->symTab, (char *) name);
++
++ retSym = (struct dynload_symbol *)&sym->value;
++ return retSym;
++}
++
++/*
++ * ======== addToSymbolTable ========
++ */
++static struct dynload_symbol *addToSymbolTable(struct Dynamic_Loader_Sym *this,
++ const char *name,
++ unsigned moduleId)
++{
++ struct Symbol *symPtr = NULL;
++ struct Symbol symbol;
++ struct dynload_symbol *pSym = NULL;
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ struct dynload_symbol *retVal;
++
++ DBC_Require(this != NULL);
++ DBC_Require(name);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ /* Check to see if symbol is already defined in symbol table */
++ if (!(lib->pTarget->attrs.baseImage)) {
++ bGblSearch = false;
++ pSym = findSymbol(this, name);
++ bGblSearch = true;
++ if (pSym) {
++ bRedefinedSymbol = true;
++ GT_1trace(DBLL_debugMask, GT_6CLASS,
++ "Symbol already defined in "
++ "symbol table: %s\n", name);
++ return NULL;
++ }
++ }
++ /* Allocate string to copy symbol name */
++ symbol.name = (char *)MEM_Calloc(strlen((char *const)name) + 1,
++ MEM_PAGED);
++ if (symbol.name == NULL)
++ return NULL;
++
++ if (symbol.name != NULL) {
++ /* Just copy name (value will be filled in by dynamic loader) */
++ strncpy(symbol.name, (char *const)name,
++ strlen((char *const)name) + 1);
++
++ /* Add symbol to symbol table */
++ symPtr = (struct Symbol *)GH_insert(lib->symTab, (void *)name,
++ (void *)&symbol);
++ if (symPtr == NULL)
++ MEM_Free(symbol.name);
++
++ }
++ if (symPtr != NULL)
++ retVal = (struct dynload_symbol *)&symPtr->value;
++ else
++ retVal = NULL;
++
++ return retVal;
++}
++
++/*
++ * ======== purgeSymbolTable ========
++ */
++static void purgeSymbolTable(struct Dynamic_Loader_Sym *this, unsigned moduleId)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ /* May not need to do anything */
++}
++
++/*
++ * ======== allocate ========
++ */
++static void *allocate(struct Dynamic_Loader_Sym *this, unsigned memsize)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ void *buf;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ buf = MEM_Calloc(memsize, MEM_PAGED);
++
++ return buf;
++}
++
++/*
++ * ======== deallocate ========
++ */
++static void deallocate(struct Dynamic_Loader_Sym *this, void *memPtr)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ MEM_Free(memPtr);
++}
++
++/*
++ * ======== errorReport ========
++ */
++static void errorReport(struct Dynamic_Loader_Sym *this, const char *errstr,
++ va_list args)
++{
++ struct DBLLSymbol *pSymbol = (struct DBLLSymbol *)this;
++ struct DBLL_LibraryObj *lib;
++ char tempBuf[MAXEXPR];
++
++ DBC_Require(this != NULL);
++ lib = pSymbol->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ vsnprintf((char *)tempBuf, MAXEXPR, (char *)errstr, args);
++ GT_1trace(DBLL_debugMask, GT_5CLASS, "%s\n", tempBuf);
++}
++
++/* Dynamic_Loader_Allocate */
++
++/*
++ * ======== rmmAlloc ========
++ */
++static int rmmAlloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info, unsigned align)
++{
++ struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
++ struct DBLL_LibraryObj *lib;
++ DSP_STATUS status = DSP_SOK;
++ u32 memType;
++ struct RMM_Addr rmmAddr;
++ s32 retVal = TRUE;
++ unsigned stype = DLOAD_SECTION_TYPE(info->type);
++ char *pToken = NULL;
++ char *szSecLastToken = NULL;
++ char *szLastToken = NULL;
++ char *szSectName = NULL;
++ char *pszCur;
++ s32 tokenLen = 0;
++ s32 segId = -1;
++ s32 req = -1;
++ s32 count = 0;
++ u32 allocSize = 0;
++
++ DBC_Require(this != NULL);
++ lib = pAlloc->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
++ DBLL_BSS : DBLL_DATA;
++
++ /* Attempt to extract the segment ID and requirement information from
++ the name of the section */
++ DBC_Require(info->name);
++ tokenLen = strlen((char *)(info->name)) + 1;
++
++ szSectName = MEM_Calloc(tokenLen, MEM_PAGED);
++ szLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
++ szSecLastToken = MEM_Calloc(tokenLen, MEM_PAGED);
++
++ if (szSectName == NULL || szSecLastToken == NULL ||
++ szLastToken == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ strncpy(szSectName, (char *)(info->name), tokenLen);
++ pszCur = szSectName;
++ while ((pToken = strsep(&pszCur, ":")) && *pToken != '\0') {
++ strncpy(szSecLastToken, szLastToken, strlen(szLastToken) + 1);
++ strncpy(szLastToken, pToken, strlen(pToken) + 1);
++ pToken = strsep(&pszCur, ":");
++ count++; /* optimizes processing*/
++ }
++ /* If pToken is 0 or 1, and szSecLastToken is DYN_DARAM or DYN_SARAM,
++ or DYN_EXTERNAL, then mem granularity information is present
++ within the section name - only process if there are at least three
++ tokens within the section name (just a minor optimization)*/
++ if (count >= 3)
++ strict_strtol(szLastToken, 10, (long *)&req);
++
++ if ((req == 0) || (req == 1)) {
++ if (strcmp(szSecLastToken, "DYN_DARAM") == 0) {
++ segId = 0;
++ } else {
++ if (strcmp(szSecLastToken, "DYN_SARAM") == 0) {
++ segId = 1;
++ } else {
++ if (strcmp(szSecLastToken,
++ "DYN_EXTERNAL") == 0) {
++ segId = 2;
++ }
++ }
++ }
++ if (segId != -1) {
++ GT_2trace(DBLL_debugMask, GT_5CLASS,
++ "Extracted values for memory"
++ " granularity req [%d] segId [%d]\n",
++ req, segId);
++ }
++ }
++ MEM_Free(szSectName);
++ szSectName = NULL;
++ MEM_Free(szLastToken);
++ szLastToken = NULL;
++ MEM_Free(szSecLastToken);
++ szSecLastToken = NULL;
++func_cont:
++ if (memType == DBLL_CODE)
++ allocSize = info->size + GEM_L1P_PREFETCH_SIZE;
++ else
++ allocSize = info->size;
++ /* TODO - ideally, we can pass the alignment requirement also
++ * from here */
++ if (lib != NULL) {
++ status = (lib->pTarget->attrs.alloc)(lib->pTarget->
++ attrs.rmmHandle, memType, allocSize, align,
++ (u32 *)&rmmAddr, segId, req, FALSE);
++ }
++ if (DSP_FAILED(status)) {
++ retVal = false;
++ } else {
++ /* RMM gives word address. Need to convert to byte address */
++ info->load_addr = rmmAddr.addr * DSPWORDSIZE;
++ info->run_addr = info->load_addr;
++ info->context = (u32)rmmAddr.segid;
++ GT_3trace(DBLL_debugMask, GT_5CLASS,
++ "Remote alloc: %s base = 0x%lx len"
++ "= 0x%lx\n", info->name, info->load_addr / DSPWORDSIZE,
++ info->size / DSPWORDSIZE);
++ }
++ return retVal;
++}
++
++/*
++ * ======== rmmDealloc ========
++ */
++static void rmmDealloc(struct Dynamic_Loader_Allocate *this,
++ struct LDR_SECTION_INFO *info)
++{
++ struct DBLLAlloc *pAlloc = (struct DBLLAlloc *)this;
++ struct DBLL_LibraryObj *lib;
++ u32 segid;
++ DSP_STATUS status = DSP_SOK;
++ unsigned stype = DLOAD_SECTION_TYPE(info->type);
++ u32 memType;
++ u32 freeSize = 0;
++
++ memType = (stype == DLOAD_TEXT) ? DBLL_CODE : (stype == DLOAD_BSS) ?
++ DBLL_BSS : DBLL_DATA;
++ DBC_Require(this != NULL);
++ lib = pAlloc->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* segid was set by alloc function */
++ segid = (u32)info->context;
++ if (memType == DBLL_CODE)
++ freeSize = info->size + GEM_L1P_PREFETCH_SIZE;
++ else
++ freeSize = info->size;
++ if (lib != NULL) {
++ status = (lib->pTarget->attrs.free)(lib->pTarget->
++ attrs.symHandle, segid, info->load_addr / DSPWORDSIZE,
++ freeSize, false);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_2trace(DBLL_debugMask, GT_5CLASS,
++ "Remote dealloc: base = 0x%lx len ="
++ "0x%lx\n", info->load_addr / DSPWORDSIZE,
++ freeSize / DSPWORDSIZE);
++ }
++}
++
++/* Dynamic_Loader_Initialize */
++/*
++ * ======== connect ========
++ */
++static int connect(struct Dynamic_Loader_Initialize *this)
++{
++ return true;
++}
++
++/*
++ * ======== readMem ========
++ * This function does not need to be implemented.
++ */
++static int readMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nbytes)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ int bytesRead = 0;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* Need WMD_BRD_Read function */
++ return bytesRead;
++}
++
++/*
++ * ======== writeMem ========
++ */
++static int writeMem(struct Dynamic_Loader_Initialize *this, void *buf,
++ LDR_ADDR addr, struct LDR_SECTION_INFO *info,
++ unsigned nBytes)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ struct DBLL_SectInfo sectInfo;
++ u32 memType;
++ bool retVal = true;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++
++ memType = (DLOAD_SECTION_TYPE(info->type) == DLOAD_TEXT) ? DBLL_CODE :
++ DBLL_DATA;
++ if (lib != NULL) {
++ retVal = (*lib->pTarget->attrs.write)(lib->pTarget->
++ attrs.wHandle, addr, buf, nBytes, memType);
++ }
++ if (lib->pTarget->attrs.logWrite) {
++ sectInfo.name = info->name;
++ sectInfo.runAddr = info->run_addr;
++ sectInfo.loadAddr = info->load_addr;
++ sectInfo.size = info->size;
++ sectInfo.type = memType;
++ /* Pass the information about what we've written to
++ * another module */
++ (*lib->pTarget->attrs.logWrite)(lib->pTarget->
++ attrs.logWriteHandle, &sectInfo, addr, nBytes);
++ }
++ return retVal;
++}
++
++/*
++ * ======== fillMem ========
++ * Fill nBytes of memory at a given address with a given value by
++ * writing from a buffer containing the given value. Write in
++ * sets of MAXEXPR (128) bytes to avoid large stack buffer issues.
++ */
++static int fillMem(struct Dynamic_Loader_Initialize *this, LDR_ADDR addr,
++ struct LDR_SECTION_INFO *info, unsigned nBytes,
++ unsigned val)
++{
++ bool retVal = true;
++ char *pBuf;
++ struct DBLL_LibraryObj *lib;
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ pBuf = NULL;
++ /* Pass the NULL pointer to writeMem to get the start address of Shared
++ memory. This is a trick to just get the start address, there is no
++ writing taking place with this Writemem
++ */
++ if ((lib->pTarget->attrs.write) != (DBLL_WriteFxn)NoOp)
++ writeMem(this, &pBuf, addr, info, 0);
++ if (pBuf)
++ memset(pBuf, val, nBytes);
++
++ return retVal;
++}
++
++/*
++ * ======== execute ========
++ */
++static int execute(struct Dynamic_Loader_Initialize *this, LDR_ADDR start)
++{
++ struct DBLLInit *pInit = (struct DBLLInit *)this;
++ struct DBLL_LibraryObj *lib;
++ bool retVal = true;
++
++ DBC_Require(this != NULL);
++ lib = pInit->lib;
++ DBC_Require(MEM_IsValidHandle(lib, DBLL_LIBSIGNATURE));
++ /* Save entry point */
++ if (lib != NULL)
++ lib->entry = (u32)start;
++
++ return retVal;
++}
++
++/*
++ * ======== release ========
++ */
++static void release(struct Dynamic_Loader_Initialize *this)
++{
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dev.c b/drivers/dsp/bridge/pmgr/dev.c
+new file mode 100644
+index 0000000..1c2f7d5
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dev.c
+@@ -0,0 +1,1476 @@
++/*
++ * dev.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dev.c ========
++ * Description:
++ * Implementation of 'Bridge Mini-driver device operations.
++ *
++ * Public Functions:
++ * DEV_BrdWriteFxn
++ * DEV_CreateDevice
++ * DEV_Create2
++ * DEV_Destroy2
++ * DEV_DestroyDevice
++ * DEV_GetChnlMgr
++ * DEV_GetCmmMgr
++ * DEV_GetCodMgr
++ * DEV_GetDehMgr
++ * DEV_GetDevNode
++ * DEV_GetDSPWordSize
++ * DEV_GetFirst
++ * DEV_GetIntfFxns
++ * DEV_GetIOMgr
++ * DEV_GetNext
++ * DEV_GetNodeManager
++ * DEV_GetSymbol
++ * DEV_GetWMDContext
++ * DEV_Exit
++ * DEV_Init
++ * DEV_InsertProcObject
++ * DEV_IsLocked
++ * DEV_NotifyClient
++ * DEV_RegisterNotify
++ * DEV_ReleaseCodMgr
++ * DEV_RemoveDevice
++ * DEV_RemoveProcObject
++ * DEV_SetChnlMgr
++ * DEV_SetMsgMgr
++ * DEV_SetLockOwner
++ * DEV_StartDevice
++ *
++ * Private Functions:
++ * FxnNotImplemented
++ * InitCodMgr
++ * InsertDevObject
++ * IsValidHandle
++ * RemoveDevObject
++ * StoreInterfaceFxns
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Jan-2005 hn Support for IVA DEH
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 09-Feb-2004 vp Updated to support IVA.
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 29-Nov-2001 jeh Check for DSP_ENOTIMPL status of DEH create function.
++ *! 05-Nov-2001 kc Added support for DEH module.
++ *! 05-Aug-2001 ag Shared memory registration moved to WMD_IO_OnLoaded().
++ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
++ *! 11-Apr-2001 rr: Removed CMM_RegisterGPPSMSeg.
++ *! 02-Apr-2001 rr: CHNL_Create failure is printed out.
++ *! 15-Jan-2001 jeh Removed call to IO_OnLoaded() from DEV_Create2().
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name update.
++ *! 15-Dec-2000 rr: Dev_Create2 returns error if NODE_CreateMgr fails.
++ *! 05-Dec-2000 jeh Moved IO_OnLoaded() to PROC_Load. Added DEV_SetMsgMgr.
++ *! 05-Dev-2000 ag SM Heap for messaging registered via CMM_RegisterGPPSMSeg().
++ *! SM heap base and size currently taken from registry.
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 17-Nov-2000 jeh Added calls to get IO manager (IO_Create), IO_OnLoaded().
++ *! 06-Oct-2000 rr: DEV_Destroy2 and DEV_Create2 added.
++ *! 02-Oct-2000 rr: DEV_GetNodeManager added.
++ *! 11-Aug-2000 ag: Added DEV_GetCmmMgr(), CMM_Init() & CMM_Exit().
++ *! Removed <dspbridge/std.h> & <stdwin.h>, added <dspbridge/dbtype.h>
++ *! 10-Aug-2000 rr: DEV_InsertProcObject/RemoveProcObject added.
++ *! DEV_Cleanup calls PROC_Detach if it is a matching process.
++ *! 27-Jul-2000 rr: DEV is in new directoy DEV and produces devlib.lib
++ *! 17-Jul-2000 rr: DRV Object holds the list of Dev Objects. DEV gets
++ *! the List and Next devices through DRV.
++ *! DEV object has a back pointer to DRV Object.
++ *! 06-Jun-2000 jeh Added DEV_GetSymbol().
++ *! 09-May-2000 rr: dwMemBase has index for multiple windows need.
++ *! 28-Feb-2000 rr: New GT Usage implemented.
++ *! 03-Feb-2000 rr: GT and Module init/exit Changes.(Done up front from
++ *! SERVICES)
++ *! 31-Jan-2000 rr: Comments changed after code review.
++ *! 21-Jan-2000 rr: windows.h, tchar.h, HMODULE removed. FreeLibrary replaced
++ *! with LDR_FreeModule
++ *! 17-Jan-2000 rr: CFG_Get/SetPrivateDword renamed to CFG_Get/SetDevObject.
++ *! StoreInterfaceFxns stores the new fxn WMD_BRD_SETSTATE.
++ *! 20-Nov-1999 ag: Actual uSMLength = total - monitor offset.
++ *! 12-Nov-1999 rr: bIRQ and IRQAttrib taken from the struct CFG_HOSTRES.
++ *! dMemBase is added with offset for monitor taken from
++ *! registry.
++ *! 31-Oct-1999 ag: Added CHNL support.
++ *! 10-Sep-1999 rr: GT Enabled. DEV_Create will Load the Mini Driver and will
++ *! find its fxn table. Right now lot of things are hardcoded
++ *! as the REG is not ready.
++ *! 10-Jun-1996 rr: Created from WSX
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/ldr.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++#include <dspbridge/wcd.h> /* WCD version info. */
++
++#include <dspbridge/chnl.h>
++#include <dspbridge/io.h>
++#include <dspbridge/msg.h>
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++#define SIGNATURE 0x5f564544 /* "DEV_" (in reverse) */
++#define MAKEVERSION(major, minor) (major * 10 + minor)
++#define WCDVERSION MAKEVERSION(WCD_MAJOR_VERSION, WCD_MINOR_VERSION)
++
++/* The WMD device object: */
++struct DEV_OBJECT {
++ /* LST requires "link" to be first field! */
++ struct LST_ELEM link; /* Link to next DEV_OBJECT. */
++ u32 devType; /* Device Type */
++ u32 dwSignature; /* Used for object validation. */
++ struct CFG_DEVNODE *hDevNode; /* Platform specific device id */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
++ struct WMD_DRV_INTERFACE intfFxns; /* Function interface to WMD. */
++ struct BRD_OBJECT *lockOwner; /* Client with exclusive access. */
++ struct COD_MANAGER *hCodMgr; /* Code manager handle. */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager. */
++ struct DEH_MGR *hDehMgr; /* DEH manager. */
++ struct MSG_MGR *hMsgMgr; /* Message manager. */
++ struct IO_MGR *hIOMgr; /* IO manager (CHNL, MSG) */
++ struct CMM_OBJECT *hCmmMgr; /* SM memory manager. */
++ struct DMM_OBJECT *hDmmMgr; /* Dynamic memory manager. */
++ struct LDR_MODULE *hModule; /* WMD Module handle. */
++ u32 uWordSize; /* DSP word size: quick access. */
++ struct DRV_OBJECT *hDrvObject; /* Driver Object */
++ struct LST_LIST *procList; /* List of Proceeosr attached to
++ * this device */
++ struct NODE_MGR *hNodeMgr;
++} ;
++
++/* ----------------------------------- Globals */
++static u32 cRefs; /* Module reference count */
++#if GT_TRACE
++static struct GT_Mask debugMask = { NULL, NULL }; /* For debugging */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS FxnNotImplemented(int arg, ...);
++static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject);
++static bool IsValidHandle(struct DEV_OBJECT *hObj);
++static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
++ OUT struct WMD_DRV_INTERFACE *pIntfFxns);
++/*
++ * ======== DEV_BrdWriteFxn ========
++ * Purpose:
++ * Exported function to be used as the COD write function. This function
++ * is passed a handle to a DEV_hObject, then calls the
++ * device's WMD_BRD_Write() function.
++ */
++u32 DEV_BrdWriteFxn(void *pArb, u32 ulDspAddr, void *pHostBuf,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)pArb;
++ u32 ulWritten = 0;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pHostBuf != NULL); /* Required of BrdWrite(). */
++ GT_5trace(debugMask, GT_ENTER,
++ "Entered DEV_BrdWriteFxn, pArb: 0x%x\n\t\t"
++ "ulDspAddr: 0x%x\n\t\tpHostBuf: 0x%x\n \t\tulNumBytes: 0x%x\n"
++ "\t\tnMemSpace: 0x%x\n", pArb, ulDspAddr, pHostBuf,
++ ulNumBytes, nMemSpace);
++ if (IsValidHandle(pDevObject)) {
++ /* Require of BrdWrite() */
++ DBC_Assert(pDevObject->hWmdContext != NULL);
++ status = (*pDevObject->intfFxns.pfnBrdWrite)(pDevObject->
++ hWmdContext, pHostBuf, ulDspAddr, ulNumBytes,
++ nMemSpace);
++ /* Special case of getting the address only */
++ if (ulNumBytes == 0)
++ ulNumBytes = 1;
++ if (DSP_SUCCEEDED(status))
++ ulWritten = ulNumBytes;
++
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_BrdWriteFxn ulWritten: 0x%x\n",
++ ulWritten);
++ return ulWritten;
++}
++
++/*
++ * ======== DEV_CreateDevice ========
++ * Purpose:
++ * Called by the operating system to load the PM Mini Driver for a
++ * PM board (device).
++ */
++DSP_STATUS DEV_CreateDevice(OUT struct DEV_OBJECT **phDevObject,
++ IN CONST char *pstrWMDFileName,
++ IN CONST struct CFG_HOSTRES *pHostConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig,
++ struct CFG_DEVNODE *hDevNode)
++{
++ struct LDR_MODULE *hModule = NULL;
++ struct WMD_DRV_INTERFACE *pDrvFxns = NULL;
++ struct DEV_OBJECT *pDevObject = NULL;
++ struct CHNL_MGRATTRS mgrAttrs;
++ struct IO_ATTRS ioMgrAttrs;
++ u32 uNumWindows;
++ struct DRV_OBJECT *hDrvObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevObject != NULL);
++ DBC_Require(pstrWMDFileName != NULL);
++ DBC_Require(pHostConfig != NULL);
++ DBC_Require(pDspConfig != NULL);
++
++ GT_5trace(debugMask, GT_ENTER,
++ "Entered DEV_CreateDevice, phDevObject: 0x%x\n"
++ "\t\tpstrWMDFileName: 0x%x\n\t\tpHostConfig:0x%x\n\t\t"
++ "pDspConfig: 0x%x\n\t\tnhDevNode: 0x%x\n", phDevObject,
++ pstrWMDFileName, pHostConfig, pDspConfig, hDevNode);
++ /* Get the WMD interface functions*/
++ WMD_DRV_Entry(&pDrvFxns, pstrWMDFileName);
++ if (DSP_FAILED(CFG_GetObject((u32 *) &hDrvObject, REG_DRV_OBJECT))) {
++ /* don't propogate CFG errors from this PROC function */
++ GT_0trace(debugMask, GT_7CLASS,
++ "Failed to get the DRV Object \n");
++ status = DSP_EFAIL;
++ }
++ /* Create the device object, and pass a handle to the WMD for
++ * storage. */
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(pDrvFxns);
++ MEM_AllocObject(pDevObject, struct DEV_OBJECT, SIGNATURE);
++ if (pDevObject) {
++ /* Fill out the rest of the Dev Object structure: */
++ pDevObject->hDevNode = hDevNode;
++ pDevObject->hModule = hModule;
++ pDevObject->hCodMgr = NULL;
++ pDevObject->hChnlMgr = NULL;
++ pDevObject->hDehMgr = NULL;
++ pDevObject->lockOwner = NULL;
++ pDevObject->uWordSize = pDspConfig->uWordSize;
++ pDevObject->hDrvObject = hDrvObject;
++ pDevObject->devType = DSP_UNIT;
++ /* Store this WMD's interface functions, based on its
++ * version. */
++ StoreInterfaceFxns(pDrvFxns, &pDevObject->intfFxns);
++ /* Call WMD_DEV_CREATE() to get the WMD's device
++ * context handle. */
++ status = (pDevObject->intfFxns.pfnDevCreate)
++ (&pDevObject->hWmdContext, pDevObject,
++ pHostConfig, pDspConfig);
++ /* Assert WMD_DEV_Create()'s ensure clause: */
++ DBC_Assert(DSP_FAILED(status) || (pDevObject->
++ hWmdContext != NULL));
++ } else {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Out Of Memory");
++ status = DSP_EMEMORY;
++ }
++ }
++ /* Attempt to create the COD manager for this device: */
++ if (DSP_SUCCEEDED(status))
++ status = InitCodMgr(pDevObject);
++
++ /* Attempt to create the channel manager for this device: */
++ if (DSP_SUCCEEDED(status)) {
++ mgrAttrs.cChannels = CHNL_MAXCHANNELS;
++ ioMgrAttrs.bIRQ = pHostConfig->bIRQRegisters;
++ ioMgrAttrs.fShared = (pHostConfig->bIRQAttrib & CFG_IRQSHARED);
++ ioMgrAttrs.uWordSize = pDspConfig->uWordSize;
++ mgrAttrs.uWordSize = pDspConfig->uWordSize;
++ uNumWindows = pHostConfig->wNumMemWindows;
++ if (uNumWindows) {
++ /* Assume last memory window is for CHNL */
++ ioMgrAttrs.dwSMBase = pHostConfig->dwMemBase[1] +
++ pHostConfig->dwOffsetForMonitor;
++ ioMgrAttrs.uSMLength = pHostConfig->dwMemLength[1] -
++ pHostConfig->dwOffsetForMonitor;
++ } else {
++ ioMgrAttrs.dwSMBase = 0;
++ ioMgrAttrs.uSMLength = 0;
++ GT_0trace(debugMask, GT_7CLASS,
++ "**There is no memory reserved for "
++ "shared structures**\n");
++ }
++ status = CHNL_Create(&pDevObject->hChnlMgr, pDevObject,
++ &mgrAttrs);
++ if (status == DSP_ENOTIMPL) {
++ /* It's OK for a device not to have a channel
++ * manager: */
++ status = DSP_SOK;
++ }
++ /* Create CMM mgr even if Msg Mgr not impl. */
++ status = CMM_Create(&pDevObject->hCmmMgr,
++ (struct DEV_OBJECT *)pDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Failed to Create SM "
++ "Manager\n");
++ }
++ /* Only create IO manager if we have a channel manager */
++ if (DSP_SUCCEEDED(status) && pDevObject->hChnlMgr) {
++ status = IO_Create(&pDevObject->hIOMgr, pDevObject,
++ &ioMgrAttrs);
++ }
++ /* Only create DEH manager if we have an IO manager */
++ if (DSP_SUCCEEDED(status)) {
++ /* Instantiate the DEH module */
++ status = (*pDevObject->intfFxns.pfnDehCreate)
++ (&pDevObject->hDehMgr, pDevObject);
++ }
++ /* Create DMM mgr . */
++ status = DMM_Create(&pDevObject->hDmmMgr,
++ (struct DEV_OBJECT *)pDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_Create: Failed to Create DMM "
++ "Manager\n");
++ }
++ }
++ /* Add the new DEV_Object to the global list: */
++ if (DSP_SUCCEEDED(status)) {
++ LST_InitElem(&pDevObject->link);
++ status = DRV_InsertDevObject(hDrvObject, pDevObject);
++ }
++ /* Create the Processor List */
++ if (DSP_SUCCEEDED(status)) {
++ pDevObject->procList = LST_Create();
++ if (!(pDevObject->procList)) {
++ status = DSP_EFAIL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Create: "
++ "Failed to Create Proc List");
++ }
++ }
++ /* If all went well, return a handle to the dev object;
++ * else, cleanup and return NULL in the OUT parameter. */
++ if (DSP_SUCCEEDED(status)) {
++ *phDevObject = pDevObject;
++ GT_1trace(debugMask, GT_1CLASS,
++ "DEV_CreateDevice Succeeded \nDevObject "
++ "0x%x\n", pDevObject);
++ } else {
++ if (pDevObject && pDevObject->procList)
++ LST_Delete(pDevObject->procList);
++
++ if (pDevObject && pDevObject->hCodMgr)
++ COD_Delete(pDevObject->hCodMgr);
++
++ if (pDevObject && pDevObject->hDmmMgr)
++ DMM_Destroy(pDevObject->hDmmMgr);
++
++ if (pDevObject)
++ MEM_FreeObject(pDevObject);
++
++ *phDevObject = NULL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_CreateDevice Failed\n");
++ }
++ GT_1trace(debugMask, GT_1CLASS, "Exiting DEV_Create: DevObject 0x%x\n",
++ *phDevObject);
++ DBC_Ensure((DSP_SUCCEEDED(status) && IsValidHandle(*phDevObject)) ||
++ (DSP_FAILED(status) && !*phDevObject));
++ return status;
++}
++
++/*
++ * ======== DEV_Create2 ========
++ * Purpose:
++ * After successful loading of the image from WCD_InitComplete2
++ * (PROC Auto_Start) or PROC_Load this fxn is called. This creates
++ * the Node Manager and updates the DEV Object.
++ */
++DSP_STATUS DEV_Create2(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_Create2, hDevObject: 0x%x\n", hDevObject);
++ /* There can be only one Node Manager per DEV object */
++ DBC_Assert(!pDevObject->hNodeMgr);
++ status = NODE_CreateMgr(&pDevObject->hNodeMgr, hDevObject);
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_Create2: NODE_CreateMgr failed, "
++ "0x%x!\n", status);
++ pDevObject->hNodeMgr = NULL;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Create2: Failed!!\n");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr != NULL)
++ || (DSP_FAILED(status) && pDevObject->hNodeMgr == NULL));
++ GT_2trace(debugMask, GT_ENTER,
++ "Exiting DEV_Create2, hNodeMgr: 0x%x, status:"
++ " 0x%x\n", pDevObject->hNodeMgr, status);
++ return status;
++}
++
++/*
++ * ======== DEV_Destroy2 ========
++ * Purpose:
++ * Destroys the Node manager for this device.
++ */
++DSP_STATUS DEV_Destroy2(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_Destroy2, hDevObject: 0x%x\n",
++ hDevObject);
++ if (pDevObject->hNodeMgr) {
++ if (DSP_FAILED(NODE_DeleteMgr(pDevObject->hNodeMgr)))
++ status = DSP_EFAIL;
++ else
++ pDevObject->hNodeMgr = NULL;
++
++ }
++ if (DSP_FAILED(status))
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy2 failed!!\n");
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevObject->hNodeMgr == NULL) ||
++ DSP_FAILED(status));
++ GT_2trace(debugMask, GT_ENTER,
++ "Exiting DEV_Destroy2, hNodeMgr: 0x%x, status"
++ " = 0x%x\n", pDevObject->hNodeMgr, status);
++ return status;
++}
++
++/*
++ * ======== DEV_DestroyDevice ========
++ * Purpose:
++ * Destroys the channel manager for this device, if any, calls
++ * WMD_DEV_Destroy(), and then attempts to unload the WMD module.
++ */
++DSP_STATUS DEV_DestroyDevice(struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(debugMask, GT_ENTER, "Entered DEV_DestroyDevice, hDevObject: "
++ "0x%x\n", hDevObject);
++ if (IsValidHandle(hDevObject)) {
++ if (pDevObject->hCodMgr)
++ COD_Delete(pDevObject->hCodMgr);
++
++ if (pDevObject->hNodeMgr)
++ NODE_DeleteMgr(pDevObject->hNodeMgr);
++
++ /* Free the io, channel, and message managers for this board: */
++ if (pDevObject->hIOMgr) {
++ IO_Destroy(pDevObject->hIOMgr);
++ pDevObject->hIOMgr = NULL;
++ }
++ if (pDevObject->hChnlMgr) {
++ CHNL_Destroy(pDevObject->hChnlMgr);
++ pDevObject->hChnlMgr = NULL;
++ }
++ if (pDevObject->hMsgMgr)
++ MSG_Delete(pDevObject->hMsgMgr);
++
++ if (pDevObject->hDehMgr) {
++ /* Uninitialize DEH module. */
++ (*pDevObject->intfFxns.pfnDehDestroy)
++ (pDevObject->hDehMgr);
++ }
++ if (pDevObject->hCmmMgr)
++ CMM_Destroy(pDevObject->hCmmMgr, true);
++
++ if (pDevObject->hDmmMgr)
++ DMM_Destroy(pDevObject->hDmmMgr);
++
++ /* Call the driver's WMD_DEV_Destroy() function: */
++ /* Require of DevDestroy */
++ DBC_Assert(pDevObject->hWmdContext != NULL);
++ status = (*pDevObject->intfFxns.pfnDevDestroy)
++ (pDevObject->hWmdContext);
++ if (DSP_SUCCEEDED(status)) {
++ if (pDevObject->procList)
++ LST_Delete(pDevObject->procList);
++
++ /* Remove this DEV_Object from the global list: */
++ DRV_RemoveDevObject(pDevObject->hDrvObject, pDevObject);
++ /* Free The library * LDR_FreeModule
++ * (pDevObject->hModule);*/
++ /* Free this dev object: */
++ MEM_FreeObject(pDevObject);
++ }
++ } else {
++ GT_0trace(debugMask, GT_7CLASS, "DEV_Destroy: Invlaid handle");
++ status = DSP_EHANDLE;
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_destroy: status 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_GetChnlMgr ========
++ * Purpose:
++ * Retrieve the handle to the channel manager handle created for this
++ * device.
++ */
++DSP_STATUS DEV_GetChnlMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CHNL_MGR **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetChnlMgr, hDevObject: 0x%x\n\t"
++ "\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hChnlMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetChnlMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetChnlMgr: status 0x%x\t\n hMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetCmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the shared memory manager created for this
++ * device.
++ */
++DSP_STATUS DEV_GetCmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct CMM_OBJECT **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetCmmMgr, hDevObject: 0x%x\n\t"
++ "\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hCmmMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetCmmMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetCmmMgr: status 0x%x\t\nhMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetDmmMgr ========
++ * Purpose:
++ * Retrieve the handle to the dynamic memory manager created for this
++ * device.
++ */
++DSP_STATUS DEV_GetDmmMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DMM_OBJECT **phMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER, "Entered DEV_GetDmmMgr, hDevObject: "
++ "0x%x\n\t\tphMgr: 0x%x\n", hDevObject, phMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phMgr = pDevObject->hDmmMgr;
++ } else {
++ *phMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDmmMgr: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetDmmMgr: status 0x%x\t\n hMgr: "
++ "0x%x\n", status, *phMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phMgr != NULL) &&
++ (*phMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetCodMgr ========
++ * Purpose:
++ * Retrieve the COD manager create for this device.
++ */
++DSP_STATUS DEV_GetCodMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct COD_MANAGER **phCodMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phCodMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetCodMgr, hDevObject: 0x%x\n\t\t"
++ "phCodMgr: 0x%x\n", hDevObject, phCodMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phCodMgr = pDevObject->hCodMgr;
++ } else {
++ *phCodMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_GetCodMgr, invalid handle: 0x%x\n",
++ hDevObject);
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetCodMgr: status 0x%x\t\n hCodMgr:"
++ " 0x%x\n", status, *phCodMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phCodMgr != NULL) &&
++ (*phCodMgr == NULL)));
++ return status;
++}
++
++/*
++ * ========= DEV_GetDehMgr ========
++ */
++DSP_STATUS DEV_GetDehMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct DEH_MGR **phDehMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDehMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++ if (IsValidHandle(hDevObject)) {
++ *phDehMgr = hDevObject->hDehMgr;
++ } else {
++ *phDehMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDehMgr: Invalid handle");
++ }
++ return status;
++}
++
++/*
++ * ======== DEV_GetDevNode ========
++ * Purpose:
++ * Retrieve the platform specific device ID for this device.
++ */
++DSP_STATUS DEV_GetDevNode(struct DEV_OBJECT *hDevObject,
++ OUT struct CFG_DEVNODE **phDevNode)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevNode != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetDevNode, hDevObject: 0x%x\n\t"
++ "\tphDevNode: 0x%x\n", hDevObject, phDevNode);
++ if (IsValidHandle(hDevObject)) {
++ *phDevNode = pDevObject->hDevNode;
++ } else {
++ *phDevNode = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetDevNode: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetDevNode: status 0x%x\t\nhDevNode:"
++ "0x%x\n", status, *phDevNode);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phDevNode != NULL) &&
++ (*phDevNode == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetFirst ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list
++ * DEV_OBJECTs maintained by DEV.
++ */
++struct DEV_OBJECT *DEV_GetFirst(void)
++{
++ struct DEV_OBJECT *pDevObject = NULL;
++
++ pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++
++ DBC_Ensure((pDevObject == NULL) || IsValidHandle(pDevObject));
++
++ return pDevObject;
++}
++
++/*
++ * ======== DEV_GetIntfFxns ========
++ * Purpose:
++ * Retrieve the WMD interface function structure for the loaded WMD.
++ * ppIntfFxns != NULL.
++ */
++DSP_STATUS DEV_GetIntfFxns(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DRV_INTERFACE **ppIntfFxns)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(ppIntfFxns != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetIntfFxns, hDevObject: 0x%x\n\t"
++ "\tppIntfFxns: 0x%x\n", hDevObject, ppIntfFxns);
++ if (IsValidHandle(hDevObject)) {
++ *ppIntfFxns = &pDevObject->intfFxns;
++ } else {
++ *ppIntfFxns = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetIntDxns: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetIntFxns: status 0x%x\t\n"
++ "ppIntFxns: 0x%x\n", status, *ppIntfFxns);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((ppIntfFxns != NULL) &&
++ (*ppIntfFxns == NULL)));
++ return status;
++}
++
++/*
++ * ========= DEV_GetIOMgr ========
++ */
++DSP_STATUS DEV_GetIOMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct IO_MGR **phIOMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++
++ if (IsValidHandle(hDevObject)) {
++ *phIOMgr = hDevObject->hIOMgr;
++ } else {
++ *phIOMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS, "DEV_GetIOMgr: Invalid handle");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DEV_GetNext ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list
++ * of DEV_OBJECTs maintained by DEV, after having previously called
++ * DEV_GetFirst() and zero or more DEV_GetNext
++ */
++struct DEV_OBJECT *DEV_GetNext(struct DEV_OBJECT *hDevObject)
++{
++ struct DEV_OBJECT *pNextDevObject = NULL;
++
++ if (IsValidHandle(hDevObject)) {
++ pNextDevObject = (struct DEV_OBJECT *)
++ DRV_GetNextDevObject((u32)hDevObject);
++ }
++ DBC_Ensure((pNextDevObject == NULL) || IsValidHandle(pNextDevObject));
++ return pNextDevObject;
++}
++
++/*
++ * ========= DEV_GetMsgMgr ========
++ */
++void DEV_GetMsgMgr(struct DEV_OBJECT *hDevObject,
++ OUT struct MSG_MGR **phMsgMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(MEM_IsValidHandle(hDevObject, SIGNATURE));
++
++ *phMsgMgr = hDevObject->hMsgMgr;
++}
++
++/*
++ * ======== DEV_GetNodeManager ========
++ * Purpose:
++ * Retrieve the Node Manager Handle
++ */
++DSP_STATUS DEV_GetNodeManager(struct DEV_OBJECT *hDevObject,
++ OUT struct NODE_MGR **phNodeMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNodeMgr != NULL);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetNodeManager, hDevObject: 0x%x"
++ "\n\t\tphNodeMgr: 0x%x\n", hDevObject, phNodeMgr);
++ if (IsValidHandle(hDevObject)) {
++ *phNodeMgr = pDevObject->hNodeMgr;
++ } else {
++ *phNodeMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_1trace(debugMask, GT_7CLASS,
++ "DEV_GetNodeManager, invalid handle: 0x"
++ "%x\n", hDevObject);
++ }
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetNodeManager: status 0x%x\t\nhMgr:"
++ " 0x%x\n", status, *phNodeMgr);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phNodeMgr != NULL) &&
++ (*phNodeMgr == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_GetSymbol ========
++ */
++DSP_STATUS DEV_GetSymbol(struct DEV_OBJECT *hDevObject,
++ IN CONST char *pstrSym, OUT u32 *pulValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct COD_MANAGER *hCodMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pstrSym != NULL && pulValue != NULL);
++
++ GT_3trace(debugMask, GT_ENTER,
++ "Entered DEV_GetSymbol, hDevObject: 0x%x\n\t\t"
++ "pstrSym: 0x%x\n\t\tpulValue: 0x%x\n", hDevObject, pstrSym,
++ pulValue);
++ if (IsValidHandle(hDevObject)) {
++ status = DEV_GetCodMgr(hDevObject, &hCodMgr);
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(hCodMgr != NULL);
++ status = COD_GetSymValue(hCodMgr, (char *)pstrSym,
++ pulValue);
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetSymbol: Invalid handle");
++ }
++ GT_2trace(debugMask, GT_ENTER, "Exit DEV_GetSymbol: status 0x%x\t\n"
++ "hWmdContext: 0x%x\n", status, *pulValue);
++ return status;
++}
++
++/*
++ * ======== DEV_GetWMDContext ========
++ * Purpose:
++ * Retrieve the WMD Context handle, as returned by the WMD_Create fxn.
++ */
++DSP_STATUS DEV_GetWMDContext(struct DEV_OBJECT *hDevObject,
++ OUT struct WMD_DEV_CONTEXT **phWmdContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phWmdContext != NULL);
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_GetWMDContext, hDevObject: 0x%x\n"
++ "\t\tphWmdContext: 0x%x\n", hDevObject, phWmdContext);
++ if (IsValidHandle(hDevObject)) {
++ *phWmdContext = pDevObject->hWmdContext;
++ } else {
++ *phWmdContext = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_GetWMDContext: Invalid handle");
++ }
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Exit DEV_GetWMDContext: status 0x%x\t\n"
++ "hWmdContext: 0x%x\n", status, *phWmdContext);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phWmdContext != NULL) &&
++ (*phWmdContext == NULL)));
++ return status;
++}
++
++/*
++ * ======== DEV_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void DEV_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ if (cRefs == 0) {
++ CMM_Exit();
++ DMM_Exit();
++ }
++
++ GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Exit, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DEV_Init ========
++ * Purpose:
++ * Initialize DEV's private state, keeping a reference count on each call.
++ */
++bool DEV_Init(void)
++{
++ bool fCmm, fDmm, fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ DBC_Assert(!debugMask.flags);
++ GT_create(&debugMask, "DV"); /* "DV" for DeVice */
++ fCmm = CMM_Init();
++ fDmm = DMM_Init();
++
++ fRetval = fCmm && fDmm;
++
++ if (!fRetval) {
++ if (fCmm)
++ CMM_Exit();
++
++
++ if (fDmm)
++ DMM_Exit();
++
++ }
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(debugMask, GT_5CLASS, "Entered DEV_Init, ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== DEV_NotifyClients ========
++ * Purpose:
++ * Notify all clients of this device of a change in device status.
++ */
++DSP_STATUS DEV_NotifyClients(struct DEV_OBJECT *hDevObject, u32 ulStatus)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ struct DEV_OBJECT *pDevObject = hDevObject;
++ DSP_HPROCESSOR hProcObject;
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_NotifyClients, hDevObject: 0x%x\n"
++ "\t\tulStatus: 0x%x\n", hDevObject, ulStatus);
++ for (hProcObject = (DSP_HPROCESSOR)LST_First(pDevObject->procList);
++ hProcObject != NULL;
++ hProcObject = (DSP_HPROCESSOR)LST_Next(pDevObject->procList,
++ (struct LST_ELEM *)hProcObject))
++ PROC_NotifyClients(hProcObject, (u32) ulStatus);
++
++ return status;
++}
++
++/*
++ * ======== DEV_RemoveDevice ========
++ */
++DSP_STATUS DEV_RemoveDevice(struct CFG_DEVNODE *hDevNode)
++{
++ struct DEV_OBJECT *hDevObject; /* handle to device object */
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject;
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_RemoveDevice, hDevNode: 0x%x\n", hDevNode);
++ /* Retrieve the device object handle originaly stored with
++ * the DevNode: */
++ status = CFG_GetDevObject(hDevNode, (u32 *)&hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ /* Remove the Processor List */
++ pDevObject = (struct DEV_OBJECT *)hDevObject;
++ /* Destroy the device object. */
++ status = DEV_DestroyDevice(hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ /* Null out the handle stored with the DevNode. */
++ GT_0trace(debugMask, GT_1CLASS,
++ "DEV_RemoveDevice, success");
++ }
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exit DEV_RemoveDevice, status: 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_SetChnlMgr ========
++ * Purpose:
++ * Set the channel manager for this device.
++ */
++DSP_STATUS DEV_SetChnlMgr(struct DEV_OBJECT *hDevObject, struct CHNL_MGR *hMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = hDevObject;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_SetChnlMgr, hDevObject: 0x%x\n\t"
++ "\thMgr:0x%x\n", hDevObject, hMgr);
++ if (IsValidHandle(hDevObject)) {
++ pDevObject->hChnlMgr = hMgr;
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(debugMask, GT_7CLASS,
++ "DEV_SetChnlMgr, Invalid handle\n");
++ }
++ DBC_Ensure(DSP_FAILED(status) || (pDevObject->hChnlMgr == hMgr));
++ return status;
++}
++
++/*
++ * ======== DEV_SetMsgMgr ========
++ * Purpose:
++ * Set the message manager for this device.
++ */
++void DEV_SetMsgMgr(struct DEV_OBJECT *hDevObject, struct MSG_MGR *hMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDevObject));
++ GT_2trace(debugMask, GT_ENTER,
++ "Entered DEV_SetMsgMgr, hDevObject: 0x%x\n\t\t"
++ "hMgr: 0x%x\n", hDevObject, hMgr);
++ hDevObject->hMsgMgr = hMgr;
++}
++
++/*
++ * ======== DEV_StartDevice ========
++ * Purpose:
++ * Initializes the new device with the BRIDGE environment.
++ */
++DSP_STATUS DEV_StartDevice(struct CFG_DEVNODE *hDevNode)
++{
++ struct DEV_OBJECT *hDevObject = NULL; /* handle to 'Bridge Device */
++ struct CFG_HOSTRES hostRes; /* resources struct. */
++ struct CFG_DSPRES dspRes; /* DSP resources struct */
++ char szWMDFileName[CFG_MAXSEARCHPATHLEN] = "UMA"; /* wmd filename */
++ DSP_STATUS status;
++ struct MGR_OBJECT *hMgrObject = NULL;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entered DEV_StartDevice, hDevObject: 0x%x\n", hDevNode);
++ status = CFG_GetHostResources(hDevNode, &hostRes);
++ if (DSP_SUCCEEDED(status)) {
++ /* Get DSP resources of device from Registry: */
++ status = CFG_GetDSPResources(hDevNode, &dspRes);
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to get WMD DSP resources"
++ " from registry: 0x%x ", status);
++ }
++ } else {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to get WMD Host resources "
++ "from registry: 0x%x ", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Given all resources, create a device object. */
++ status = DEV_CreateDevice(&hDevObject, szWMDFileName, &hostRes,
++ &dspRes, hDevNode);
++ if (DSP_SUCCEEDED(status)) {
++ /* Store away the hDevObject with the DEVNODE */
++ status = CFG_SetDevObject(hDevNode, (u32)hDevObject);
++ if (DSP_FAILED(status)) {
++ /* Clean up */
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to set DevObject in the "
++ "Registry: 0x%x", status);
++ DEV_DestroyDevice(hDevObject);
++ hDevObject = NULL;
++ }
++ } else {
++ GT_1trace(debugMask, GT_7CLASS,
++ "Failed to Create Device: 0x%x",
++ status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Create the Manager Object */
++ status = MGR_Create(&hMgrObject, hDevNode);
++ }
++ if (DSP_FAILED(status)) {
++ GT_1trace(debugMask, GT_7CLASS, "Failed to MGR object: 0x%x",
++ status);
++ status = DSP_EFAIL;
++ }
++ if (DSP_FAILED(status)) {
++ if (hDevObject)
++ DEV_DestroyDevice(hDevObject);
++
++ /* Ensure the device extension is NULL */
++ CFG_SetDevObject(hDevNode, 0L);
++ }
++ GT_1trace(debugMask, GT_ENTER, "Exiting DEV_StartDevice status 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== FxnNotImplemented ========
++ * Purpose:
++ * Takes the place of a WMD Null Function.
++ * Parameters:
++ * Multiple, optional.
++ * Returns:
++ * DSP_ENOTIMPL: Always.
++ */
++static DSP_STATUS FxnNotImplemented(int arg, ...)
++{
++ DBG_Trace(DBG_LEVEL1,
++ "WARNING: Calling a non-implemented WMD function.\n");
++
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== IsValidHandle ========
++ * Purpose:
++ * Validate the device object handle.
++ * Parameters:
++ * hDevObject: Handle to device object created with
++ * DEV_CreateDevice().
++ * Returns:
++ * true if handle is valid; false otherwise.
++ * Requires:
++ * Ensures:
++ */
++static bool IsValidHandle(struct DEV_OBJECT *hObj)
++{
++ bool retVal;
++
++ retVal = (hObj != NULL) && (hObj->dwSignature == SIGNATURE);
++
++ return retVal;
++}
++
++/*
++ * ======== InitCodMgr ========
++ * Purpose:
++ * Create a COD manager for this device.
++ * Parameters:
++ * pDevObject: Pointer to device object created with
++ * DEV_CreateDevice()
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EHANDLE: Invalid hDevObject.
++ * Requires:
++ * Should only be called once by DEV_CreateDevice() for a given DevObject.
++ * Ensures:
++ */
++static DSP_STATUS InitCodMgr(struct DEV_OBJECT *pDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ char *szDummyFile = "dummy";
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(!IsValidHandle(pDevObject) ||
++ (pDevObject->hCodMgr == NULL));
++ GT_1trace(debugMask, GT_ENTER, "Entering InitCodMgr pDevObject: 0x%x",
++ pDevObject);
++ status = COD_Create(&pDevObject->hCodMgr, szDummyFile, NULL);
++ GT_1trace(debugMask, GT_ENTER, "Exiting InitCodMgr status 0x%x\n ",
++ status);
++ return status;
++}
++
++/*
++ * ======== DEV_InsertProcObject ========
++ * Purpose:
++ * Insert a ProcObject into the list maintained by DEV.
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject: Ptr to Dev Object where the list is.
++ * pbAlreadyAttached: Ptr to return the bool
++ * Returns:
++ * DSP_SOK: If successful.
++ * Requires:
++ * List Exists
++ * hDevObject is Valid handle
++ * DEV Initialized
++ * pbAlreadyAttached != NULL
++ * hProcObject != 0
++ * Ensures:
++ * DSP_SOK and List is not Empty.
++ */
++DSP_STATUS DEV_InsertProcObject(struct DEV_OBJECT *hDevObject,
++ u32 hProcObject,
++ OUT bool *pbAlreadyAttached)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
++
++ GT_2trace(debugMask, GT_ENTER,
++ "Entering DEV_InsetProcObject pProcObject 0x%x"
++ "pDevObject 0x%x\n", hProcObject, hDevObject);
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(pDevObject));
++ DBC_Require(hProcObject != 0);
++ DBC_Require(pDevObject->procList != NULL);
++ DBC_Require(pbAlreadyAttached != NULL);
++ if (!LST_IsEmpty(pDevObject->procList))
++ *pbAlreadyAttached = true;
++
++ /* Add DevObject to tail. */
++ LST_PutTail(pDevObject->procList, (struct LST_ELEM *)hProcObject);
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Exiting DEV_InsetProcObject status 0x%x\n", status);
++ DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDevObject->procList));
++
++ return status;
++}
++
++/*
++ * ======== DEV_RemoveProcObject ========
++ * Purpose:
++ * Search for and remove a Proc object from the given list maintained
++ * by the DEV
++ * Parameters:
++ * pProcObject: Ptr to ProcObject to insert.
++ * pDevObject Ptr to Dev Object where the list is.
++ * Returns:
++ * DSP_SOK: If successful.
++ * Requires:
++ * List exists and is not empty
++ * hProcObject != 0
++ * hDevObject is a valid Dev handle.
++ * Ensures:
++ * Details:
++ * List will be deleted when the DEV is destroyed.
++ */
++DSP_STATUS DEV_RemoveProcObject(struct DEV_OBJECT *hDevObject,
++ u32 hProcObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct LST_ELEM *pCurElem;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hDevObject;
++
++ DBC_Require(IsValidHandle(pDevObject));
++ DBC_Require(hProcObject != 0);
++ DBC_Require(pDevObject->procList != NULL);
++ DBC_Require(!LST_IsEmpty(pDevObject->procList));
++
++ GT_1trace(debugMask, GT_ENTER,
++ "Entering DEV_RemoveProcObject hDevObject "
++ "0x%x\n", hDevObject);
++ /* Search list for pDevObject: */
++ for (pCurElem = LST_First(pDevObject->procList); pCurElem != NULL;
++ pCurElem = LST_Next(pDevObject->procList, pCurElem)) {
++ /* If found, remove it. */
++ if ((u32)pCurElem == hProcObject) {
++ LST_RemoveElem(pDevObject->procList, pCurElem);
++ status = DSP_SOK;
++ break;
++ }
++ }
++ GT_1trace(debugMask, GT_ENTER, "DEV_RemoveProcObject returning 0x%x\n",
++ status);
++ return status;
++}
++
++DSP_STATUS DEV_GetDevType(struct DEV_OBJECT *hdevObject, u32 *devType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)hdevObject;
++
++ *devType = pDevObject->devType;
++
++ return status;
++}
++
++/*
++ * ======== StoreInterfaceFxns ========
++ * Purpose:
++ * Copy the WMD's interface functions into the device object,
++ * ensuring that FxnNotImplemented() is set for:
++ *
++ * 1. All WMD function pointers which are NULL; and
++ * 2. All function slots in the struct DEV_OBJECT structure which have no
++ * corresponding slots in the the WMD's interface, because the WMD
++ * is of an *older* version.
++ * Parameters:
++ * pIntfFxns: Interface Fxn Structure of the WCD's Dev Object.
++ * pDrvFxns: Interface Fxns offered by the WMD during DEV_Create().
++ * Returns:
++ * Requires:
++ * Input pointers are valid.
++ * WMD is *not* written for a newer WCD.
++ * Ensures:
++ * All function pointers in the dev object's Fxn interface are not NULL.
++ */
++static void StoreInterfaceFxns(struct WMD_DRV_INTERFACE *pDrvFxns,
++ OUT struct WMD_DRV_INTERFACE *pIntfFxns)
++{
++ u32 dwWMDVersion;
++
++ /* Local helper macro: */
++#define StoreFxn(cast, pfn) \
++ (pIntfFxns->pfn = ((pDrvFxns->pfn != NULL) ? pDrvFxns->pfn : \
++ (cast)FxnNotImplemented))
++
++ DBC_Require(pIntfFxns != NULL);
++ DBC_Require(pDrvFxns != NULL);
++ DBC_Require(MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
++ pDrvFxns->dwWCDMinorVersion) <= WCDVERSION);
++ dwWMDVersion = MAKEVERSION(pDrvFxns->dwWCDMajorVersion,
++ pDrvFxns->dwWCDMinorVersion);
++ pIntfFxns->dwWCDMajorVersion = pDrvFxns->dwWCDMajorVersion;
++ pIntfFxns->dwWCDMinorVersion = pDrvFxns->dwWCDMinorVersion;
++ /* Install functions up to WCD version .80 (first alpha): */
++ if (dwWMDVersion > 0) {
++ StoreFxn(WMD_DEV_CREATE, pfnDevCreate);
++ StoreFxn(WMD_DEV_DESTROY, pfnDevDestroy);
++ StoreFxn(WMD_DEV_CTRL, pfnDevCntrl);
++ StoreFxn(WMD_BRD_MONITOR, pfnBrdMonitor);
++ StoreFxn(WMD_BRD_START, pfnBrdStart);
++ StoreFxn(WMD_BRD_STOP, pfnBrdStop);
++ StoreFxn(WMD_BRD_STATUS, pfnBrdStatus);
++ StoreFxn(WMD_BRD_READ, pfnBrdRead);
++ StoreFxn(WMD_BRD_WRITE, pfnBrdWrite);
++ StoreFxn(WMD_BRD_SETSTATE, pfnBrdSetState);
++ StoreFxn(WMD_BRD_MEMCOPY, pfnBrdMemCopy);
++ StoreFxn(WMD_BRD_MEMWRITE, pfnBrdMemWrite);
++ StoreFxn(WMD_BRD_MEMMAP, pfnBrdMemMap);
++ StoreFxn(WMD_BRD_MEMUNMAP, pfnBrdMemUnMap);
++ StoreFxn(WMD_CHNL_CREATE, pfnChnlCreate);
++ StoreFxn(WMD_CHNL_DESTROY, pfnChnlDestroy);
++ StoreFxn(WMD_CHNL_OPEN, pfnChnlOpen);
++ StoreFxn(WMD_CHNL_CLOSE, pfnChnlClose);
++ StoreFxn(WMD_CHNL_ADDIOREQ, pfnChnlAddIOReq);
++ StoreFxn(WMD_CHNL_GETIOC, pfnChnlGetIOC);
++ StoreFxn(WMD_CHNL_CANCELIO, pfnChnlCancelIO);
++ StoreFxn(WMD_CHNL_FLUSHIO, pfnChnlFlushIO);
++ StoreFxn(WMD_CHNL_GETINFO, pfnChnlGetInfo);
++ StoreFxn(WMD_CHNL_GETMGRINFO, pfnChnlGetMgrInfo);
++ StoreFxn(WMD_CHNL_IDLE, pfnChnlIdle);
++ StoreFxn(WMD_CHNL_REGISTERNOTIFY, pfnChnlRegisterNotify);
++ StoreFxn(WMD_DEH_CREATE, pfnDehCreate);
++ StoreFxn(WMD_DEH_DESTROY, pfnDehDestroy);
++ StoreFxn(WMD_DEH_NOTIFY, pfnDehNotify);
++ StoreFxn(WMD_DEH_REGISTERNOTIFY, pfnDehRegisterNotify);
++ StoreFxn(WMD_DEH_GETINFO, pfnDehGetInfo);
++ StoreFxn(WMD_IO_CREATE, pfnIOCreate);
++ StoreFxn(WMD_IO_DESTROY, pfnIODestroy);
++ StoreFxn(WMD_IO_ONLOADED, pfnIOOnLoaded);
++ StoreFxn(WMD_IO_GETPROCLOAD, pfnIOGetProcLoad);
++ StoreFxn(WMD_MSG_CREATE, pfnMsgCreate);
++ StoreFxn(WMD_MSG_CREATEQUEUE, pfnMsgCreateQueue);
++ StoreFxn(WMD_MSG_DELETE, pfnMsgDelete);
++ StoreFxn(WMD_MSG_DELETEQUEUE, pfnMsgDeleteQueue);
++ StoreFxn(WMD_MSG_GET, pfnMsgGet);
++ StoreFxn(WMD_MSG_PUT, pfnMsgPut);
++ StoreFxn(WMD_MSG_REGISTERNOTIFY, pfnMsgRegisterNotify);
++ StoreFxn(WMD_MSG_SETQUEUEID, pfnMsgSetQueueId);
++ }
++ /* Add code for any additional functions in newer WMD versions here: */
++ /* Ensure postcondition: */
++ DBC_Ensure(pIntfFxns->pfnDevCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnDevDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnDevCntrl != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdMonitor != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStart != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStop != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdStatus != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdRead != NULL);
++ DBC_Ensure(pIntfFxns->pfnBrdWrite != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlOpen != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlClose != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlAddIOReq != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetIOC != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlCancelIO != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlFlushIO != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlGetMgrInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlIdle != NULL);
++ DBC_Ensure(pIntfFxns->pfnChnlRegisterNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehDestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehRegisterNotify != NULL);
++ DBC_Ensure(pIntfFxns->pfnDehGetInfo != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOCreate != NULL);
++ DBC_Ensure(pIntfFxns->pfnIODestroy != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOOnLoaded != NULL);
++ DBC_Ensure(pIntfFxns->pfnIOGetProcLoad != NULL);
++ DBC_Ensure(pIntfFxns->pfnMsgSetQueueId != NULL);
++
++#undef StoreFxn
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/dmm.c b/drivers/dsp/bridge/pmgr/dmm.c
+new file mode 100644
+index 0000000..803de93
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/dmm.c
+@@ -0,0 +1,692 @@
++/*
++ * dmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== dmm.c ========
++ * Purpose:
++ * The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
++ * space that can be directly mapped to any MPU buffer or memory region
++ *
++ * Public Functions:
++ * DMM_CreateTables
++ * DMM_Create
++ * DMM_Destroy
++ * DMM_Exit
++ * DMM_Init
++ * DMM_MapMemory
++ * DMM_Reset
++ * DMM_ReserveMemory
++ * DMM_UnMapMemory
++ * DMM_UnReserveMemory
++ *
++ * Private Functions:
++ * AddRegion
++ * CreateRegion
++ * GetRegion
++ * GetFreeRegion
++ * GetMappedRegion
++ *
++ * Notes:
++ * Region: Generic memory entitiy having a start address and a size
++ * Chunk: Reserved region
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 04-Jun-2008 Hari K : Optimized DMM implementation. Removed linked list
++ *! and instead used Table approach.
++ *! 19-Apr-2004 sb: Integrated Alan's code review updates.
++ *! 17-Mar-2004 ap: Fixed GetRegion for size=0 using tighter bound.
++ *! 20-Feb-2004 sb: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/proc.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++/* Object signatures */
++#define DMMSIGNATURE 0x004d4d44 /* "DMM" (in reverse) */
++
++#define DMM_ADDR_VIRTUAL(a) \
++ (((struct MapPage *)(a) - pVirtualMappingTable) * PG_SIZE_4K +\
++ dynMemMapBeg)
++#define DMM_ADDR_TO_INDEX(a) (((a) - dynMemMapBeg) / PG_SIZE_4K)
++
++/* DMM Mgr */
++struct DMM_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ /* Dmm Lock is used to serialize access mem manager for
++ * multi-threads. */
++ struct SYNC_CSOBJECT *hDmmLock; /* Lock to access dmm mgr */
++};
++
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++struct MapPage {
++ u32 RegionSize:15;
++ u32 MappedSize:15;
++ u32 bReserved:1;
++ u32 bMapped:1;
++};
++
++/* Create the free list */
++static struct MapPage *pVirtualMappingTable;
++static u32 iFreeRegion; /* The index of free region */
++static u32 iFreeSize;
++static u32 *pPhysicalAddrTable; /* Physical address of MPU buffer */
++static u32 dynMemMapBeg; /* The Beginning of dynamic memory mapping */
++static u32 TableSize;/* The size of virtual and physical pages tables */
++
++/* ----------------------------------- Function Prototypes */
++static struct MapPage *GetRegion(u32 addr);
++static struct MapPage *GetFreeRegion(u32 aSize);
++static struct MapPage *GetMappedRegion(u32 aAddr);
++#ifdef DSP_DMM_DEBUG
++u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
++#endif
++
++/* ======== DMM_CreateTables ========
++ * Purpose:
++ * Create table to hold the information of physical address
++ * the buffer pages that is passed by the user, and the table
++ * to hold the information of the virtual memory that is reserved
++ * for DSP.
++ */
++DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_CreateTables () hDmmMgr %x, addr"
++ " %x, size %x\n", hDmmMgr, addr, size);
++ status = DMM_DeleteTables(pDmmObj);
++ if (DSP_SUCCEEDED(status)) {
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ dynMemMapBeg = addr;
++ TableSize = (size/PG_SIZE_4K) + 1;
++ /* Create the free list */
++ pVirtualMappingTable = (struct MapPage *) MEM_Calloc
++ (TableSize*sizeof(struct MapPage), MEM_NONPAGED);
++ if (pVirtualMappingTable == NULL)
++ status = DSP_EMEMORY;
++ else {
++ /* This table will be used
++ * to store the virtual to physical
++ * address translations
++ */
++ pPhysicalAddrTable = (u32 *)MEM_Calloc
++ (TableSize*sizeof(u32), MEM_NONPAGED);
++ GT_1trace(DMM_debugMask, GT_4CLASS,
++ "DMM_CreateTables: Allocate"
++ "memory for pPhysicalAddrTable=%d entries\n",
++ TableSize);
++ if (pPhysicalAddrTable == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_CreateTables: Memory allocation for "
++ "pPhysicalAddrTable failed\n");
++ } else {
++ /* On successful allocation,
++ * all entries are zero ('free') */
++ iFreeRegion = 0;
++ iFreeSize = TableSize*PG_SIZE_4K;
++ pVirtualMappingTable[0].RegionSize = TableSize;
++ }
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ } else
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_CreateTables: DMM_DeleteTables"
++ "Failure\n");
++
++ GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_CreateTables status"
++ "0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== DMM_Create ========
++ * Purpose:
++ * Create a dynamic memory manager object.
++ */
++DSP_STATUS DMM_Create(OUT struct DMM_OBJECT **phDmmMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DMM_MGRATTRS *pMgrAttrs)
++{
++ struct DMM_OBJECT *pDmmObject = NULL;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDmmMgr != NULL);
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "DMM_Create: phDmmMgr: 0x%x hDevObject: "
++ "0x%x pMgrAttrs: 0x%x\n", phDmmMgr, hDevObject, pMgrAttrs);
++ *phDmmMgr = NULL;
++ /* create, zero, and tag a cmm mgr object */
++ MEM_AllocObject(pDmmObject, struct DMM_OBJECT, DMMSIGNATURE);
++ if (pDmmObject != NULL) {
++ status = SYNC_InitializeCS(&pDmmObject->hDmmLock);
++ if (DSP_SUCCEEDED(status))
++ *phDmmMgr = pDmmObject;
++ else
++ DMM_Destroy(pDmmObject);
++ } else {
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_Create: Object Allocation "
++ "Failure(DMM Object)\n");
++ status = DSP_EMEMORY;
++ }
++ GT_2trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_Create status %x pDmmObject %x\n",
++ status, pDmmObject);
++
++ return status;
++}
++
++/*
++ * ======== DMM_Destroy ========
++ * Purpose:
++ * Release the communication memory manager resources.
++ */
++DSP_STATUS DMM_Destroy(struct DMM_OBJECT *hDmmMgr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_Destroy () hDmmMgr %x\n", hDmmMgr);
++ DBC_Require(cRefs > 0);
++ if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
++ status = DMM_DeleteTables(pDmmObj);
++ if (DSP_SUCCEEDED(status)) {
++ /* Delete CS & dmm mgr object */
++ SYNC_DeleteCS(pDmmObj->hDmmLock);
++ MEM_FreeObject(pDmmObj);
++ } else
++ GT_0trace(DMM_debugMask, GT_7CLASS,
++ "DMM_Destroy: DMM_DeleteTables "
++ "Failure\n");
++ } else
++ status = DSP_EHANDLE;
++ GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_Destroy status %x\n",
++ status);
++ return status;
++}
++
++
++/*
++ * ======== DMM_DeleteTables ========
++ * Purpose:
++ * Delete DMM Tables.
++ */
++DSP_STATUS DMM_DeleteTables(struct DMM_OBJECT *hDmmMgr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_DeleteTables () hDmmMgr %x\n", hDmmMgr);
++ DBC_Require(cRefs > 0);
++ if (MEM_IsValidHandle(hDmmMgr, DMMSIGNATURE)) {
++ /* Delete all DMM tables */
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ if (pVirtualMappingTable != NULL)
++ MEM_Free(pVirtualMappingTable);
++
++ if (pPhysicalAddrTable != NULL)
++ MEM_Free(pPhysicalAddrTable);
++
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ } else
++ status = DSP_EHANDLE;
++ GT_1trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_DeleteTables status %x\n", status);
++ return status;
++}
++
++
++
++
++/*
++ * ======== DMM_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void DMM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "exiting DMM_Exit, ref count:0x%x\n", cRefs);
++}
++
++/*
++ * ======== DMM_GetHandle ========
++ * Purpose:
++ * Return the dynamic memory manager object for this device.
++ * This is typically called from the client process.
++ */
++DSP_STATUS DMM_GetHandle(DSP_HPROCESSOR hProcessor,
++ OUT struct DMM_OBJECT **phDmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "DMM_GetHandle: hProcessor %x, phDmmMgr"
++ "%x\n", hProcessor, phDmmMgr);
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDmmMgr != NULL);
++ if (hProcessor != NULL)
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ else
++ hDevObject = DEV_GetFirst(); /* default */
++
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDmmMgr(hDevObject, phDmmMgr);
++
++ GT_2trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_GetHandle status %x, "
++ "*phDmmMgr %x\n", status, phDmmMgr ? *phDmmMgr : NULL);
++ return status;
++}
++
++/*
++ * ======== DMM_Init ========
++ * Purpose:
++ * Initializes private state of DMM module.
++ */
++bool DMM_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ /*"DM" for Dymanic Memory Manager */
++ GT_create(&DMM_debugMask, "DM");
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_Init, ref count:0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ pVirtualMappingTable = NULL ;
++ pPhysicalAddrTable = NULL ;
++ TableSize = 0;
++
++ return fRetval;
++}
++
++/*
++ * ======== DMM_MapMemory ========
++ * Purpose:
++ * Add a mapping block to the reserved chunk. DMM assumes that this block
++ * will be mapped in the DSP/IVA's address space. DMM returns an error if a
++ * mapping overlaps another one. This function stores the info that will be
++ * required later while unmapping the block.
++ */
++DSP_STATUS DMM_MapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_MapMemory () hDmmMgr %x, "
++ "addr %x, size %x\n", hDmmMgr, addr, size);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ /* Find the Reserved memory chunk containing the DSP block to
++ * be mapped */
++ chunk = (struct MapPage *)GetRegion(addr);
++ if (chunk != NULL) {
++ /* Mark the region 'mapped', leave the 'reserved' info as-is */
++ chunk->bMapped = true;
++ chunk->MappedSize = (size/PG_SIZE_4K);
++ } else
++ status = DSP_ENOTFOUND;
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_2trace(DMM_debugMask, GT_4CLASS,
++ "Leaving DMM_MapMemory status %x, chunk %x\n",
++ status, chunk);
++ return status;
++}
++
++/*
++ * ======== DMM_ReserveMemory ========
++ * Purpose:
++ * Reserve a chunk of virtually contiguous DSP/IVA address space.
++ */
++DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 size,
++ u32 *pRsvAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *node;
++ u32 rsvAddr = 0;
++ u32 rsvSize = 0;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_ReserveMemory () hDmmMgr %x, "
++ "size %x, pRsvAddr %x\n", hDmmMgr, size, pRsvAddr);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ /* Try to get a DSP chunk from the free list */
++ node = GetFreeRegion(size);
++ if (node != NULL) {
++ /* DSP chunk of given size is available. */
++ rsvAddr = DMM_ADDR_VIRTUAL(node);
++ /* Calculate the number entries to use */
++ rsvSize = size/PG_SIZE_4K;
++ if (rsvSize < node->RegionSize) {
++ /* Mark remainder of free region */
++ node[rsvSize].bMapped = false;
++ node[rsvSize].bReserved = false;
++ node[rsvSize].RegionSize = node->RegionSize - rsvSize;
++ node[rsvSize].MappedSize = 0;
++ }
++ /* GetRegion will return first fit chunk. But we only use what
++ is requested. */
++ node->bMapped = false;
++ node->bReserved = true;
++ node->RegionSize = rsvSize;
++ node->MappedSize = 0;
++ /* Return the chunk's starting address */
++ *pRsvAddr = rsvAddr;
++ } else
++ /*dSP chunk of given size is not available */
++ status = DSP_EMEMORY;
++
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_3trace(DMM_debugMask, GT_4CLASS,
++ "Leaving ReserveMemory status %x, rsvAddr"
++ " %x, rsvSize %x\n", status, rsvAddr, rsvSize);
++ return status;
++}
++
++
++/*
++ * ======== DMM_UnMapMemory ========
++ * Purpose:
++ * Remove the mapped block from the reserved chunk.
++ */
++DSP_STATUS DMM_UnMapMemory(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 *pSize)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_UnMapMemory () hDmmMgr %x, "
++ "addr %x, pSize %x\n", hDmmMgr, addr, pSize);
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++ chunk = GetMappedRegion(addr) ;
++ if (chunk == NULL)
++ status = DSP_ENOTFOUND ;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Unmap the region */
++ *pSize = chunk->MappedSize * PG_SIZE_4K;
++ chunk->bMapped = false;
++ chunk->MappedSize = 0;
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_3trace(DMM_debugMask, GT_ENTER,
++ "Leaving DMM_UnMapMemory status %x, chunk"
++ " %x, *pSize %x\n", status, chunk, *pSize);
++
++ return status;
++}
++
++/*
++ * ======== DMM_UnReserveMemory ========
++ * Purpose:
++ * Free a chunk of reserved DSP/IVA address space.
++ */
++DSP_STATUS DMM_UnReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 rsvAddr)
++{
++ struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr;
++ struct MapPage *chunk;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 chunkSize;
++
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "Entered DMM_UnReserveMemory () hDmmMgr "
++ "%x, rsvAddr %x\n", hDmmMgr, rsvAddr);
++
++ SYNC_EnterCS(pDmmObj->hDmmLock);
++
++ /* Find the chunk containing the reserved address */
++ chunk = GetMappedRegion(rsvAddr);
++ if (chunk == NULL)
++ status = DSP_ENOTFOUND;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Free all the mapped pages for this reserved region */
++ i = 0;
++ while (i < chunk->RegionSize) {
++ if (chunk[i].bMapped) {
++ /* Remove mapping from the page tables. */
++ chunkSize = chunk[i].MappedSize;
++ /* Clear the mapping flags */
++ chunk[i].bMapped = false;
++ chunk[i].MappedSize = 0;
++ i += chunkSize;
++ } else
++ i++;
++ }
++ /* Clear the flags (mark the region 'free') */
++ chunk->bReserved = false;
++ /* NOTE: We do NOT coalesce free regions here.
++ * Free regions are coalesced in GetRegion(), as it traverses
++ *the whole mapping table
++ */
++ }
++ SYNC_LeaveCS(pDmmObj->hDmmLock);
++ GT_2trace(DMM_debugMask, GT_ENTER,
++ "Leaving DMM_UnReserveMemory status %x"
++ " chunk %x\n", status, chunk);
++ return status;
++}
++
++
++/*
++ * ======== GetRegion ========
++ * Purpose:
++ * Returns a region containing the specified memory region
++ */
++static struct MapPage *GetRegion(u32 aAddr)
++{
++ struct MapPage *currRegion = NULL;
++ u32 i = 0;
++
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetRegion () "
++ " aAddr %x\n", aAddr);
++
++ if (pVirtualMappingTable != NULL) {
++ /* find page mapped by this address */
++ i = DMM_ADDR_TO_INDEX(aAddr);
++ if (i < TableSize)
++ currRegion = pVirtualMappingTable + i;
++ }
++ GT_3trace(DMM_debugMask, GT_4CLASS,
++ "Leaving GetRegion currRegion %x, iFreeRegion %d\n,"
++ "iFreeSize %d\n", currRegion, iFreeRegion, iFreeSize) ;
++ return currRegion;
++}
++
++/*
++ * ======== GetFreeRegion ========
++ * Purpose:
++ * Returns the requested free region
++ */
++static struct MapPage *GetFreeRegion(u32 aSize)
++{
++ struct MapPage *currRegion = NULL;
++ u32 i = 0;
++ u32 RegionSize = 0;
++ u32 nextI = 0;
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetFreeRegion () "
++ "aSize 0x%x\n", aSize);
++
++ if (pVirtualMappingTable == NULL)
++ return currRegion;
++ if (aSize > iFreeSize) {
++ /* Find the largest free region
++ * (coalesce during the traversal) */
++ while (i < TableSize) {
++ RegionSize = pVirtualMappingTable[i].RegionSize;
++ nextI = i+RegionSize;
++ if (pVirtualMappingTable[i].bReserved == false) {
++ /* Coalesce, if possible */
++ if (nextI < TableSize &&
++ pVirtualMappingTable[nextI].bReserved
++ == false) {
++ pVirtualMappingTable[i].RegionSize +=
++ pVirtualMappingTable[nextI].RegionSize;
++ continue;
++ }
++ RegionSize *= PG_SIZE_4K;
++ if (RegionSize > iFreeSize) {
++ iFreeRegion = i;
++ iFreeSize = RegionSize;
++ }
++ }
++ i = nextI;
++ }
++ }
++ if (aSize <= iFreeSize) {
++ currRegion = pVirtualMappingTable + iFreeRegion;
++ iFreeRegion += (aSize / PG_SIZE_4K);
++ iFreeSize -= aSize;
++ }
++ return currRegion;
++}
++
++/*
++ * ======== GetMappedRegion ========
++ * Purpose:
++ * Returns the requestedmapped region
++ */
++static struct MapPage *GetMappedRegion(u32 aAddr)
++{
++ u32 i = 0;
++ struct MapPage *currRegion = NULL;
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered GetMappedRegion () "
++ "aAddr 0x%x\n", aAddr);
++
++ if (pVirtualMappingTable == NULL)
++ return currRegion;
++
++ i = DMM_ADDR_TO_INDEX(aAddr);
++ if (i < TableSize && (pVirtualMappingTable[i].bMapped ||
++ pVirtualMappingTable[i].bReserved))
++ currRegion = pVirtualMappingTable + i;
++ return currRegion;
++}
++
++/*
++ * ======== DMM_GetPhysicalAddrTable ========
++ * Purpose:
++ * Returns the physical table address
++ */
++u32 *DMM_GetPhysicalAddrTable(void)
++{
++ GT_1trace(DMM_debugMask, GT_ENTER, "Entered "
++ "DMM_GetPhysicalAddrTable()- pPhysicalAddrTable 0x%x\n",
++ pPhysicalAddrTable);
++ return pPhysicalAddrTable;
++}
++
++#ifdef DSP_DMM_DEBUG
++u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr)
++{
++ struct MapPage *curNode = NULL;
++ u32 i;
++ u32 freemem = 0;
++ u32 bigsize = 0;
++
++ SYNC_EnterCS(hDmmMgr->hDmmLock);
++
++ if (pVirtualMappingTable != NULL) {
++ for (i = 0; i < TableSize; i +=
++ pVirtualMappingTable[i].RegionSize) {
++ curNode = pVirtualMappingTable + i;
++ if (curNode->bReserved == TRUE) {
++ /*printk("RESERVED size = 0x%x, "
++ "Map size = 0x%x\n",
++ (curNode->RegionSize * PG_SIZE_4K),
++ (curNode->bMapped == false) ? 0 :
++ (curNode->MappedSize * PG_SIZE_4K));
++*/
++ } else {
++/* printk("UNRESERVED size = 0x%x\n",
++ (curNode->RegionSize * PG_SIZE_4K));
++*/
++ freemem += (curNode->RegionSize * PG_SIZE_4K);
++ if (curNode->RegionSize > bigsize)
++ bigsize = curNode->RegionSize;
++ }
++ }
++ }
++ printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
++ freemem/(1024*1024));
++ printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
++ (((TableSize * PG_SIZE_4K)-freemem))/(1024*1024));
++ printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
++ (bigsize*PG_SIZE_4K/(1024*1024)));
++ SYNC_LeaveCS(hDmmMgr->hDmmLock);
++
++ return 0;
++}
++#endif
+diff --git a/drivers/dsp/bridge/pmgr/io.c b/drivers/dsp/bridge/pmgr/io.c
+new file mode 100644
+index 0000000..cdfe0dc
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/io.c
+@@ -0,0 +1,205 @@
++/*
++ * io.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== io.c ========
++ * Description:
++ * IO manager interface: Manages IO between CHNL and MSG.
++ *
++ * Public Functions:
++ * IO_Create
++ * IO_Destroy
++ * IO_Exit
++ * IO_Init
++ * IO_OnLoaded
++ *
++ * Notes:
++ * This interface is basically a pass through to the WMD IO functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 04-Apr-2001 rr WSX_STATUS initialized in IO_Create.
++ *! 07-Nov-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <ioobj.h>
++#include <dspbridge/iodefs.h>
++#include <dspbridge/io.h>
++
++/* ----------------------------------- Globals */
++static u32 cRefs;
++
++#if GT_TRACE
++static struct GT_Mask IO_DebugMask = { NULL, NULL }; /* WCD IO Mask */
++#endif
++
++/*
++ * ======== IO_Create ========
++ * Purpose:
++ * Create an IO manager object, responsible for managing IO between
++ * CHNL and MSG
++ */
++DSP_STATUS IO_Create(OUT struct IO_MGR **phIOMgr, struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR *hIOMgr = NULL;
++ struct IO_MGR_ *pIOMgr = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++
++ GT_3trace(IO_DebugMask, GT_ENTER, "Entered IO_Create: phIOMgr: 0x%x\t "
++ "hDevObject: 0x%x\tpMgrAttrs: 0x%x\n",
++ phIOMgr, hDevObject, pMgrAttrs);
++
++ *phIOMgr = NULL;
++
++ /* A memory base of 0 implies no memory base: */
++ if ((pMgrAttrs->dwSMBase != 0) && (pMgrAttrs->uSMLength == 0)) {
++ status = CHNL_E_INVALIDMEMBASE;
++ GT_0trace(IO_DebugMask, GT_7CLASS,
++ "IO_Create:Invalid Mem Base\n");
++ }
++
++ if (pMgrAttrs->uWordSize == 0) {
++ status = CHNL_E_INVALIDWORDSIZE;
++ GT_0trace(IO_DebugMask, GT_7CLASS,
++ "IO_Create:Invalid Word size\n");
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++
++ /* Let WMD channel module finish the create: */
++ status = (*pIntfFxns->pfnIOCreate)(&hIOMgr, hDevObject,
++ pMgrAttrs);
++
++ if (DSP_SUCCEEDED(status)) {
++ pIOMgr = (struct IO_MGR_ *) hIOMgr;
++ pIOMgr->pIntfFxns = pIntfFxns;
++ pIOMgr->hDevObject = hDevObject;
++
++ /* Return the new channel manager handle: */
++ *phIOMgr = hIOMgr;
++ GT_1trace(IO_DebugMask, GT_1CLASS,
++ "IO_Create: Success hIOMgr: 0x%x\n",
++ hIOMgr);
++ }
++ }
++
++ GT_2trace(IO_DebugMask, GT_ENTER,
++ "Exiting IO_Create: hIOMgr: 0x%x, status:"
++ " 0x%x\n", hIOMgr, status);
++
++ return status;
++}
++
++/*
++ * ======== IO_Destroy ========
++ * Purpose:
++ * Delete IO manager.
++ */
++DSP_STATUS IO_Destroy(struct IO_MGR *hIOMgr)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct IO_MGR_ *pIOMgr = (struct IO_MGR_ *)hIOMgr;
++ DSP_STATUS status;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(IO_DebugMask, GT_ENTER, "Entered IO_Destroy: hIOMgr: 0x%x\n",
++ hIOMgr);
++
++ pIntfFxns = pIOMgr->pIntfFxns;
++
++ /* Let WMD channel module destroy the IO_MGR: */
++ status = (*pIntfFxns->pfnIODestroy) (hIOMgr);
++
++ GT_2trace(IO_DebugMask, GT_ENTER,
++ "Exiting IO_Destroy: pIOMgr: 0x%x, status:"
++ " 0x%x\n", pIOMgr, status);
++ return status;
++}
++
++/*
++ * ======== IO_Exit ========
++ * Purpose:
++ * Discontinue usage of the IO module.
++ */
++void IO_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(IO_DebugMask, GT_5CLASS,
++ "Entered IO_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== IO_Init ========
++ * Purpose:
++ * Initialize the IO module's private state.
++ */
++bool IO_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!IO_DebugMask.flags);
++ GT_create(&IO_DebugMask, "IO"); /* "IO" for IO */
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(IO_DebugMask, GT_5CLASS,
++ "Entered IO_Init, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
+diff --git a/drivers/dsp/bridge/pmgr/ioobj.h b/drivers/dsp/bridge/pmgr/ioobj.h
+new file mode 100644
+index 0000000..f473a63
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/ioobj.h
+@@ -0,0 +1,52 @@
++/*
++ * ioobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ioobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library IO objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 01/16/97 gp: Created from chnlpriv.h
++ */
++
++#ifndef IOOBJ_
++#define IOOBJ_
++
++#include <dspbridge/devdefs.h>
++#include <dspbridge/wmd.h>
++
++/*
++ * This struct is the first field in a IO_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct IO_MGR_ {
++ /* These must be the first fields in a IO_MGR struct: */
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context. */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++ struct DEV_OBJECT *hDevObject; /* Device this board represents. */
++} ;
++
++#endif /* IOOBJ_ */
+diff --git a/drivers/dsp/bridge/pmgr/msg.c b/drivers/dsp/bridge/pmgr/msg.c
+new file mode 100644
+index 0000000..bbf5174
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/msg.c
+@@ -0,0 +1,173 @@
++/*
++ * msg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg.c ========
++ * Description:
++ * DSP/BIOS Bridge MSG Module.
++ *
++ * Public Functions:
++ * MSG_Create
++ * MSG_Delete
++ * MSG_Exit
++ * MSG_Init
++ *
++ *! Revision History:
++ *! =================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 15-May-2001 ag Changed SUCCEEDED to DSP_SUCCEEDED.
++ *! 16-Feb-2001 jeh Fixed some comments.
++ *! 15-Dec-2000 rr MSG_Create returns DSP_EFAIL if pfnMsgCreate fails.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <msgobj.h>
++#include <dspbridge/msg.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MSG_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++static u32 cRefs; /* module reference count */
++
++/*
++ * ======== MSG_Create ========
++ * Purpose:
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ */
++DSP_STATUS MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct MSG_MGR_ *pMsgMgr;
++ struct MSG_MGR *hMsgMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(msgCallback != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_3trace(MSG_debugMask, GT_ENTER, "MSG_Create: phMsgMgr: 0x%x\t"
++ "hDevObject: 0x%x\tmsgCallback: 0x%x\n",
++ phMsgMgr, hDevObject, msgCallback);
++
++ *phMsgMgr = NULL;
++
++ DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++
++ /* Let WMD message module finish the create: */
++ status = (*pIntfFxns->pfnMsgCreate)(&hMsgMgr, hDevObject, msgCallback);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in WCD message module's fields of the MSG_MGR
++ * structure */
++ pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
++ pMsgMgr->pIntfFxns = pIntfFxns;
++
++ /* Finally, return the new message manager handle: */
++ *phMsgMgr = hMsgMgr;
++ GT_1trace(MSG_debugMask, GT_1CLASS,
++ "MSG_Create: Success pMsgMgr: 0x%x\n", pMsgMgr);
++ } else {
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++/*
++ * ======== MSG_Delete ========
++ * Purpose:
++ * Delete a MSG manager allocated in MSG_Create().
++ */
++void MSG_Delete(struct MSG_MGR *hMsgMgr)
++{
++ struct MSG_MGR_ *pMsgMgr = (struct MSG_MGR_ *)hMsgMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++
++ GT_1trace(MSG_debugMask, GT_ENTER, "MSG_Delete: hMsgMgr: 0x%x\n",
++ hMsgMgr);
++
++ pIntfFxns = pMsgMgr->pIntfFxns;
++
++ /* Let WMD message module destroy the MSG_MGR: */
++ (*pIntfFxns->pfnMsgDelete)(hMsgMgr);
++
++ DBC_Ensure(!MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++}
++
++/*
++ * ======== MSG_Exit ========
++ */
++void MSG_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ GT_1trace(MSG_debugMask, GT_5CLASS,
++ "Entered MSG_Exit, ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MSG_Init ========
++ */
++bool MSG_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!MSG_debugMask.flags);
++ GT_create(&MSG_debugMask, "MG"); /* "MG" for MsG */
++ }
++
++ cRefs++;
++
++ GT_1trace(MSG_debugMask, GT_5CLASS, "MSG_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++
++ return true;
++}
++
+diff --git a/drivers/dsp/bridge/pmgr/msgobj.h b/drivers/dsp/bridge/pmgr/msgobj.h
+new file mode 100644
+index 0000000..63d025b
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/msgobj.h
+@@ -0,0 +1,52 @@
++/*
++ * msgobj.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msgobj.h ========
++ * Description:
++ * Structure subcomponents of channel class library MSG objects which
++ * are exposed to class driver from mini-driver.
++ *
++ * Public Functions:
++ * None.
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 17-Nov-2000 jeh Created.
++ */
++
++#ifndef MSGOBJ_
++#define MSGOBJ_
++
++#include <dspbridge/wmd.h>
++
++#include <dspbridge/msgdefs.h>
++
++/*
++ * This struct is the first field in a MSG_MGR struct, as implemented in
++ * a WMD channel class library. Other, implementation specific fields
++ * follow this structure in memory.
++ */
++struct MSG_MGR_ {
++ /* The first two fields must match those in msgobj.h */
++ u32 dwSignature;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++};
++
++#endif /* MSGOBJ_ */
++
+diff --git a/drivers/dsp/bridge/pmgr/wcd.c b/drivers/dsp/bridge/pmgr/wcd.c
+new file mode 100644
+index 0000000..859043d
+--- /dev/null
++++ b/drivers/dsp/bridge/pmgr/wcd.c
+@@ -0,0 +1,1647 @@
++/*
++ * wcd.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== wcd.c ========
++ * Description:
++ * Common WCD functions, also includes the wrapper
++ * functions called directly by the DeviceIOControl interface.
++ *
++ * Public Functions:
++ * WCD_CallDevIOCtl
++ * WCD_Init
++ * WCD_InitComplete2
++ * WCD_Exit
++ * <MOD>WRAP_*
++ *
++ *! Revision History:
++ *! ================
++ *! 29-Apr-2004 hp Call PROC_AutoStart only for DSP device
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping APIs
++ *! 03-Apr-2003 sb Process environment pointer in PROCWRAP_Load
++ *! 24-Feb-2003 swa PMGR Code review comments incorporated.
++ *! 30-Jan-2002 ag CMMWRAP_AllocBuf name changed to CMMWRAP_CallocBuf
++ *! 15-Jan-2002 ag Added actual bufSize param to STRMWRAP_Reclaim[issue].
++ *! 14-Dec-2001 rr ARGS_NODE_CONNECT maps the pAttr.
++ *! 03-Oct-2001 rr ARGS_NODE_ALLOCMSGBUF/FREEMSGBUF maps the pAttr.
++ *! 10-Sep-2001 ag Added CMD_CMM_GETHANDLE.
++ *! 23-Apr-2001 jeh Pass pStatus to NODE_Terminate.
++ *! 11-Apr-2001 jeh STRMWRAP_Reclaim embedded pointer is mapped and unmapped.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 06-Dec-2000 jeh WRAP_MAP2CALLER pointers in RegisterNotify calls.
++ *! 05-Dec-2000 ag: Removed MAP2CALLER in NODEWRAP_FreeMsgBuf().
++ *! 22-Nov-2000 kc: Added MGRWRAP_GetPerf_Data().
++ *! 20-Nov-2000 jeh Added MSG_Init()/MSG_Exit(), IO_Init()/IO_Exit().
++ *! WRAP pointers to handles for PROC_Attach, NODE_Allocate.
++ *! 27-Oct-2000 jeh Added NODEWRAP_AllocMsgBuf, NODEWRAP_FreeMsgBuf. Removed
++ *! NODEWRAP_GetMessageStream.
++ *! 12-Oct-2000 ag: Added user CMM wrappers.
++ *! 05-Oct-2000 rr: WcdInitComplete2 will fail even if one BRD or PROC
++ *! AutoStart fails.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 13-Sep-2000 jeh Pass ARGS_NODE_CONNECT.pAttrs to NODE_Connect().
++ *! 11-Aug-2000 rr: Part of node enabled.
++ *! 31-Jul-2000 rr: UTIL_Wrap and MEM_Wrap added to RM.
++ *! 27-Jul-2000 rr: PROCWRAP, NODEWRAP and STRMWRAP implemented.
++ *! STRM and some NODE Wrappers are not implemented.
++ *! 27-Jun-2000 rr: MGRWRAP fxns added.IFDEF to build for PM or DSP/BIOS Bridge
++ *! 08-Feb-2000 rr File name changed to wcd.c
++ *! 03-Feb-2000 rr: Module initialization are done by SERVICES init. GT Class
++ *! changes for module init/exit fxns.
++ *! 24-Jan-2000 rr: Merged with Scott's code.
++ *! 21-Jan-1999 sg: Changed ARGS_CHNL_GETMODE field name from pdwMode to pMode.
++ *! 17-Jan-2000 rr: BRD_GetStatus does WRAP_MAP2CALLER for state.
++ *! 14-Dec-1999 ag: Removed _MAP2CALLER in CHNL_GetMgr().
++ *! 13-Dec-1999 rr: BRDWRAP_GetSymbol, BRDWRAP_GetTrace uses WRAP_MAP2CALLER
++ *! macros.BRDWRAP_Load maps and unmaps embedded pointers.
++ *! 10-Dec-1999 ag: User CHNL bufs mapped in _AddIOReq & _GetIOCompletion.
++ *! 09-Dec-1999 rr: BRDWRAP_Open and CHNLWRAP_GetMgr does not map
++ *! pointer as there was a change in config.c
++ *! 06-Dec-1999 rr: BRD_Read and Write Maps the buf pointers.
++ *! 03-Dec-1999 rr: CHNLWRAP_GetMgr and BRDWRAP_Open maps hDevNode pointer.
++ *! WCD_InitComplete2 Included for BRD_AutoStart.
++ *! 16-Nov-1999 ag: Map buf to process in CHNLWRAP_AllocBuffer().
++ *! CHNL_GetMgr() Mapping Fix.
++ *! 10-Nov-1999 ag: Removed unnecessary calls to WRAP_MAP2CALLER.
++ *! 08-Nov-1999 kc: Added MEMRY & enabled BRD_IOCtl for tests.
++ *! 29-Oct-1999 ag: Added CHNL.
++ *! 29-Oct-1999 kc: Added trace statements; added ptr mapping; updated
++ *! use of UTIL module API.
++ *! 29-Oct-1999 rr: Wrapper functions does the Mapping of the Pointers.
++ *! in WinCE all the explicit pointers will be converted
++ *! by the OS during interprocess but not the embedded pointers.
++ *! 16-Oct-1999 kc: Code review cleanup.
++ *! 07-Oct-1999 kc: Added UTILWRAP_TestDll() to run PM test harness. See
++ *! /src/doc/pmtest.doc for more detail.
++ *! 09-Sep-1999 rr: After exactly two years(!). Adopted for WinCE. GT Enabled.
++ *! 09-Sep-1997 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/services.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/chnl.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/disp.h>
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++#include <dspbridge/rmm.h>
++
++
++/* ----------------------------------- Others */
++#include <dspbridge/msg.h>
++#include <dspbridge/cmm.h>
++#include <dspbridge/io.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/_dcd.h>
++#include <dspbridge/dbdcd.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define MAX_TRACEBUFLEN 255
++#define MAX_LOADARGS 16
++#define MAX_NODES 64
++#define MAX_STREAMS 16
++#define MAX_BUFS 64
++
++/* Following two macros should ideally have do{}while(0) */
++
++#define cp_fm_usr(dest, src, status, elements) \
++ if (DSP_SUCCEEDED(status)) {\
++ if (unlikely(src == NULL) || \
++ unlikely(copy_from_user(dest, src, elements * sizeof(*(dest))))) { \
++ GT_1trace(WCD_debugMask, GT_7CLASS, \
++ "copy_from_user failed, src=0x%x\n", src); \
++ status = DSP_EPOINTER ; \
++ } \
++ }
++
++#define cp_to_usr(dest, src, status, elements) \
++ if (DSP_SUCCEEDED(status)) {\
++ if (unlikely(dest == NULL) || \
++ unlikely(copy_to_user(dest, src, elements * sizeof(*(src))))) { \
++ GT_1trace(WCD_debugMask, GT_7CLASS, \
++ "copy_to_user failed, dest=0x%x\n", dest); \
++ status = DSP_EPOINTER ;\
++ } \
++ }
++
++/* Device IOCtl function pointer */
++struct WCD_Cmd {
++ u32(*fxn)(union Trapped_Args *args);
++ u32 dwIndex;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask WCD_debugMask = { NULL, NULL }; /* Core VxD Mask */
++#endif
++static u32 WCD_cRefs;
++
++/*
++ * Function table.
++ * The order of these functions MUST be the same as the order of the command
++ * numbers defined in wcdioctl.h This is how an IOCTL number in user mode
++ * turns into a function call in kernel mode.
++ */
++static struct WCD_Cmd WCD_cmdTable[] = {
++ /* MGR module */
++ {MGRWRAP_EnumNode_Info, CMD_MGR_ENUMNODE_INFO_OFFSET},
++ {MGRWRAP_EnumProc_Info, CMD_MGR_ENUMPROC_INFO_OFFSET},
++ {MGRWRAP_RegisterObject, CMD_MGR_REGISTEROBJECT_OFFSET},
++ {MGRWRAP_UnregisterObject, CMD_MGR_UNREGISTEROBJECT_OFFSET},
++ {MGRWRAP_WaitForBridgeEvents, CMD_MGR_WAIT_OFFSET},
++#ifndef RES_CLEANUP_DISABLE
++ {MGRWRAP_GetProcessResourcesInfo, CMD_MGR_RESOUCES_OFFSET},
++#endif
++ /* PROC Module */
++ {PROCWRAP_Attach, CMD_PROC_ATTACH_OFFSET},
++ {PROCWRAP_Ctrl, CMD_PROC_CTRL_OFFSET},
++ {PROCWRAP_Detach, CMD_PROC_DETACH_OFFSET},
++ {PROCWRAP_EnumNode_Info, CMD_PROC_ENUMNODE_OFFSET},
++ {PROCWRAP_EnumResources, CMD_PROC_ENUMRESOURCES_OFFSET},
++ {PROCWRAP_GetState, CMD_PROC_GETSTATE_OFFSET},
++ {PROCWRAP_GetTrace, CMD_PROC_GETTRACE_OFFSET},
++ {PROCWRAP_Load, CMD_PROC_LOAD_OFFSET},
++ {PROCWRAP_RegisterNotify, CMD_PROC_REGISTERNOTIFY_OFFSET},
++ {PROCWRAP_Start, CMD_PROC_START_OFFSET},
++ {PROCWRAP_ReserveMemory, CMD_PROC_RSVMEM_OFFSET},
++ {PROCWRAP_UnReserveMemory, CMD_PROC_UNRSVMEM_OFFSET},
++ {PROCWRAP_Map, CMD_PROC_MAPMEM_OFFSET},
++ {PROCWRAP_UnMap, CMD_PROC_UNMAPMEM_OFFSET},
++ {PROCWRAP_FlushMemory, CMD_PROC_FLUSHMEMORY_OFFSET},
++ {PROCWRAP_Stop, CMD_PROC_STOP_OFFSET},
++ {PROCWRAP_InvalidateMemory, CMD_PROC_INVALIDATEMEMORY_OFFSET},
++ /* NODE Module */
++ {NODEWRAP_Allocate, CMD_NODE_ALLOCATE_OFFSET},
++ {NODEWRAP_AllocMsgBuf, CMD_NODE_ALLOCMSGBUF_OFFSET},
++ {NODEWRAP_ChangePriority, CMD_NODE_CHANGEPRIORITY_OFFSET},
++ {NODEWRAP_Connect, CMD_NODE_CONNECT_OFFSET},
++ {NODEWRAP_Create, CMD_NODE_CREATE_OFFSET},
++ {NODEWRAP_Delete, CMD_NODE_DELETE_OFFSET},
++ {NODEWRAP_FreeMsgBuf, CMD_NODE_FREEMSGBUF_OFFSET},
++ {NODEWRAP_GetAttr, CMD_NODE_GETATTR_OFFSET},
++ {NODEWRAP_GetMessage, CMD_NODE_GETMESSAGE_OFFSET},
++ {NODEWRAP_Pause, CMD_NODE_PAUSE_OFFSET},
++ {NODEWRAP_PutMessage, CMD_NODE_PUTMESSAGE_OFFSET},
++ {NODEWRAP_RegisterNotify, CMD_NODE_REGISTERNOTIFY_OFFSET},
++ {NODEWRAP_Run, CMD_NODE_RUN_OFFSET},
++ {NODEWRAP_Terminate, CMD_NODE_TERMINATE_OFFSET},
++ {NODEWRAP_GetUUIDProps, CMD_NODE_GETUUIDPROPS_OFFSET},
++ /* STRM wrapper functions */
++ {STRMWRAP_AllocateBuffer, CMD_STRM_ALLOCATEBUFFER_OFFSET},
++ {STRMWRAP_Close, CMD_STRM_CLOSE_OFFSET},
++ {STRMWRAP_FreeBuffer, CMD_STRM_FREEBUFFER_OFFSET},
++ {STRMWRAP_GetEventHandle, CMD_STRM_GETEVENTHANDLE_OFFSET},
++ {STRMWRAP_GetInfo, CMD_STRM_GETINFO_OFFSET},
++ {STRMWRAP_Idle, CMD_STRM_IDLE_OFFSET},
++ {STRMWRAP_Issue, CMD_STRM_ISSUE_OFFSET},
++ {STRMWRAP_Open, CMD_STRM_OPEN_OFFSET},
++ {STRMWRAP_Reclaim, CMD_STRM_RECLAIM_OFFSET},
++ {STRMWRAP_RegisterNotify, CMD_STRM_REGISTERNOTIFY_OFFSET},
++ {STRMWRAP_Select, CMD_STRM_SELECT_OFFSET},
++ /* CMM module */
++ {CMMWRAP_CallocBuf, CMD_CMM_ALLOCBUF_OFFSET},
++ {CMMWRAP_FreeBuf, CMD_CMM_FREEBUF_OFFSET},
++ {CMMWRAP_GetHandle, CMD_CMM_GETHANDLE_OFFSET},
++ {CMMWRAP_GetInfo, CMD_CMM_GETINFO_OFFSET}
++};
++
++/*
++ * ======== WCD_CallDevIOCtl ========
++ * Purpose:
++ * Call the (wrapper) function for the corresponding WCD IOCTL.
++ */
++inline DSP_STATUS WCD_CallDevIOCtl(u32 cmd, union Trapped_Args *args,
++ u32 *pResult)
++{
++ if ((cmd < (sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd)))) {
++ /* make the fxn call via the cmd table */
++ *pResult = (*WCD_cmdTable[cmd].fxn) (args);
++ return DSP_SOK;
++ } else {
++ return DSP_EINVALIDARG;
++ }
++}
++
++/*
++ * ======== WCD_Exit ========
++ */
++void WCD_Exit(void)
++{
++ DBC_Require(WCD_cRefs > 0);
++ WCD_cRefs--;
++ GT_1trace(WCD_debugMask, GT_5CLASS,
++ "Entered WCD_Exit, ref count: 0x%x\n", WCD_cRefs);
++ if (WCD_cRefs == 0) {
++ /* Release all WCD modules initialized in WCD_Init(). */
++ COD_Exit();
++ DEV_Exit();
++ CHNL_Exit();
++ MSG_Exit();
++ IO_Exit();
++ STRM_Exit();
++ NTFY_Exit();
++ DISP_Exit();
++ NODE_Exit();
++ PROC_Exit();
++ MGR_Exit();
++ RMM_exit();
++ DRV_Exit();
++ SERVICES_Exit();
++ }
++ DBC_Ensure(WCD_cRefs >= 0);
++}
++
++/*
++ * ======== WCD_Init ========
++ * Purpose:
++ * Module initialization is done by SERVICES Init.
++ */
++bool WCD_Init(void)
++{
++ bool fInit = true;
++ bool fDRV, fDEV, fCOD, fSERVICES, fCHNL, fMSG, fIO;
++ bool fMGR, fPROC, fNODE, fDISP, fNTFY, fSTRM, fRMM;
++#ifdef DEBUG
++ /* runtime check of Device IOCtl array. */
++ u32 i;
++ for (i = 1; i < (sizeof(WCD_cmdTable) / sizeof(struct WCD_Cmd)); i++)
++ DBC_Assert(WCD_cmdTable[i - 1].dwIndex == i);
++
++#endif
++ if (WCD_cRefs == 0) {
++ /* initialize all SERVICES modules */
++ fSERVICES = SERVICES_Init();
++ /* initialize debugging module */
++ DBC_Assert(!WCD_debugMask.flags);
++ GT_create(&WCD_debugMask, "CD"); /* CD for class driver */
++ /* initialize class driver and other modules */
++ fDRV = DRV_Init();
++ fMGR = MGR_Init();
++ fPROC = PROC_Init();
++ fNODE = NODE_Init();
++ fDISP = DISP_Init();
++ fNTFY = NTFY_Init();
++ fSTRM = STRM_Init();
++ fRMM = RMM_init();
++ fCHNL = CHNL_Init();
++ fMSG = MSG_Init();
++ fIO = IO_Init();
++ fDEV = DEV_Init();
++ fCOD = COD_Init();
++ fInit = fSERVICES && fDRV && fDEV && fCHNL && fCOD &&
++ fMSG && fIO;
++ fInit = fInit && fMGR && fPROC && fRMM;
++ if (!fInit) {
++ if (fSERVICES)
++ SERVICES_Exit();
++
++ if (fDRV)
++ DRV_Exit();
++
++ if (fMGR)
++ MGR_Exit();
++
++ if (fSTRM)
++ STRM_Exit();
++
++ if (fPROC)
++ PROC_Exit();
++
++ if (fNODE)
++ NODE_Exit();
++
++ if (fDISP)
++ DISP_Exit();
++
++ if (fNTFY)
++ NTFY_Exit();
++
++ if (fCHNL)
++ CHNL_Exit();
++
++ if (fMSG)
++ MSG_Exit();
++
++ if (fIO)
++ IO_Exit();
++
++ if (fDEV)
++ DEV_Exit();
++
++ if (fCOD)
++ COD_Exit();
++
++ if (fRMM)
++ RMM_exit();
++
++ }
++ }
++ if (fInit)
++ WCD_cRefs++;
++
++ GT_1trace(WCD_debugMask, GT_5CLASS,
++ "Entered WCD_Init, ref count: 0x%x\n", WCD_cRefs);
++ return fInit;
++}
++
++/*
++ * ======== WCD_InitComplete2 ========
++ * Purpose:
++ * Perform any required WCD, and WMD initialization which
++ * cannot not be performed in WCD_Init() or DEV_StartDevice() due
++ * to the fact that some services are not yet
++ * completely initialized.
++ * Parameters:
++ * Returns:
++ * DSP_SOK: Allow this device to load
++ * DSP_EFAIL: Failure.
++ * Requires:
++ * WCD initialized.
++ * Ensures:
++ */
++DSP_STATUS WCD_InitComplete2(void)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_DEVNODE *DevNode;
++ struct DEV_OBJECT *hDevObject;
++ u32 devType;
++
++ DBC_Require(WCD_cRefs > 0);
++ GT_0trace(WCD_debugMask, GT_ENTER, "Entered WCD_InitComplete\n");
++ /* Walk the list of DevObjects, get each devnode, and attempting to
++ * autostart the board. Note that this requires COF loading, which
++ * requires KFILE. */
++ for (hDevObject = DEV_GetFirst(); hDevObject != NULL;
++ hDevObject = DEV_GetNext(hDevObject)) {
++ if (DSP_FAILED(DEV_GetDevNode(hDevObject, &DevNode)))
++ continue;
++
++ if (DSP_FAILED(DEV_GetDevType(hDevObject, &devType)))
++ continue;
++
++ if ((devType == DSP_UNIT) || (devType == IVA_UNIT)) {
++ if (DSP_FAILED(PROC_AutoStart(DevNode, hDevObject))) {
++ GT_0trace(WCD_debugMask, GT_1CLASS,
++ "WCD_InitComplete2 Failed\n");
++ status = DSP_EFAIL;
++ /* break; */
++ }
++ } else
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "Ignoring PROC_AutoStart "
++ "for Device Type = 0x%x \n", devType);
++ } /* End For Loop */
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "Exiting WCD_InitComplete status 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== MGRWRAP_EnumNode_Info ========
++ */
++u32 MGRWRAP_EnumNode_Info(union Trapped_Args *args)
++{
++ u8 *pNDBProps;
++ u32 uNumNodes;
++ DSP_STATUS status = DSP_SOK;
++ u32 size = args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "MGR_EnumNodeInfo: entered args:\n0x%x"
++ " uNode: 0x%x\tpNDBProps: 0x%x\tuNDBPropsSize: "
++ "0x%x\tpuNumNodes\n", args->ARGS_MGR_ENUMNODE_INFO.uNode,
++ args->ARGS_MGR_ENUMNODE_INFO.pNDBProps,
++ args->ARGS_MGR_ENUMNODE_INFO.uNDBPropsSize,
++ args->ARGS_MGR_ENUMNODE_INFO.puNumNodes);
++ pNDBProps = MEM_Alloc(size, MEM_NONPAGED);
++ if (pNDBProps == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_EnumNodeInfo(args->ARGS_MGR_ENUMNODE_INFO.uNode,
++ (struct DSP_NDBPROPS *)pNDBProps,
++ size, &uNumNodes);
++ }
++ cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.pNDBProps, pNDBProps, status,
++ size);
++ cp_to_usr(args->ARGS_MGR_ENUMNODE_INFO.puNumNodes, &uNumNodes, status,
++ 1);
++ if (pNDBProps)
++ MEM_Free(pNDBProps);
++
++ return status;
++}
++
++/*
++ * ======== MGRWRAP_EnumProc_Info ========
++ */
++u32 MGRWRAP_EnumProc_Info(union Trapped_Args *args)
++{
++ u8 *pProcessorInfo;
++ u32 uNumProcs;
++ DSP_STATUS status = DSP_SOK;
++ u32 size = args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_EnumProc_Info: entered args:\n"
++ "0x%x uProcessor: 0x%x\tpProcessorInfo: 0x%x\t"
++ "uProcessorInfoSize: 0x%x\tpuNumProcs \n",
++ args->ARGS_MGR_ENUMPROC_INFO.uProcessor,
++ args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo,
++ args->ARGS_MGR_ENUMPROC_INFO.uProcessorInfoSize,
++ args->ARGS_MGR_ENUMPROC_INFO.puNumProcs);
++ pProcessorInfo = MEM_Alloc(size, MEM_NONPAGED);
++ if (pProcessorInfo == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_EnumProcessorInfo(args->
++ ARGS_MGR_ENUMPROC_INFO.uProcessor,
++ (struct DSP_PROCESSORINFO *)pProcessorInfo,
++ size, &uNumProcs);
++ }
++ cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.pProcessorInfo, pProcessorInfo,
++ status, size);
++ cp_to_usr(args->ARGS_MGR_ENUMPROC_INFO.puNumProcs, &uNumProcs,
++ status, 1);
++ if (pProcessorInfo)
++ MEM_Free(pProcessorInfo);
++
++ return status;
++}
++
++#define WRAP_MAP2CALLER(x) x
++/*
++ * ======== MGRWRAP_RegisterObject ========
++ */
++u32 MGRWRAP_RegisterObject(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_RegisterObject: entered pg2hMsg "
++ "0x%x\n", args->ARGS_MGR_REGISTEROBJECT.pUuid);
++ retVal = DCD_RegisterObject(WRAP_MAP2CALLER
++ (args->ARGS_MGR_REGISTEROBJECT.pUuid),
++ args->ARGS_MGR_REGISTEROBJECT.objType,
++ WRAP_MAP2CALLER(args->ARGS_MGR_REGISTEROBJECT.pszPathName));
++ return retVal;
++}
++
++/*
++ * ======== MGRWRAP_UnregisterObject ========
++ */
++u32 MGRWRAP_UnregisterObject(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_UnregisterObject: entered pg2hMsg"
++ " 0x%x\n", args->ARGS_MGR_UNREGISTEROBJECT.pUuid);
++ retVal = DCD_UnregisterObject(WRAP_MAP2CALLER
++ (args->ARGS_MGR_UNREGISTEROBJECT.pUuid),
++ args->ARGS_MGR_UNREGISTEROBJECT.objType);
++
++ return retVal;
++}
++
++/*
++ * ======== MGRWRAP_WaitForBridgeEvents ========
++ */
++u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION *aNotifications[MAX_EVENTS];
++ struct DSP_NOTIFICATION notifications[MAX_EVENTS];
++ u32 uIndex, i;
++ u32 uCount = args->ARGS_MGR_WAIT.uCount;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_WaitForBridgeEvents: entered\n");
++
++ if (uCount > MAX_EVENTS)
++ status = DSP_EINVALIDARG;
++
++ /* get the array of pointers to user structures */
++ cp_fm_usr(aNotifications, args->ARGS_MGR_WAIT.aNotifications,
++ status, uCount);
++ /* get the events */
++ for (i = 0; i < uCount; i++) {
++ cp_fm_usr(&notifications[i], aNotifications[i], status, 1);
++ if (DSP_SUCCEEDED(status)) {
++ /* set the array of pointers to kernel structures*/
++ aNotifications[i] = &notifications[i];
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = MGR_WaitForBridgeEvents(aNotifications, uCount,
++ &uIndex, args->ARGS_MGR_WAIT.uTimeout);
++ }
++ cp_to_usr(args->ARGS_MGR_WAIT.puIndex, &uIndex, status, 1);
++ return status;
++}
++
++
++#ifndef RES_CLEANUP_DISABLE
++/*
++ * ======== MGRWRAP_GetProcessResourceInfo ========
++ */
++u32 MGRWRAP_GetProcessResourcesInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 uSize = 0;
++ u8 *pBuf = MEM_Alloc(8092, MEM_NONPAGED);
++ status = DRV_ProcDisplayResInfo(pBuf, &uSize);
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "MGRWRAP_GetProcessResourcesInfo:uSize=%d :\n", uSize);
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status, uSize);
++ GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
++ "123MGRWRAP_GetProcessResourcesInfo:**************\n");
++ GT_0trace(WCD_debugMask, GT_ENTER, "\n***********"
++ "456MGRWRAP_GetProcessResourcesInfo:**************\n");
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pSize, &uSize, status, 1);
++ MEM_Free(pBuf);
++ return status;
++}
++#endif
++
++
++/*
++ * ======== PROCWRAP_Attach ========
++ */
++u32 PROCWRAP_Attach(union Trapped_Args *args)
++{
++ DSP_HPROCESSOR processor;
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_PROCESSORATTRIN attrIn, *pAttrIn = NULL;
++
++ GT_3trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Attach: entered args:\n" "0x%x"
++ " uProcessor: 0x%x\tpAttrIn: 0x%x\tphProcessor \n",
++ args->ARGS_PROC_ATTACH.uProcessor,
++ args->ARGS_PROC_ATTACH.pAttrIn,
++ args->ARGS_PROC_ATTACH.phProcessor);
++ /* Optional argument */
++ if (args->ARGS_PROC_ATTACH.pAttrIn) {
++ cp_fm_usr(&attrIn, args->ARGS_PROC_ATTACH.pAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrIn = &attrIn;
++
++ }
++ status = PROC_Attach(args->ARGS_PROC_ATTACH.uProcessor, pAttrIn,
++ &processor);
++ cp_to_usr(args->ARGS_PROC_ATTACH.phProcessor, &processor, status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Ctrl ========
++ */
++u32 PROCWRAP_Ctrl(union Trapped_Args *args)
++{
++ u32 cbDataSize, __user *pSize = (u32 __user *)
++ args->ARGS_PROC_CTRL.pArgs;
++ u8 *pArgs = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ GT_3trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Ctrl: entered args:\n 0x%x"
++ " uProcessor: 0x%x\tdwCmd: 0x%x\tpArgs \n",
++ args->ARGS_PROC_CTRL.hProcessor,
++ args->ARGS_PROC_CTRL.dwCmd,
++ args->ARGS_PROC_CTRL.pArgs);
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_PROC_CTRL.pArgs, status,
++ cbDataSize);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Ctrl(args->ARGS_PROC_CTRL.hProcessor,
++ args->ARGS_PROC_CTRL.dwCmd,
++ (struct DSP_CBDATA *)pArgs);
++ }
++
++ /* cp_to_usr(args->ARGS_PROC_CTRL.pArgs, pArgs, status, 1);*/
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Detach ========
++ */
++u32 PROCWRAP_Detach(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_1trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Detach: entered args\n0x%x "
++ "hProceesor \n", args->ARGS_PROC_DETACH.hProcessor);
++ retVal = PROC_Detach(args->ARGS_PROC_DETACH.hProcessor);
++
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_EnumNode_Info ========
++ */
++u32 PROCWRAP_EnumNode_Info(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ DSP_HNODE aNodeTab[MAX_NODES];
++ u32 uNumNodes;
++ u32 uAllocated;
++
++ GT_5trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_EnumNode_Info:entered args:\n0x"
++ "%xhProcessor:0x%x\taNodeTab:0x%x\tuNodeTabSize:"
++ "%0x%x\tpuNumNodes%\n0x%x puAllocated: \n",
++ args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
++ args->ARGS_PROC_ENUMNODE_INFO.aNodeTab,
++ args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
++ args->ARGS_PROC_ENUMNODE_INFO.puNumNodes,
++ args->ARGS_PROC_ENUMNODE_INFO.puAllocated);
++ DBC_Require(args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize <= MAX_NODES);
++ status = PROC_EnumNodes(args->ARGS_PROC_ENUMNODE_INFO.hProcessor,
++ aNodeTab,
++ args->ARGS_PROC_ENUMNODE_INFO.uNodeTabSize,
++ &uNumNodes, &uAllocated);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.aNodeTab, aNodeTab, status,
++ uNumNodes);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puNumNodes, &uNumNodes,
++ status, 1);
++ cp_to_usr(args->ARGS_PROC_ENUMNODE_INFO.puAllocated, &uAllocated,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_FlushMemory ========
++ */
++u32 PROCWRAP_FlushMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_FlushMemory: entered\n");
++
++ status = PROC_FlushMemory(args->ARGS_PROC_FLUSHMEMORY.hProcessor,
++ args->ARGS_PROC_FLUSHMEMORY.pMpuAddr,
++ args->ARGS_PROC_FLUSHMEMORY.ulSize,
++ args->ARGS_PROC_FLUSHMEMORY.ulFlags);
++ return status;
++}
++
++
++/*
++ * ======== PROCWRAP_InvalidateMemory ========
++ */
++u32 PROCWRAP_InvalidateMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_InvalidateMemory:entered\n");
++
++ status = PROC_InvalidateMemory(
++ args->ARGS_PROC_INVALIDATEMEMORY.hProcessor,
++ args->ARGS_PROC_INVALIDATEMEMORY.pMpuAddr,
++ args->ARGS_PROC_INVALIDATEMEMORY.ulSize);
++ return status;
++}
++
++
++/*
++ * ======== PROCWRAP_EnumResources ========
++ */
++u32 PROCWRAP_EnumResources(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_4trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_EnumResources: entered args:\n"
++ "0x%x hProcessor: 0x%x\tuResourceMask: 0x%x\tpResourceInfo"
++ " 0x%x\tuResourceInfoSixe \n",
++ args->ARGS_PROC_ENUMRESOURCES.hProcessor,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceType,
++ args->ARGS_PROC_ENUMRESOURCES.pResourceInfo,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceInfoSize);
++ retVal = PROC_GetResourceInfo(args->ARGS_PROC_ENUMRESOURCES.hProcessor,
++ args->ARGS_PROC_ENUMRESOURCES.uResourceType,
++ WRAP_MAP2CALLER(args->ARGS_PROC_ENUMRESOURCES.
++ pResourceInfo), args->ARGS_PROC_ENUMRESOURCES.
++ uResourceInfoSize);
++
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_GetState ========
++ */
++u32 PROCWRAP_GetState(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_PROCESSORSTATE procStatus;
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetState: entered\n");
++ status = PROC_GetState(args->ARGS_PROC_GETSTATE.hProcessor, &procStatus,
++ args->ARGS_PROC_GETSTATE.uStateInfoSize);
++ cp_to_usr(args->ARGS_PROC_GETSTATE.pProcStatus, &procStatus, status, 1);
++ return status;
++
++}
++
++/*
++ * ======== PROCWRAP_GetTrace ========
++ */
++u32 PROCWRAP_GetTrace(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ u8 *pBuf;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetTrace: entered\n");
++
++ DBC_Require(args->ARGS_PROC_GETTRACE.uMaxSize <= MAX_TRACEBUFLEN);
++
++ pBuf = MEM_Calloc(args->ARGS_PROC_GETTRACE.uMaxSize, MEM_NONPAGED);
++ if (pBuf != NULL) {
++ status = PROC_GetTrace(args->ARGS_PROC_GETTRACE.hProcessor,
++ pBuf, args->ARGS_PROC_GETTRACE.uMaxSize);
++ } else {
++ status = DSP_EMEMORY;
++ }
++ cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status,
++ args->ARGS_PROC_GETTRACE.uMaxSize);
++ if (pBuf)
++ MEM_Free(pBuf);
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Load ========
++ */
++u32 PROCWRAP_Load(union Trapped_Args *args)
++{
++ s32 i, len;
++ DSP_STATUS status = DSP_SOK;
++ char *temp;
++ s32 argc = args->ARGS_PROC_LOAD.iArgc;
++ u8 **argv, **envp = NULL;
++
++
++ DBC_Require(argc > 0);
++ DBC_Require(argc <= MAX_LOADARGS);
++
++ argv = MEM_Alloc(argc * sizeof(u8 *), MEM_NONPAGED);
++ if (argv == NULL)
++ status = DSP_EMEMORY;
++
++ cp_fm_usr(argv, args->ARGS_PROC_LOAD.aArgv, status, argc);
++ for (i = 0; DSP_SUCCEEDED(status) && (i < argc); i++) {
++ if (argv[i] != NULL) {
++ /* User space pointer to argument */
++ temp = (char *) argv[i];
++ len = strlen_user((char *)temp);
++ /* Kernel space pointer to argument */
++ argv[i] = MEM_Alloc(len, MEM_NONPAGED);
++ if (argv[i] == NULL) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ cp_fm_usr(argv[i], temp, status, len);
++ }
++ }
++ /* TODO: validate this */
++ if (args->ARGS_PROC_LOAD.aEnvp != NULL) {
++ /* number of elements in the envp array including NULL */
++ len = 0;
++ do {
++ len++;
++ get_user(temp, args->ARGS_PROC_LOAD.aEnvp);
++ } while (temp);
++ envp = MEM_Alloc(len * sizeof(u8 *), MEM_NONPAGED);
++ if (envp == NULL)
++ status = DSP_EMEMORY;
++
++ cp_fm_usr(envp, args->ARGS_PROC_LOAD.aEnvp, status, len);
++ for (i = 0; DSP_SUCCEEDED(status) && (envp[i] != NULL); i++) {
++ /* User space pointer to argument */
++ temp = (char *)envp[i];
++ len = strlen_user((char *)temp);
++ /* Kernel space pointer to argument */
++ envp[i] = MEM_Alloc(len, MEM_NONPAGED);
++ if (envp[i] == NULL) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ cp_fm_usr(envp[i], temp, status, len);
++ }
++ }
++ GT_5trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_Load, hProcessor: 0x%x\n\tiArgc:"
++ "0x%x\n\taArgv: 0x%x\n\taArgv[0]: %s\n\taEnvp: 0x%0x\n",
++ args->ARGS_PROC_LOAD.hProcessor,
++ args->ARGS_PROC_LOAD.iArgc, args->ARGS_PROC_LOAD.aArgv,
++ argv[0], args->ARGS_PROC_LOAD.aEnvp);
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Load(args->ARGS_PROC_LOAD.hProcessor,
++ args->ARGS_PROC_LOAD.iArgc,
++ (CONST char **)argv, (CONST char **)envp);
++ }
++ if (envp != NULL) {
++ i = 0;
++ while (envp[i] != NULL)
++ MEM_Free(envp[i++]);
++
++ MEM_Free(envp);
++ }
++ if (argv != NULL) {
++ for (i = 0; i < argc; i++) {
++ if (argv[i] != NULL)
++ MEM_Free(argv[i]);
++
++ }
++ MEM_Free(argv);
++ }
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Map ========
++ */
++u32 PROCWRAP_Map(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ void *pMapAddr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Map: entered\n");
++ status = PROC_Map(args->ARGS_PROC_MAPMEM.hProcessor,
++ args->ARGS_PROC_MAPMEM.pMpuAddr,
++ args->ARGS_PROC_MAPMEM.ulSize,
++ args->ARGS_PROC_MAPMEM.pReqAddr, &pMapAddr,
++ args->ARGS_PROC_MAPMEM.ulMapAttr);
++ if (DSP_SUCCEEDED(status)) {
++ if (put_user(pMapAddr, args->ARGS_PROC_MAPMEM.ppMapAddr))
++ status = DSP_EINVALIDARG;
++
++ }
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_RegisterNotify ========
++ */
++u32 PROCWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = PROC_RegisterNotify(args->ARGS_PROC_REGISTER_NOTIFY.hProcessor,
++ args->ARGS_PROC_REGISTER_NOTIFY.uEventMask,
++ args->ARGS_PROC_REGISTER_NOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_PROC_REGISTER_NOTIFY.hNotification, &notification,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_ReserveMemory ========
++ */
++u32 PROCWRAP_ReserveMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ void *pRsvAddr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_ReserveMemory: entered\n");
++ status = PROC_ReserveMemory(args->ARGS_PROC_RSVMEM.hProcessor,
++ args->ARGS_PROC_RSVMEM.ulSize, &pRsvAddr);
++ if (put_user(pRsvAddr, args->ARGS_PROC_RSVMEM.ppRsvAddr))
++ status = DSP_EINVALIDARG;
++
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Start ========
++ */
++u32 PROCWRAP_Start(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Start: entered\n");
++ retVal = PROC_Start(args->ARGS_PROC_START.hProcessor);
++ return retVal;
++}
++
++/*
++ * ======== PROCWRAP_UnMap ========
++ */
++u32 PROCWRAP_UnMap(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_UnMap: entered\n");
++ status = PROC_UnMap(args->ARGS_PROC_UNMAPMEM.hProcessor,
++ args->ARGS_PROC_UNMAPMEM.pMapAddr);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_UnReserveMemory ========
++ */
++u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "PROCWRAP_UnReserveMemory: entered\n");
++ status = PROC_UnReserveMemory(args->ARGS_PROC_UNRSVMEM.hProcessor,
++ args->ARGS_PROC_UNRSVMEM.pRsvAddr);
++ return status;
++}
++
++/*
++ * ======== PROCWRAP_Stop ========
++ */
++u32 PROCWRAP_Stop(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_Stop: entered\n");
++ retVal = PROC_Stop(args->ARGS_PROC_STOP.hProcessor);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Allocate ========
++ */
++u32 NODEWRAP_Allocate(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_UUID nodeId;
++ u32 cbDataSize;
++ u32 __user *pSize = (u32 __user *)args->ARGS_NODE_ALLOCATE.pArgs;
++ u8 *pArgs = NULL;
++ struct DSP_NODEATTRIN attrIn, *pAttrIn = NULL;
++ struct NODE_OBJECT *hNode;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Allocate: entered\n");
++
++ /* Optional argument */
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_NODE_ALLOCATE.pArgs, status,
++ cbDataSize);
++ }
++ cp_fm_usr(&nodeId, args->ARGS_NODE_ALLOCATE.pNodeID, status, 1);
++ /* Optional argument */
++ if (args->ARGS_NODE_ALLOCATE.pAttrIn) {
++ cp_fm_usr(&attrIn, args->ARGS_NODE_ALLOCATE.pAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrIn = &attrIn;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_Allocate(args->ARGS_NODE_ALLOCATE.hProcessor,
++ &nodeId, (struct DSP_CBDATA *)pArgs,
++ pAttrIn, &hNode);
++ }
++ cp_to_usr(args->ARGS_NODE_ALLOCATE.phNode, &hNode, status, 1);
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_AllocMsgBuf ========
++ */
++u32 NODEWRAP_AllocMsgBuf(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_BUFFERATTR *pAttr = NULL;
++ struct DSP_BUFFERATTR attr;
++ u8 *pBuffer = NULL;
++
++ if (args->ARGS_NODE_ALLOCMSGBUF.pAttr) { /* Optional argument */
++ cp_fm_usr(&attr, args->ARGS_NODE_ALLOCMSGBUF.pAttr, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttr = &attr;
++
++ }
++ /* IN OUT argument */
++ cp_fm_usr(&pBuffer, args->ARGS_NODE_ALLOCMSGBUF.pBuffer, status, 1);
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_AllocMsgBuf(args->ARGS_NODE_ALLOCMSGBUF.hNode,
++ args->ARGS_NODE_ALLOCMSGBUF.uSize,
++ pAttr, &pBuffer);
++ }
++ cp_to_usr(args->ARGS_NODE_ALLOCMSGBUF.pBuffer, &pBuffer, status, 1)
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_ChangePriority ========
++ */
++u32 NODEWRAP_ChangePriority(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_ChangePriority: entered\n");
++ retVal = NODE_ChangePriority(args->ARGS_NODE_CHANGEPRIORITY.hNode,
++ args->ARGS_NODE_CHANGEPRIORITY.iPriority);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Connect ========
++ */
++u32 NODEWRAP_Connect(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_STRMATTR attrs;
++ struct DSP_STRMATTR *pAttrs = NULL;
++ u32 cbDataSize;
++ u32 __user *pSize = (u32 __user *)args->ARGS_NODE_CONNECT.pConnParam;
++ u8 *pArgs = NULL;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Connect: entered\n");
++
++ /* Optional argument */
++ if (pSize) {
++ if (get_user(cbDataSize, pSize))
++ status = DSP_EFAIL;
++
++ cbDataSize += sizeof(u32);
++ if (DSP_SUCCEEDED(status)) {
++ pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED);
++ if (pArgs == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ cp_fm_usr(pArgs, args->ARGS_NODE_CONNECT.pConnParam, status,
++ cbDataSize);
++ }
++ if (args->ARGS_NODE_CONNECT.pAttrs) { /* Optional argument */
++ cp_fm_usr(&attrs, args->ARGS_NODE_CONNECT.pAttrs, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttrs = &attrs;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_Connect(args->ARGS_NODE_CONNECT.hNode,
++ args->ARGS_NODE_CONNECT.uStream,
++ args->ARGS_NODE_CONNECT.hOtherNode,
++ args->ARGS_NODE_CONNECT.uOtherStream,
++ pAttrs, (struct DSP_CBDATA *)pArgs);
++ }
++ if (pArgs)
++ MEM_Free(pArgs);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Create ========
++ */
++u32 NODEWRAP_Create(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Create: entered\n");
++ retVal = NODE_Create(args->ARGS_NODE_CREATE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Delete ========
++ */
++u32 NODEWRAP_Delete(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Delete: entered\n");
++ retVal = NODE_Delete(args->ARGS_NODE_DELETE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_FreeMsgBuf ========
++ */
++u32 NODEWRAP_FreeMsgBuf(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_BUFFERATTR *pAttr = NULL;
++ struct DSP_BUFFERATTR attr;
++ if (args->ARGS_NODE_FREEMSGBUF.pAttr) { /* Optional argument */
++ cp_fm_usr(&attr, args->ARGS_NODE_FREEMSGBUF.pAttr, status, 1);
++ if (DSP_SUCCEEDED(status))
++ pAttr = &attr;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_FreeMsgBuf(args->ARGS_NODE_FREEMSGBUF.hNode,
++ args->ARGS_NODE_FREEMSGBUF.pBuffer,
++ pAttr);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_GetAttr ========
++ */
++u32 NODEWRAP_GetAttr(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NODEATTR attr;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetAttr: entered\n");
++
++ status = NODE_GetAttr(args->ARGS_NODE_GETATTR.hNode, &attr,
++ args->ARGS_NODE_GETATTR.uAttrSize);
++ cp_to_usr(args->ARGS_NODE_GETATTR.pAttr, &attr, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_GetMessage ========
++ */
++u32 NODEWRAP_GetMessage(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ struct DSP_MSG msg;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_GetMessage: entered\n");
++
++ status = NODE_GetMessage(args->ARGS_NODE_GETMESSAGE.hNode, &msg,
++ args->ARGS_NODE_GETMESSAGE.uTimeout);
++
++ cp_to_usr(args->ARGS_NODE_GETMESSAGE.pMessage, &msg, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Pause ========
++ */
++u32 NODEWRAP_Pause(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Pause: entered\n");
++ retVal = NODE_Pause(args->ARGS_NODE_PAUSE.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_PutMessage ========
++ */
++u32 NODEWRAP_PutMessage(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_MSG msg;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_PutMessage: entered\n");
++
++ cp_fm_usr(&msg, args->ARGS_NODE_PUTMESSAGE.pMessage, status, 1);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = NODE_PutMessage(args->ARGS_NODE_PUTMESSAGE.hNode, &msg,
++ args->ARGS_NODE_PUTMESSAGE.uTimeout);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_RegisterNotify ========
++ */
++u32 NODEWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = NODE_RegisterNotify(args->ARGS_NODE_REGISTERNOTIFY.hNode,
++ args->ARGS_NODE_REGISTERNOTIFY.uEventMask,
++ args->ARGS_NODE_REGISTERNOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_NODE_REGISTERNOTIFY.hNotification, &notification,
++ status, 1);
++ return status;
++}
++
++/*
++ * ======== NODEWRAP_Run ========
++ */
++u32 NODEWRAP_Run(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Run: entered\n");
++ retVal = NODE_Run(args->ARGS_NODE_RUN.hNode);
++
++ return retVal;
++}
++
++/*
++ * ======== NODEWRAP_Terminate ========
++ */
++u32 NODEWRAP_Terminate(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ DSP_STATUS tempstatus;
++
++ GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Terminate: entered\n");
++
++ status = NODE_Terminate(args->ARGS_NODE_TERMINATE.hNode, &tempstatus);
++
++ cp_to_usr(args->ARGS_NODE_TERMINATE.pStatus, &tempstatus, status, 1);
++
++ return status;
++}
++
++
++/*
++ * ======== NODEWRAP_GetUUIDProps ========
++ */
++u32 NODEWRAP_GetUUIDProps(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_UUID nodeId;
++ struct DSP_NDBPROPS *pnodeProps = NULL;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_GetUUIDPropste: entered\n");
++
++
++ cp_fm_usr(&nodeId, args->ARGS_NODE_GETUUIDPROPS.pNodeID, status, 1);
++ pnodeProps = MEM_Alloc(sizeof(struct DSP_NDBPROPS), MEM_NONPAGED);
++ if (pnodeProps != NULL) {
++ status = NODE_GetUUIDProps(args->
++ ARGS_NODE_GETUUIDPROPS.hProcessor,
++ &nodeId, pnodeProps);
++ cp_to_usr(args->ARGS_NODE_GETUUIDPROPS.pNodeProps, pnodeProps,
++ status, 1);
++ } else
++ status = DSP_EMEMORY;
++ if (pnodeProps)
++ MEM_Free(pnodeProps);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_AllocateBuffer ========
++ */
++u32 STRMWRAP_AllocateBuffer(union Trapped_Args *args)
++{
++ DSP_STATUS status;
++ u8 **apBuffer = NULL;
++ u32 uNumBufs = args->ARGS_STRM_ALLOCATEBUFFER.uNumBufs;
++
++ DBC_Require(uNumBufs <= MAX_BUFS);
++
++ apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
++
++ status = STRM_AllocateBuffer(args->ARGS_STRM_ALLOCATEBUFFER.hStream,
++ args->ARGS_STRM_ALLOCATEBUFFER.uSize,
++ apBuffer, uNumBufs);
++ cp_to_usr(args->ARGS_STRM_ALLOCATEBUFFER.apBuffer, apBuffer, status,
++ uNumBufs);
++ if (apBuffer)
++ MEM_Free(apBuffer);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Close ========
++ */
++u32 STRMWRAP_Close(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Close(args->ARGS_STRM_CLOSE.hStream);
++
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_FreeBuffer ========
++ */
++u32 STRMWRAP_FreeBuffer(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u8 **apBuffer = NULL;
++ u32 uNumBufs = args->ARGS_STRM_FREEBUFFER.uNumBufs;
++
++ DBC_Require(uNumBufs <= MAX_BUFS);
++
++ apBuffer = MEM_Alloc((uNumBufs * sizeof(u8 *)), MEM_NONPAGED);
++
++ cp_fm_usr(apBuffer, args->ARGS_STRM_FREEBUFFER.apBuffer, status,
++ uNumBufs);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_FreeBuffer(args->ARGS_STRM_FREEBUFFER.hStream,
++ apBuffer, uNumBufs);
++ }
++ cp_to_usr(args->ARGS_STRM_FREEBUFFER.apBuffer, apBuffer, status,
++ uNumBufs);
++ if (apBuffer)
++ MEM_Free(apBuffer);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_GetEventHandle ========
++ */
++u32 STRMWRAP_GetEventHandle(union Trapped_Args *args)
++{
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== STRMWRAP_GetInfo ========
++ */
++u32 STRMWRAP_GetInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_INFO strmInfo;
++ struct DSP_STREAMINFO user;
++ struct DSP_STREAMINFO *temp;
++
++ cp_fm_usr(&strmInfo, args->ARGS_STRM_GETINFO.pStreamInfo, status, 1);
++ temp = strmInfo.pUser;
++
++ strmInfo.pUser = &user;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_GetInfo(args->ARGS_STRM_GETINFO.hStream,
++ &strmInfo, args->ARGS_STRM_GETINFO.uStreamInfoSize);
++ }
++ cp_to_usr(temp, strmInfo.pUser, status, 1);
++ strmInfo.pUser = temp;
++ cp_to_usr(args->ARGS_STRM_GETINFO.pStreamInfo, &strmInfo, status, 1);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Idle ========
++ */
++u32 STRMWRAP_Idle(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Idle(args->ARGS_STRM_IDLE.hStream,
++ args->ARGS_STRM_IDLE.bFlush);
++
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_Issue ========
++ */
++u32 STRMWRAP_Issue(union Trapped_Args *args)
++{
++ u32 retVal;
++
++ retVal = STRM_Issue(args->ARGS_STRM_ISSUE.hStream,
++ args->ARGS_STRM_ISSUE.pBuffer,
++ args->ARGS_STRM_ISSUE.dwBytes,
++ args->ARGS_STRM_ISSUE.dwBufSize,
++ args->ARGS_STRM_ISSUE.dwArg);
++
++ /* This is a user space pointer */
++ return retVal;
++}
++
++/*
++ * ======== STRMWRAP_Open ========
++ */
++u32 STRMWRAP_Open(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_ATTR attr;
++ struct STRM_OBJECT *pStrm;
++ struct DSP_STREAMATTRIN strmAttrIn;
++
++ cp_fm_usr(&attr, args->ARGS_STRM_OPEN.pAttrIn, status, 1);
++
++ if (attr.pStreamAttrIn != NULL) { /* Optional argument */
++ cp_fm_usr(&strmAttrIn, attr.pStreamAttrIn, status, 1);
++ if (DSP_SUCCEEDED(status))
++ attr.pStreamAttrIn = &strmAttrIn;
++
++ }
++ status = STRM_Open(args->ARGS_STRM_OPEN.hNode,
++ args->ARGS_STRM_OPEN.uDirection,
++ args->ARGS_STRM_OPEN.uIndex, &attr, &pStrm);
++ cp_to_usr(args->ARGS_STRM_OPEN.phStream, &pStrm, status, 1);
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Reclaim ========
++ */
++u32 STRMWRAP_Reclaim(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ u8 *pBufPtr;
++ u32 ulBytes;
++ u32 dwArg;
++ u32 ulBufSize;
++
++ status = STRM_Reclaim(args->ARGS_STRM_RECLAIM.hStream, &pBufPtr,
++ &ulBytes, &ulBufSize, &dwArg);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBufPtr, &pBufPtr, status, 1);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBytes, &ulBytes, status, 1);
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pdwArg, &dwArg, status, 1);
++
++ if (args->ARGS_STRM_RECLAIM.pBufSize != NULL) {
++ cp_to_usr(args->ARGS_STRM_RECLAIM.pBufSize, &ulBufSize,
++ status, 1);
++ }
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_RegisterNotify ========
++ */
++u32 STRMWRAP_RegisterNotify(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NOTIFICATION notification;
++
++ GT_0trace(WCD_debugMask, GT_ENTER,
++ "NODEWRAP_RegisterNotify: entered\n");
++
++ /* Initialize the notification data structure */
++ notification.psName = NULL;
++ notification.handle = NULL;
++
++ status = STRM_RegisterNotify(args->ARGS_STRM_REGISTERNOTIFY.hStream,
++ args->ARGS_STRM_REGISTERNOTIFY.uEventMask,
++ args->ARGS_STRM_REGISTERNOTIFY.uNotifyType,
++ &notification);
++ cp_to_usr(args->ARGS_STRM_REGISTERNOTIFY.hNotification, &notification,
++ status, 1);
++
++ return status;
++}
++
++/*
++ * ======== STRMWRAP_Select ========
++ */
++u32 STRMWRAP_Select(union Trapped_Args *args)
++{
++ u32 mask;
++ struct STRM_OBJECT *aStrmTab[MAX_STREAMS];
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(args->ARGS_STRM_SELECT.nStreams <= MAX_STREAMS);
++
++ cp_fm_usr(aStrmTab, args->ARGS_STRM_SELECT.aStreamTab, status,
++ args->ARGS_STRM_SELECT.nStreams);
++ if (DSP_SUCCEEDED(status)) {
++ status = STRM_Select(aStrmTab, args->ARGS_STRM_SELECT.nStreams,
++ &mask, args->ARGS_STRM_SELECT.uTimeout);
++ }
++ cp_to_usr(args->ARGS_STRM_SELECT.pMask, &mask, status, 1);
++ return status;
++}
++
++/* CMM */
++
++/*
++ * ======== CMMWRAP_CallocBuf ========
++ */
++u32 CMMWRAP_CallocBuf(union Trapped_Args *args)
++{
++ /* This operation is done in kernel */
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== CMMWRAP_FreeBuf ========
++ */
++u32 CMMWRAP_FreeBuf(union Trapped_Args *args)
++{
++ /* This operation is done in kernel */
++ return DSP_ENOTIMPL;
++}
++
++/*
++ * ======== CMMWRAP_GetHandle ========
++ */
++u32 CMMWRAP_GetHandle(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr;
++
++ status = CMM_GetHandle(args->ARGS_CMM_GETHANDLE.hProcessor, &hCmmMgr);
++
++ cp_to_usr(args->ARGS_CMM_GETHANDLE.phCmmMgr, &hCmmMgr, status, 1);
++
++ return status;
++}
++
++/*
++ * ======== CMMWRAP_GetInfo ========
++ */
++u32 CMMWRAP_GetInfo(union Trapped_Args *args)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_INFO cmmInfo;
++
++ status = CMM_GetInfo(args->ARGS_CMM_GETINFO.hCmmMgr, &cmmInfo);
++
++ cp_to_usr(args->ARGS_CMM_GETINFO.pCmmInfo, &cmmInfo, status, 1);
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/dbdcd.c b/drivers/dsp/bridge/rmgr/dbdcd.c
+new file mode 100644
+index 0000000..c5ec8f9
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/dbdcd.c
+@@ -0,0 +1,1573 @@
++/*
++ * dbdcd.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbdcd.c ========
++ * Description:
++ * This file contains the implementation of the DSP/BIOS Bridge
++ * Configuration Database (DCD).
++ *
++ * Notes:
++ * The fxn DCD_GetObjects can apply a callback fxn to each DCD object
++ * that is located in a specified COFF file. At the moment,
++ * DCD_AutoRegister, DCD_AutoUnregister, and NLDR module all use
++ * DCD_GetObjects.
++ *
++ *! Revision History
++ *! ================
++ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
++ *! 17-Dec-2002 map Modified DCD_GetDepLibs, DCD_GetNumDepLibs, GetDepLibInfo
++ *! to include phase information
++ *! 02-Dec-2002 map Modified DCD_GetLibraryName for phases in different
++ *! libraries
++ *! 26-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
++ *! DCD implementation.
++ *! 17-Jul-2002 jeh Call COD_Open() instead of COD_OpenBase(), call COD_Close()
++ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 vp Ported to Linux platform
++ *! 15-Mar-2002 jeh Read dynamic loading memory requirements into node object
++ *! data. Added DCD_GetLibraryName().
++ *! 13-Feb-2002 jeh Get system stack size in GetAttrsFromBuf().
++ *! 01-Aug-2001 ag: Added check for PROC "extended" attributes used for
++ *! DSP-MMU setup. These are private attributes.
++ *! 18-Apr-2001 jeh Use COD_OpenBase instead of COD_LoadBase.
++ *! 03-Apr-2001 sg: Changed error names to DSP_EDCD* format.
++ *! 11-Jan-2001 jeh Changes to DCD_GetObjectDef to match node.cdb, proc.cdb.
++ *! 12-Dec-2000 kc: Added DCD_AutoUnregister. MSGNODE, DAISNODE added in
++ *! GetAttrsFromBuf
++ *! 22-Nov-2000 kc: Replaced sprintf() calls with strncat.
++ *! 09-Nov-2000 kc: Optimized DCD module.
++ *! 30-Oct-2000 kc: Added DCD_AutoRegister function; changed local var. names.
++ *! 29-Sep-2000 kc: Added code review changes (src/reviews/dcd_reviews.txt).
++ *! 06-Sep-2000 jeh Get message segid, message notification type. Added Atoi()
++ *! to replace atoi(), until cdb generation can output in
++ *! decimal format.
++ *! 26-Jul-2000 kc: Created.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/uuidutil.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbdcd.h>
++
++/* ----------------------------------- Global defines. */
++#define SIGNATURE 0x5f444344 /* "DCD_" (in reverse). */
++
++#define IsValidHandle(h) (((h) != NULL) && (h->dwSignature == SIGNATURE))
++
++#define MAX_INT2CHAR_LENGTH 16 /* Maximum int2char len of 32 bit int. */
++
++/* Name of section containing dependent libraries */
++#define DEPLIBSECT ".dspbridge_deplibs"
++
++/* DCD specific structures. */
++struct DCD_MANAGER {
++ u32 dwSignature; /* Used for object validation. */
++ struct COD_MANAGER *hCodMgr; /* Handle to COD manager object. */
++};
++
++/* Global reference variables. */
++static u32 cRefs;
++static u32 cEnumRefs;
++
++extern struct GT_Mask curTrace;
++
++/* helper function prototypes. */
++static s32 Atoi(char *pszBuf);
++
++static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
++ enum DSP_DCDOBJTYPE objType,
++ struct DCD_GENERICOBJ *pGenObj);
++
++static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize);
++
++static char DspChar2GppChar(char *pWord, s32 cDspCharSize);
++
++static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT u16 *pNumLibs,
++ OPTIONAL OUT u16 *pNumPersLibs,
++ OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
++ OPTIONAL OUT bool *pPersistentDepLibs,
++ IN enum NLDR_PHASE phase);
++
++/*
++ * ======== DCD_AutoRegister ========
++ * Purpose:
++ * Parses the supplied image and resigsters with DCD.
++ */
++
++DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_AutoRegister: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++ status = DCD_GetObjects(hDcdMgr, pszCoffPath,
++ (DCD_REGISTERFXN)DCD_RegisterObject,
++ (void *)pszCoffPath);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoRegister: invalid DCD manager handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_AutoUnregister ========
++ * Purpose:
++ * Parses the supplied DSP image and unresiters from DCD.
++ */
++DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
++ IN char *pszCoffPath)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_AutoUnregister: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++ status = DCD_GetObjects(hDcdMgr, pszCoffPath,
++ (DCD_REGISTERFXN)DCD_RegisterObject,
++ NULL);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoUnregister: invalid DCD manager"
++ " handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_CreateManager ========
++ * Purpose:
++ * Creates DCD manager.
++ */
++DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
++ OUT struct DCD_MANAGER **phDcdMgr)
++{
++ struct COD_MANAGER *hCodMgr; /* COD manager handle */
++ struct DCD_MANAGER *pDcdMgr = NULL; /* DCD Manager pointer */
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs >= 0);
++ DBC_Require(phDcdMgr);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_CreateManager: phDcdMgr 0x%x\n",
++ phDcdMgr);
++
++ status = COD_Create(&hCodMgr, pszZlDllName, NULL);
++ if (DSP_SUCCEEDED(status)) {
++
++ /* Create a DCD object. */
++ MEM_AllocObject(pDcdMgr, struct DCD_MANAGER, SIGNATURE);
++ if (pDcdMgr != NULL) {
++
++ /* Fill out the object. */
++ pDcdMgr->hCodMgr = hCodMgr;
++
++ /* Return handle to this DCD interface. */
++ *phDcdMgr = pDcdMgr;
++
++ GT_2trace(curTrace, GT_5CLASS,
++ "DCD_CreateManager: pDcdMgr 0x%x, "
++ " hCodMgr 0x%x", pDcdMgr, hCodMgr);
++ } else {
++ status = DSP_EMEMORY;
++
++ /*
++ * If allocation of DcdManager object failed, delete the
++ * COD manager.
++ */
++ COD_Delete(hCodMgr);
++
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_CreateManager: MEM_AllocObject failed\n");
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_CreateManager: COD_Create failed\n");
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status)) || ((hCodMgr == NULL) &&
++ (status == DSP_EFAIL)) || ((pDcdMgr == NULL) &&
++ (status == DSP_EMEMORY)));
++
++ return status;
++}
++
++/*
++ * ======== DCD_DestroyManager ========
++ * Purpose:
++ * Frees DCD Manager object.
++ */
++DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr;
++ DSP_STATUS status = DSP_EHANDLE;
++
++ DBC_Require(cRefs >= 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_DestroyManager: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ if (IsValidHandle(hDcdMgr)) {
++
++ /* Delete the COD manager. */
++ COD_Delete(pDcdMgr->hCodMgr);
++
++ /* Deallocate a DCD manager object. */
++ MEM_FreeObject(pDcdMgr);
++
++ status = DSP_SOK;
++ } else {
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_DestroyManager: invalid DCD manager handle.\n");
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_EnumerateObject ========
++ * Purpose:
++ * Enumerates objects in the DCD.
++ */
++DSP_STATUS DCD_EnumerateObject(IN s32 cIndex, IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DSP_UUID *pUuid)
++{
++ DSP_STATUS status = DSP_SOK;
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szValue[REG_MAXREGPATHLENGTH];
++ char szData[REG_MAXREGPATHLENGTH];
++ u32 dwValueSize;
++ u32 dwDataSize;
++ struct DSP_UUID dspUuid;
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++ u32 dwKeyLen = 0;
++
++ DBC_Require(cRefs >= 0);
++ DBC_Require(cIndex >= 0);
++ DBC_Require(pUuid != NULL);
++
++ GT_3trace(curTrace, GT_ENTER,
++ "DCD_EnumerateObject: cIndex %d, objType %d, "
++ " pUuid 0x%x\n", cIndex, objType, pUuid);
++
++ if ((cIndex != 0) && (cEnumRefs == 0)) {
++ /*
++ * If an enumeration is being performed on an index greater
++ * than zero, then the current cEnumRefs must have been
++ * incremented to greater than zero.
++ */
++ status = DSP_ECHANGEDURINGENUM;
++ } else {
++ /* Enumerate a specific key in the registry by index. */
++ dwValueSize = REG_MAXREGPATHLENGTH;
++ dwDataSize = REG_MAXREGPATHLENGTH;
++
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++
++ /* Create proper REG key; concatenate DCD_REGKEY with
++ * objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, "_\0", 2);
++ } else {
++ status = DSP_EFAIL;
++ }
++
++ /* This snprintf is guaranteed not to exceed max size of an
++ * integer. */
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d",
++ objType);
++
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType,
++ strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_EnumValue(NULL, cIndex, szRegKey, szValue,
++ &dwValueSize, szData,
++ &dwDataSize);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Create UUID value using string retrieved from
++ * registry. */
++ UUID_UuidFromString(szValue, &dspUuid);
++
++ *pUuid = dspUuid;
++
++ /* Increment cEnumRefs to update reference count. */
++ cEnumRefs++;
++
++ status = DSP_SOK;
++ } else if (status == REG_E_NOMOREITEMS) {
++ /* At the end of enumeration. Reset cEnumRefs. */
++ cEnumRefs = 0;
++
++ status = DSP_SENUMCOMPLETE;
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(curTrace, GT_6CLASS,
++ "DCD_EnumerateObject: REG_EnumValue"
++ " failed, status = 0x%x\n", status);
++ }
++ }
++
++ DBC_Ensure(pUuid || (status == DSP_EFAIL));
++
++ return status;
++}
++
++/*
++ * ======== DCD_Exit ========
++ * Purpose:
++ * Discontinue usage of the DCD module.
++ */
++void DCD_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(curTrace, GT_5CLASS, "DCD_Exit: cRefs 0x%x\n", cRefs);
++
++ cRefs--;
++ if (cRefs == 0) {
++ REG_Exit();
++ COD_Exit();
++ MEM_Exit();
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DCD_GetDepLibs ========
++ */
++DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ u16 numLibs, OUT struct DSP_UUID *pDepLibUuids,
++ OUT bool *pPersistentDepLibs, IN enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pUuid != NULL);
++ DBC_Require(pDepLibUuids != NULL);
++ DBC_Require(pPersistentDepLibs != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ status = GetDepLibInfo(hDcdMgr, pUuid, &numLibs, NULL, pDepLibUuids,
++ pPersistentDepLibs, phase);
++
++ return status;
++}
++
++/*
++ * ======== DCD_GetNumDepLibs ========
++ */
++DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid, OUT u16 *pNumLibs,
++ OUT u16 *pNumPersLibs, IN enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pNumLibs != NULL);
++ DBC_Require(pNumPersLibs != NULL);
++ DBC_Require(pUuid != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ status = GetDepLibInfo(hDcdMgr, pUuid, pNumLibs, pNumPersLibs,
++ NULL, NULL, phase);
++
++ return status;
++}
++
++/*
++ * ======== DCD_GetObjectDef ========
++ * Purpose:
++ * Retrieves the properties of a node or processor based on the UUID and
++ * object type.
++ */
++DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pObjUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ OUT struct DCD_GENERICOBJ *pObjDef)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ struct COD_LIBRARYOBJ *lib = NULL;
++ DSP_STATUS status = DSP_SOK;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ u32 dwBufSize; /* Used by REG functions */
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char *szUuid; /*[MAXUUIDLEN];*/
++ char szRegData[REG_MAXREGPATHLENGTH];
++ char szSectName[MAXUUIDLEN + 2]; /* ".[UUID]\0" */
++ char *pszCoffBuf;
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pObjDef != NULL);
++ DBC_Require(pObjUuid != NULL);
++
++ GT_4trace(curTrace, GT_ENTER,
++ "DCD_GetObjectDef: hDcdMgr 0x%x, " "objUuid"
++ " 0x%x, objType 0x%x, pObjDef 0x%x\n", hDcdMgr, pObjUuid,
++ objType, pObjDef);
++ szUuid = (char *)MEM_Calloc(MAXUUIDLEN, MEM_PAGED);
++ if (!szUuid)
++ return status = DSP_EMEMORY;
++
++ if (!IsValidHandle(hDcdMgr)) {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: invalid "
++ "DCD manager handle.\n");
++ goto func_end;
++ }
++ /* Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString(pObjUuid, szUuid, MAXUUIDLEN);
++
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ /* Retrieve paths from the registry based on struct DSP_UUID */
++ dwBufSize = REG_MAXREGPATHLENGTH;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, szRegKey, szRegKey, (u8 *)szRegData,
++ &dwBufSize);
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EUUID;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "REG_GetValue() failed\n");
++ goto func_end;
++ }
++ /* Open COFF file. */
++ status = COD_Open(pDcdMgr->hCodMgr, szRegData, COD_NOLOAD, &lib);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDLOADBASE;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "COD_OpenBase() failed\n");
++ goto func_end;
++ }
++ /* Ensure szUuid + 1 is not greater than sizeof szSectName. */
++ DBC_Assert((strlen(szUuid) + 1) < sizeof(szSectName));
++ /* Create section name based on node UUID. A period is
++ * pre-pended to the UUID string to form the section name.
++ * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
++ strncpy(szSectName, ".", 2);
++ strncat(szSectName, szUuid, strlen(szUuid));
++ /* Get section information. */
++ status = COD_GetSection(lib, szSectName, &ulAddr, &ulLen);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDGETSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef:"
++ " COD_GetSection() failed\n");
++ goto func_end;
++ }
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
++#ifdef _DB_TIOMAP
++ if (strstr(szRegData, "iva") == NULL) {
++ /* Locate section by objectID and read its content. */
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++ } else {
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++ GT_0trace(curTrace, GT_4CLASS,
++ "Skipped Byte swap for IVA !!\n");
++ }
++#else
++ status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Compres DSP buffer to conform to PC format. */
++ if (strstr(szRegData, "iva") == NULL) {
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ } else {
++ CompressBuf(pszCoffBuf, ulLen, 1);
++ GT_0trace(curTrace, GT_4CLASS, "Compressing IVA "
++ "COFF buffer by 1 for IVA !!\n");
++ }
++ /* Parse the content of the COFF buffer. */
++ status = GetAttrsFromBuf(pszCoffBuf, ulLen, objType, pObjDef);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDPARSESECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "GetAttrsFromBuf() failed\n");
++ }
++ } else {
++ status = DSP_EDCDREADSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
++ "COD_ReadSection() failed\n");
++ }
++ /* Free the previously allocated dynamic buffer. */
++ MEM_Free(pszCoffBuf);
++func_end:
++ if (lib)
++ COD_Close(lib);
++
++ if (szUuid)
++ MEM_Free(szUuid);
++ return status;
++}
++
++/*
++ * ======== DCD_GetObjects ========
++ */
++DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr, IN char *pszCoffPath,
++ DCD_REGISTERFXN registerFxn, void *handle)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ DSP_STATUS status = DSP_SOK;
++ char *pszCoffBuf;
++ char *pszCur;
++ struct COD_LIBRARYOBJ *lib = NULL;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ char seps[] = ":, ";
++ char *pToken = NULL;
++ struct DSP_UUID dspUuid;
++ s32 cObjectType;
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(curTrace, GT_ENTER,
++ "DCD_GetObjects: hDcdMgr 0x%x\n", hDcdMgr);
++ if (!IsValidHandle(hDcdMgr)) {
++ status = DSP_EHANDLE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: invalid DCD manager handle.\n");
++ goto func_end;
++ }
++ /* Open DSP coff file, don't load symbols. */
++ status = COD_Open(pDcdMgr->hCodMgr, pszCoffPath, COD_NOLOAD, &lib);
++ if (DSP_FAILED(status)) {
++ status = DSP_EDCDLOADBASE;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_AutoRegister: COD_Open() failed\n");
++ goto func_cont;
++ }
++ /* Get DCD_RESIGER_SECTION section information. */
++ status = COD_GetSection(lib, DCD_REGISTER_SECTION, &ulAddr, &ulLen);
++ if (DSP_FAILED(status) || !(ulLen > 0)) {
++ status = DSP_EDCDNOAUTOREGISTER;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: COD_GetSection() "
++ "- no auto register section\n");
++ goto func_cont;
++ }
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
++#ifdef _DB_TIOMAP
++ if (strstr(pszCoffPath, "iva") == NULL) {
++ /* Locate section by objectID and read its content. */
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
++ pszCoffBuf, ulLen);
++ } else {
++ GT_0trace(curTrace, GT_4CLASS, "Skipped Byte swap for IVA!!\n");
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
++ pszCoffBuf, ulLen);
++ }
++#else
++ status = COD_ReadSection(lib, DCD_REGISTER_SECTION, pszCoffBuf, ulLen);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Compress DSP buffer to conform to PC format. */
++ GT_0trace(curTrace, GT_4CLASS,
++ "Successfully read section !!\n");
++ if (strstr(pszCoffPath, "iva") == NULL) {
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ } else {
++ CompressBuf(pszCoffBuf, ulLen, 1);
++ GT_0trace(curTrace, GT_4CLASS, "Compress COFF buffer "
++ "with 1 word for IVA !!\n");
++ }
++ /* Read from buffer and register object in buffer. */
++ pszCur = pszCoffBuf;
++ while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
++ /* Retrieve UUID string. */
++ UUID_UuidFromString(pToken, &dspUuid);
++ /* Retrieve object type */
++ pToken = strsep(&pszCur, seps);
++ /* Retrieve object type */
++ cObjectType = Atoi(pToken);
++ /*
++ * Apply registerFxn to the found DCD object.
++ * Possible actions include:
++ *
++ * 1) Register found DCD object.
++ * 2) Unregister found DCD object (when handle == NULL)
++ * 3) Add overlay node.
++ */
++ GT_1trace(curTrace, GT_4CLASS, "Registering objtype "
++ "%d \n", cObjectType);
++ status = registerFxn(&dspUuid, cObjectType, handle);
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(curTrace, GT_5CLASS,
++ "DCD_GetObjects: status 0x%x\n",
++ status);
++ } else {
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_GetObjects: "
++ "registration() failed\n");
++ /* if error occurs, break from while loop. */
++ break;
++ }
++ }
++ } else {
++ status = DSP_EDCDREADSECT;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjects: "
++ "COD_ReadSection() failed\n");
++ }
++ /* Free the previously allocated dynamic buffer. */
++ MEM_Free(pszCoffBuf);
++func_cont:
++ if (lib)
++ COD_Close(lib);
++
++func_end:
++ return status;
++}
++
++/*
++ * ======== DCD_GetLibraryName ========
++ * Purpose:
++ * Retrieves the library name for the given UUID.
++ *
++ */
++DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT char *pstrLibName, IN OUT u32 *pdwSize,
++ enum NLDR_PHASE phase, OUT bool *fPhaseSplit)
++{
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szUuid[MAXUUIDLEN];
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pUuid != NULL);
++ DBC_Require(pstrLibName != NULL);
++ DBC_Require(pdwSize != NULL);
++ DBC_Require(IsValidHandle(hDcdMgr));
++
++ GT_4trace(curTrace, GT_ENTER,
++ "DCD_GetLibraryName: hDcdMgr 0x%x, pUuid 0x%x, "
++ " pstrLibName 0x%x, pdwSize 0x%x\n", hDcdMgr, pUuid,
++ pstrLibName, pdwSize);
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ switch (phase) {
++ case NLDR_CREATE:
++ /* create phase type */
++ sprintf(szObjType, "%d", DSP_DCDCREATELIBTYPE);
++ break;
++ case NLDR_EXECUTE:
++ /* execute phase type */
++ sprintf(szObjType, "%d", DSP_DCDEXECUTELIBTYPE);
++ break;
++ case NLDR_DELETE:
++ /* delete phase type */
++ sprintf(szObjType, "%d", DSP_DCDDELETELIBTYPE);
++ break;
++ case NLDR_NOPHASE:
++ /* known to be a dependent library */
++ sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
++ break;
++ default:
++ status = -1;
++ DBC_Assert(false);
++ }
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType))
++ < REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to find match in registry. */
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Retrieve path from the registry based on DSP_UUID */
++ status = REG_GetValue(NULL, szRegKey, szRegKey,
++ (u8 *)pstrLibName, pdwSize);
++ }
++ /* If can't find, phases might be registered as generic LIBRARYTYPE */
++ if (DSP_FAILED(status) && phase != NLDR_NOPHASE) {
++ if (fPhaseSplit)
++ *fPhaseSplit = false;
++
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, "_\0", 2);
++ } else {
++ status = DSP_EFAIL;
++ }
++ sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
++ if ((strlen(szRegKey) + strlen(szObjType))
++ < REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ status = REG_GetValue(NULL, szRegKey, szRegKey,
++ (u8 *)pstrLibName, pdwSize);
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_Init ========
++ * Purpose:
++ * Initialize the DCD module.
++ */
++bool DCD_Init(void)
++{
++ bool fInitMEM;
++ bool fInitREG;
++ bool fInitCOD;
++ bool fInit = true;
++
++ DBC_Require(cRefs >= 0);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_Init: (on enter) cRefs = 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0) {
++
++ /* Initialize required modules. */
++ fInitMEM = MEM_Init();
++ fInitCOD = COD_Init();
++ fInitREG = REG_Init();
++ if (!fInitMEM || !fInitCOD || !fInitREG) {
++ fInit = false;
++ GT_0trace(curTrace, GT_6CLASS, "DCD_Init failed\n");
++ /* Exit initialized modules. */
++ if (fInitMEM)
++ MEM_Exit();
++
++ if (fInitCOD)
++ COD_Exit();
++
++ if (fInitREG)
++ REG_Exit();
++
++ }
++ }
++
++ if (fInit)
++ cRefs++;
++
++
++ GT_1trace(curTrace, GT_5CLASS, "DCD_Init: (on exit) cRefs = 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs == 0)));
++
++ return fInit;
++}
++
++/*
++ * ======== DCD_RegisterObject ========
++ * Purpose:
++ * Registers a node or a processor with the DCD.
++ * If pszPathName == NULL, unregister the specified DCD object.
++ */
++DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType,
++ IN char *pszPathName)
++{
++ DSP_STATUS status = DSP_SOK;
++ char szRegKey[REG_MAXREGPATHLENGTH];
++ char szUuid[MAXUUIDLEN + 1];
++ u32 dwPathSize = 0;
++ u32 dwKeyLen; /* Len of REG key. */
++ char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pUuid != NULL);
++ DBC_Require((objType == DSP_DCDNODETYPE) ||
++ (objType == DSP_DCDPROCESSORTYPE) ||
++ (objType == DSP_DCDLIBRARYTYPE) ||
++ (objType == DSP_DCDCREATELIBTYPE) ||
++ (objType == DSP_DCDEXECUTELIBTYPE) ||
++ (objType == DSP_DCDDELETELIBTYPE));
++
++ GT_3trace(curTrace, GT_ENTER, "DCD_RegisterObject: object UUID 0x%x, "
++ "objType %d, szPathName %s\n", pUuid, objType, pszPathName);
++ /*
++ * Pre-determine final key length. It's length of DCD_REGKEY +
++ * "_\0" + length of szObjType string + terminating NULL.
++ */
++ dwKeyLen = strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
++ DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
++ /* Create proper REG key; concatenate DCD_REGKEY with objType. */
++ strncpy(szRegKey, DCD_REGKEY, strlen(DCD_REGKEY) + 1);
++ if ((strlen(szRegKey) + strlen("_\0")) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, "_\0", 2);
++ else
++ status = DSP_EFAIL;
++
++ status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
++ if (status == -1) {
++ status = DSP_EFAIL;
++ } else {
++ status = DSP_SOK;
++ if ((strlen(szRegKey) + strlen(szObjType)) <
++ REG_MAXREGPATHLENGTH) {
++ strncat(szRegKey, szObjType, strlen(szObjType) + 1);
++ } else {
++ status = DSP_EFAIL;
++ }
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
++ if ((strlen(szRegKey) + MAXUUIDLEN) < REG_MAXREGPATHLENGTH)
++ strncat(szRegKey, szUuid, MAXUUIDLEN);
++ else
++ status = DSP_EFAIL;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * If pszPathName != NULL, perform registration, otherwise,
++ * perform unregistration.
++ */
++ if (pszPathName) {
++ /* Add new reg value (UUID+objType) with COFF path
++ * info. */
++ dwPathSize = strlen(pszPathName) + 1;
++ status = REG_SetValue(NULL, szRegKey, szRegKey, REG_SZ,
++ (u8 *)pszPathName, dwPathSize);
++ GT_3trace(curTrace, GT_6CLASS,
++ "REG_SetValue REG_SZ=%d, "
++ "(u8 *)pszPathName=%s, dwPathSize=%d\n",
++ REG_SZ, pszPathName, dwPathSize);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_RegisterObject: REG_SetValue failed!\n");
++ }
++ } else {
++ /* Deregister an existing object. */
++ status = REG_DeleteValue(NULL, szRegKey, szRegKey);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_6CLASS,
++ "DCD_UnregisterObject: "
++ "REG_DeleteValue failed!\n");
++ }
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Because the node database has been updated through a
++ * successful object registration/de-registration operation,
++ * we need to reset the object enumeration counter to allow
++ * current enumerations to reflect this update in the node
++ * database.
++ */
++
++ cEnumRefs = 0;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DCD_UnregisterObject ========
++ * Call DCD_Register object with pszPathName set to NULL to
++ * perform actual object de-registration.
++ */
++DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
++ IN enum DSP_DCDOBJTYPE objType)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pUuid != NULL);
++ DBC_Require((objType == DSP_DCDNODETYPE) ||
++ (objType == DSP_DCDPROCESSORTYPE) ||
++ (objType == DSP_DCDLIBRARYTYPE) ||
++ (objType == DSP_DCDCREATELIBTYPE) ||
++ (objType == DSP_DCDEXECUTELIBTYPE) ||
++ (objType == DSP_DCDDELETELIBTYPE));
++
++ GT_2trace(curTrace, GT_ENTER,
++ "DCD_UnregisterObject: object UUID 0x%x, "
++ "objType %d\n", pUuid, objType);
++
++ /*
++ * When DCD_RegisterObject is called with NULL as pathname,
++ * it indicates an unregister object operation.
++ */
++ status = DCD_RegisterObject(pUuid, objType, NULL);
++
++ return status;
++}
++
++/*
++ **********************************************************************
++ * DCD Helper Functions
++ **********************************************************************
++ */
++
++/*
++ * ======== Atoi ========
++ * Purpose:
++ * This function converts strings in decimal or hex format to integers.
++ */
++static s32 Atoi(char *pszBuf)
++{
++ s32 result = 0;
++ char *pch = pszBuf;
++ char c;
++ char first;
++ s32 base = 10;
++ s32 len;
++
++ while (isspace(*pch))
++ pch++;
++
++ first = *pch;
++ if (first == '-' || first == '+') {
++ pch++;
++ } else {
++ /* Determine if base 10 or base 16 */
++ len = strlen(pch);
++ if (len > 1) {
++ c = pch[1];
++ if ((*pch == '0' && (c == 'x' || c == 'X'))) {
++ base = 16;
++ pch += 2;
++ }
++ c = pch[len - 1];
++ if (c == 'h' || c == 'H')
++ base = 16;
++
++ }
++ }
++
++ while (isdigit(c = *pch) || ((base == 16) && isxdigit(c))) {
++ result *= base;
++ if ('A' <= c && c <= 'F') {
++ c = c - 'A' + 10;
++ } else {
++ if ('a' <= c && c <= 'f')
++ c = c - 'a' + 10;
++ else
++ c -= '0';
++
++ }
++ result += c;
++ ++pch;
++ }
++
++ return result;
++}
++
++/*
++ * ======== GetAttrsFromBuf ========
++ * Purpose:
++ * Parse the content of a buffer filled with DSP-side data and
++ * retrieve an object's attributes from it. IMPORTANT: Assume the
++ * buffer has been converted from DSP format to GPP format.
++ */
++static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
++ enum DSP_DCDOBJTYPE objType,
++ struct DCD_GENERICOBJ *pGenObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ char seps[] = ", ";
++ char *pszCur;
++ char *token;
++ s32 cLen = 0;
++ u32 i = 0;
++#ifdef _DB_TIOMAP
++ s32 iEntry;
++#endif
++
++ DBC_Require(pszBuf != NULL);
++ DBC_Require(ulBufSize != 0);
++ DBC_Require((objType == DSP_DCDNODETYPE)
++ || (objType == DSP_DCDPROCESSORTYPE));
++ DBC_Require(pGenObj != NULL);
++
++
++ switch (objType) {
++ case DSP_DCDNODETYPE:
++ /*
++ * Parse COFF sect buffer to retrieve individual tokens used
++ * to fill in object attrs.
++ */
++ pszCur = pszBuf;
++ token = strsep(&pszCur, seps);
++
++ /* u32 cbStruct */
++ pGenObj->objData.nodeObj.ndbProps.cbStruct =
++ (u32) Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* DSP_UUID uiNodeID */
++ UUID_UuidFromString(token,
++ &pGenObj->objData.nodeObj.ndbProps.uiNodeID);
++ token = strsep(&pszCur, seps);
++
++ /* acName */
++ DBC_Require(token);
++ cLen = strlen(token);
++ if (cLen > DSP_MAXNAMELEN - 1)
++ cLen = DSP_MAXNAMELEN - 1;
++
++ strncpy(pGenObj->objData.nodeObj.ndbProps.acName,
++ token, cLen);
++ pGenObj->objData.nodeObj.ndbProps.acName[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++ /* u32 uNodeType */
++ pGenObj->objData.nodeObj.ndbProps.uNodeType = Atoi(token);
++ token = strsep(&pszCur, seps);
++ /* u32 bCacheOnGPP */
++ pGenObj->objData.nodeObj.ndbProps.bCacheOnGPP = Atoi(token);
++ token = strsep(&pszCur, seps);
++ /* DSP_RESOURCEREQMTS dspResourceReqmts */
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.cbStruct =
++ (u32) Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uStaticDataSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uGlobalDataSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uProgramMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCExecutionTime = Atoi(token);
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCPeriod = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uWCDeadline = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uAvgExectionTime = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
++ uMinimumPeriod = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* s32 iPriority */
++ pGenObj->objData.nodeObj.ndbProps.iPriority = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uStackSize */
++ pGenObj->objData.nodeObj.ndbProps.uStackSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uSysStackSize */
++ pGenObj->objData.nodeObj.ndbProps.uSysStackSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uStackSeg */
++ pGenObj->objData.nodeObj.ndbProps.uStackSeg = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uMessageDepth */
++ pGenObj->objData.nodeObj.ndbProps.uMessageDepth = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uNumInputStreams */
++ pGenObj->objData.nodeObj.ndbProps.uNumInputStreams =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uNumOutputStreams */
++ pGenObj->objData.nodeObj.ndbProps.uNumOutputStreams =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* u32 uTimeout */
++ pGenObj->objData.nodeObj.ndbProps.uTimeout =
++ Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrCreatePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrCreatePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrCreatePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrCreatePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrExecutePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrExecutePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrExecutePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrExecutePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrDeletePhaseFxn */
++ DBC_Require(token);
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrDeletePhaseFxn =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrDeletePhaseFxn,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrDeletePhaseFxn[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++
++ /* Segment id for message buffers */
++ pGenObj->objData.nodeObj.uMsgSegid = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* Message notification type */
++ pGenObj->objData.nodeObj.uMsgNotifyType = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ /* char * pstrIAlgName */
++ if (token) {
++ cLen = strlen(token);
++ pGenObj->objData.nodeObj.pstrIAlgName =
++ MEM_Calloc(cLen + 1, MEM_PAGED);
++ strncpy(pGenObj->objData.nodeObj.pstrIAlgName,
++ token, cLen);
++ pGenObj->objData.nodeObj.pstrIAlgName[cLen] = '\0';
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Load type (static, dynamic, or overlay) */
++ if (token) {
++ pGenObj->objData.nodeObj.usLoadType = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Dynamic load data requirements */
++ if (token) {
++ pGenObj->objData.nodeObj.ulDataMemSegMask = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Dynamic load code requirements */
++ if (token) {
++ pGenObj->objData.nodeObj.ulCodeMemSegMask = Atoi(token);
++ token = strsep(&pszCur, seps);
++ }
++
++ /* Extract node profiles into node properties */
++ if (token) {
++
++ pGenObj->objData.nodeObj.ndbProps.uCountProfiles =
++ Atoi(token);
++ for (i = 0; i < pGenObj->objData.nodeObj.ndbProps.
++ uCountProfiles; i++) {
++ token = strsep(&pszCur, seps);
++ if (token) {
++ /* Heap Size for the node */
++ pGenObj->objData.nodeObj.ndbProps.
++ aProfiles[i].ulHeapSize =
++ Atoi(token);
++ }
++ }
++ }
++ token = strsep(&pszCur, seps);
++ if (token) {
++ pGenObj->objData.nodeObj.ndbProps.uStackSegName =
++ (u32)(token);
++ }
++
++ break;
++
++ case DSP_DCDPROCESSORTYPE:
++ /*
++ * Parse COFF sect buffer to retrieve individual tokens used
++ * to fill in object attrs.
++ */
++ pszCur = pszBuf;
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.cbStruct = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorFamily = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorType = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uClockRate = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.ulInternalMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.ulExternalMemSize = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.uProcessorID = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.tyRunningRTOS = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.nNodeMinPriority = Atoi(token);
++ token = strsep(&pszCur, seps);
++
++ pGenObj->objData.procObj.nNodeMaxPriority = Atoi(token);
++
++#ifdef _DB_TIOMAP
++ /* Proc object may contain additional(extended) attributes. */
++ /* attr must match proc.hxx */
++ for (iEntry = 0; iEntry < 7; iEntry++) {
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.extProcObj.tyTlb[iEntry].ulGppPhys =
++ Atoi(token);
++
++ token = strsep(&pszCur, seps);
++ pGenObj->objData.extProcObj.tyTlb[iEntry].ulDspVirt =
++ Atoi(token);
++ }
++#endif
++
++ break;
++
++ default:
++ status = DSP_EFAIL;
++ break;
++ }
++
++ return status;
++}
++
++/*
++ * ======== CompressBuffer ========
++ * Purpose:
++ * Compress the DSP buffer, if necessary, to conform to PC format.
++ */
++static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize)
++{
++ char *p;
++ char ch;
++ char *q;
++
++ p = pszBuf;
++ if (p == NULL)
++ return;
++
++ for (q = pszBuf; q < (pszBuf + ulBufSize);) {
++
++ ch = DspChar2GppChar(q, cCharSize);
++ if (ch == '\\') {
++ q += cCharSize;
++ ch = DspChar2GppChar(q, cCharSize);
++ switch (ch) {
++ case 't':
++ *p = '\t';
++ break;
++
++ case 'n':
++ *p = '\n';
++ break;
++
++ case 'r':
++ *p = '\r';
++ break;
++
++ case '0':
++ *p = '\0';
++ break;
++
++ default:
++ *p = ch;
++ break;
++ }
++ } else {
++ *p = ch;
++ }
++ p++;
++ q += cCharSize;
++ }
++
++ /* NULL out remainder of buffer. */
++ while (p < q)
++ *p++ = '\0';
++
++}
++
++/*
++ * ======== DspChar2GppChar ========
++ * Purpose:
++ * Convert DSP char to host GPP char in a portable manner
++ */
++static char DspChar2GppChar(char *pWord, s32 cDspCharSize)
++{
++ char ch = '\0';
++ char *chSrc;
++ s32 i;
++
++ for (chSrc = pWord, i = cDspCharSize; i > 0; i--)
++ ch |= *chSrc++;
++
++ return ch;
++}
++
++/*
++ * ======== GetDepLibInfo ========
++ */
++static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
++ IN struct DSP_UUID *pUuid,
++ IN OUT u16 *pNumLibs,
++ OPTIONAL OUT u16 *pNumPersLibs,
++ OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
++ OPTIONAL OUT bool *pPersistentDepLibs,
++ enum NLDR_PHASE phase)
++{
++ struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
++ char *pszCoffBuf = NULL;
++ char *pszCur;
++ char *pszFileName = NULL;
++ struct COD_LIBRARYOBJ *lib = NULL;
++ u32 ulAddr = 0; /* Used by COD_GetSection */
++ u32 ulLen = 0; /* Used by COD_GetSection */
++ u32 dwDataSize = COD_MAXPATHLENGTH;
++ char seps[] = ", ";
++ char *pToken = NULL;
++ bool fGetUuids = (pDepLibUuids != NULL);
++ u16 nDepLibs = 0;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ DBC_Require(IsValidHandle(hDcdMgr));
++ DBC_Require(pNumLibs != NULL);
++ DBC_Require(pUuid != NULL);
++
++ GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
++ hDcdMgr);
++
++ /* Initialize to 0 dependent libraries, if only counting number of
++ * dependent libraries */
++ if (!fGetUuids) {
++ *pNumLibs = 0;
++ *pNumPersLibs = 0;
++ }
++
++ /* Allocate a buffer for file name */
++ pszFileName = MEM_Calloc(dwDataSize, MEM_PAGED);
++ if (pszFileName == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Get the name of the library */
++ status = DCD_GetLibraryName(hDcdMgr, pUuid, pszFileName,
++ &dwDataSize, phase, NULL);
++ }
++ /* Open the library */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_Open(pDcdMgr->hCodMgr, pszFileName,
++ COD_NOLOAD, &lib);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get dependent library section information. */
++ status = COD_GetSection(lib, DEPLIBSECT, &ulAddr, &ulLen);
++
++ if (DSP_FAILED(status)) {
++ /* Ok, no dependent libraries */
++ ulLen = 0;
++ status = DSP_SNODEPENDENTLIBS;
++ }
++ }
++
++ if (DSP_FAILED(status) || !(ulLen > 0))
++ goto func_cont;
++
++ /* Allocate zeroed buffer. */
++ pszCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
++ if (pszCoffBuf == NULL)
++ status = DSP_EMEMORY;
++
++ /* Read section contents. */
++ status = COD_ReadSection(lib, DEPLIBSECT, pszCoffBuf, ulLen);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Compress and format DSP buffer to conform to PC format. */
++ CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
++ /* Read from buffer */
++ pszCur = pszCoffBuf;
++ while ((pToken = strsep(&pszCur, seps)) && *pToken != '\0') {
++ if (fGetUuids) {
++ if (nDepLibs >= *pNumLibs) {
++ /* Gone beyond the limit */
++ break;
++ } else {
++ /* Retrieve UUID string. */
++ UUID_UuidFromString(pToken,
++ &(pDepLibUuids[nDepLibs]));
++ /* Is this library persistent? */
++ pToken = strsep(&pszCur, seps);
++ pPersistentDepLibs[nDepLibs] = Atoi(pToken);
++ nDepLibs++;
++ }
++ } else {
++ /* Advanc to next token */
++ pToken = strsep(&pszCur, seps);
++ if (Atoi(pToken))
++ (*pNumPersLibs)++;
++
++ /* Just counting number of dependent libraries */
++ (*pNumLibs)++;
++ }
++ }
++func_cont:
++ if (lib)
++ COD_Close(lib);
++
++ /* Free previously allocated dynamic buffers. */
++ if (pszFileName)
++ MEM_Free(pszFileName);
++
++ if (pszCoffBuf)
++ MEM_Free(pszCoffBuf);
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/disp.c b/drivers/dsp/bridge/rmgr/disp.c
+new file mode 100644
+index 0000000..3fbbf01
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/disp.c
+@@ -0,0 +1,916 @@
++/*
++ * disp.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== disp.c ========
++ *
++ * Description:
++ * Node Dispatcher interface. Communicates with Resource Manager Server
++ * (RMS) on DSP. Access to RMS is synchronized in NODE.
++ *
++ * Public Functions:
++ * DISP_Create
++ * DISP_Delete
++ * DISP_Exit
++ * DISP_Init
++ * DISP_NodeChangePriority
++ * DISP_NodeCreate
++ * DISP_NodeDelete
++ * DISP_NodePause
++ * DISP_NodeRun
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 vp Ported to Linux platform
++ *! 16-May-2002 jeh Added DISP_DoCinit().
++ *! 24-Apr-2002 jeh Added DISP_MemWrite().
++ *! 13-Feb-2002 jeh Pass system stack size to RMS.
++ *! 16-Jan-2002 ag Added bufsize param to _ChnlAddIOReq() fxn
++ *! 10-May-2001 jeh Code Review cleanup.
++ *! 26-Sep-2000 jeh Fixed status values in SendMessage().
++ *! 19-Jun-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/dev.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/chnldefs.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/nodedefs.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/rms_sh.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/disp.h>
++
++#define DISP_SIGNATURE 0x50534944 /* "PSID" */
++
++/* Size of a reply from RMS */
++#define REPLYSIZE (3 * sizeof(RMS_WORD))
++
++/* Reserved channel offsets for communication with RMS */
++#define CHNLTORMSOFFSET 0
++#define CHNLFROMRMSOFFSET 1
++
++#define CHNLIOREQS 1
++
++#define SwapWord(x) (((u32)(x) >> 16) | ((u32)(x) << 16))
++
++/*
++ * ======== DISP_OBJECT ========
++ */
++struct DISP_OBJECT {
++ u32 dwSignature; /* Used for object validation */
++ struct DEV_OBJECT *hDevObject; /* Device for this processor */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager */
++ struct CHNL_OBJECT *hChnlToDsp; /* Channel for commands to RMS */
++ struct CHNL_OBJECT *hChnlFromDsp; /* Channel for replies from RMS */
++ u8 *pBuf; /* Buffer for commands, replies */
++ u32 ulBufsize; /* pBuf size in bytes */
++ u32 ulBufsizeRMS; /* pBuf size in RMS words */
++ u32 uCharSize; /* Size of DSP character */
++ u32 uWordSize; /* Size of DSP word */
++ u32 uDataMauSize; /* Size of DSP Data MAU */
++};
++
++static u32 cRefs;
++
++/* Debug msgs: */
++#if GT_TRACE
++static struct GT_Mask DISP_DebugMask = { NULL, NULL };
++#endif
++
++static void DeleteDisp(struct DISP_OBJECT *hDisp);
++static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
++ struct NODE_STRMDEF strmDef, u32 max,
++ u32 uCharsInRMSWord);
++static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
++ u32 ulBytes, OUT u32 *pdwArg);
++
++/*
++ * ======== DISP_Create ========
++ * Create a NODE Dispatcher object.
++ */
++DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct DISP_ATTRS *pDispAttrs)
++{
++ struct DISP_OBJECT *pDisp;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulChnlId;
++ struct CHNL_ATTRS chnlAttrs;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDispObject != NULL);
++ DBC_Require(pDispAttrs != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_3trace(DISP_DebugMask, GT_ENTER, "DISP_Create: phDispObject: 0x%x\t"
++ "hDevObject: 0x%x\tpDispAttrs: 0x%x\n", phDispObject,
++ hDevObject, pDispAttrs);
++
++ *phDispObject = NULL;
++
++ /* Allocate Node Dispatcher object */
++ MEM_AllocObject(pDisp, struct DISP_OBJECT, DISP_SIGNATURE);
++ if (pDisp == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: MEM_AllocObject() failed!\n");
++ } else {
++ pDisp->hDevObject = hDevObject;
++ }
++
++ /* Get Channel manager and WMD function interface */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDevObject, &(pDisp->hChnlMgr));
++ if (DSP_SUCCEEDED(status)) {
++ (void) DEV_GetIntfFxns(hDevObject, &pIntfFxns);
++ pDisp->pIntfFxns = pIntfFxns;
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Failed to get "
++ "channel manager! status = 0x%x\n", status);
++ }
++ }
++
++ /* check device type and decide if streams or messag'ing is used for
++ * RMS/EDS */
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ status = DEV_GetDevType(hDevObject, &devType);
++ GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP for "
++ "device = 0x%x\n", devType);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ if (devType != DSP_UNIT) {
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Unkown device "
++ "type in Device object !! \n");
++ status = DSP_EFAIL;
++ goto func_cont;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pDisp->uCharSize = DSPWORDSIZE;
++ pDisp->uWordSize = DSPWORDSIZE;
++ pDisp->uDataMauSize = DSPWORDSIZE;
++ /* Open channels for communicating with the RMS */
++ chnlAttrs.uIOReqs = CHNLIOREQS;
++ chnlAttrs.hEvent = NULL;
++ ulChnlId = pDispAttrs->ulChnlOffset + CHNLTORMSOFFSET;
++ status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlToDsp),
++ pDisp->hChnlMgr, CHNL_MODETODSP, ulChnlId, &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Channel to RMS "
++ "open failed, chnl id = %d, status = 0x%x\n",
++ ulChnlId, status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulChnlId = pDispAttrs->ulChnlOffset + CHNLFROMRMSOFFSET;
++ status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlFromDsp),
++ pDisp->hChnlMgr, CHNL_MODEFROMDSP, ulChnlId,
++ &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Channel from RMS "
++ "open failed, chnl id = %d, status = 0x%x\n",
++ ulChnlId, status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate buffer for commands, replies */
++ pDisp->ulBufsize = pDispAttrs->ulChnlBufSize;
++ pDisp->ulBufsizeRMS = RMS_COMMANDBUFSIZE;
++ pDisp->pBuf = MEM_Calloc(pDisp->ulBufsize, MEM_PAGED);
++ if (pDisp->pBuf == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Create: Failed "
++ "to allocate channel buffer!\n");
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status))
++ *phDispObject = pDisp;
++ else
++ DeleteDisp(pDisp);
++
++ DBC_Ensure(((DSP_FAILED(status)) && ((*phDispObject == NULL))) ||
++ ((DSP_SUCCEEDED(status)) &&
++ (MEM_IsValidHandle((*phDispObject), DISP_SIGNATURE))));
++ return status;
++}
++
++/*
++ * ======== DISP_Delete ========
++ * Delete the NODE Dispatcher.
++ */
++void DISP_Delete(struct DISP_OBJECT *hDisp)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++
++ GT_1trace(DISP_DebugMask, GT_ENTER,
++ "DISP_Delete: hDisp: 0x%x\n", hDisp);
++
++ DeleteDisp(hDisp);
++
++ DBC_Ensure(!MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++}
++
++/*
++ * ======== DISP_Exit ========
++ * Discontinue usage of DISP module.
++ */
++void DISP_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(DISP_DebugMask, GT_5CLASS,
++ "Entered DISP_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== DISP_Init ========
++ * Initialize the DISP module.
++ */
++bool DISP_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!DISP_DebugMask.flags);
++ GT_create(&DISP_DebugMask, "DI"); /* "DI" for DIspatcher */
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(DISP_DebugMask, GT_5CLASS,
++ "DISP_Init(), ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++ return fRetVal;
++}
++
++/*
++ * ======== DISP_NodeChangePriority ========
++ * Change the priority of a node currently running on the target.
++ */
++DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT *hDisp,
++ struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, NODE_ENV nodeEnv,
++ s32 nPriority)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeChangePriority: hDisp: "
++ "0x%x\thNode: 0x%x\tulRMSFxn: 0x%x\tnodeEnv: 0x%x\tnPriority\n",
++ hDisp, hNode, ulRMSFxn, nodeEnv, nPriority);
++
++ /* Send message to RMS to change priority */
++ pCommand = (struct RMS_Command *)(hDisp->pBuf);
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)nodeEnv;
++ pCommand->arg2 = nPriority;
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeChangePriority failed! "
++ "status = 0x%x\n", status);
++ }
++ return status;
++}
++
++/*
++ * ======== DISP_NodeCreate ========
++ * Create a node on the DSP by remotely calling the node's create function.
++ */
++DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulCreateFxn,
++ IN CONST struct NODE_CREATEARGS *pArgs,
++ OUT NODE_ENV *pNodeEnv)
++{
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++ struct RMS_Command *pCommand;
++ struct RMS_MsgArgs *pMsgArgs;
++ struct RMS_MoreTaskArgs *pMoreTaskArgs;
++ enum NODE_TYPE nodeType;
++ u32 dwLength;
++ RMS_WORD *pdwBuf = NULL;
++ u32 ulBytes;
++ u32 i;
++ u32 total;
++ u32 uCharsInRMSWord;
++ s32 taskArgsOffset;
++ s32 sioInDefOffset;
++ s32 sioOutDefOffset;
++ s32 sioDefsOffset;
++ s32 argsOffset = -1;
++ s32 offset;
++ struct NODE_STRMDEF strmDef;
++ u32 max;
++ DSP_STATUS status = DSP_SOK;
++ struct DSP_NODEINFO nodeInfo;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++ DBC_Require(NODE_GetType(hNode) != NODE_DEVICE);
++ DBC_Require(pNodeEnv != NULL);
++
++ GT_6trace(DISP_DebugMask, GT_ENTER,
++ "DISP_NodeCreate: hDisp: 0x%x\thNode:"
++ " 0x%x\tulRMSFxn: 0x%x\tulCreateFxn: 0x%x\tpArgs: 0x%x\tpNodeEnv:"
++ " 0x%x\n", hDisp, hNode, ulRMSFxn, ulCreateFxn, pArgs, pNodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP "
++ "for device = 0x%x\n", devType);
++
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (devType != DSP_UNIT) {
++ GT_1trace(DISP_DebugMask, GT_7CLASS,
++ "DISP_NodeCreate unknown device "
++ "type = 0x%x\n", devType);
++ goto func_end;
++ }
++ DBC_Require(pArgs != NULL);
++ nodeType = NODE_GetType(hNode);
++ msgArgs = pArgs->asa.msgArgs;
++ max = hDisp->ulBufsizeRMS; /*Max # of RMS words that can be sent */
++ DBC_Assert(max == RMS_COMMANDBUFSIZE);
++ uCharsInRMSWord = sizeof(RMS_WORD) / hDisp->uCharSize;
++ /* Number of RMS words needed to hold arg data */
++ dwLength = (msgArgs.uArgLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
++ /* Make sure msg args and command fit in buffer */
++ total = sizeof(struct RMS_Command) / sizeof(RMS_WORD) +
++ sizeof(struct RMS_MsgArgs)
++ / sizeof(RMS_WORD) - 1 + dwLength;
++ if (total >= max) {
++ status = DSP_EFAIL;
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message args too"
++ " large for buffer! Message args size = %d, max = %d\n",
++ total, max);
++ }
++ /*
++ * Fill in buffer to send to RMS.
++ * The buffer will have the following format:
++ *
++ * RMS command:
++ * Address of RMS_CreateNode()
++ * Address of node's create function
++ * dummy argument
++ * node type
++ *
++ * Message Args:
++ * max number of messages
++ * segid for message buffer allocation
++ * notification type to use when message is received
++ * length of message arg data
++ * message args data
++ *
++ * Task Args (if task or socket node):
++ * priority
++ * stack size
++ * system stack size
++ * stack segment
++ * misc
++ * number of input streams
++ * pSTRMInDef[] - offsets of STRM definitions for input streams
++ * number of output streams
++ * pSTRMOutDef[] - offsets of STRM definitions for output
++ * streams
++ * STRMInDef[] - array of STRM definitions for input streams
++ * STRMOutDef[] - array of STRM definitions for output streams
++ *
++ * Socket Args (if DAIS socket node):
++ *
++ */
++ if (DSP_SUCCEEDED(status)) {
++ total = 0; /* Total number of words in buffer so far */
++ pdwBuf = (RMS_WORD *)hDisp->pBuf;
++ pCommand = (struct RMS_Command *)pdwBuf;
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)(ulCreateFxn);
++ if (NODE_GetLoadType(hNode) == NLDR_DYNAMICLOAD) {
++ /* Flush ICACHE on Load */
++ pCommand->arg2 = 1; /* dummy argument */
++ } else {
++ /* Do not flush ICACHE */
++ pCommand->arg2 = 0; /* dummy argument */
++ }
++ pCommand->data = NODE_GetType(hNode);
++ /*
++ * argsOffset is the offset of the data field in struct
++ * RMS_Command structure. We need this to calculate stream
++ * definition offsets.
++ */
++ argsOffset = 3;
++ total += sizeof(struct RMS_Command) / sizeof(RMS_WORD);
++ /* Message args */
++ pMsgArgs = (struct RMS_MsgArgs *) (pdwBuf + total);
++ pMsgArgs->maxMessages = msgArgs.uMaxMessages;
++ pMsgArgs->segid = msgArgs.uSegid;
++ pMsgArgs->notifyType = msgArgs.uNotifyType;
++ pMsgArgs->argLength = msgArgs.uArgLength;
++ total += sizeof(struct RMS_MsgArgs) / sizeof(RMS_WORD) - 1;
++ memcpy(pdwBuf + total, msgArgs.pData, msgArgs.uArgLength);
++ total += dwLength;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If node is a task node, copy task create arguments into buffer */
++ if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
++ taskArgs = pArgs->asa.taskArgs;
++ taskArgsOffset = total;
++ total += sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD) +
++ 1 + taskArgs.uNumInputs + taskArgs.uNumOutputs;
++ /* Copy task arguments */
++ if (total < max) {
++ total = taskArgsOffset;
++ pMoreTaskArgs = (struct RMS_MoreTaskArgs *)(pdwBuf +
++ total);
++ /*
++ * Get some important info about the node. Note that we
++ * don't just reach into the hNode struct because
++ * that would break the node object's abstraction.
++ */
++ GetNodeInfo(hNode, &nodeInfo);
++ GT_2trace(DISP_DebugMask, GT_ENTER,
++ "uExecutionPriority %x, nPriority %x\n",
++ nodeInfo.uExecutionPriority,
++ taskArgs.nPriority);
++ pMoreTaskArgs->priority = nodeInfo.uExecutionPriority;
++ pMoreTaskArgs->stackSize = taskArgs.uStackSize;
++ pMoreTaskArgs->sysstackSize = taskArgs.uSysStackSize;
++ pMoreTaskArgs->stackSeg = taskArgs.uStackSeg;
++ pMoreTaskArgs->heapAddr = taskArgs.uDSPHeapAddr;
++ pMoreTaskArgs->heapSize = taskArgs.uHeapSize;
++ pMoreTaskArgs->misc = taskArgs.ulDaisArg;
++ pMoreTaskArgs->numInputStreams = taskArgs.uNumInputs;
++ total +=
++ sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD);
++ GT_2trace(DISP_DebugMask, GT_7CLASS,
++ "DISP::::uDSPHeapAddr %x, "
++ "uHeapSize %x\n", taskArgs.uDSPHeapAddr,
++ taskArgs.uHeapSize);
++ /* Keep track of pSIOInDef[] and pSIOOutDef[]
++ * positions in the buffer, since this needs to be
++ * filled in later. */
++ sioInDefOffset = total;
++ total += taskArgs.uNumInputs;
++ pdwBuf[total++] = taskArgs.uNumOutputs;
++ sioOutDefOffset = total;
++ total += taskArgs.uNumOutputs;
++ sioDefsOffset = total;
++ /* Fill SIO defs and offsets */
++ offset = sioDefsOffset;
++ for (i = 0; i < taskArgs.uNumInputs; i++) {
++ if (DSP_FAILED(status))
++ break;
++
++ pdwBuf[sioInDefOffset + i] =
++ (offset - argsOffset)
++ * (sizeof(RMS_WORD) / DSPWORDSIZE);
++ strmDef = taskArgs.strmInDef[i];
++ status = FillStreamDef(pdwBuf, &total, offset,
++ strmDef, max, uCharsInRMSWord);
++ offset = total;
++ }
++ for (i = 0; (i < taskArgs.uNumOutputs) &&
++ (DSP_SUCCEEDED(status)); i++) {
++ pdwBuf[sioOutDefOffset + i] =
++ (offset - argsOffset)
++ * (sizeof(RMS_WORD) / DSPWORDSIZE);
++ strmDef = taskArgs.strmOutDef[i];
++ status = FillStreamDef(pdwBuf, &total, offset,
++ strmDef, max, uCharsInRMSWord);
++ offset = total;
++ }
++ if (DSP_FAILED(status)) {
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message"
++ " args to large for buffer! Message args"
++ " size = %d, max = %d\n", total, max);
++ }
++ } else {
++ /* Args won't fit */
++ status = DSP_EFAIL;
++ GT_2trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate: Message args "
++ " too large for buffer! Message args size = %d"
++ ", max = %d\n", total, max);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulBytes = total * sizeof(RMS_WORD);
++ DBC_Assert(ulBytes < (RMS_COMMANDBUFSIZE * sizeof(RMS_WORD)));
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ ulBytes, pNodeEnv);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate failed! "
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's create function
++ * on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeCreate, "
++ "DSP-side Node Create failed: 0x%x\n",
++ status);
++ }
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== DISP_NodeDelete ========
++ * purpose:
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ *
++ */
++DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulDeleteFxn, NODE_ENV nodeEnv)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER,
++ "DISP_NodeDelete: hDisp: 0x%xthNode: "
++ "0x%x\tulRMSFxn: 0x%x\tulDeleteFxn: 0x%x\tnodeEnv: 0x%x\n",
++ hDisp, hNode, ulRMSFxn, ulDeleteFxn, nodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ if (DSP_SUCCEEDED(status)) {
++
++ if (devType == DSP_UNIT) {
++
++ /*
++ * Fill in buffer to send to RMS
++ */
++ pCommand = (struct RMS_Command *)hDisp->pBuf;
++ pCommand->fxn = (RMS_WORD)(ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD)nodeEnv;
++ pCommand->arg2 = (RMS_WORD)(ulDeleteFxn);
++ pCommand->data = NODE_GetType(hNode);
++
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeDelete failed!"
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's delete
++ * function on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeDelete, "
++ "DSP-side Node Delete failed: 0x%x\n",
++ status);
++ }
++ }
++
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== DISP_NodeRun ========
++ * purpose:
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via DISP_NodePause()) on the DSP.
++ */
++DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
++ u32 ulRMSFxn, u32 ulExecuteFxn, NODE_ENV nodeEnv)
++{
++ u32 dwArg;
++ struct RMS_Command *pCommand;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
++ DBC_Require(hNode != NULL);
++
++ GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeRun: hDisp: 0x%xthNode: \
++ 0x%x\tulRMSFxn: 0x%x\tulExecuteFxn: 0x%x\tnodeEnv: 0x%x\n", \
++ hDisp, hNode, ulRMSFxn, ulExecuteFxn, nodeEnv);
++
++ status = DEV_GetDevType(hDisp->hDevObject, &devType);
++
++ if (DSP_SUCCEEDED(status)) {
++
++ if (devType == DSP_UNIT) {
++
++ /*
++ * Fill in buffer to send to RMS.
++ */
++ pCommand = (struct RMS_Command *) hDisp->pBuf;
++ pCommand->fxn = (RMS_WORD) (ulRMSFxn);
++ pCommand->arg1 = (RMS_WORD) nodeEnv;
++ pCommand->arg2 = (RMS_WORD) (ulExecuteFxn);
++ pCommand->data = NODE_GetType(hNode);
++
++ status = SendMessage(hDisp, NODE_GetTimeout(hNode),
++ sizeof(struct RMS_Command), &dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeRun failed!"
++ "status = 0x%x\n", status);
++ } else {
++ /*
++ * Message successfully received from RMS.
++ * Return the status of the Node's execute
++ * function on the DSP-side
++ */
++ status = (((RMS_WORD *)(hDisp->pBuf))[0]);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_NodeRun, DSP-side Node "
++ "Execute failed: 0x%x\n",
++ status);
++ }
++ }
++
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== DeleteDisp ========
++ * purpose:
++ * Frees the resources allocated for the dispatcher.
++ */
++static void DeleteDisp(struct DISP_OBJECT *hDisp)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++ if (MEM_IsValidHandle(hDisp, DISP_SIGNATURE)) {
++ pIntfFxns = hDisp->pIntfFxns;
++
++ /* Free Node Dispatcher resources */
++ if (hDisp->hChnlFromDsp) {
++ /* Channel close can fail only if the channel handle
++ * is invalid. */
++ status = (*pIntfFxns->pfnChnlClose)
++ (hDisp->hChnlFromDsp);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Delete: Failed to "
++ "close channel from RMS: 0x%x\n",
++ status);
++ }
++ }
++ if (hDisp->hChnlToDsp) {
++ status = (*pIntfFxns->pfnChnlClose)(hDisp->hChnlToDsp);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "DISP_Delete: Failed to "
++ "close channel to RMS: 0x%x\n",
++ status);
++ }
++ }
++ if (hDisp->pBuf)
++ MEM_Free(hDisp->pBuf);
++
++ MEM_FreeObject(hDisp);
++ }
++}
++
++/*
++ * ======== FillStreamDef ========
++ * purpose:
++ * Fills stream definitions.
++ */
++static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
++ struct NODE_STRMDEF strmDef, u32 max,
++ u32 uCharsInRMSWord)
++{
++ struct RMS_StrmDef *pStrmDef;
++ u32 total = *ptotal;
++ u32 uNameLen;
++ u32 dwLength;
++ DSP_STATUS status = DSP_SOK;
++
++ if (total + sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) >= max) {
++ status = DSP_EFAIL;
++ } else {
++ pStrmDef = (struct RMS_StrmDef *)(pdwBuf + total);
++ pStrmDef->bufsize = strmDef.uBufsize;
++ pStrmDef->nbufs = strmDef.uNumBufs;
++ pStrmDef->segid = strmDef.uSegid;
++ pStrmDef->align = strmDef.uAlignment;
++ pStrmDef->timeout = strmDef.uTimeout;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Since we haven't added the device name yet, subtract
++ * 1 from total.
++ */
++ total += sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) - 1;
++ DBC_Require(strmDef.szDevice);
++ dwLength = strlen(strmDef.szDevice) + 1;
++
++ /* Number of RMS_WORDS needed to hold device name */
++ uNameLen = (dwLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
++
++ if (total + uNameLen >= max) {
++ status = DSP_EFAIL;
++ } else {
++ /*
++ * Zero out last word, since the device name may not
++ * extend to completely fill this word.
++ */
++ pdwBuf[total + uNameLen - 1] = 0;
++ /** TODO USE SERVICES **/
++ memcpy(pdwBuf + total, strmDef.szDevice, dwLength);
++ total += uNameLen;
++ *ptotal = total;
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== SendMessage ======
++ * Send command message to RMS, get reply from RMS.
++ */
++static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
++ u32 ulBytes, u32 *pdwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_OBJECT *hChnl;
++ u32 dwArg = 0;
++ u8 *pBuf;
++ struct CHNL_IOC chnlIOC;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pdwArg != NULL);
++
++ *pdwArg = (u32) NULL;
++ pIntfFxns = hDisp->pIntfFxns;
++ hChnl = hDisp->hChnlToDsp;
++ pBuf = hDisp->pBuf;
++
++ /* Send the command */
++ status = (*pIntfFxns->pfnChnlAddIOReq) (hChnl, pBuf, ulBytes, 0,
++ 0L, dwArg);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel AddIOReq to"
++ " RMS failed! Status = 0x%x\n", status);
++ goto func_cont;
++ }
++ status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
++ if (DSP_SUCCEEDED(status)) {
++ if (!CHNL_IsIOComplete(chnlIOC)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage failed! "
++ "Channel IOC status = 0x%x\n",
++ chnlIOC.status);
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel GetIOC to"
++ " RMS failed! Status = 0x%x\n", status);
++ }
++func_cont:
++ /* Get the reply */
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ hChnl = hDisp->hChnlFromDsp;
++ ulBytes = REPLYSIZE;
++ status = (*pIntfFxns->pfnChnlAddIOReq)(hChnl, pBuf, ulBytes,
++ 0, 0L, dwArg);
++ if (DSP_FAILED(status)) {
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Channel AddIOReq "
++ "from RMS failed! Status = 0x%x\n", status);
++ goto func_end;
++ }
++ status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
++ if (DSP_SUCCEEDED(status)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else if (chnlIOC.cBytes < ulBytes) {
++ /* Did not get all of the reply from the RMS */
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Did not get all"
++ "of reply from RMS! Bytes received: %d\n",
++ chnlIOC.cBytes);
++ status = DSP_EFAIL;
++ } else {
++ if (CHNL_IsIOComplete(chnlIOC)) {
++ DBC_Assert(chnlIOC.pBuf == pBuf);
++ status = (*((RMS_WORD *)chnlIOC.pBuf));
++ *pdwArg = (((RMS_WORD *)(chnlIOC.pBuf))[1]);
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ /* GetIOC failed */
++ GT_1trace(DISP_DebugMask, GT_6CLASS,
++ "SendMessage: Failed to get "
++ "reply from RMS! Status = 0x%x\n", status);
++ }
++func_end:
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c
+new file mode 100644
+index 0000000..256ce12
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv.c
+@@ -0,0 +1,1893 @@
++/*
++ * drv.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv.c ========
++ * Description:
++ * DSP/BIOS Bridge resource allocation module.
++ *
++ * Public Functions:
++ * DRV_Create
++ * DRV_Destroy
++ * DRV_Exit
++ * DRV_GetDevObject
++ * DRV_GetDevExtension
++ * DRV_GetFirstDevObject
++ * DRV_GetNextDevObject
++ * DRV_GetNextDevExtension
++ * DRV_Init
++ * DRV_InsertDevObject
++ * DRV_RemoveDevObject
++ * DRV_RequestResources
++ * DRV_ReleaseResources
++ *
++ *! Revision History
++ *! ======== ========
++ *! 19-Apr-2004 sb: Replaced OS specific APIs with MEM_AllocPhysMem and
++ MEM_FreePhysMem. Fixed warnings. Cosmetic updates.
++ *! 12-Apr-2004 hp: IVA clean up during bridge-uninstall
++ *! 05-Jan-2004 vp: Updated for 24xx platform
++ *! 21-Mar-2003 sb: Get SHM size from registry
++ *! 10-Feb-2003 vp: Code review updates
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 30-Oct-2000 kc: Modified usage of REG_SetValue.
++ *! 06-Sep-2000 jeh Read channel info into struct CFG_HOSTRES in
++ *! RequestISAResources()
++ *! 21-Sep-2000 rr: numwindows is calculated instead of default value in
++ *! RequestISAResources.
++ *! 07-Aug-2000 rr: static list of dev objects removed.
++ *! 27-Jul-2000 rr: RequestResources split into two(Request and Release)
++ *! Device extension created to hold the DevNodeString.
++ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
++ *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
++ *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
++ *! 09-May-2000 rr: PCI Support is not L301 specific.Use of MEM_Calloc
++ *! instead of MEM_Alloc.
++ *! 28-Mar-2000 rr: PCI Support added. L301 Specific. TBD.
++ *! 03-Feb-2000 rr: GT and Module Init/exit Changes. Merged with kc.
++ *! 19-Jan-2000 rr: DBC_Ensure in RequestPCMCIA moved within PCCARD ifdef
++ *! 29-Dec-1999 rr: PCCard support for any slot.Bus type stored in the
++ *! struct CFG_HOSTRES Structure.
++ *! 17-Dec-1999 rr: if PCCARD_Init fails we return DSP_EFAIL.
++ *! DBC_Ensure checks for sucess and pDevice != NULL
++ *! 11-Dec-1999 ag: #define "Isa" renamed to "IsaBus".
++ *! 09-Dec-1999 rr: windows.h included to remove warnings.
++ *! 02-Dec-1999 rr: struct GT_Mask is with in if DEBUG. Request resources checks
++ *! status while making call to Reg functions.
++ *! 23-Nov-1999 rr: windows.h included
++ *! 19-Nov-1999 rr: DRV_RELEASE bug while setting the registry to zero.
++ *! fixed.
++ *! 12-Nov-1999 rr: RequestResources() reads values from the registry.
++ *! Hardcoded bIRQRegister define removed.
++ *! 05-Nov-1999 rr: Added hardcoded device interrupt.
++ *! 25-Oct-1999 rr: Resource structure removed. Now it uses the Host
++ *! Resource structure directly.
++ *! 15-Oct-1999 rr: Resource Structure modified. See drv.h
++ *! dwBusType taken from the registry.Hard coded
++ *! registry entries removed.
++ *! 05-Oct-1999 rr: Calling DEV_StartDevice moved to wcdce.c. DRV_Register
++ *! MiniDriver has been renamed to DRV_RequestResources.
++ *! DRV_UnRegisterMiniDriver fxn removed.
++ *! 24-Sep-1999 rr: Significant changes to the RegisterMiniDriver fxns.
++ *! Now it is simpler. IT stores the dev node in the
++ *! registry, assign resources and calls the DEV_Start.
++ *! 10-Sep-1999 rr: Register Minidriver modified.
++ *! - Resource structure follows the NT model
++ *! 08-Aug-1999 rr: Adopted for WinCE. Exports Fxns removed. Hull Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/node.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/wmdchnl.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x5f52474d /* "DRV_" (in reverse) */
++
++struct DRV_OBJECT {
++ u32 dwSignature;
++ struct LST_LIST *devList;
++ struct LST_LIST *devNodeString;
++#ifndef RES_CLEANUP_DISABLE
++ struct PROCESS_CONTEXT *procCtxtList;
++#endif
++};
++
++/*
++ * This is the Device Extension. Named with the Prefix
++ * DRV_ since it is living in this module
++ */
++struct DRV_EXT {
++ struct LST_ELEM link;
++ char szString[MAXREGPATHLENGTH];
++};
++
++/* ----------------------------------- Globals */
++static s32 cRefs;
++
++#if GT_TRACE
++extern struct GT_Mask curTrace;
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 fRequest);
++static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 fRequest);
++
++#ifndef RES_CLEANUP_DISABLE
++/* GPP PROCESS CLEANUP CODE */
++
++static DSP_STATUS PrintProcessInformation(void);
++static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt);
++static DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt);
++extern enum NODE_STATE NODE_GetState(HANDLE hNode);
++
++/* Get the process context list from driver object */
++
++/* Set the Process ID */
++DSP_STATUS DRV_ProcSetPID(HANDLE hPCtxt, s32 hProcess)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(hPCtxt != NULL);
++
++ pCtxt->pid = hProcess;
++ return status;
++}
++
++
++/* Getting the head of the process context list */
++DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
++ struct DRV_OBJECT *hDrvObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++
++ DBC_Assert(hDrvObject != NULL);
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_GetProcCtxtList: 2 *pPctxt:%x, pDrvObject"
++ ":%x", *pPctxt, pDrvObject);
++ *pPctxt = pDrvObject->procCtxtList;
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_GetProcCtxtList: 3 *pPctxt:%x, pDrvObject"
++ ":%x", *pPctxt, pDrvObject);
++ return status;
++}
++
++
++
++/* Get a particular process context based on process handle (phProcess) */
++DSP_STATUS DRV_GetProcContext(u32 phProcess,
++ struct DRV_OBJECT *hDrvObject,
++ HANDLE hPCtxt, DSP_HNODE hNode,
++ u32 pMapAddr)
++{
++ struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++ struct DMM_RES_OBJECT *pTempDMM2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMM = NULL;
++ s32 pCtxtFound = 0;
++
++ DBC_Assert(pDrvObject != NULL);
++ pCtxtList = pDrvObject->procCtxtList;
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 2");
++ while ((pCtxtList != NULL) && (pCtxtList->pid != phProcess)) {
++ pCtxtList = pCtxtList->next;
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 3");
++ }
++ if (pCtxtList == NULL) {
++ if (hNode != NULL) {
++ pCtxtList = pDrvObject->procCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
++ pTempNode = pCtxtList->pNodeList;
++ while ((pTempNode != NULL) &&
++ (pTempNode->hNode != hNode)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pTempNode != NULL) {
++ pCtxtFound = 1;
++ status = DSP_SOK;
++ } else {
++ pCtxtList = pCtxtList->next;
++ }
++ }
++ } else if ((pMapAddr != 0) && (pCtxtFound == 0)) {
++ pCtxtList = pDrvObject->procCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
++ pTempDMM = pCtxtList->pDMMList;
++ while ((pTempDMM != NULL) &&
++ (pTempDMM->ulDSPAddr != pMapAddr)) {
++ pTempDMM2 = pTempDMM;
++ pTempDMM = pTempDMM->next;
++ }
++ if (pTempDMM != NULL) {
++ pCtxtFound = 1;
++ status = DSP_SOK;
++ } else {
++ pCtxtList = pCtxtList->next;
++ }
++ }
++ if (pCtxtList == NULL)
++ status = DSP_ENOTFOUND;
++
++ }
++ } else{
++ status = DSP_SOK;
++ }
++ GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 4");
++ *pCtxt = pCtxtList;
++ return status;
++}
++
++
++/* Add a new process context to process context list */
++DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct DRV_OBJECT *hDRVObject;
++
++ GT_0trace(curTrace, GT_ENTER, "\n In DRV_InsertProcContext\n");
++ status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ DBC_Assert(hDRVObject != NULL);
++ *pCtxt = MEM_Calloc(1 * sizeof(struct PROCESS_CONTEXT), MEM_PAGED);
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext Calling "
++ "DRV_GetProcCtxtList\n");
++ DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext After Calling "
++ "DRV_GetProcCtxtList\n");
++ if (pCtxtList != NULL) {
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext and pCtxt is "
++ "not Null\n");
++ while (pCtxtList->next != NULL)
++ pCtxtList = pCtxtList->next;
++
++ pCtxtList->next = *pCtxt;
++ } else {
++ GT_0trace(curTrace, GT_ENTER,
++ "\n In DRV_InsertProcContext and "
++ "pCtxt is Null\n");
++ hDRVObject->procCtxtList = *pCtxt;
++ }
++ return status;
++}
++
++/* Delete a process context from process resource context list */
++DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
++ HANDLE hPCtxt, HANDLE hProcess)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxt2 = NULL;
++ struct PROCESS_CONTEXT *pTmp = NULL;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++
++ DBC_Assert(hDRVObject != NULL);
++ DRV_GetProcContext((u32)hProcess, hDRVObject, &pCtxt2, NULL, 0);
++
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 12");
++ DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 13");
++ pTmp = pCtxtList;
++ while ((pCtxtList != NULL) && (pCtxtList != pCtxt2)) {
++ pTmp = pCtxtList;
++ pCtxtList = pCtxtList->next;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_RemoveProcContext: 2");
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 3");
++ if (hDRVObject->procCtxtList == pCtxt2)
++ hDRVObject->procCtxtList = pCtxt2->next;
++
++ if (pCtxtList == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTmp->next != NULL)
++ pTmp->next = pTmp->next->next;
++
++ MEM_Free(pCtxt2);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 7");
++
++ return status;
++}
++
++/* Update the state of process context */
++DSP_STATUS DRV_ProcUpdatestate(HANDLE hPCtxt, enum GPP_PROC_RES_STATE status)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status1 = DSP_SOK;
++ if (pCtxt != NULL) {
++ pCtxt->resState = status;
++ } else {
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_ProcUpdatestate: Failed to update "
++ "process state");
++ }
++ return status1;
++}
++
++/* Allocate and add a node resource element
++* This function is called from .Node_Allocate. */
++DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE hNodeRes,
++ HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT **pNodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNodeRes = NULL;
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 1");
++ *pNodeRes = (struct NODE_RES_OBJECT *)MEM_Calloc
++ (1 * sizeof(struct NODE_RES_OBJECT), MEM_PAGED);
++ DBC_Assert(hPCtxt != NULL);
++ if ((*pNodeRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 12");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ (*pNodeRes)->hNode = hNode;
++ if (pCtxt->pNodeList != NULL) {
++ pTempNodeRes = pCtxt->pNodeList;
++ while (pTempNodeRes->next != NULL)
++ pTempNodeRes = pTempNodeRes->next;
++
++ pTempNodeRes->next = *pNodeRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertNodeResElement: 2");
++ } else {
++ pCtxt->pNodeList = *pNodeRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertNodeResElement: 3");
++ }
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 4");
++ return status;
++}
++
++/* Release all Node resources and its context
++* This is called from .Node_Delete. */
++DSP_STATUS DRV_RemoveNodeResElement(HANDLE hNodeRes, HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = pCtxt->pNodeList;
++ struct NODE_RES_OBJECT *pTempNode = pCtxt->pNodeList;
++
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "\nDRV_RemoveNodeResElement: 1\n");
++ while ((pTempNode != NULL) && (pTempNode != pNodeRes)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pCtxt->pNodeList == pNodeRes)
++ pCtxt->pNodeList = pNodeRes->next;
++
++ if (pTempNode == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTempNode2->next != NULL)
++ pTempNode2->next = pTempNode2->next->next;
++
++ MEM_Free(pTempNode);
++ return status;
++}
++
++/* Actual Node De-Allocation */
++static DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pNodeList = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ u32 nState;
++
++ DBC_Assert(hPCtxt != NULL);
++ pNodeList = pCtxt->pNodeList;
++ while (pNodeList != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_ProcFreeNodeRes: 1");
++ pNodeRes = pNodeList;
++ pNodeList = pNodeList->next;
++ if (pNodeRes->nodeAllocated) {
++ nState = NODE_GetState(pNodeRes->hNode) ;
++ GT_1trace(curTrace, GT_5CLASS,
++ "DRV_ProcFreeNodeRes: Node state %x\n", nState);
++ if (nState <= NODE_DELETING) {
++ if ((nState == NODE_RUNNING) ||
++ (nState == NODE_PAUSED) ||
++ (nState == NODE_TERMINATING)) {
++ GT_1trace(curTrace, GT_5CLASS,
++ "Calling Node_Terminate for Node:"
++ " 0x%x\n", pNodeRes->hNode);
++ status = NODE_Terminate
++ (pNodeRes->hNode, &status);
++ GT_1trace(curTrace, GT_5CLASS,
++ "Calling Node_Delete for Node:"
++ " 0x%x\n", pNodeRes->hNode);
++ status = NODE_Delete(pNodeRes->hNode);
++ GT_1trace(curTrace, GT_5CLASS,
++ "the status after the NodeDelete %x\n",
++ status);
++ } else if ((nState == NODE_ALLOCATED)
++ || (nState == NODE_CREATED))
++ status = NODE_Delete(pNodeRes->hNode);
++ }
++ }
++ pNodeRes->nodeAllocated = 0;
++ }
++ return status;
++}
++
++/* Allocate the DMM resource element
++* This is called from Proc_Map. after the actual resource is allocated */
++DSP_STATUS DRV_InsertDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ *pDMMRes = (struct DMM_RES_OBJECT *)
++ MEM_Calloc(1 * sizeof(struct DMM_RES_OBJECT), MEM_PAGED);
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 1");
++ if ((*pDMMRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_5CLASS, "DRV_InsertDMMResElement: 2");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (pCtxt->pDMMList != NULL) {
++ GT_0trace(curTrace, GT_5CLASS,
++ "DRV_InsertDMMResElement: 3");
++ pTempDMMRes = pCtxt->pDMMList;
++ while (pTempDMMRes->next != NULL)
++ pTempDMMRes = pTempDMMRes->next;
++
++ pTempDMMRes->next = *pDMMRes;
++ } else {
++ pCtxt->pDMMList = *pDMMRes;
++ GT_0trace(curTrace, GT_5CLASS,
++ "DRV_InsertDMMResElement: 4");
++ }
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 5");
++ return status;
++}
++
++
++
++/* Release DMM resource element context
++* This is called from Proc_UnMap. after the actual resource is freed */
++DSP_STATUS DRV_RemoveDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempDMMRes2 = pCtxt->pDMMList;
++ pTempDMMRes = pCtxt->pDMMList;
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 1");
++ while ((pTempDMMRes != NULL) && (pTempDMMRes != pDMMRes)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 2");
++ pTempDMMRes2 = pTempDMMRes;
++ pTempDMMRes = pTempDMMRes->next;
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 3");
++ if (pCtxt->pDMMList == pTempDMMRes)
++ pCtxt->pDMMList = pTempDMMRes->next;
++
++ if (pTempDMMRes == NULL)
++ return DSP_ENOTFOUND;
++ else if (pTempDMMRes2->next != NULL)
++ pTempDMMRes2->next = pTempDMMRes2->next->next;
++
++ MEM_Free(pDMMRes);
++ GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 4");
++ return status;
++}
++
++/* Update DMM resource status */
++DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize,
++ u32 pReqAddr, u32 pMapAddr,
++ HANDLE hProcessor)
++{
++ struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(hDMMRes != NULL);
++ pDMMRes->ulMpuAddr = pMpuAddr;
++ pDMMRes->ulDSPAddr = pMapAddr;
++ pDMMRes->ulDSPResAddr = pReqAddr;
++ pDMMRes->dmmSize = ulSize;
++ pDMMRes->hProcessor = hProcessor;
++ pDMMRes->dmmAllocated = 1;
++
++ return status;
++}
++
++/* Actual DMM De-Allocation */
++DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n");
++ while (pDMMList != NULL) {
++ pDMMRes = pDMMList;
++ pDMMList = pDMMList->next;
++ if (pDMMRes->dmmAllocated) {
++ status = PROC_UnMap(pDMMRes->hProcessor,
++ (void *)pDMMRes->ulDSPResAddr);
++ status = PROC_UnReserveMemory(pDMMRes->hProcessor,
++ (void *)pDMMRes->ulDSPResAddr);
++ pDMMRes->dmmAllocated = 0;
++ }
++ }
++ return status;
++}
++
++
++/* Release all DMM resources and its context
++* This is called from .bridge_release. */
++DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMMRes = NULL;
++
++ DBC_Assert(pCtxt != NULL);
++ DRV_ProcFreeDMMRes(pCtxt);
++ pTempDMMRes = pCtxt->pDMMList;
++ while (pTempDMMRes != NULL) {
++ pTempDMMRes2 = pTempDMMRes;
++ pTempDMMRes = pTempDMMRes->next;
++ MEM_Free(pTempDMMRes2);
++ }
++ pCtxt->pDMMList = NULL;
++ return status;
++}
++
++DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE hDMMRes, HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
++ DSP_STATUS status = DSP_SOK;
++ struct DMM_RES_OBJECT *pTempDMM2 = NULL;
++ struct DMM_RES_OBJECT *pTempDMM = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempDMM = pCtxt->pDMMList;
++ while ((pTempDMM != NULL) && (pTempDMM->ulDSPAddr != pMapAddr)) {
++ GT_3trace(curTrace, GT_ENTER,
++ "DRV_GetDMMResElement: 2 pTempDMM:%x "
++ "pTempDMM->ulDSPAddr:%x pMapAddr:%x\n", pTempDMM,
++ pTempDMM->ulDSPAddr, pMapAddr);
++ pTempDMM2 = pTempDMM;
++ pTempDMM = pTempDMM->next;
++ }
++ if (pTempDMM != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 3");
++ *pDMMRes = pTempDMM;
++ } else {
++ status = DSP_ENOTFOUND;
++ } GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 4");
++ return status;
++}
++
++/* Update Node allocation status */
++void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ DBC_Assert(hNodeRes != NULL);
++ pNodeRes->nodeAllocated = status;
++}
++
++/* Update Node Heap status */
++void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status)
++{
++ struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
++ DBC_Assert(hNodeRes != NULL);
++ pNodeRes->heapAllocated = status;
++}
++
++/* Release all Node resources and its context
++* This is called from .bridge_release.
++*/
++DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ DRV_ProcFreeNodeRes(pCtxt);
++ pTempNode = pCtxt->pNodeList;
++ while (pTempNode != NULL) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ MEM_Free(pTempNode2);
++ }
++ pCtxt->pNodeList = NULL;
++ return status;
++}
++
++/* Getting the node resource element */
++
++DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE hNodeRes, HANDLE hPCtxt)
++{
++ struct NODE_RES_OBJECT **nodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_RES_OBJECT *pTempNode2 = NULL;
++ struct NODE_RES_OBJECT *pTempNode = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ pTempNode = pCtxt->pNodeList;
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetNodeResElement: 1");
++ while ((pTempNode != NULL) && (pTempNode->hNode != hNode)) {
++ pTempNode2 = pTempNode;
++ pTempNode = pTempNode->next;
++ }
++ if (pTempNode != NULL)
++ *nodeRes = pTempNode;
++ else
++ status = DSP_ENOTFOUND;
++
++ return status;
++}
++
++
++
++/* Allocate the STRM resource element
++* This is called after the actual resource is allocated
++*/
++DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStreamHandle, HANDLE hSTRMRes,
++ HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT **pSTRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
++ DBC_Assert(hPCtxt != NULL);
++
++ *pSTRMRes = (struct STRM_RES_OBJECT *)
++ MEM_Calloc(1 * sizeof(struct STRM_RES_OBJECT), MEM_PAGED);
++ if ((*pSTRMRes == NULL) || (hPCtxt == NULL)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_InsertSTRMResElement: 2");
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ (*pSTRMRes)->hStream = hStreamHandle;
++ if (pCtxt->pSTRMList != NULL) {
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertiSTRMResElement: 3");
++ pTempSTRMRes = pCtxt->pSTRMList;
++ while (pTempSTRMRes->next != NULL)
++ pTempSTRMRes = pTempSTRMRes->next;
++
++ pTempSTRMRes->next = *pSTRMRes;
++ } else {
++ pCtxt->pSTRMList = *pSTRMRes;
++ GT_0trace(curTrace, GT_ENTER,
++ "DRV_InsertSTRMResElement: 4");
++ }
++ }
++ return status;
++}
++
++
++
++/* Release Stream resource element context
++* This function called after the actual resource is freed
++*/
++DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT *pSTRMRes = (struct STRM_RES_OBJECT *)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes2 = pCtxt->pSTRMList;
++ struct STRM_RES_OBJECT *pTempSTRMRes = pCtxt->pSTRMList;
++
++ DBC_Assert(hPCtxt != NULL);
++ while ((pTempSTRMRes != NULL) && (pTempSTRMRes != pSTRMRes)) {
++ pTempSTRMRes2 = pTempSTRMRes;
++ pTempSTRMRes = pTempSTRMRes->next;
++ }
++ if (pCtxt->pSTRMList == pTempSTRMRes)
++ pCtxt->pSTRMList = pTempSTRMRes->next;
++
++ if (pTempSTRMRes == NULL)
++ status = DSP_ENOTFOUND;
++ else if (pTempSTRMRes2->next != NULL)
++ pTempSTRMRes2->next = pTempSTRMRes2->next->next;
++
++ MEM_Free(pSTRMRes);
++ return status;
++}
++
++
++/* Actual Stream De-Allocation */
++static DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ u8 **apBuffer = NULL;
++ struct STRM_RES_OBJECT *pSTRMList = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ u8 *pBufPtr;
++ u32 ulBytes;
++ u32 dwArg;
++ s32 ulBufSize;
++
++
++ DBC_Assert(hPCtxt != NULL);
++ pSTRMList = pCtxt->pSTRMList;
++ while (pSTRMList != NULL) {
++ pSTRMRes = pSTRMList;
++ pSTRMList = pSTRMList->next;
++ if (pSTRMRes->uNumBufs != 0) {
++ apBuffer = MEM_Alloc((pSTRMRes->uNumBufs *
++ sizeof(u8 *)), MEM_NONPAGED);
++ status = STRM_FreeBuffer(pSTRMRes->hStream, apBuffer,
++ pSTRMRes->uNumBufs);
++ MEM_Free(apBuffer);
++ }
++ status = STRM_Close(pSTRMRes->hStream);
++ if (DSP_FAILED(status)) {
++ if (status == DSP_EPENDING) {
++ status = STRM_Reclaim(pSTRMRes->hStream,
++ &pBufPtr, &ulBytes,
++ (u32 *)&ulBufSize, &dwArg);
++ if (DSP_SUCCEEDED(status))
++ status = STRM_Close(pSTRMRes->hStream);
++
++ }
++ }
++ }
++ return status1;
++}
++
++/* Release all Stream resources and its context
++* This is called from .bridge_release.
++*/
++DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE hPCtxt)
++{
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRMRes2 = NULL;
++ struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
++
++ DBC_Assert(hPCtxt != NULL);
++ DRV_ProcFreeSTRMRes(pCtxt);
++ pTempSTRMRes = pCtxt->pSTRMList;
++ while (pTempSTRMRes != NULL) {
++ pTempSTRMRes2 = pTempSTRMRes;
++ pTempSTRMRes = pTempSTRMRes->next;
++ MEM_Free(pTempSTRMRes2);
++ }
++ pCtxt->pSTRMList = NULL;
++ return status;
++}
++
++
++/* Getting the stream resource element */
++DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT *pTempSTRM2 = NULL;
++ struct STRM_RES_OBJECT *pTempSTRM = pCtxt->pSTRMList;
++
++ DBC_Assert(hPCtxt != NULL);
++ while ((pTempSTRM != NULL) && (pTempSTRM->hStream != hStrm)) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 2");
++ pTempSTRM2 = pTempSTRM;
++ pTempSTRM = pTempSTRM->next;
++ }
++ if (pTempSTRM != NULL) {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 3");
++ *STRMRes = pTempSTRM;
++ } else {
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 4");
++ status = DSP_ENOTFOUND;
++ }
++ GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 5");
++ return status;
++}
++
++/* Updating the stream resource element */
++DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE hSTRMRes, HANDLE hPCtxt)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
++
++ DBC_Assert(hPCtxt != NULL);
++ (*STRMRes)->uNumBufs = uNumBufs;
++ return status;
++}
++
++/* Displaying the resources allocated by a process */
++DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf1, u32 *pSize)
++{
++ struct PROCESS_CONTEXT *pCtxt = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
++ u32 tempCount = 1;
++ HANDLE hDrvObject = NULL;
++ void *pBuf = pBuf1;
++ u8 pTempBuf[250];
++ u32 tempStrLen = 0, tempStrLen2 = 0;
++ DSP_STATUS status = DSP_SOK;
++
++ CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxt, (struct DRV_OBJECT *)hDrvObject);
++ GT_0trace(curTrace, GT_ENTER, "*********************"
++ "DRV_ProcDisplayResourceInfo:*\n");
++ while (pCtxt != NULL) {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "-------------------------------------"
++ "-----------------------------------\n");
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ if (pCtxt->resState == PROC_RES_ALLOCATED) {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "GPP Process Resource State: "
++ "pCtxt->resState = PROC_RES_ALLOCATED, "
++ " Process ID: %d\n", pCtxt->pid);
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ } else {
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "GPP Resource State: pCtxt->resState"
++ " = PROC_RES_DEALLOCATED, Process ID:%d\n",
++ pCtxt->pid);
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ }
++ pNodeRes = pCtxt->pNodeList;
++ tempCount = 1;
++ while (pNodeRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pNodeList->hNode:%x\n",
++ tempCount, pNodeRes->hNode);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "Node Resource Information: Node #"
++ " %d Node Handle hNode:0X%x\n",
++ tempCount, (u32)pNodeRes->hNode);
++ pNodeRes = pNodeRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pDSPHEAPRes = pCtxt->pDSPHEAPList;
++ while (pDSPHEAPRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pDSPHEAPRList->ulMpuAddr:%x\n",
++ tempCount, pDSPHEAPRes->ulMpuAddr);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "DSP Heap Resource Info: HEAP # %d"
++ " Mapped GPP Address: 0x%x, size: 0x%x\n",
++ tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
++ (u32)pDSPHEAPRes->heapSize);
++ pDSPHEAPRes = pDSPHEAPRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pDMMRes = pCtxt->pDMMList;
++ while (pDMMRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ " pCtxt->pDMMList->ulMpuAddr:%x\n",
++ tempCount,
++ pDMMRes->ulMpuAddr);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "DMM Resource Info: DMM # %d Mapped"
++ " GPP Address: 0x%x, size: 0x%x\n",
++ tempCount, (u32)pDMMRes->ulMpuAddr,
++ (u32)pDMMRes->dmmSize);
++ pDMMRes = pDMMRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ tempCount = 1;
++ pSTRMRes = pCtxt->pSTRMList;
++ while (pSTRMRes != NULL) {
++ GT_2trace(curTrace, GT_ENTER,
++ "DRV_ProcDisplayResourceInfo: #:%d "
++ "pCtxt->pSTRMList->hStream:%x\n", tempCount,
++ pSTRMRes->hStream);
++ tempStrLen2 = sprintf((char *)pTempBuf,
++ "Stream Resource info: STRM # %d "
++ "Stream Handle: 0x%x \n",
++ tempCount, (u32)pSTRMRes->hStream);
++ pSTRMRes = pSTRMRes->next;
++ tempStrLen2 += 2;
++ memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
++ tempStrLen += tempStrLen2;
++ tempCount++;
++ }
++ pCtxt = pCtxt->next;
++ }
++ *pSize = tempStrLen;
++ status = PrintProcessInformation();
++ GT_0trace(curTrace, GT_ENTER, "*********************"
++ "DRV_ProcDisplayResourceInfo:**\n");
++ return status;
++}
++
++/*
++ * ======== PrintProcessInformation ========
++ * Purpose:
++ * This function prints the Process's information stored in
++ * the process context list. Some of the information that
++ * it displays is Process's state, Node, Stream, DMM, and
++ * Heap information.
++ */
++static DSP_STATUS PrintProcessInformation(void)
++{
++ struct DRV_OBJECT *hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pCtxtList = NULL;
++ struct NODE_RES_OBJECT *pNodeRes = NULL;
++ struct DMM_RES_OBJECT *pDMMRes = NULL;
++ struct STRM_RES_OBJECT *pSTRMRes = NULL;
++ struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
++ DSP_STATUS status = DSP_SOK;
++ u32 tempCount;
++ u32 procID;
++
++ /* Get the Process context list */
++ CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxtList, hDrvObject);
++ GT_0trace(curTrace, GT_4CLASS, "\n### Debug information"
++ " for DSP bridge ##\n");
++ GT_0trace(curTrace, GT_4CLASS, " \n ###The processes"
++ " information is as follows ### \n") ;
++ GT_0trace(curTrace, GT_4CLASS, " ====================="
++ "============ \n");
++ /* Go through the entries in the Process context list */
++ while (pCtxtList != NULL) {
++ GT_1trace(curTrace, GT_4CLASS, "\nThe process"
++ " id is %d\n", pCtxtList->pid);
++ GT_0trace(curTrace, GT_4CLASS, " -------------------"
++ "---------\n");
++ if (pCtxtList->resState == PROC_RES_ALLOCATED) {
++ GT_0trace(curTrace, GT_4CLASS, " \nThe Process"
++ " is in Allocated state\n");
++ } else {
++ GT_0trace(curTrace, GT_4CLASS, "\nThe Process"
++ " is in DeAllocated state\n");
++ }
++ GT_1trace(curTrace, GT_4CLASS, "\nThe hProcessor"
++ " handle is: 0X%x\n",
++ (u32)pCtxtList->hProcessor);
++ if (pCtxtList->hProcessor != NULL) {
++ PROC_GetProcessorId(pCtxtList->hProcessor, &procID);
++ if (procID == DSP_UNIT) {
++ GT_0trace(curTrace, GT_4CLASS,
++ "\nProcess connected to"
++ " DSP Processor\n");
++ } else if (procID == IVA_UNIT) {
++ GT_0trace(curTrace, GT_4CLASS,
++ "\nProcess connected to"
++ " IVA Processor\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "\n***ERROR:Invalid Processor Id***\n");
++ }
++ }
++ pNodeRes = pCtxtList->pNodeList;
++ tempCount = 1;
++ while (pNodeRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Nodes allocated by"
++ " this Process are***\n");
++ GT_2trace(curTrace, GT_4CLASS,
++ "Node # %d Node Handle hNode:0x%x\n",
++ tempCount, (u32)pNodeRes->hNode);
++ pNodeRes = pNodeRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Nodes"
++ " allocated by this Process***\n");
++ tempCount = 1;
++ pDSPHEAPRes = pCtxtList->pDSPHEAPList;
++ while (pDSPHEAPRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Heaps allocated by"
++ " this Process are***\n");
++ GT_3trace(curTrace, GT_4CLASS,
++ "DSP Heap Resource Info: HEAP # %d "
++ "Mapped GPP Address:0x%x, Size: 0x%lx\n",
++ tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
++ pDSPHEAPRes->heapSize);
++ pDSPHEAPRes = pDSPHEAPRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Heaps allocated"
++ " by this Process***\n");
++ tempCount = 1;
++ pDMMRes = pCtxtList->pDMMList;
++ while (pDMMRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***The DMM resources allocated by"
++ " this Process are***\n");
++ GT_3trace(curTrace, GT_4CLASS,
++ "DMM Resource Info: DMM # %d "
++ "Mapped GPP Address:0X%lx, Size: 0X%lx\n",
++ tempCount, pDMMRes->ulMpuAddr,
++ pDMMRes->dmmSize);
++ pDMMRes = pDMMRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no DMM resources"
++ " allocated by this Process***\n");
++ tempCount = 1;
++ pSTRMRes = pCtxtList->pSTRMList;
++ while (pSTRMRes != NULL) {
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n***The Stream resources allocated by"
++ " this Process are***\n");
++ GT_2trace(curTrace, GT_4CLASS,
++ "Stream Resource info: STRM # %d"
++ "Stream Handle:0X%x\n", tempCount,
++ (u32)pSTRMRes->hStream);
++ pSTRMRes = pSTRMRes->next;
++ tempCount++;
++ }
++ if (tempCount == 1)
++ GT_0trace(curTrace, GT_4CLASS,
++ "\n ***There are no Stream resources"
++ "allocated by this Process***\n");
++ pCtxtList = pCtxtList->next;
++ }
++ return status;
++}
++
++/* GPP PROCESS CLEANUP CODE END */
++#endif
++
++/*
++ * ======== = DRV_Create ======== =
++ * Purpose:
++ * DRV Object gets created only once during Driver Loading.
++ */
++DSP_STATUS DRV_Create(OUT struct DRV_OBJECT **phDRVObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = NULL;
++
++ DBC_Require(phDRVObject != NULL);
++ DBC_Require(cRefs > 0);
++ GT_1trace(curTrace, GT_ENTER, "Entering DRV_Create"
++ " phDRVObject 0x%x\n", phDRVObject);
++ MEM_AllocObject(pDRVObject, struct DRV_OBJECT, SIGNATURE);
++ if (pDRVObject) {
++ /* Create and Initialize List of device objects */
++ pDRVObject->devList = LST_Create();
++ if (pDRVObject->devList) {
++ /* Create and Initialize List of device Extension */
++ pDRVObject->devNodeString = LST_Create();
++ if (!(pDRVObject->devNodeString)) {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Create DRV_EXT list ");
++ MEM_FreeObject(pDRVObject);
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Create Dev List ");
++ MEM_FreeObject(pDRVObject);
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Allocate Memory for DRV Obj");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Store the DRV Object in the Registry */
++ if (DSP_SUCCEEDED
++ (CFG_SetObject((u32) pDRVObject, REG_DRV_OBJECT))) {
++ GT_1trace(curTrace, GT_1CLASS,
++ "DRV Obj Created pDrvObject 0x%x\n ",
++ pDRVObject);
++ *phDRVObject = pDRVObject;
++ } else {
++ /* Free the DRV Object */
++ status = DSP_EFAIL;
++ MEM_Free(pDRVObject);
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to update the Registry with "
++ "DRV Object ");
++ }
++ }
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting DRV_Create: phDRVObject: 0x%x\tstatus:"
++ "0x%x\n", phDRVObject, status);
++ DBC_Ensure(DSP_FAILED(status) ||
++ MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== DRV_Exit ========
++ * Purpose:
++ * Discontinue usage of the DRV module.
++ */
++void DRV_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_0trace(curTrace, GT_5CLASS, "Entering DRV_Exit \n");
++
++ cRefs--;
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== = DRV_Destroy ======== =
++ * purpose:
++ * Invoked during bridge de-initialization
++ */
++DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDRVObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++
++ GT_1trace(curTrace, GT_ENTER, "Entering DRV_Destroy"
++ " hDRVObject 0x%x\n", hDRVObject);
++ /*
++ * Delete the List if it exists.Should not come here
++ * as the DRV_RemoveDevObject and the Last DRV_RequestResources
++ * removes the list if the lists are empty.
++ */
++ if (pDRVObject->devList) {
++ /* Could assert if the list is not empty */
++ LST_Delete(pDRVObject->devList);
++ }
++ if (pDRVObject->devNodeString) {
++ /* Could assert if the list is not empty */
++ LST_Delete(pDRVObject->devNodeString);
++ }
++ MEM_FreeObject(pDRVObject);
++ /* Update the DRV Object in Registry to be 0 */
++ (void)CFG_SetObject(0, REG_DRV_OBJECT);
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting DRV_Destroy: hDRVObject: 0x%x\tstatus:"
++ "0x%x\n", hDRVObject, status);
++ DBC_Ensure(!MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== DRV_GetDevObject ========
++ * Purpose:
++ * Given a index, returns a handle to DevObject from the list.
++ */
++DSP_STATUS DRV_GetDevObject(u32 uIndex, struct DRV_OBJECT *hDrvObject,
++ struct DEV_OBJECT **phDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++#if GT_TRACE /* pDrvObject is used only for Assertions and debug messages.*/
++ struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
++#endif
++ struct DEV_OBJECT *pDevObject;
++ u32 i;
++ DBC_Require(MEM_IsValidHandle(pDrvObject, SIGNATURE));
++ DBC_Require(phDevObject != NULL);
++ DBC_Require(uIndex >= 0);
++ DBC_Require(cRefs > 0);
++ DBC_Assert(!(LST_IsEmpty(pDrvObject->devList)));
++ GT_3trace(curTrace, GT_ENTER,
++ "Entered DRV_GetDevObject, args:\n\tuIndex: "
++ "0x%x\n\thDrvObject: 0x%x\n\tphDevObject: 0x%x\n",
++ uIndex, hDrvObject, phDevObject);
++ pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ for (i = 0; i < uIndex; i++) {
++ pDevObject =
++ (struct DEV_OBJECT *)DRV_GetNextDevObject((u32)pDevObject);
++ }
++ if (pDevObject) {
++ *phDevObject = (struct DEV_OBJECT *) pDevObject;
++ status = DSP_SOK;
++ } else {
++ *phDevObject = NULL;
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "DRV: Could not get the DevObject\n");
++ }
++ GT_2trace(curTrace, GT_ENTER,
++ "Exiting Drv_GetDevObject\n\tstatus: 0x%x\n\t"
++ "hDevObject: 0x%x\n", status, *phDevObject);
++ return status;
++}
++
++/*
++ * ======== DRV_GetFirstDevObject ========
++ * Purpose:
++ * Retrieve the first Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DRV.
++ */
++u32 DRV_GetFirstDevObject(void)
++{
++ u32 dwDevObject = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++ if ((pDrvObject->devList != NULL) &&
++ !LST_IsEmpty(pDrvObject->devList))
++ dwDevObject = (u32) LST_First(pDrvObject->devList);
++ }
++
++ return dwDevObject;
++}
++
++/*
++ * ======== DRV_GetFirstDevNodeString ========
++ * Purpose:
++ * Retrieve the first Device Extension from an internal linked list of
++ * of Pointer to DevNode Strings maintained by DRV.
++ */
++u32 DRV_GetFirstDevExtension(void)
++{
++ u32 dwDevExtension = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++
++ if ((pDrvObject->devNodeString != NULL) &&
++ !LST_IsEmpty(pDrvObject->devNodeString)) {
++ dwDevExtension = (u32)LST_First(pDrvObject->
++ devNodeString);
++ }
++ }
++
++ return dwDevExtension;
++}
++
++/*
++ * ======== DRV_GetNextDevObject ========
++ * Purpose:
++ * Retrieve the next Device Object handle from an internal linked list of
++ * of DEV_OBJECTs maintained by DRV, after having previously called
++ * DRV_GetFirstDevObject() and zero or more DRV_GetNext.
++ */
++u32 DRV_GetNextDevObject(u32 hDevObject)
++{
++ u32 dwNextDevObject = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ DBC_Require(hDevObject != 0);
++
++ if (DSP_SUCCEEDED
++ (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
++
++ if ((pDrvObject->devList != NULL) &&
++ !LST_IsEmpty(pDrvObject->devList)) {
++ dwNextDevObject = (u32)LST_Next(pDrvObject->devList,
++ (struct LST_ELEM *)hDevObject);
++ }
++ }
++ return dwNextDevObject;
++}
++
++/*
++ * ======== DRV_GetNextDevExtension ========
++ * Purpose:
++ * Retrieve the next Device Extension from an internal linked list of
++ * of pointer to DevNodeString maintained by DRV, after having previously
++ * called DRV_GetFirstDevExtension() and zero or more
++ * DRV_GetNextDevExtension().
++ */
++u32 DRV_GetNextDevExtension(u32 hDevExtension)
++{
++ u32 dwDevExtension = 0;
++ struct DRV_OBJECT *pDrvObject;
++
++ DBC_Require(hDevExtension != 0);
++
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDrvObject,
++ REG_DRV_OBJECT))) {
++ if ((pDrvObject->devNodeString != NULL) &&
++ !LST_IsEmpty(pDrvObject->devNodeString)) {
++ dwDevExtension = (u32)LST_Next(pDrvObject->
++ devNodeString,
++ (struct LST_ELEM *)hDevExtension);
++ }
++ }
++
++ return dwDevExtension;
++}
++
++/*
++ * ======== DRV_Init ========
++ * Purpose:
++ * Initialize DRV module private state.
++ */
++DSP_STATUS DRV_Init(void)
++{
++ s32 fRetval = 1; /* function return value */
++
++ DBC_Require(cRefs >= 0);
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(curTrace, GT_5CLASS, "Entering DRV_Entry crefs 0x%x \n",
++ cRefs);
++
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== DRV_InsertDevObject ========
++ * Purpose:
++ * Insert a DevObject into the list of Manager object.
++ */
++DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDRVObject,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hDevObject != NULL);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ DBC_Assert(pDRVObject->devList);
++
++ GT_2trace(curTrace, GT_ENTER,
++ "Entering DRV_InsertProcObject hDRVObject "
++ "0x%x\n, hDevObject 0x%x\n", hDRVObject, hDevObject);
++
++ LST_PutTail(pDRVObject->devList, (struct LST_ELEM *)hDevObject);
++
++ GT_1trace(curTrace, GT_ENTER,
++ "Exiting InsertDevObject status 0x%x\n", status);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDRVObject->devList));
++
++ return status;
++}
++
++/*
++ * ======== DRV_RemoveDevObject ========
++ * Purpose:
++ * Search for and remove a DeviceObject from the given list of DRV
++ * objects.
++ */
++DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDRVObject,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
++ struct LST_ELEM *pCurElem;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
++ DBC_Require(hDevObject != NULL);
++
++ DBC_Require(pDRVObject->devList != NULL);
++ DBC_Require(!LST_IsEmpty(pDRVObject->devList));
++
++ GT_2trace(curTrace, GT_ENTER,
++ "Entering DRV_RemoveDevObject hDevObject "
++ "0x%x\n, hDRVObject 0x%x\n", hDevObject, hDRVObject);
++ /* Search list for pProcObject: */
++ for (pCurElem = LST_First(pDRVObject->devList); pCurElem != NULL;
++ pCurElem = LST_Next(pDRVObject->devList, pCurElem)) {
++ /* If found, remove it. */
++ if ((struct DEV_OBJECT *) pCurElem == hDevObject) {
++ LST_RemoveElem(pDRVObject->devList, pCurElem);
++ status = DSP_SOK;
++ break;
++ }
++ }
++ /* Remove list if empty. */
++ if (LST_IsEmpty(pDRVObject->devList)) {
++ LST_Delete(pDRVObject->devList);
++ pDRVObject->devList = NULL;
++ }
++ DBC_Ensure((pDRVObject->devList == NULL) ||
++ !LST_IsEmpty(pDRVObject->devList));
++ GT_1trace(curTrace, GT_ENTER,
++ "DRV_RemoveDevObject returning 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== DRV_RequestResources ========
++ * Purpose:
++ * Requests resources from the OS.
++ */
++DSP_STATUS DRV_RequestResources(u32 dwContext, u32 *pDevNodeString)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject;
++ struct DRV_EXT *pszdevNode;
++
++ DBC_Require(dwContext != 0);
++ DBC_Require(pDevNodeString != NULL);
++ GT_0trace(curTrace, GT_ENTER, "Entering DRV_RequestResources\n");
++ /*
++ * Allocate memory to hold the string. This will live untill
++ * it is freed in the Release resources. Update the driver object
++ * list.
++ */
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDRVObject,
++ REG_DRV_OBJECT))) {
++ pszdevNode = MEM_Calloc(sizeof(struct DRV_EXT), MEM_NONPAGED);
++ if (pszdevNode) {
++ LST_InitElem(&pszdevNode->link);
++ strncpy((char *) pszdevNode->szString,
++ (char *)dwContext, MAXREGPATHLENGTH);
++ /* Update the Driver Object List */
++ *pDevNodeString = (u32)pszdevNode->szString;
++ LST_PutTail(pDRVObject->devNodeString,
++ (struct LST_ELEM *)pszdevNode);
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to Allocate Memory devNodeString ");
++ status = DSP_EFAIL;
++ *pDevNodeString = 0;
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to get Driver Object from Registry");
++ *pDevNodeString = 0;
++ }
++
++ if (!(strcmp((char *) dwContext, "TIOMAP1510"))) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Allocating resources for UMA \n");
++ status = RequestBridgeResourcesDSP(dwContext, DRV_ASSIGN);
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(curTrace, GT_7CLASS, "Unknown Device ");
++ }
++
++ if (DSP_FAILED(status)) {
++ GT_0trace(curTrace, GT_7CLASS,
++ "Failed to reserve bridge resources ");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDevNodeString != NULL &&
++ !LST_IsEmpty(pDRVObject->devNodeString)) ||
++ (DSP_FAILED(status) && *pDevNodeString == 0));
++
++ return status;
++}
++
++/*
++ * ======== DRV_ReleaseResources ========
++ * Purpose:
++ * Releases resources from the OS.
++ */
++DSP_STATUS DRV_ReleaseResources(u32 dwContext, struct DRV_OBJECT *hDrvObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDrvObject;
++ struct DRV_EXT *pszdevNode;
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DRV_Release Resources\n");
++
++ if (!(strcmp((char *)((struct DRV_EXT *)dwContext)->szString,
++ "TIOMAP1510"))) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Releasing DSP-Bridge resources \n");
++ status = RequestBridgeResources(dwContext, DRV_RELEASE);
++ } else {
++ GT_0trace(curTrace, GT_1CLASS, " Unknown device\n");
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ "Failed to relese bridge resources\n");
++ }
++
++ /*
++ * Irrespective of the status go ahead and clean it
++ * The following will over write the status.
++ */
++ for (pszdevNode = (struct DRV_EXT *)DRV_GetFirstDevExtension();
++ pszdevNode != NULL; pszdevNode = (struct DRV_EXT *)
++ DRV_GetNextDevExtension((u32)pszdevNode)) {
++ if ((u32)pszdevNode == dwContext) {
++ /* Found it */
++ /* Delete from the Driver object list */
++ LST_RemoveElem(pDRVObject->devNodeString,
++ (struct LST_ELEM *)pszdevNode);
++ MEM_Free((void *) pszdevNode);
++ break;
++ }
++ /* Delete the List if it is empty */
++ if (LST_IsEmpty(pDRVObject->devNodeString)) {
++ LST_Delete(pDRVObject->devNodeString);
++ pDRVObject->devNodeString = NULL;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== RequestBridgeResources ========
++ * Purpose:
++ * Reserves shared memory for bridge.
++ */
++static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 bRequest)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES *pResources;
++ u32 dwBuffSize;
++
++ struct DRV_EXT *driverExt;
++ u32 shm_size;
++
++ DBC_Require(dwContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResources \n");
++
++ if (!bRequest) {
++ driverExt = (struct DRV_EXT *)dwContext;
++ /* Releasing resources by deleting the registry key */
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++ if (DSP_FAILED(REG_GetValue(NULL, (char *)driverExt->szString,
++ CURRENTCONFIG, (u8 *)pResources, &dwBuffSize))) {
++ status = CFG_E_RESOURCENOTAVAIL;
++ GT_0trace(curTrace, GT_1CLASS,
++ "REG_GetValue Failed \n");
++ } else {
++ GT_0trace(curTrace, GT_1CLASS,
++ "REG_GetValue Succeeded \n");
++ }
++
++ if (pResources != NULL) {
++ dwBuffSize = sizeof(shm_size);
++ status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
++ (u8 *)&shm_size, &dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ if ((pResources->dwMemBase[1]) &&
++ (pResources->dwMemPhys[1])) {
++ MEM_FreePhysMem((void *)pResources->
++ dwMemBase[1], pResources->dwMemPhys[1],
++ shm_size);
++ }
++ } else {
++ GT_1trace(curTrace, GT_7CLASS,
++ "Error getting SHM size from registry: "
++ "%x. Not calling MEM_FreePhysMem\n",
++ status);
++ }
++ pResources->dwMemBase[1] = 0;
++ pResources->dwMemPhys[1] = 0;
++
++ if (pResources->dwPrmBase)
++ iounmap((void *)pResources->dwPrmBase);
++ if (pResources->dwCmBase)
++ iounmap((void *)pResources->dwCmBase);
++ if (pResources->dwMboxBase)
++ iounmap((void *)pResources->dwMboxBase);
++ if (pResources->dwMemBase[0])
++ iounmap((void *)pResources->dwMemBase[0]);
++ if (pResources->dwMemBase[2])
++ iounmap((void *)pResources->dwMemBase[2]);
++ if (pResources->dwMemBase[3])
++ iounmap((void *)pResources->dwMemBase[3]);
++ if (pResources->dwMemBase[4])
++ iounmap((void *)pResources->dwMemBase[4]);
++ if (pResources->dwWdTimerDspBase)
++ iounmap((void *)pResources->dwWdTimerDspBase);
++ if (pResources->dwDmmuBase)
++ iounmap((void *)pResources->dwDmmuBase);
++ if (pResources->dwPerBase)
++ iounmap((void *)pResources->dwPerBase);
++ if (pResources->dwPerPmBase)
++ iounmap((void *)pResources->dwPerPmBase);
++ if (pResources->dwCorePmBase)
++ iounmap((void *)pResources->dwCorePmBase);
++ if (pResources->dwSysCtrlBase) {
++ iounmap((void *)pResources->dwSysCtrlBase);
++ /* don't set pResources->dwSysCtrlBase to null
++ * as it is used in BOARD_Stop */
++ }
++ pResources->dwPrmBase = (u32) NULL;
++ pResources->dwCmBase = (u32) NULL;
++ pResources->dwMboxBase = (u32) NULL;
++ pResources->dwMemBase[0] = (u32) NULL;
++ pResources->dwMemBase[2] = (u32) NULL;
++ pResources->dwMemBase[3] = (u32) NULL;
++ pResources->dwMemBase[4] = (u32) NULL;
++ pResources->dwWdTimerDspBase = (u32) NULL;
++ pResources->dwDmmuBase = (u32) NULL;
++
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *)driverExt->szString,
++ CURRENTCONFIG, REG_BINARY, (u8 *)pResources,
++ (u32)dwBuffSize);
++ /* Set all the other entries to NULL */
++ MEM_Free(pResources);
++ }
++ GT_0trace(curTrace, GT_ENTER, " <- RequestBridgeResources \n");
++ return status;
++ }
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++ if (pResources != NULL) {
++ /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
++ pResources->wNumMemWindows = 2;
++ /* First window is for DSP internal memory */
++
++ pResources->dwPrmBase = (u32)ioremap(OMAP_IVA2_PRM_BASE,
++ OMAP_IVA2_PRM_SIZE);
++ pResources->dwCmBase = (u32)ioremap(OMAP_IVA2_CM_BASE,
++ OMAP_IVA2_CM_SIZE);
++ pResources->dwMboxBase = (u32)ioremap(OMAP_MBOX_BASE,
++ OMAP_MBOX_SIZE);
++ pResources->dwSysCtrlBase = (u32)ioremap(OMAP_SYSC_BASE,
++ OMAP_SYSC_SIZE);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
++ pResources->dwMemBase[0]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
++ pResources->dwMemBase[3]);
++ GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
++ pResources->dwPrmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
++ pResources->dwCmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
++ pResources->dwWdTimerDspBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
++ pResources->dwMboxBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
++ pResources->dwDmmuBase);
++
++ /* for 24xx base port is not mapping the mamory for DSP
++ * internal memory TODO Do a ioremap here */
++ /* Second window is for DSP external memory shared with MPU */
++ if (DSP_SUCCEEDED(status)) {
++ /* for Linux, these are hard-coded values */
++ pResources->dwBusType = 0;
++ pResources->bIRQRegisters = 0;
++ pResources->bIRQAttrib = 0;
++ pResources->dwOffsetForMonitor = 0;
++ pResources->dwChnlOffset = 0;
++ /* CHNL_MAXCHANNELS */
++ pResources->dwNumChnls = CHNL_MAXCHANNELS;
++ pResources->dwChnlBufSize = 0x400;
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *) dwContext,
++ CURRENTCONFIG, REG_BINARY,
++ (u8 *)pResources,
++ sizeof(struct CFG_HOSTRES));
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Successfully set the registry "
++ "value for CURRENTCONFIG\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ " Failed to set the registry "
++ "value for CURRENTCONFIG\n");
++ }
++ }
++ MEM_Free(pResources);
++ }
++ /* End Mem alloc */
++ return status;
++}
++
++/*
++ * ======== RequestBridgeResourcesDSP ========
++ * Purpose:
++ * Reserves shared memory for bridge.
++ */
++static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 bRequest)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES *pResources;
++ u32 dwBuffSize;
++ u32 dmaAddr;
++ u32 shm_size;
++
++ DBC_Require(dwContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResourcesDSP \n");
++
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++
++ pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
++
++ if (pResources != NULL) {
++ if (DSP_FAILED(CFG_GetHostResources((struct CFG_DEVNODE *)
++ dwContext, pResources))) {
++ /* Call CFG_GetHostResources to get reserve resouces */
++ status = RequestBridgeResources(dwContext, bRequest);
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources
++ ((struct CFG_DEVNODE *) dwContext,
++ pResources);
++ }
++ }
++ /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
++ pResources->wNumMemWindows = 4;
++
++ pResources->dwMemBase[0] = 0;
++ pResources->dwMemBase[2] = (u32)ioremap(OMAP_DSP_MEM1_BASE,
++ OMAP_DSP_MEM1_SIZE);
++ pResources->dwMemBase[3] = (u32)ioremap(OMAP_DSP_MEM2_BASE,
++ OMAP_DSP_MEM2_SIZE);
++ pResources->dwMemBase[4] = (u32)ioremap(OMAP_DSP_MEM3_BASE,
++ OMAP_DSP_MEM3_SIZE);
++ pResources->dwPerBase = (u32)ioremap(OMAP_PER_CM_BASE,
++ OMAP_PER_CM_SIZE);
++ pResources->dwPerPmBase = (u32)ioremap(OMAP_PER_PRM_BASE,
++ OMAP_PER_PRM_SIZE);
++ pResources->dwCorePmBase = (u32)ioremap(OMAP_CORE_PRM_BASE,
++ OMAP_CORE_PRM_SIZE);
++ pResources->dwDmmuBase = (u32)ioremap(OMAP_DMMU_BASE,
++ OMAP_DMMU_SIZE);
++ pResources->dwWdTimerDspBase = 0;
++
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
++ pResources->dwMemBase[0]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[1] 0x%x\n",
++ pResources->dwMemBase[1]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[2] 0x%x\n",
++ pResources->dwMemBase[2]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
++ pResources->dwMemBase[3]);
++ GT_1trace(curTrace, GT_2CLASS, "dwMemBase[4] 0x%x\n",
++ pResources->dwMemBase[4]);
++ GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
++ pResources->dwPrmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
++ pResources->dwCmBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
++ pResources->dwWdTimerDspBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
++ pResources->dwMboxBase);
++ GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
++ pResources->dwDmmuBase);
++ dwBuffSize = sizeof(shm_size);
++ status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
++ (u8 *)&shm_size, &dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate Physically contiguous,
++ * non-cacheable memory */
++ pResources->dwMemBase[1] =
++ (u32)MEM_AllocPhysMem(shm_size, 0x100000,
++ &dmaAddr);
++ if (pResources->dwMemBase[1] == 0) {
++ status = DSP_EMEMORY;
++ GT_0trace(curTrace, GT_7CLASS,
++ "SHM reservation Failed\n");
++ } else {
++ pResources->dwMemLength[1] = shm_size;
++ pResources->dwMemPhys[1] = dmaAddr;
++
++ GT_3trace(curTrace, GT_1CLASS,
++ "Bridge SHM address 0x%x dmaAddr"
++ " %x size %x\n",
++ pResources->dwMemBase[1],
++ dmaAddr, shm_size);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* for Linux, these are hard-coded values */
++ pResources->dwBusType = 0;
++ pResources->bIRQRegisters = 0;
++ pResources->bIRQAttrib = 0;
++ pResources->dwOffsetForMonitor = 0;
++ pResources->dwChnlOffset = 0;
++ /* CHNL_MAXCHANNELS */
++ pResources->dwNumChnls = CHNL_MAXCHANNELS;
++ pResources->dwChnlBufSize = 0x400;
++ dwBuffSize = sizeof(struct CFG_HOSTRES);
++ status = REG_SetValue(NULL, (char *)dwContext,
++ CURRENTCONFIG, REG_BINARY,
++ (u8 *)pResources,
++ sizeof(struct CFG_HOSTRES));
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(curTrace, GT_1CLASS,
++ " Successfully set the registry"
++ " value for CURRENTCONFIG\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ " Failed to set the registry value"
++ " for CURRENTCONFIG\n");
++ }
++ }
++ MEM_Free(pResources);
++ }
++ /* End Mem alloc */
++ return status;
++}
+diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c
+new file mode 100644
+index 0000000..4aa7de6
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv_interface.c
+@@ -0,0 +1,777 @@
++/*
++ * drv_interface.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== linux_driver.c ========
++ * Description:
++ * DSP/BIOS Bridge driver interface.
++ *
++ * Public Functions:
++ * driver_init
++ * driver_exit
++ * driver_open
++ * driver_release
++ * driver_ioctl
++ * driver_mmap
++ *
++ *! Revision History
++ *! ================
++ *! 21-Apr-2004 map Deprecated use of MODULE_PARM for kernel versions
++ *! greater than 2.5, use module_param.
++ *! 08-Mar-2004 sb Added the dsp_debug argument, which keeps the DSP in self
++ *! loop after image load and waits in a loop for DSP to start
++ *! 16-Feb-2004 vp Deprecated the usage of MOD_INC_USE_COUNT and
++ *! MOD_DEC_USE_COUNT
++ *! for kernel versions greater than 2.5
++ *! 20-May-2003 vp Added unregister functions for the DPM.
++ *! 24-Mar-2003 sb Pass pid instead of driverContext to DSP_Close
++ *! 24-Mar-2003 vp Added Power Management support.
++ *! 21-Mar-2003 sb Configure SHM size using insmod argument shm_size
++ *! 10-Feb-2003 vp Updated based on code review comments
++ *! 18-Oct-2002 sb Created initial version
++ */
++
++/* ----------------------------------- Host OS */
++
++#include <dspbridge/host_os.h>
++#include <linux/platform_device.h>
++#include <linux/pm.h>
++
++#ifdef MODULE
++#include <linux/module.h>
++#endif
++
++#include <linux/device.h>
++#include <linux/init.h>
++#include <linux/moduleparam.h>
++#include <linux/cdev.h>
++
++#include <mach/board-3430sdp.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/gt.h>
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/services.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/wcdioctl.h>
++#include <dspbridge/_dcd.h>
++#include <dspbridge/dspdrv.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/pwr.h>
++
++/* ----------------------------------- This */
++#include <drv_interface.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/cfg.h>
++#include <dspbridge/resourcecleanup.h>
++#include <dspbridge/chnl.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drvdefs.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dbreg.h>
++#endif
++
++#ifdef CONFIG_BRIDGE_DVFS
++#include <mach/omap-pm.h>
++#include <mach-omap2/omap3-opp.h>
++#endif
++
++#define BRIDGE_NAME "C6410"
++/* ----------------------------------- Globals */
++#define DRIVER_NAME "DspBridge"
++#define DRIVER_MAJOR 0 /* Linux assigns our Major device number */
++#define DRIVER_MINOR 0 /* Linux assigns our Major device number */
++s32 dsp_debug;
++
++struct platform_device *omap_dspbridge_dev;
++
++struct bridge_dev {
++ struct cdev cdev;
++};
++
++static struct bridge_dev *bridge_device;
++
++static struct class *bridge_class;
++
++static u32 driverContext;
++#ifdef CONFIG_BRIDGE_DEBUG
++static char *GT_str;
++#endif /* CONFIG_BRIDGE_DEBUG */
++static s32 driver_major = DRIVER_MAJOR;
++static s32 driver_minor = DRIVER_MINOR;
++static char *base_img;
++char *iva_img;
++static char *num_procs = "C55=1";
++static s32 shm_size = 0x400000; /* 4 MB */
++static u32 phys_mempool_base;
++static u32 phys_mempool_size;
++static int tc_wordswapon; /* Default value is always false */
++
++#ifdef CONFIG_PM
++struct omap34xx_bridge_suspend_data {
++ int suspended;
++ wait_queue_head_t suspend_wq;
++};
++
++static struct omap34xx_bridge_suspend_data bridge_suspend_data;
++
++static int omap34xxbridge_suspend_lockout(
++ struct omap34xx_bridge_suspend_data *s, struct file *f)
++{
++ if ((s)->suspended) {
++ if ((f)->f_flags & O_NONBLOCK)
++ return DSP_EDPMSUSPEND;
++ wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
++ }
++ return 0;
++}
++
++#endif
++
++#ifdef DEBUG
++module_param(GT_str, charp, 0);
++MODULE_PARM_DESC(GT_str, "GT string, default = NULL");
++
++module_param(dsp_debug, int, 0);
++MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
++#endif
++
++module_param(driver_major, int, 0); /* Driver's major number */
++MODULE_PARM_DESC(driver_major, "Major device number, default = 0 (auto)");
++
++module_param(driver_minor, int, 0); /* Driver's major number */
++MODULE_PARM_DESC(driver_minor, "Minor device number, default = 0 (auto)");
++
++module_param(base_img, charp, 0);
++MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
++
++module_param(shm_size, int, 0);
++MODULE_PARM_DESC(shm_size, "SHM size, default = 4 MB, minimum = 64 KB");
++
++module_param(phys_mempool_base, uint, 0);
++MODULE_PARM_DESC(phys_mempool_base,
++ "Physical memory pool base passed to driver");
++
++module_param(phys_mempool_size, uint, 0);
++MODULE_PARM_DESC(phys_mempool_size,
++ "Physical memory pool size passed to driver");
++module_param(tc_wordswapon, int, 0);
++MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
++
++MODULE_AUTHOR("Texas Instruments");
++MODULE_LICENSE("GPL");
++
++static char *driver_name = DRIVER_NAME;
++
++#ifdef CONFIG_BRIDGE_DEBUG
++static struct GT_Mask driverTrace;
++#endif /* CONFIG_BRIDGE_DEBUG */
++
++static struct file_operations bridge_fops = {
++ .open = bridge_open,
++ .release = bridge_release,
++ .ioctl = bridge_ioctl,
++ .mmap = bridge_mmap,
++};
++
++#ifdef CONFIG_PM
++static u32 timeOut = 1000;
++#ifdef CONFIG_BRIDGE_DVFS
++static struct clk *clk_handle;
++s32 dsp_max_opps = VDD1_OPP3;
++#endif
++
++/* Maximum Opps that can be requested by IVA*/
++/*vdd1 rate table*/
++#ifdef CONFIG_BRIDGE_DVFS
++const struct omap_opp vdd1_rate_table_bridge[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {S125M, VDD1_OPP1, 0},
++ /*OPP2*/
++ {S250M, VDD1_OPP2, 0},
++ /*OPP3*/
++ {S500M, VDD1_OPP3, 0},
++ /*OPP4*/
++ {S550M, VDD1_OPP4, 0},
++ /*OPP5*/
++ {S600M, VDD1_OPP5, 0},
++};
++#endif
++#endif
++
++struct dspbridge_platform_data *omap_dspbridge_pdata;
++
++u32 vdd1_dsp_freq[6][4] = {
++ {0, 0, 0, 0},
++ /*OPP1*/
++ {0, 90000, 0, 86000},
++ /*OPP2*/
++ {0, 180000, 80000, 170000},
++ /*OPP3*/
++ {0, 360000, 160000, 340000},
++ /*OPP4*/
++ {0, 396000, 325000, 376000},
++ /*OPP5*/
++ {0, 430000, 355000, 430000},
++};
++
++#ifdef CONFIG_BRIDGE_DVFS
++static int dspbridge_post_scale(struct notifier_block *op, unsigned long level,
++ void *ptr)
++{
++ PWR_PM_PostScale(PRCM_VDD1, level);
++ return 0;
++}
++
++static struct notifier_block iva_clk_notifier = {
++ .notifier_call = dspbridge_post_scale,
++ NULL,
++};
++#endif
++
++static int __devinit omap34xx_bridge_probe(struct platform_device *pdev)
++{
++ int status;
++ u32 initStatus;
++ u32 temp;
++ dev_t dev = 0 ;
++ int result;
++#ifdef CONFIG_BRIDGE_DVFS
++ int i = 0;
++#endif
++ struct dspbridge_platform_data *pdata = pdev->dev.platform_data;
++
++ omap_dspbridge_dev = pdev;
++
++ /* use 2.6 device model */
++ if (driver_major) {
++ dev = MKDEV(driver_major, driver_minor);
++ result = register_chrdev_region(dev, 1, driver_name);
++ } else {
++ result = alloc_chrdev_region(&dev, driver_minor, 1,
++ driver_name);
++ driver_major = MAJOR(dev);
++ }
++
++ if (result < 0) {
++ GT_1trace(driverTrace, GT_7CLASS, "bridge_init: "
++ "Can't get Major %d \n", driver_major);
++ return result;
++ }
++
++ bridge_device = kmalloc(sizeof(struct bridge_dev), GFP_KERNEL);
++ if (!bridge_device) {
++ result = -ENOMEM;
++ unregister_chrdev_region(dev, 1);
++ return result;
++ }
++ memset(bridge_device, 0, sizeof(struct bridge_dev));
++ cdev_init(&bridge_device->cdev, &bridge_fops);
++ bridge_device->cdev.owner = THIS_MODULE;
++ bridge_device->cdev.ops = &bridge_fops;
++
++ status = cdev_add(&bridge_device->cdev, dev, 1);
++
++ if (status) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "Failed to add the bridge device \n");
++ return status;
++ }
++
++ /* udev support */
++ bridge_class = class_create(THIS_MODULE, "ti_bridge");
++
++ if (IS_ERR(bridge_class))
++ GT_0trace(driverTrace, GT_7CLASS,
++ "Error creating bridge class \n");
++
++ device_create(bridge_class, NULL, MKDEV(driver_major, driver_minor),
++ NULL, "DspBridge");
++
++ GT_init();
++ GT_create(&driverTrace, "LD");
++
++#ifdef DEBUG
++ if (GT_str)
++ GT_set(GT_str);
++#elif defined(DDSP_DEBUG_PRODUCT) && GT_TRACE
++ GT_set("**=67");
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_init\n");
++
++#ifdef CONFIG_PM
++ /* Initialize the wait queue */
++ if (!status) {
++ bridge_suspend_data.suspended = 0;
++ init_waitqueue_head(&bridge_suspend_data.suspend_wq);
++ }
++#endif
++
++ SERVICES_Init();
++
++ /* Autostart flag. This should be set to true if the DSP image should
++ * be loaded and run during bridge module initialization */
++
++ if (base_img) {
++ temp = true;
++ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
++ sizeof(temp));
++ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *)base_img,
++ strlen(base_img) + 1);
++ } else {
++ temp = false;
++ REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
++ sizeof(temp));
++ REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *) "\0", (u32)2);
++ }
++ REG_SetValue(NULL, NULL, NUMPROCS, REG_SZ, (u8 *) num_procs,
++ strlen(num_procs) + 1);
++
++ if (shm_size >= 0x10000) { /* 64 KB */
++ initStatus = REG_SetValue(NULL, NULL, SHMSIZE, REG_DWORD,
++ (u8 *)&shm_size, sizeof(shm_size));
++ } else {
++ initStatus = DSP_EINVALIDARG;
++ status = -1;
++ GT_0trace(driverTrace, GT_7CLASS,
++ "SHM size must be at least 64 KB\n");
++ }
++ GT_1trace(driverTrace, GT_7CLASS,
++ "requested shm_size = 0x%x\n", shm_size);
++
++ if (pdata->phys_mempool_base && pdata->phys_mempool_size) {
++ phys_mempool_base = pdata->phys_mempool_base;
++ phys_mempool_size = pdata->phys_mempool_size;
++ }
++
++ if (phys_mempool_base > 0x0) {
++ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLBASE,
++ REG_DWORD, (u8 *)&phys_mempool_base,
++ sizeof(phys_mempool_base));
++ }
++ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_base = 0x%x \n",
++ phys_mempool_base);
++
++ if (phys_mempool_size > 0x0) {
++ initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLSIZE,
++ REG_DWORD, (u8 *)&phys_mempool_size,
++ sizeof(phys_mempool_size));
++ }
++ GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_size = 0x%x\n",
++ phys_mempool_base);
++ if ((phys_mempool_base > 0x0) && (phys_mempool_size > 0x0))
++ MEM_ExtPhysPoolInit(phys_mempool_base, phys_mempool_size);
++ if (tc_wordswapon) {
++ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is enabled\n");
++ REG_SetValue(NULL, NULL, TCWORDSWAP, REG_DWORD,
++ (u8 *)&tc_wordswapon, sizeof(tc_wordswapon));
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is disabled\n");
++ REG_SetValue(NULL, NULL, TCWORDSWAP,
++ REG_DWORD, (u8 *)&tc_wordswapon,
++ sizeof(tc_wordswapon));
++ }
++ if (DSP_SUCCEEDED(initStatus)) {
++#ifdef CONFIG_BRIDGE_DVFS
++ for (i = 0; i < 6; i++)
++ pdata->mpu_speed[i] = vdd1_rate_table_bridge[i].rate;
++
++ clk_handle = clk_get(NULL, "iva2_ck");
++ if (!clk_handle) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_get failed to get iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_get PASS to get iva2_ck \n");
++ }
++ if (!clk_notifier_register(clk_handle, &iva_clk_notifier)) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_register PASS for iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_register FAIL for iva2_ck \n");
++ }
++#endif
++ driverContext = DSP_Init(&initStatus);
++ if (DSP_FAILED(initStatus)) {
++ status = -1;
++ GT_0trace(driverTrace, GT_7CLASS,
++ "DSP/BIOS Bridge initialization Failed\n");
++ } else {
++ GT_0trace(driverTrace, GT_5CLASS,
++ "DSP/BIOS Bridge driver loaded\n");
++ }
++ }
++
++ DBC_Assert(status == 0);
++ DBC_Assert(DSP_SUCCEEDED(initStatus));
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_init\n");
++ return status;
++}
++
++static int __devexit omap34xx_bridge_remove(struct platform_device *pdev)
++{
++ dev_t devno;
++ bool ret;
++ DSP_STATUS dsp_status = DSP_SOK;
++ HANDLE hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pTmp = NULL;
++ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
++ struct PROCESS_CONTEXT *pCtxttraverse = NULL;
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_exit\n");
++
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
++ while (pCtxtclosed != NULL) {
++ DRV_RemoveAllResources(pCtxtclosed);
++ if (pCtxtclosed->hProcessor != NULL) {
++ DRV_GetProcCtxtList(&pCtxttraverse,
++ (struct DRV_OBJECT *)hDrvObject);
++ if (pCtxttraverse->next == NULL) {
++ PROC_Detach(pCtxtclosed->hProcessor);
++ goto func_cont;
++ }
++ if ((pCtxtclosed->pid == pCtxttraverse->pid) &&
++ (pCtxttraverse->next != NULL)) {
++ pCtxttraverse = pCtxttraverse->next;
++ }
++ while ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->hProcessor
++ != pCtxttraverse->hProcessor)) {
++ pCtxttraverse = pCtxttraverse->next;
++ if ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->pid == pCtxttraverse->pid)) {
++ pCtxttraverse = pCtxttraverse->next;
++ }
++ }
++ if (pCtxttraverse == NULL)
++ PROC_Detach(pCtxtclosed->hProcessor);
++ }
++func_cont:
++ pTmp = pCtxtclosed->next;
++ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
++ pCtxtclosed, (void *)pCtxtclosed->pid);
++ pCtxtclosed = pTmp;
++ }
++
++ /* unregister the clock notifier */
++#ifdef CONFIG_BRIDGE_DVFS
++ if (!clk_notifier_unregister(clk_handle, &iva_clk_notifier)) {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_unregister PASS for iva2_ck \n");
++ } else {
++ GT_0trace(driverTrace, GT_7CLASS,
++ "clk_notifier_unregister PASS for iva2_ck \n");
++ }
++
++ clk_put(clk_handle);
++ clk_handle = NULL;
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++
++ if (driverContext) {
++ ret = DSP_Deinit(driverContext);
++ driverContext = 0;
++
++ DBC_Assert(ret == true);
++ }
++ SERVICES_Exit();
++ GT_exit();
++
++ devno = MKDEV(driver_major, driver_minor);
++ if (bridge_device) {
++ cdev_del(&bridge_device->cdev);
++ kfree(bridge_device);
++ }
++ unregister_chrdev_region(devno, 1);
++ if (bridge_class) {
++ /* remove the device from sysfs */
++ device_destroy(bridge_class, MKDEV(driver_major, driver_minor));
++ class_destroy(bridge_class);
++
++ }
++ return 0;
++}
++
++
++#ifdef CONFIG_PM
++static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ u32 status;
++ u32 command = PWR_EMERGENCYDEEPSLEEP;
++
++ status = PWR_SleepDSP(command, timeOut);
++ if (DSP_FAILED(status))
++ return -1;
++
++ bridge_suspend_data.suspended = 1;
++ return 0;
++}
++
++static int bridge_resume(struct platform_device *pdev)
++{
++ u32 status;
++
++ status = PWR_WakeDSP(timeOut);
++ if (DSP_FAILED(status))
++ return -1;
++
++ bridge_suspend_data.suspended = 0;
++ wake_up(&bridge_suspend_data.suspend_wq);
++ return 0;
++}
++#else
++#define bridge_suspend NULL
++#define bridge_resume NULL
++#endif
++
++static struct platform_driver bridge_driver = {
++ .driver = {
++ .name = BRIDGE_NAME,
++ },
++ .probe = omap34xx_bridge_probe,
++ .remove = __devexit_p(omap34xx_bridge_remove),
++ .suspend = bridge_suspend,
++ .resume = bridge_resume,
++};
++
++static int __init bridge_init(void)
++{
++ return platform_driver_register(&bridge_driver);
++}
++
++static void __exit bridge_exit(void)
++{
++ platform_driver_unregister(&bridge_driver);
++}
++
++/* This function is called when an application opens handle to the
++ * bridge driver. */
++
++static int bridge_open(struct inode *ip, struct file *filp)
++{
++ int status = 0;
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ DSP_STATUS dsp_status = DSP_SOK;
++ HANDLE hDrvObject = NULL;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++ struct PROCESS_CONTEXT *next_node = NULL;
++ struct PROCESS_CONTEXT *pCtxtclosed = NULL;
++ struct PROCESS_CONTEXT *pCtxttraverse = NULL;
++ struct task_struct *tsk = NULL;
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++
++ /* Checking weather task structure for all process existing
++ * in the process context list If not removing those processes*/
++ if (DSP_FAILED(dsp_status))
++ goto func_cont;
++
++ DRV_GetProcCtxtList(&pCtxtclosed, (struct DRV_OBJECT *)hDrvObject);
++ while (pCtxtclosed != NULL) {
++ tsk = find_task_by_vpid(pCtxtclosed->pid);
++ next_node = pCtxtclosed->next;
++
++ if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
++
++ GT_1trace(driverTrace, GT_5CLASS,
++ "***Task structure not existing for "
++ "process***%d\n", pCtxtclosed->pid);
++ DRV_RemoveAllResources(pCtxtclosed);
++ if (pCtxtclosed->hProcessor != NULL) {
++ DRV_GetProcCtxtList(&pCtxttraverse,
++ (struct DRV_OBJECT *)hDrvObject);
++ if (pCtxttraverse->next == NULL) {
++ PROC_Detach(pCtxtclosed->hProcessor);
++ } else {
++ if ((pCtxtclosed->pid ==
++ pCtxttraverse->pid) &&
++ (pCtxttraverse->next != NULL)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ }
++ while ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->hProcessor
++ != pCtxttraverse->hProcessor)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ if ((pCtxttraverse != NULL) &&
++ (pCtxtclosed->pid ==
++ pCtxttraverse->pid)) {
++ pCtxttraverse =
++ pCtxttraverse->next;
++ }
++ }
++ if (pCtxttraverse == NULL) {
++ PROC_Detach
++ (pCtxtclosed->hProcessor);
++ }
++ }
++ }
++ DRV_RemoveProcContext((struct DRV_OBJECT *)hDrvObject,
++ pCtxtclosed,
++ (void *)pCtxtclosed->pid);
++ }
++ pCtxtclosed = next_node;
++ }
++func_cont:
++ dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(dsp_status))
++ dsp_status = DRV_InsertProcContext(
++ (struct DRV_OBJECT *)hDrvObject, &pPctxt);
++
++ if (pPctxt != NULL) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ }
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
++ return status;
++}
++
++/* This function is called when an application closes handle to the bridge
++ * driver. */
++static int bridge_release(struct inode *ip, struct file *filp)
++{
++ int status;
++ u32 pid;
++
++ GT_0trace(driverTrace, GT_ENTER, "-> driver_release\n");
++
++ /* Return PID instead of process handle */
++ pid = current->pid;
++
++ status = DSP_Close(pid);
++
++
++ (status == true) ? (status = 0) : (status = -1);
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_release\n");
++
++ return status;
++}
++
++/* This function provides IO interface to the bridge driver. */
++static int bridge_ioctl(struct inode *ip, struct file *filp, unsigned int code,
++ unsigned long args)
++{
++ int status;
++ u32 retval = DSP_SOK;
++ union Trapped_Args pBufIn;
++
++ DBC_Require(filp != NULL);
++#ifdef CONFIG_PM
++ status = omap34xxbridge_suspend_lockout(&bridge_suspend_data, filp);
++ if (status != 0)
++ return status;
++#endif
++
++ GT_0trace(driverTrace, GT_ENTER, " -> driver_ioctl\n");
++
++ /* Deduct one for the CMD_BASE. */
++ code = (code - 1);
++
++ status = copy_from_user(&pBufIn, (union Trapped_Args *)args,
++ sizeof(union Trapped_Args));
++
++ if (status >= 0) {
++ status = WCD_CallDevIOCtl(code, &pBufIn, &retval);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = retval;
++ } else {
++ GT_1trace(driverTrace, GT_7CLASS,
++ "IOCTL Failed, code : 0x%x\n", code);
++ status = -1;
++ }
++
++ }
++
++ GT_0trace(driverTrace, GT_ENTER, " <- driver_ioctl\n");
++
++ return status;
++}
++
++/* This function maps kernel space memory to user space memory. */
++static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
++{
++#if GT_TRACE
++ u32 offset = vma->vm_pgoff << PAGE_SHIFT;
++#endif
++ u32 status;
++
++ DBC_Assert(vma->vm_start < vma->vm_end);
++
++ vma->vm_flags |= VM_RESERVED | VM_IO;
++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++ GT_6trace(driverTrace, GT_3CLASS,
++ "vm filp %p offset %lx start %lx end %lx"
++ " page_prot %lx flags %lx\n", filp, offset, vma->vm_start,
++ vma->vm_end, vma->vm_page_prot, vma->vm_flags);
++
++ status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot);
++ if (status != 0)
++ status = -EAGAIN;
++
++ return status;
++}
++
++#ifndef RES_CLEANUP_DISABLE
++/* To remove all process resources before removing the process from the
++ * process context list*/
++DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
++ if (pCtxt != NULL) {
++ DRV_RemoveAllSTRMResElements(pCtxt);
++ DRV_RemoveAllNodeResElements(pCtxt);
++ DRV_RemoveAllDMMResElements(pCtxt);
++ DRV_ProcUpdatestate(pCtxt, PROC_RES_FREED);
++ }
++ return status;
++}
++#endif
++
++/* Bridge driver initialization and de-initialization functions */
++module_init(bridge_init);
++module_exit(bridge_exit);
++
+diff --git a/drivers/dsp/bridge/rmgr/drv_interface.h b/drivers/dsp/bridge/rmgr/drv_interface.h
+new file mode 100644
+index 0000000..f5b068e
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/drv_interface.h
+@@ -0,0 +1,40 @@
++/*
++ * drv_interface.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== drv_interface.h ========
++ *
++ *! Revision History
++ *! ================
++ *! 24-Mar-2003 vp Added hooks for Power Management Test
++ *! 18-Feb-2003 vp Code review updates
++ *! 18-Oct-2002 sb Created initial version
++
++ */
++
++#ifndef _DRV_INTERFACE_H_
++#define _DRV_INTERFACE_H_
++
++/* Prototypes for all functions in this bridge */
++static int __init bridge_init(void); /* Initialize bridge */
++static void __exit bridge_exit(void); /* Opposite of initialize */
++static int bridge_open(struct inode *, struct file *); /* Open */
++static int bridge_release(struct inode *, struct file *); /* Release */
++static int bridge_ioctl(struct inode *, struct file *, unsigned int,
++ unsigned long);
++static int bridge_mmap(struct file *filp, struct vm_area_struct *vma);
++#endif /* ifndef _DRV_INTERFACE_H_ */
+diff --git a/drivers/dsp/bridge/rmgr/dspdrv.c b/drivers/dsp/bridge/rmgr/dspdrv.c
+new file mode 100644
+index 0000000..a7a74fc
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/dspdrv.c
+@@ -0,0 +1,276 @@
++/*
++ * dspdrv.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dspdrv.c ========
++ * Description:
++ * Interface to allocate and free bridge resources.
++ *
++ *! Revision History
++ *! ================
++ *! 12-Apr-2004 hp: Compile IVA only for 24xx.
++ *! 09-Feb-2004 vp: Updated to support IVA.
++ *! 10-Feb-2003 vp: Code review updates.
++ *! 18-oct-2002 vp: Ported to the Linux platform.
++ *! 03-Mar-2002 rr: DSP_Deinit bug fixed (gets the Mgrhandle from registry
++ *! before calling MGR_Destroy.
++ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
++ *! 02-Apr-2001 rr: WCD_InitComplete2 return value is not checked thus
++ *! sllowing the class driver to load irrespective of
++ *! the image load.
++ *! 30-Oct-2000 kc: Made changes w.r.t. usage of REG_SetValue.
++ *! 05-Oct-2000 rr: WCD_InitComplete2 return value checked for RM.
++ *! Failure in WCD_InitComplete2 will cause the
++ *! DSP_Init to fail.
++ *! 12-Aug-2000 kc: Changed REG_EnumValue to REG_EnumKey.
++ *! 07-Aug-2000 rr: MGR_Create does the job of loading the DCD Dll.
++ *! 26-Jul-2000 rr: Driver Object holds the DevNodeStrings for each
++ *! DevObjects. Static variables removed. Returns
++ *! the Driver Object in DSP_Init.
++ *! 17-Jul-2000 rr: Driver Object is created in DSP_Init and that holds
++ *! the list of Device objects.
++ *! 07-Jul-2000 rr: RM implementaion started.
++ *! 24-May-2000 ag: Cleaned up debug msgs.
++ *! 02-May-2000 rr: DSP_Open returns GetCallerProcess as dwOpenContext.
++ *! 03-Feb-2000 rr: GT Changes.
++ *! 28-Jan-2000 rr: Code Cleaned up.Type void changed to void.
++ *! DSP_Deinit checks return values.dwCode in
++ *! DSP_IO_CONTROL is decoded(not hard coded)
++ *! 27-Jan-2000 rr: REG_EnumValue Used .EnumerateKey fxn removed.
++ *! 13-Jan-2000 rr: CFG_GetPrivateDword renamed to CFG_GetDevObject.
++ *! 29-Dec-1999 rr: Code Cleaned up
++ *! 09-Dec-1999 rr: EnumerateKey changed for retail build.
++ *! 06-Dec-1999 rr: ArrayofInstalledNode, index and ArrayofInstalledDev
++ *! is Global.DevObject stores this pointer as hDevNode.
++ *! 02-Dec-1999 rr: DBG_SetGT and RetailMSG conditionally included.
++ *! Comments changed.Deinit handled.Code cleaned up.
++ *! DSP_IOControl, Close, Deinit returns bool values.
++ *! Calls WCD_InitComplete2 for Board AutoStart.
++ *! 29-Nov-1999 rr: DSP_IOControl returns the result through pBufOut.
++ *! Global Arrays keeps track of installed devices.
++ *! 19-Nov-1999 rr: DSP_Init handles multiple drivers.
++ *! 12-Nov-1999 rr: GetDriverKey and EnumerateKey functions added.
++ *! for multiple mini driver support.PCCARD flag
++ *! checking to include PCMCIA related stuff.
++ *! 25-Oct-1999 rr: GT_Init is called within the Process Attach.
++ *! return value initalized to S_OK upfront in the
++ *! Process Attach.
++ *! 15-Oct-1999 rr: DSP_DeInit handles the return values
++ *! 05-Oct-1999 rr: All the PCMCIA related functions are now in PCCARD.c
++ *! DRV_Request Resources is used instead of the
++ *! RegisterMiniDriver as it sounds close to what we are doing.
++ *! 24-Sep-1999 rr: DRV_RegisterMiniDriver is being called from here. Only
++ *! neccessaryPCMCIA fxns are here. Soon they will move out
++ *! either to a seperate file for bus specific inits.
++ *! 10-Sep-1999 rr: GT Enabled. Considerably changed the driver structure as
++ *! - This is the Class driver. After successfully initialized
++ *! the Class driver will attempt to load the Mini driver.
++ *! - Need to seperate the PCMCIA stuff based on bus type.
++ *! - Changed the name of the file to wcdce.c
++ *! - Made the Media Handle as Global again
++ *!
++ *! 19-Aug-1999 rr: Removed the Global hbhMediaHandle. Included the MemTest.
++ *! Modified the DSP_Init, now three windows are opened.
++ *! Split the driver into PDD so that hardware dependent
++ *! functions will reside in PDD.
++ *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet card driver.
++ *!
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/_dcd.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dspdrv.h>
++
++/* ----------------------------------- Globals */
++struct GT_Mask curTrace;
++
++/*
++ * ======== DSP_Init ========
++ * Allocates bridge resources. Loads a base image onto DSP, if specified.
++ */
++u32 DSP_Init(OUT u32 *initStatus)
++{
++ char devNode[MAXREGPATHLENGTH] = "TIOMAP1510";
++ DSP_STATUS status = DSP_EFAIL;
++ struct DRV_OBJECT *drvObject = NULL;
++ u32 index = 0;
++ u32 deviceNode;
++ u32 deviceNodeString;
++
++ GT_create(&curTrace, "DD");
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Init \r\n");
++
++ if (DSP_FAILED(WCD_Init())) {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed \n");
++ goto func_cont;
++ } /* End WCD_Exit */
++ if (DSP_FAILED(DRV_Create(&drvObject))) {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_Create Failed \n");
++ WCD_Exit();
++ goto func_cont;
++ } /* End DRV_Create */
++ GT_0trace(curTrace, GT_5CLASS, "DSP_Init:DRV Created \r\n");
++
++ /* Request Resources */
++ if (DSP_SUCCEEDED(DRV_RequestResources((u32)&devNode,
++ &deviceNodeString))) {
++ /* Attempt to Start the Device */
++ if (DSP_SUCCEEDED(DEV_StartDevice(
++ (struct CFG_DEVNODE *)deviceNodeString))) {
++ /* Retreive the DevObject from the Registry */
++ GT_2trace(curTrace, GT_1CLASS,
++ "DSP_Init Succeeded for Device1:"
++ "%d: value: %x\n", index, deviceNodeString);
++ status = DSP_SOK;
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:DEV_StartDevice Failed\n");
++ (void)DRV_ReleaseResources
++ ((u32) deviceNodeString, drvObject);
++ status = DSP_EFAIL;
++ }
++ } else {
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:DRV_RequestResources Failed \r\n");
++ status = DSP_EFAIL;
++ } /* DRV_RequestResources */
++ index++;
++
++ /* Unwind whatever was loaded */
++ if (DSP_FAILED(status)) {
++ /* irrespective of the status of DEV_RemoveDevice we conitinue
++ * unloading. Get the Driver Object iterate through and remove.
++ * Reset the status to E_FAIL to avoid going through
++ * WCD_InitComplete2. */
++ status = DSP_EFAIL;
++ for (deviceNode = DRV_GetFirstDevExtension(); deviceNode != 0;
++ deviceNode = DRV_GetNextDevExtension(deviceNode)) {
++ (void)DEV_RemoveDevice
++ ((struct CFG_DEVNODE *)deviceNode);
++ (void)DRV_ReleaseResources((u32)deviceNode,
++ drvObject);
++ }
++ /* Remove the Driver Object */
++ (void)DRV_Destroy(drvObject);
++ drvObject = NULL;
++ WCD_Exit();
++ GT_0trace(curTrace, GT_7CLASS,
++ "DSP_Init:Logical device Failed to Load\n");
++ } /* Unwinding the loaded drivers */
++func_cont:
++ /* Attempt to Start the Board */
++ if (DSP_SUCCEEDED(status)) {
++ /* BRD_AutoStart could fail if the dsp execuetable is not the
++ * correct one. We should not propagate that error
++ * into the device loader. */
++ (void)WCD_InitComplete2();
++ GT_0trace(curTrace, GT_1CLASS, "DSP_Init Succeeded\n");
++ } else {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed\n");
++ } /* End WCD_InitComplete2 */
++ DBC_Ensure((DSP_SUCCEEDED(status) && drvObject != NULL) ||
++ (DSP_FAILED(status) && drvObject == NULL));
++ *initStatus = status;
++ /* Return the Driver Object */
++ return (u32)drvObject;
++}
++
++/*
++ * ======== DSP_Deinit ========
++ * Frees the resources allocated for bridge.
++ */
++bool DSP_Deinit(u32 deviceContext)
++{
++ bool retVal = true;
++ u32 deviceNode;
++ struct MGR_OBJECT *mgrObject = NULL;
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Deinit \r\n");
++
++ while ((deviceNode = DRV_GetFirstDevExtension()) != 0) {
++ (void)DEV_RemoveDevice((struct CFG_DEVNODE *)deviceNode);
++
++ (void)DRV_ReleaseResources((u32)deviceNode,
++ (struct DRV_OBJECT *)deviceContext);
++ }
++
++ (void) DRV_Destroy((struct DRV_OBJECT *) deviceContext);
++
++ /* Get the Manager Object from Registry
++ * MGR Destroy will unload the DCD dll */
++ if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&mgrObject, REG_MGR_OBJECT)))
++ (void)MGR_Destroy(mgrObject);
++
++ WCD_Exit();
++
++ return retVal;
++}
++
++/*
++ * ======== DSP_Close ========
++ * The Calling Process handle is passed to DEV_CleanupProcesState
++ * for cleaning up of any resources used by the application
++ */
++bool DSP_Close(u32 dwOpenContext)
++{
++ bool retVal = false;
++
++ DBC_Require(dwOpenContext != 0);
++
++ GT_0trace(curTrace, GT_ENTER, "Entering DSP_Close\n");
++
++#ifdef RES_CLEANUP_DISABLE
++
++ if (DSP_SUCCEEDED(DEV_CleanupProcessState((HANDLE) dwOpenContext))) {
++ GT_0trace(curTrace, GT_1CLASS, "DSP_Close Succeeded \r\n");
++ retVal = true;
++ } else {
++ GT_0trace(curTrace, GT_7CLASS, "DSP_Close failed \r\n");
++ }
++#endif
++
++ return retVal;
++}
+diff --git a/drivers/dsp/bridge/rmgr/mgr.c b/drivers/dsp/bridge/rmgr/mgr.c
+new file mode 100644
+index 0000000..943cf93
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/mgr.c
+@@ -0,0 +1,491 @@
++/*
++ * mgr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mgr.c ========
++ * Description:
++ * Implementation of Manager interface to the device object at the
++ * driver level. This queries the NDB data base and retrieves the
++ * data about Node and Processor.
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 12-Feb-2003 vp: Code review updates.
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 01-Aug-2001 ag: Added extended info for DSP-MMU setup support.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 22-Nov-2000 kc: Added MGR_GetPerfData.
++ *! 03-Nov-2000 rr: Updated after code review.
++ *! 25-Sep-2000 rr: Updated to Version 0.9
++ *! 10-Aug-2000 rr: dwSignature is not specifically inserted in MGR Obj
++ *! as it is taken care by MEM_AllocObject. stdwin.h added
++ *! for retail build to succeed.
++ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
++ *! 26-Jul-2000 rr: MGR_Destroy releases the hNDBDll.
++ *! 20-Jun-2000 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/mgr.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define ZLDLLNAME ""
++#define SIGNATURE 0x5f52474d /* "MGR_" (in reverse) */
++
++struct MGR_OBJECT {
++ u32 dwSignature;
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MGR_DebugMask = { NULL, NULL };
++#endif
++
++static u32 cRefs;
++
++/*
++ * ========= MGR_Create =========
++ * Purpose:
++ * MGR Object gets created only once during driver Loading.
++ */
++DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **phMgrObject,
++ struct CFG_DEVNODE *hDevNode)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct MGR_OBJECT *pMgrObject = NULL;
++
++ DBC_Require(phMgrObject != NULL);
++ DBC_Require(cRefs > 0);
++ GT_1trace(MGR_DebugMask, GT_ENTER,
++ "Entering MGR_Create phMgrObject 0x%x\n ",
++ phMgrObject);
++ MEM_AllocObject(pMgrObject, struct MGR_OBJECT, SIGNATURE);
++ if (pMgrObject) {
++ if (DSP_SUCCEEDED(DCD_CreateManager(ZLDLLNAME,
++ &pMgrObject->hDcdMgr))) {
++ /* If succeeded store the handle in the MGR Object */
++ if (DSP_SUCCEEDED(CFG_SetObject((u32)pMgrObject,
++ REG_MGR_OBJECT))) {
++ *phMgrObject = pMgrObject;
++ GT_0trace(MGR_DebugMask, GT_1CLASS,
++ "MGR_Create:MGR Created\r\n");
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create:CFG_SetObject "
++ "Failed\r\n");
++ DCD_DestroyManager(pMgrObject->hDcdMgr);
++ MEM_FreeObject(pMgrObject);
++ }
++ } else {
++ /* failed to Create DCD Manager */
++ status = DSP_EFAIL;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create:DCD_ManagerCreate Failed\r\n");
++ MEM_FreeObject(pMgrObject);
++ }
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "MGR_Create DSP_FAILED to allocate memory \n");
++ }
++ GT_2trace(MGR_DebugMask, GT_ENTER,
++ "Exiting MGR_Create: phMgrObject: 0x%x\t"
++ "status: 0x%x\n", phMgrObject, status);
++ DBC_Ensure(DSP_FAILED(status) ||
++ MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ return status;
++}
++
++/*
++ * ========= MGR_Destroy =========
++ * This function is invoked during bridge driver unloading.Frees MGR object.
++ */
++DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMgrObject;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hMgrObject, SIGNATURE));
++
++ GT_1trace(MGR_DebugMask, GT_ENTER,
++ "Entering MGR_Destroy hMgrObject 0x%x\n", hMgrObject);
++ /* Free resources */
++ if (hMgrObject->hDcdMgr)
++ DCD_DestroyManager(hMgrObject->hDcdMgr);
++
++ MEM_FreeObject(pMgrObject);
++ /* Update the Registry with NULL for MGR Object */
++ (void)CFG_SetObject(0, REG_MGR_OBJECT);
++
++ GT_2trace(MGR_DebugMask, GT_ENTER,
++ "Exiting MGR_Destroy: hMgrObject: 0x%x\t"
++ "status: 0x%x\n", hMgrObject, status);
++
++ DBC_Ensure(DSP_FAILED(status) ||
++ !MEM_IsValidHandle(hMgrObject, SIGNATURE));
++
++ return status;
++}
++
++/*
++ * ======== MGR_EnumNodeInfo ========
++ * Enumerate and get configuration information about nodes configured
++ * in the node database.
++ */
++DSP_STATUS MGR_EnumNodeInfo(u32 uNode, OUT struct DSP_NDBPROPS *pNDBProps,
++ u32 uNDBPropsSize, OUT u32 *puNumNodes)
++{
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ struct DSP_UUID Uuid, uTempUuid;
++ u32 uTempIndex = 0;
++ u32 uNodeIndex = 0;
++ struct DCD_GENERICOBJ GenObj;
++ struct MGR_OBJECT *pMgrObject = NULL;
++
++ DBC_Require(pNDBProps != NULL);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(uNDBPropsSize >= sizeof(struct DSP_NDBPROPS));
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(MGR_DebugMask, GT_ENTER, "Entered Manager_EnumNodeInfo, "
++ "args:\n\t uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
++ "0x%x\tpuNumNodes: 0x%x\n", uNode, pNDBProps,
++ uNDBPropsSize, puNumNodes);
++ *puNumNodes = 0;
++ /* Get The Manager Object from the Registry */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo:Failed To Get"
++ " MGR Object from Registry\r\n");
++ goto func_cont;
++ }
++ DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ /* Forever loop till we hit failed or no more items in the
++ * Enumeration. We will exit the loop other than DSP_SOK; */
++ while (status == DSP_SOK) {
++ status = DCD_EnumerateObject(uTempIndex++, DSP_DCDNODETYPE,
++ &uTempUuid);
++ if (status == DSP_SOK) {
++ uNodeIndex++;
++ if (uNode == (uNodeIndex - 1))
++ Uuid = uTempUuid;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (uNode > (uNodeIndex - 1)) {
++ status = DSP_EINVALIDARG;
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo: uNode"
++ " is Invalid \r\n");
++ } else {
++ status1 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
++ (struct DSP_UUID *)&Uuid,
++ DSP_DCDNODETYPE, &GenObj);
++ if (DSP_SUCCEEDED(status1)) {
++ /* Get the Obj def */
++ *pNDBProps = GenObj.objData.nodeObj.ndbProps;
++ *puNumNodes = uNodeIndex;
++ status = DSP_SOK;
++ } else {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumNodeInfo: "
++ "Failed to Get Node Info \r\n");
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ /* This could be changed during enum, EFAIL ... */
++ GT_0trace(MGR_DebugMask, GT_7CLASS, "Manager_EnumNodeInfo: "
++ "Enumeration failure\r\n");
++ status = DSP_EFAIL;
++ }
++func_cont:
++ GT_4trace(MGR_DebugMask, GT_ENTER,
++ "Exiting Manager_EnumNodeInfo, args:\n\t"
++ "uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
++ " 0x%x\tuNumNodes: 0x%x\n", uNode, pNDBProps,
++ uNDBPropsSize, *puNumNodes);
++ DBC_Ensure((DSP_SUCCEEDED(status) && *puNumNodes > 0) ||
++ (DSP_FAILED(status) && *puNumNodes == 0));
++
++ return status;
++}
++
++/*
++ * ======== MGR_EnumProcessorInfo ========
++ * Enumerate and get configuration information about available
++ * DSP processors.
++ */
++DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
++ OUT struct DSP_PROCESSORINFO *pProcessorInfo,
++ u32 uProcessorInfoSize, OUT u32 *puNumProcs)
++{
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ DSP_STATUS status2 = DSP_SOK;
++ struct DSP_UUID uTempUuid;
++ u32 uTempIndex = 0;
++ u32 uProcIndex = 0;
++ struct DCD_GENERICOBJ GenObj;
++ struct MGR_OBJECT *pMgrObject = NULL;
++ struct MGR_PROCESSOREXTINFO *pExtInfo;
++ struct DEV_OBJECT *hDevObject;
++ struct DRV_OBJECT *hDrvObject;
++ s32 devType;
++ struct CFG_DEVNODE *devNode;
++ struct CFG_DSPRES chipResources;
++ bool procDetect = false;
++
++ DBC_Require(pProcessorInfo != NULL);
++ DBC_Require(puNumProcs != NULL);
++ DBC_Require(uProcessorInfoSize >= sizeof(struct DSP_PROCESSORINFO));
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(MGR_DebugMask, GT_ENTER,
++ "Entered Manager_EnumProcessorInfo, "
++ "args:\n\tuProcessor: 0x%x\n\tpProcessorInfo: 0x%x\n\t"
++ "uProcessorInfoSize: 0x%x\tpuNumProcs: 0x%x\n", uProcessor,
++ pProcessorInfo, uProcessorInfoSize, puNumProcs);
++ *puNumProcs = 0;
++ status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(status)) {
++ status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDevType(hDevObject, (u32 *) &devType);
++ status = DEV_GetDevNode(hDevObject, &devNode);
++ if (devType == DSP_UNIT) {
++ status = CFG_GetDSPResources(devNode,
++ &chipResources);
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Unsupported dev type gotten"
++ "from device object %d\n", devType);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pProcessorInfo->uProcessorType =
++ chipResources.uChipType;
++ }
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Get The Manager Object from the Registry */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: "
++ "Failed To Get MGR Object from Registry\r\n");
++ goto func_end;
++ }
++ DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
++ /* Forever loop till we hit no more items in the
++ * Enumeration. We will exit the loop other than DSP_SOK; */
++ while (status1 == DSP_SOK) {
++ status1 = DCD_EnumerateObject(uTempIndex++,
++ DSP_DCDPROCESSORTYPE,
++ &uTempUuid);
++ if (status1 != DSP_SOK)
++ break;
++
++ uProcIndex++;
++ /* Get the Object properties to find the Device/Processor
++ * Type */
++ if (procDetect != false)
++ continue;
++
++ status2 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
++ (struct DSP_UUID *)&uTempUuid,
++ DSP_DCDPROCESSORTYPE,
++ &GenObj);
++ if (DSP_SUCCEEDED(status2)) {
++ /* Get the Obj def */
++ if (uProcessorInfoSize <
++ sizeof(struct MGR_PROCESSOREXTINFO)) {
++ *pProcessorInfo = GenObj.objData.procObj;
++ } else {
++ /* extended info */
++ pExtInfo = (struct MGR_PROCESSOREXTINFO *)
++ pProcessorInfo;
++ *pExtInfo = GenObj.objData.extProcObj;
++ }
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: Got"
++ " Proctype from DCD %x \r\n",
++ pProcessorInfo->uProcessorType);
++ /* See if we got the needed processor */
++ if (devType == DSP_UNIT) {
++ if (pProcessorInfo->uProcessorType ==
++ DSPPROCTYPE_C64)
++ procDetect = true;
++ } else if (devType == IVA_UNIT) {
++ if (pProcessorInfo->uProcessorType ==
++ IVAPROCTYPE_ARM7)
++ procDetect = true;
++ }
++ /* User applciatiuons aonly check for chip type, so
++ * this clumsy overwrite */
++ pProcessorInfo->uProcessorType =
++ chipResources.uChipType;
++ } else {
++ GT_1trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: "
++ "Failed to Get DCD Processor Info %x \r\n",
++ status2);
++ status = DSP_EFAIL;
++ }
++ }
++ *puNumProcs = uProcIndex;
++ if (procDetect == false) {
++ GT_0trace(MGR_DebugMask, GT_7CLASS,
++ "Manager_EnumProcessorInfo: Failed"
++ " to get Proc info from DCD , so use CFG registry\n");
++ pProcessorInfo->uProcessorType = chipResources.uChipType;
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== MGR_Exit ========
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void MGR_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++ cRefs--;
++ if (cRefs == 0)
++ DCD_Exit();
++
++ GT_1trace(MGR_DebugMask, GT_5CLASS,
++ "Entered MGR_Exit, ref count: 0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MGR_GetDCDHandle ========
++ * Retrieves the MGR handle. Accessor Function.
++ */
++DSP_STATUS MGR_GetDCDHandle(struct MGR_OBJECT *hMGRHandle,
++ OUT u32 *phDCDHandle)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMGRHandle;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDCDHandle != NULL);
++
++ *phDCDHandle = (u32)NULL;
++ if (MEM_IsValidHandle(pMgrObject, SIGNATURE)) {
++ *phDCDHandle = (u32) pMgrObject->hDcdMgr;
++ status = DSP_SOK;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && *phDCDHandle != (u32)NULL) ||
++ (DSP_FAILED(status) && *phDCDHandle == (u32)NULL));
++
++ return status;
++}
++
++/*
++ * ======== MGR_Init ========
++ * Initialize MGR's private state, keeping a reference count on each call.
++ */
++bool MGR_Init(void)
++{
++ bool fRetval = true;
++ bool fInitDCD = false;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++
++ /* Set the Trace mask */
++ DBC_Assert(!MGR_DebugMask.flags);
++
++ GT_create(&MGR_DebugMask, "MG"); /* "MG" for Manager */
++ fInitDCD = DCD_Init(); /* DCD Module */
++
++ if (!fInitDCD) {
++ fRetval = false;
++ GT_0trace(MGR_DebugMask, GT_6CLASS,
++ "MGR_Init failed\n");
++ }
++ }
++
++ if (fRetval)
++ cRefs++;
++
++
++ GT_1trace(MGR_DebugMask, GT_5CLASS,
++ "Entered MGR_Init, ref count: 0x%x\n", cRefs);
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== MGR_WaitForBridgeEvents ========
++ * Block on any Bridge event(s)
++ */
++DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION **aNotifications,
++ u32 uCount, OUT u32 *puIndex, u32 uTimeout)
++{
++ DSP_STATUS status;
++ struct SYNC_OBJECT *hSyncEvents[MAX_EVENTS];
++ u32 i;
++
++ DBC_Require(uCount < MAX_EVENTS);
++
++ for (i = 0; i < uCount; i++)
++ hSyncEvents[i] = aNotifications[i]->handle;
++
++ status = SYNC_WaitOnMultipleEvents(hSyncEvents, uCount, uTimeout,
++ puIndex);
++
++ return status;
++
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/nldr.c b/drivers/dsp/bridge/rmgr/nldr.c
+new file mode 100644
+index 0000000..f3c429c
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/nldr.c
+@@ -0,0 +1,1967 @@
++/*
++ * nldr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== nldr.c ========
++ * Description:
++ * DSP/BIOS Bridge dynamic + overlay Node loader.
++ *
++ * Public Functions:
++ * NLDR_Allocate
++ * NLDR_Create
++ * NLDR_Delete
++ * NLDR_Exit
++ * NLDR_Free
++ * NLDR_GetFxnAddr
++ * NLDR_Init
++ * NLDR_Load
++ * NLDR_Unload
++ *
++ * Notes:
++ *
++ *! Revision History
++ *! ================
++ *! 07-Apr-2003 map Removed references to dead DLDR module
++ *! 23-Jan-2003 map Updated RemoteAlloc to support memory granularity
++ *! 20-Jan-2003 map Updated to maintain persistent dependent libraries
++ *! 15-Jan-2003 map Adapted for use with multiple dynamic phase libraries
++ *! 19-Dec-2002 map Fixed overlay bug in AddOvlySect for overlay
++ *! sections > 1024 bytes.
++ *! 13-Dec-2002 map Fixed NLDR_GetFxnAddr bug by searching dependent
++ *! libs for symbols
++ *! 27-Sep-2002 map Added RemoteFree to convert size to words for
++ *! correct deallocation
++ *! 16-Sep-2002 map Code Review Cleanup(from dldr.c)
++ *! 29-Aug-2002 map Adjusted for ARM-side overlay copy
++ *! 05-Aug-2002 jeh Created.
++ */
++
++#include <dspbridge/host_os.h>
++
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++#ifdef DEBUG
++#include <dspbridge/dbg.h>
++#endif
++
++/* OS adaptation layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* Platform manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++
++/* Resource manager */
++#include <dspbridge/dbll.h>
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/rmm.h>
++#include <dspbridge/uuidutil.h>
++
++#include <dspbridge/nldr.h>
++
++#define NLDR_SIGNATURE 0x52444c4e /* "RDLN" */
++#define NLDR_NODESIGNATURE 0x4e444c4e /* "NDLN" */
++
++/* Name of section containing dynamic load mem */
++#define DYNMEMSECT ".dspbridge_mem"
++
++/* Name of section containing dependent library information */
++#define DEPLIBSECT ".dspbridge_deplibs"
++
++/* Max depth of recursion for loading node's dependent libraries */
++#define MAXDEPTH 5
++
++/* Max number of persistent libraries kept by a node */
++#define MAXLIBS 5
++
++/*
++ * Defines for extracting packed dynamic load memory requirements from two
++ * masks.
++ * These defines must match node.cdb and dynm.cdb
++ * Format of data/code mask is:
++ * uuuuuuuu|fueeeeee|fudddddd|fucccccc|
++ * where
++ * u = unused
++ * cccccc = prefered/required dynamic mem segid for create phase data/code
++ * dddddd = prefered/required dynamic mem segid for delete phase data/code
++ * eeeeee = prefered/req. dynamic mem segid for execute phase data/code
++ * f = flag indicating if memory is preferred or required:
++ * f = 1 if required, f = 0 if preferred.
++ *
++ * The 6 bits of the segid are interpreted as follows:
++ *
++ * If the 6th bit (bit 5) is not set, then this specifies a memory segment
++ * between 0 and 31 (a maximum of 32 dynamic loading memory segments).
++ * If the 6th bit (bit 5) is set, segid has the following interpretation:
++ * segid = 32 - Any internal memory segment can be used.
++ * segid = 33 - Any external memory segment can be used.
++ * segid = 63 - Any memory segment can be used (in this case the
++ * required/preferred flag is irrelevant).
++ *
++ */
++/* Maximum allowed dynamic loading memory segments */
++#define MAXMEMSEGS 32
++
++#define MAXSEGID 3 /* Largest possible (real) segid */
++#define MEMINTERNALID 32 /* Segid meaning use internal mem */
++#define MEMEXTERNALID 33 /* Segid meaning use external mem */
++#define NULLID 63 /* Segid meaning no memory req/pref */
++#define FLAGBIT 7 /* 7th bit is pref./req. flag */
++#define SEGMASK 0x3f /* Bits 0 - 5 */
++
++#define CREATEBIT 0 /* Create segid starts at bit 0 */
++#define DELETEBIT 8 /* Delete segid starts at bit 8 */
++#define EXECUTEBIT 16 /* Execute segid starts at bit 16 */
++
++/*
++ * Masks that define memory type. Must match defines in dynm.cdb.
++ */
++#define DYNM_CODE 0x2
++#define DYNM_DATA 0x4
++#define DYNM_CODEDATA (DYNM_CODE | DYNM_DATA)
++#define DYNM_INTERNAL 0x8
++#define DYNM_EXTERNAL 0x10
++
++/*
++ * Defines for packing memory requirement/preference flags for code and
++ * data of each of the node's phases into one mask.
++ * The bit is set if the segid is required for loading code/data of the
++ * given phase. The bit is not set, if the segid is preferred only.
++ *
++ * These defines are also used as indeces into a segid array for the node.
++ * eg node's segid[CREATEDATAFLAGBIT] is the memory segment id that the
++ * create phase data is required or preferred to be loaded into.
++ */
++#define CREATEDATAFLAGBIT 0
++#define CREATECODEFLAGBIT 1
++#define EXECUTEDATAFLAGBIT 2
++#define EXECUTECODEFLAGBIT 3
++#define DELETEDATAFLAGBIT 4
++#define DELETECODEFLAGBIT 5
++#define MAXFLAGS 6
++
++#define IsInternal(hNldr, segid) (((segid) <= MAXSEGID && \
++ hNldr->segTable[(segid)] & DYNM_INTERNAL) || \
++ (segid) == MEMINTERNALID)
++
++#define IsExternal(hNldr, segid) (((segid) <= MAXSEGID && \
++ hNldr->segTable[(segid)] & DYNM_EXTERNAL) || \
++ (segid) == MEMEXTERNALID)
++
++#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
++ (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
++
++#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
++
++ /*
++ * These names may be embedded in overlay sections to identify which
++ * node phase the section should be overlayed.
++ */
++#define PCREATE "create"
++#define PDELETE "delete"
++#define PEXECUTE "execute"
++
++#define IsEqualUUID(uuid1, uuid2) (\
++ ((uuid1).ulData1 == (uuid2).ulData1) && \
++ ((uuid1).usData2 == (uuid2).usData2) && \
++ ((uuid1).usData3 == (uuid2).usData3) && \
++ ((uuid1).ucData4 == (uuid2).ucData4) && \
++ ((uuid1).ucData5 == (uuid2).ucData5) && \
++ (strncmp((void *)(uuid1).ucData6, (void *)(uuid2).ucData6, 6)) == 0)
++
++ /*
++ * ======== MemInfo ========
++ * Format of dynamic loading memory segment info in coff file.
++ * Must match dynm.h55.
++ */
++struct MemInfo {
++ u32 segid; /* Dynamic loading memory segment number */
++ u32 base;
++ u32 len;
++ u32 type; /* Mask of DYNM_CODE, DYNM_INTERNAL, etc. */
++};
++
++/*
++ * ======== LibNode ========
++ * For maintaining a tree of library dependencies.
++ */
++struct LibNode {
++ struct DBLL_LibraryObj *lib; /* The library */
++ u16 nDepLibs; /* Number of dependent libraries */
++ struct LibNode *pDepLibs; /* Dependent libraries of lib */
++};
++
++/*
++ * ======== OvlySect ========
++ * Information needed to overlay a section.
++ */
++struct OvlySect {
++ struct OvlySect *pNextSect;
++ u32 loadAddr; /* Load address of section */
++ u32 runAddr; /* Run address of section */
++ u32 size; /* Size of section */
++ u16 page; /* DBL_CODE, DBL_DATA */
++};
++
++/*
++ * ======== OvlyNode ========
++ * For maintaining a list of overlay nodes, with sections that need to be
++ * overlayed for each of the nodes phases.
++ */
++struct OvlyNode {
++ struct DSP_UUID uuid;
++ char *pNodeName;
++ struct OvlySect *pCreateSects;
++ struct OvlySect *pDeleteSects;
++ struct OvlySect *pExecuteSects;
++ struct OvlySect *pOtherSects;
++ u16 nCreateSects;
++ u16 nDeleteSects;
++ u16 nExecuteSects;
++ u16 nOtherSects;
++ u16 createRef;
++ u16 deleteRef;
++ u16 executeRef;
++ u16 otherRef;
++};
++
++/*
++ * ======== NLDR_OBJECT ========
++ * Overlay loader object.
++ */
++struct NLDR_OBJECT {
++ u32 dwSignature; /* For object validation */
++ struct DEV_OBJECT *hDevObject; /* Device object */
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++ struct DBLL_TarObj *dbll; /* The DBL loader */
++ struct DBLL_LibraryObj *baseLib; /* Base image library */
++ struct RMM_TargetObj *rmm; /* Remote memory manager for DSP */
++ struct DBLL_Fxns dbllFxns; /* Loader function table */
++ struct DBLL_Attrs dbllAttrs; /* attrs to pass to loader functions */
++ NLDR_OVLYFXN ovlyFxn; /* "write" for overlay nodes */
++ NLDR_WRITEFXN writeFxn; /* "write" for dynamic nodes */
++ struct OvlyNode *ovlyTable; /* Table of overlay nodes */
++ u16 nOvlyNodes; /* Number of overlay nodes in base */
++ u16 nNode; /* Index for tracking overlay nodes */
++ u16 nSegs; /* Number of dynamic load mem segs */
++ u32 *segTable; /* memtypes of dynamic memory segs
++ * indexed by segid
++ */
++ u16 usDSPMauSize; /* Size of DSP MAU */
++ u16 usDSPWordSize; /* Size of DSP word */
++};
++
++/*
++ * ======== NLDR_NODEOBJECT ========
++ * Dynamic node object. This object is created when a node is allocated.
++ */
++struct NLDR_NODEOBJECT {
++ u32 dwSignature; /* For object validation */
++ struct NLDR_OBJECT *pNldr; /* Dynamic loader handle */
++ void *pPrivRef; /* Handle to pass to DBL_WriteFxn */
++ struct DSP_UUID uuid; /* Node's UUID */
++ bool fDynamic; /* Dynamically loaded node? */
++ bool fOverlay; /* Overlay node? */
++ bool *pfPhaseSplit; /* Multiple phase libraries? */
++ struct LibNode root; /* Library containing node phase */
++ struct LibNode createLib; /* Library containing create phase lib */
++ struct LibNode executeLib; /* Library containing execute phase lib */
++ struct LibNode deleteLib; /* Library containing delete phase lib */
++ struct LibNode persLib[MAXLIBS]; /* libs remain loaded until Delete */
++ s32 nPersLib; /* Number of persistent libraries */
++ /* Path in lib dependency tree */
++ struct DBLL_LibraryObj *libPath[MAXDEPTH + 1];
++ enum NLDR_PHASE phase; /* Node phase currently being loaded */
++
++ /*
++ * Dynamic loading memory segments for data and code of each phase.
++ */
++ u16 segId[MAXFLAGS];
++
++ /*
++ * Mask indicating whether each mem segment specified in segId[]
++ * is preferred or required.
++ * For example if (codeDataFlagMask & (1 << EXECUTEDATAFLAGBIT)) != 0,
++ * then it is required to load execute phase data into the memory
++ * specified by segId[EXECUTEDATAFLAGBIT].
++ */
++ u32 codeDataFlagMask;
++};
++
++/* Dynamic loader function table */
++static struct DBLL_Fxns dbllFxns = {
++ (DBLL_CloseFxn) DBLL_close,
++ (DBLL_CreateFxn) DBLL_create,
++ (DBLL_DeleteFxn) DBLL_delete,
++ (DBLL_ExitFxn) DBLL_exit,
++ (DBLL_GetAttrsFxn) DBLL_getAttrs,
++ (DBLL_GetAddrFxn) DBLL_getAddr,
++ (DBLL_GetCAddrFxn) DBLL_getCAddr,
++ (DBLL_GetSectFxn) DBLL_getSect,
++ (DBLL_InitFxn) DBLL_init,
++ (DBLL_LoadFxn) DBLL_load,
++ (DBLL_LoadSectFxn) DBLL_loadSect,
++ (DBLL_OpenFxn) DBLL_open,
++ (DBLL_ReadSectFxn) DBLL_readSect,
++ (DBLL_SetAttrsFxn) DBLL_setAttrs,
++ (DBLL_UnloadFxn) DBLL_unload,
++ (DBLL_UnloadSectFxn) DBLL_unloadSect,
++};
++
++static struct GT_Mask NLDR_debugMask = { NULL, NULL }; /* GT trace variable */
++static u32 cRefs; /* module reference count */
++
++static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
++ u32 addr, u32 nBytes);
++static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
++ enum DSP_DCDOBJTYPE objType,
++ IN void *handle);
++static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
++ struct OvlySect **pList,
++ struct DBLL_SectInfo *pSectInfo, bool *pExists,
++ u32 addr, u32 nBytes);
++static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
++ s32 mtype);
++static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
++ u16 nAlloc);
++static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
++ char *symName, struct DBLL_Symbol **sym);
++static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
++ struct LibNode *root, struct DSP_UUID uuid,
++ bool rootPersistent, struct DBLL_LibraryObj **libPath,
++ enum NLDR_PHASE phase, u16 depth);
++static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++static DSP_STATUS RemoteAlloc(void **pRef, u16 memType, u32 size,
++ u32 align, u32 *dspAddr,
++ OPTIONAL s32 segmentId, OPTIONAL s32 req,
++ bool reserve);
++static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
++ u32 size, bool reserve);
++
++static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root);
++static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase);
++static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
++ struct DBLL_LibraryObj *lib);
++static u32 findLcm(u32 a, u32 b);
++static u32 findGcf(u32 a, u32 b);
++
++/*
++ * ======== NLDR_Allocate ========
++ */
++DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr, void *pPrivRef,
++ IN CONST struct DCD_NODEPROPS *pNodeProps,
++ OUT struct NLDR_NODEOBJECT **phNldrNode,
++ IN bool *pfPhaseSplit)
++{
++ struct NLDR_NODEOBJECT *pNldrNode = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pNodeProps != NULL);
++ DBC_Require(phNldrNode != NULL);
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++
++ GT_5trace(NLDR_debugMask, GT_ENTER, "NLDR_Allocate(0x%x, 0x%x, 0x%x, "
++ "0x%x, 0x%x)\n", hNldr, pPrivRef, pNodeProps, phNldrNode,
++ pfPhaseSplit);
++
++ /* Initialize handle in case of failure */
++ *phNldrNode = NULL;
++ /* Allocate node object */
++ MEM_AllocObject(pNldrNode, struct NLDR_NODEOBJECT, NLDR_NODESIGNATURE);
++
++ if (pNldrNode == NULL) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Allocate: "
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ pNldrNode->pfPhaseSplit = pfPhaseSplit;
++ pNldrNode->nPersLib = 0;
++ pNldrNode->pNldr = hNldr;
++ pNldrNode->pPrivRef = pPrivRef;
++ /* Save node's UUID. */
++ pNldrNode->uuid = pNodeProps->ndbProps.uiNodeID;
++ /*
++ * Determine if node is a dynamically loaded node from
++ * ndbProps.
++ */
++ if (pNodeProps->usLoadType == NLDR_DYNAMICLOAD) {
++ /* Dynamic node */
++ pNldrNode->fDynamic = true;
++ /*
++ * Extract memory requirements from ndbProps masks
++ */
++ /* Create phase */
++ pNldrNode->segId[CREATEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >> CREATEBIT) &
++ SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (CREATEBIT + FLAGBIT)) & 1) <<
++ CREATEDATAFLAGBIT;
++ pNldrNode->segId[CREATECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ CREATEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (CREATEBIT + FLAGBIT)) & 1) <<
++ CREATECODEFLAGBIT;
++ /* Execute phase */
++ pNldrNode->segId[EXECUTEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >>
++ EXECUTEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (EXECUTEBIT + FLAGBIT)) & 1) <<
++ EXECUTEDATAFLAGBIT;
++ pNldrNode->segId[EXECUTECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ EXECUTEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (EXECUTEBIT + FLAGBIT)) & 1) <<
++ EXECUTECODEFLAGBIT;
++ /* Delete phase */
++ pNldrNode->segId[DELETEDATAFLAGBIT] = (u16)
++ (pNodeProps->ulDataMemSegMask >> DELETEBIT) &
++ SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulDataMemSegMask >>
++ (DELETEBIT + FLAGBIT)) & 1) <<
++ DELETEDATAFLAGBIT;
++ pNldrNode->segId[DELETECODEFLAGBIT] = (u16)
++ (pNodeProps->ulCodeMemSegMask >>
++ DELETEBIT) & SEGMASK;
++ pNldrNode->codeDataFlagMask |=
++ ((pNodeProps->ulCodeMemSegMask >>
++ (DELETEBIT + FLAGBIT)) & 1) <<
++ DELETECODEFLAGBIT;
++ } else {
++ /* Non-dynamically loaded nodes are part of the
++ * base image */
++ pNldrNode->root.lib = hNldr->baseLib;
++ /* Check for overlay node */
++ if (pNodeProps->usLoadType == NLDR_OVLYLOAD)
++ pNldrNode->fOverlay = true;
++
++ }
++ *phNldrNode = (struct NLDR_NODEOBJECT *) pNldrNode;
++ }
++ /* Cleanup on failure */
++ if (DSP_FAILED(status) && pNldrNode)
++ NLDR_Free((struct NLDR_NODEOBJECT *) pNldrNode);
++
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct NLDR_NODEOBJECT *)(*phNldrNode)),
++ NLDR_NODESIGNATURE)) || (DSP_FAILED(status) &&
++ *phNldrNode == NULL));
++ return status;
++}
++
++/*
++ * ======== NLDR_Create ========
++ */
++DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct NLDR_ATTRS *pAttrs)
++{
++ struct COD_MANAGER *hCodMgr; /* COD manager */
++ char *pszCoffBuf = NULL;
++ char szZLFile[COD_MAXPATHLENGTH];
++ struct NLDR_OBJECT *pNldr = NULL;
++ struct DBLL_Attrs saveAttrs;
++ struct DBLL_Attrs newAttrs;
++ DBLL_Flags flags;
++ u32 ulEntry;
++ u16 nSegs = 0;
++ struct MemInfo *pMemInfo;
++ u32 ulLen = 0;
++ u32 ulAddr;
++ struct RMM_Segment *rmmSegs = NULL;
++ u16 i;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNldr != NULL);
++ DBC_Require(hDevObject != NULL);
++ DBC_Require(pAttrs != NULL);
++ DBC_Require(pAttrs->pfnOvly != NULL);
++ DBC_Require(pAttrs->pfnWrite != NULL);
++ GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_Create(0x%x, 0x%x, 0x%x)\n",
++ phNldr, hDevObject, pAttrs);
++ /* Allocate dynamic loader object */
++ MEM_AllocObject(pNldr, struct NLDR_OBJECT, NLDR_SIGNATURE);
++ if (pNldr) {
++ pNldr->hDevObject = hDevObject;
++ /* warning, lazy status checking alert! */
++ status = DEV_GetCodMgr(hDevObject, &hCodMgr);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetLoader(hCodMgr, &pNldr->dbll);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetBaseLib(hCodMgr, &pNldr->baseLib);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = DSP_SOK;
++ /* end lazy status checking */
++ pNldr->usDSPMauSize = pAttrs->usDSPMauSize;
++ pNldr->usDSPWordSize = pAttrs->usDSPWordSize;
++ pNldr->dbllFxns = dbllFxns;
++ if (!(pNldr->dbllFxns.initFxn()))
++ status = DSP_EMEMORY;
++
++ } else {
++ GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Create: "
++ "Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ /* Create the DCD Manager */
++ if (DSP_SUCCEEDED(status))
++ status = DCD_CreateManager(NULL, &pNldr->hDcdMgr);
++
++ /* Get dynamic loading memory sections from base lib */
++ if (DSP_SUCCEEDED(status)) {
++ status = pNldr->dbllFxns.getSectFxn(pNldr->baseLib, DYNMEMSECT,
++ &ulAddr, &ulLen);
++ if (DSP_SUCCEEDED(status)) {
++ pszCoffBuf = MEM_Calloc(ulLen * pNldr->usDSPMauSize,
++ MEM_PAGED);
++ if (!pszCoffBuf) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ } else {
++ /* Ok to not have dynamic loading memory */
++ status = DSP_SOK;
++ ulLen = 0;
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: DBLL_getSect "
++ "failed (no dynamic loading mem segments): "
++ "0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && ulLen > 0) {
++ /* Read section containing dynamic load mem segments */
++ status = pNldr->dbllFxns.readSectFxn(pNldr->baseLib, DYNMEMSECT,
++ pszCoffBuf, ulLen);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: DBLL_read Section"
++ "failed: 0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && ulLen > 0) {
++ /* Parse memory segment data */
++ nSegs = (u16)(*((u32 *)pszCoffBuf));
++ if (nSegs > MAXMEMSEGS) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_Create: Invalid number of "
++ "dynamic load mem segments: 0x%lx\n", nSegs);
++ status = DSP_ECORRUPTFILE;
++ }
++ }
++ /* Parse dynamic load memory segments */
++ if (DSP_SUCCEEDED(status) && nSegs > 0) {
++ rmmSegs = MEM_Calloc(sizeof(struct RMM_Segment) * nSegs,
++ MEM_PAGED);
++ pNldr->segTable = MEM_Calloc(sizeof(u32) * nSegs, MEM_PAGED);
++ if (rmmSegs == NULL || pNldr->segTable == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pNldr->nSegs = nSegs;
++ pMemInfo = (struct MemInfo *)(pszCoffBuf +
++ sizeof(u32));
++ for (i = 0; i < nSegs; i++) {
++ rmmSegs[i].base = (pMemInfo + i)->base;
++ rmmSegs[i].length = (pMemInfo + i)->len;
++ rmmSegs[i].space = 0;
++ pNldr->segTable[i] = (pMemInfo + i)->type;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (proc) DLL MEMSEGMENT: %d, Base: 0x%x, "
++ "Length: 0x%x\n", i, rmmSegs[i].base,
++ rmmSegs[i].length);
++#endif
++ }
++ }
++ }
++ /* Create Remote memory manager */
++ if (DSP_SUCCEEDED(status))
++ status = RMM_create(&pNldr->rmm, rmmSegs, nSegs);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* set the alloc, free, write functions for loader */
++ pNldr->dbllFxns.getAttrsFxn(pNldr->dbll, &saveAttrs);
++ newAttrs = saveAttrs;
++ newAttrs.alloc = (DBLL_AllocFxn) RemoteAlloc;
++ newAttrs.free = (DBLL_FreeFxn) RemoteFree;
++ newAttrs.symLookup = (DBLL_SymLookup) GetSymbolValue;
++ newAttrs.symHandle = pNldr;
++ newAttrs.write = (DBLL_WriteFxn) pAttrs->pfnWrite;
++ pNldr->ovlyFxn = pAttrs->pfnOvly;
++ pNldr->writeFxn = pAttrs->pfnWrite;
++ pNldr->dbllAttrs = newAttrs;
++ }
++ if (rmmSegs)
++ MEM_Free(rmmSegs);
++
++ if (pszCoffBuf)
++ MEM_Free(pszCoffBuf);
++
++ /* Get overlay nodes */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
++ /* lazy check */
++ DBC_Assert(DSP_SUCCEEDED(status));
++ /* First count number of overlay nodes */
++ status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile, AddOvlyNode,
++ (void *) pNldr);
++ /* Now build table of overlay nodes */
++ if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
++ /* Allocate table for overlay nodes */
++ pNldr->ovlyTable =
++ MEM_Calloc(sizeof(struct OvlyNode) * pNldr->nOvlyNodes,
++ MEM_PAGED);
++ /* Put overlay nodes in the table */
++ pNldr->nNode = 0;
++ status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile,
++ AddOvlyNode,
++ (void *) pNldr);
++ }
++ }
++ /* Do a fake reload of the base image to get overlay section info */
++ if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
++ saveAttrs.write = fakeOvlyWrite;
++ saveAttrs.logWrite = AddOvlyInfo;
++ saveAttrs.logWriteHandle = pNldr;
++ flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
++ status = pNldr->dbllFxns.loadFxn(pNldr->baseLib, flags,
++ &saveAttrs, &ulEntry);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *phNldr = (struct NLDR_OBJECT *) pNldr;
++ } else {
++ if (pNldr)
++ NLDR_Delete((struct NLDR_OBJECT *) pNldr);
++
++ *phNldr = NULL;
++ }
++ /* FIXME:Temp. Fix. Must be removed */
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(((struct NLDR_OBJECT *)*phNldr),
++ NLDR_SIGNATURE))
++ || (DSP_FAILED(status) && (*phNldr == NULL)));
++ return status;
++}
++
++/*
++ * ======== NLDR_Delete ========
++ */
++void NLDR_Delete(struct NLDR_OBJECT *hNldr)
++{
++ struct OvlySect *pSect;
++ struct OvlySect *pNext;
++ u16 i;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++ GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Delete(0x%x)\n", hNldr);
++ hNldr->dbllFxns.exitFxn();
++ if (hNldr->rmm)
++ RMM_delete(hNldr->rmm);
++
++ if (hNldr->segTable)
++ MEM_Free(hNldr->segTable);
++
++ if (hNldr->hDcdMgr)
++ DCD_DestroyManager(hNldr->hDcdMgr);
++
++ /* Free overlay node information */
++ if (hNldr->ovlyTable) {
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ pSect = hNldr->ovlyTable[i].pCreateSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pDeleteSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pExecuteSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ pSect = hNldr->ovlyTable[i].pOtherSects;
++ while (pSect) {
++ pNext = pSect->pNextSect;
++ MEM_Free(pSect);
++ pSect = pNext;
++ }
++ }
++ MEM_Free(hNldr->ovlyTable);
++ }
++ MEM_FreeObject(hNldr);
++ DBC_Ensure(!MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++}
++
++/*
++ * ======== NLDR_Exit ========
++ * Discontinue usage of NLDR module.
++ */
++void NLDR_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(NLDR_debugMask, GT_5CLASS,
++ "Entered NLDR_Exit, ref count: 0x%x\n", cRefs);
++
++ if (cRefs == 0) {
++ RMM_exit();
++ NLDR_debugMask.flags = NULL;
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== NLDR_Free ========
++ */
++void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++
++ GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Free(0x%x)\n", hNldrNode);
++
++ MEM_FreeObject(hNldrNode);
++}
++
++/*
++ * ======== NLDR_GetFxnAddr ========
++ */
++DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode, char *pstrFxn,
++ u32 *pulAddr)
++{
++ struct DBLL_Symbol *pSym;
++ struct NLDR_OBJECT *hNldr;
++ DSP_STATUS status = DSP_SOK;
++ bool status1 = false;
++ s32 i = 0;
++ struct LibNode root = { NULL, 0, NULL };
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++ DBC_Require(pulAddr != NULL);
++ DBC_Require(pstrFxn != NULL);
++ GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_GetFxnAddr(0x%x, %s, 0x%x)\n",
++ hNldrNode, pstrFxn, pulAddr);
++
++ hNldr = hNldrNode->pNldr;
++ /* Called from NODE_Create(), NODE_Delete(), or NODE_Run(). */
++ if (hNldrNode->fDynamic && *hNldrNode->pfPhaseSplit) {
++ switch (hNldrNode->phase) {
++ case NLDR_CREATE:
++ root = hNldrNode->createLib;
++ break;
++ case NLDR_EXECUTE:
++ root = hNldrNode->executeLib;
++ break;
++ case NLDR_DELETE:
++ root = hNldrNode->deleteLib;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ } else {
++ /* for Overlay nodes or non-split Dynamic nodes */
++ root = hNldrNode->root;
++ }
++ status1 = hNldr->dbllFxns.getCAddrFxn(root.lib, pstrFxn, &pSym);
++ if (!status1)
++ status1 = hNldr->dbllFxns.getAddrFxn(root.lib, pstrFxn, &pSym);
++
++ /* If symbol not found, check dependent libraries */
++ if (!status1) {
++ for (i = 0; i < root.nDepLibs; i++) {
++ status1 = hNldr->dbllFxns.getAddrFxn(root.pDepLibs[i].
++ lib, pstrFxn, &pSym);
++ if (!status1) {
++ status1 = hNldr->dbllFxns.getCAddrFxn(root.
++ pDepLibs[i].lib, pstrFxn, &pSym);
++ }
++ if (status1) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++ /* Check persistent libraries */
++ if (!status1) {
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ status1 = hNldr->dbllFxns.getAddrFxn(hNldrNode->
++ persLib[i].lib, pstrFxn, &pSym);
++ if (!status1) {
++ status1 =
++ hNldr->dbllFxns.getCAddrFxn(hNldrNode->
++ persLib[i].lib, pstrFxn, &pSym);
++ }
++ if (status1) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++
++ if (status1) {
++ *pulAddr = pSym->value;
++ } else {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "NLDR_GetFxnAddr: Symbol not found: "
++ "%s\n", pstrFxn);
++ status = DSP_ESYMBOL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== NLDR_GetRmmManager ========
++ * Given a NLDR object, retrieve RMM Manager Handle
++ */
++DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
++ OUT struct RMM_TargetObj **phRmmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct NLDR_OBJECT *pNldrObject = hNldrObject;
++ DBC_Require(phRmmMgr != NULL);
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_GetRmmManager(0x%x, 0x%x)\n",
++ hNldrObject, phRmmMgr);
++ if (MEM_IsValidHandle(hNldrObject, NLDR_SIGNATURE)) {
++ *phRmmMgr = pNldrObject->rmm;
++ } else {
++ *phRmmMgr = NULL;
++ status = DSP_EHANDLE;
++ GT_0trace(NLDR_debugMask, GT_7CLASS,
++ "NLDR_GetRmmManager:Invalid handle");
++ }
++
++ GT_2trace(NLDR_debugMask, GT_ENTER, "Exit NLDR_GetRmmManager: status "
++ "0x%x\n\tphRmmMgr: 0x%x\n", status, *phRmmMgr);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phRmmMgr != NULL) &&
++ (*phRmmMgr == NULL)));
++
++ return status;
++}
++
++/*
++ * ======== NLDR_Init ========
++ * Initialize the NLDR module.
++ */
++bool NLDR_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!NLDR_debugMask.flags);
++ GT_create(&NLDR_debugMask, "DL"); /* "DL" for DLdr */
++
++ RMM_init();
++ }
++
++ cRefs++;
++
++ GT_1trace(NLDR_debugMask, GT_5CLASS, "NLDR_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure(cRefs > 0);
++ return true;
++}
++
++/*
++ * ======== NLDR_Load ========
++ */
++DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr;
++ struct DSP_UUID libUUID;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++
++ hNldr = hNldrNode->pNldr;
++
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Load(0x%x, 0x%x)\n",
++ hNldrNode, phase);
++
++ if (hNldrNode->fDynamic) {
++ hNldrNode->phase = phase;
++
++ libUUID = hNldrNode->uuid;
++
++ /* At this point, we may not know if node is split into
++ * different libraries. So we'll go ahead and load the
++ * library, and then save the pointer to the appropriate
++ * location after we know. */
++
++ status = LoadLib(hNldrNode, &hNldrNode->root, libUUID, false,
++ hNldrNode->libPath, phase, 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ if (*hNldrNode->pfPhaseSplit) {
++ switch (phase) {
++ case NLDR_CREATE:
++ hNldrNode->createLib = hNldrNode->root;
++ break;
++
++ case NLDR_EXECUTE:
++ hNldrNode->executeLib = hNldrNode->root;
++ break;
++
++ case NLDR_DELETE:
++ hNldrNode->deleteLib = hNldrNode->root;
++ break;
++
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ }
++ }
++ } else {
++ if (hNldrNode->fOverlay)
++ status = LoadOvly(hNldrNode, phase);
++
++ }
++
++ return status;
++}
++
++/*
++ * ======== NLDR_Unload ========
++ */
++DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct LibNode *pRootLib = NULL;
++ s32 i = 0;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
++ GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Unload(0x%x, 0x%x)\n",
++ hNldrNode, phase);
++ if (hNldrNode != NULL) {
++ if (hNldrNode->fDynamic) {
++ if (*hNldrNode->pfPhaseSplit) {
++ switch (phase) {
++ case NLDR_CREATE:
++ pRootLib = &hNldrNode->createLib;
++ break;
++ case NLDR_EXECUTE:
++ pRootLib = &hNldrNode->executeLib;
++ break;
++ case NLDR_DELETE:
++ pRootLib = &hNldrNode->deleteLib;
++ /* Unload persistent libraries */
++ for (i = 0; i < hNldrNode->nPersLib;
++ i++) {
++ UnloadLib(hNldrNode,
++ &hNldrNode->persLib[i]);
++ }
++ hNldrNode->nPersLib = 0;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ } else {
++ /* Unload main library */
++ pRootLib = &hNldrNode->root;
++ }
++ UnloadLib(hNldrNode, pRootLib);
++ } else {
++ if (hNldrNode->fOverlay)
++ UnloadOvly(hNldrNode, phase);
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== AddOvlyInfo ========
++ */
++static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
++ u32 addr, u32 nBytes)
++{
++ char *pNodeName;
++ char *pSectName = (char *)sectInfo->name;
++ bool fExists = false;
++ char seps = ':';
++ char *pch;
++ u16 i;
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Is this an overlay section (load address != run address)? */
++ if (sectInfo->loadAddr == sectInfo->runAddr)
++ goto func_end;
++
++ /* Find the node it belongs to */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ pNodeName = hNldr->ovlyTable[i].pNodeName;
++ DBC_Require(pNodeName);
++ if (strncmp(pNodeName, pSectName + 1,
++ strlen(pNodeName)) == 0) {
++ /* Found the node */
++ break;
++ }
++ }
++ if (!(i < hNldr->nOvlyNodes))
++ goto func_end;
++
++ /* Determine which phase this section belongs to */
++ for (pch = pSectName + 1; *pch && *pch != seps; pch++)
++ ;;
++
++ if (*pch) {
++ pch++; /* Skip over the ':' */
++ if (strncmp(pch, PCREATE, strlen(PCREATE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pCreateSects, sectInfo, &fExists, addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nCreateSects++;
++
++ } else
++ if (strncmp(pch, PDELETE, strlen(PDELETE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pDeleteSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nDeleteSects++;
++
++ } else
++ if (strncmp(pch, PEXECUTE, strlen(PEXECUTE)) == 0) {
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pExecuteSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nExecuteSects++;
++
++ } else {
++ /* Put in "other" sectins */
++ status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
++ pOtherSects, sectInfo, &fExists,
++ addr, nBytes);
++ if (DSP_SUCCEEDED(status) && !fExists)
++ hNldr->ovlyTable[i].nOtherSects++;
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== AddOvlyNode =========
++ * Callback function passed to DCD_GetObjects.
++ */
++static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
++ enum DSP_DCDOBJTYPE objType,
++ IN void *handle)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ char *pNodeName = NULL;
++ char *pBuf = NULL;
++ u32 uLen;
++ struct DCD_GENERICOBJ objDef;
++ DSP_STATUS status = DSP_SOK;
++
++ if (objType != DSP_DCDNODETYPE)
++ goto func_end;
++
++ status = DCD_GetObjectDef(hNldr->hDcdMgr, pUuid, objType, &objDef);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If overlay node, add to the list */
++ if (objDef.objData.nodeObj.usLoadType == NLDR_OVLYLOAD) {
++ if (hNldr->ovlyTable == NULL) {
++ hNldr->nOvlyNodes++;
++ } else {
++ /* Add node to table */
++ hNldr->ovlyTable[hNldr->nNode].uuid = *pUuid;
++ DBC_Require(objDef.objData.nodeObj.ndbProps.acName);
++ uLen = strlen(objDef.objData.nodeObj.ndbProps.acName);
++ pNodeName = objDef.objData.nodeObj.ndbProps.acName;
++ pBuf = MEM_Calloc(uLen + 1, MEM_PAGED);
++ if (pBuf == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(pBuf, pNodeName, uLen);
++ hNldr->ovlyTable[hNldr->nNode].pNodeName = pBuf;
++ hNldr->nNode++;
++ }
++ }
++ }
++ /* These were allocated in DCD_GetObjectDef */
++ if (objDef.objData.nodeObj.pstrCreatePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrCreatePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrExecutePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrExecutePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrDeletePhaseFxn)
++ MEM_Free(objDef.objData.nodeObj.pstrDeletePhaseFxn);
++
++ if (objDef.objData.nodeObj.pstrIAlgName)
++ MEM_Free(objDef.objData.nodeObj.pstrIAlgName);
++
++func_end:
++ return status;
++}
++
++/*
++ * ======== AddOvlySect ========
++ */
++static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
++ struct OvlySect **pList,
++ struct DBLL_SectInfo *pSectInfo, bool *pExists,
++ u32 addr, u32 nBytes)
++{
++ struct OvlySect *pNewSect = NULL;
++ struct OvlySect *pLastSect;
++ struct OvlySect *pSect;
++ DSP_STATUS status = DSP_SOK;
++
++ pSect = pLastSect = *pList;
++ *pExists = false;
++ while (pSect) {
++ /*
++ * Make sure section has not already been added. Multiple
++ * 'write' calls may be made to load the section.
++ */
++ if (pSect->loadAddr == addr) {
++ /* Already added */
++ *pExists = true;
++ break;
++ }
++ pLastSect = pSect;
++ pSect = pSect->pNextSect;
++ }
++
++ if (!pSect) {
++ /* New section */
++ pNewSect = MEM_Calloc(sizeof(struct OvlySect), MEM_PAGED);
++ if (pNewSect == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pNewSect->loadAddr = addr;
++ pNewSect->runAddr = pSectInfo->runAddr +
++ (addr - pSectInfo->loadAddr);
++ pNewSect->size = nBytes;
++ pNewSect->page = pSectInfo->type;
++ }
++
++ /* Add to the list */
++ if (DSP_SUCCEEDED(status)) {
++ if (*pList == NULL) {
++ /* First in the list */
++ *pList = pNewSect;
++ } else {
++ pLastSect->pNextSect = pNewSect;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== fakeOvlyWrite ========
++ */
++static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
++ s32 mtype)
++{
++ return (s32)nBytes;
++}
++
++/*
++ * ======== FreeSects ========
++ */
++static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
++ u16 nAlloc)
++{
++ struct OvlySect *pSect = pPhaseSects;
++ u16 i = 0;
++ bool fRet;
++
++ while (pSect && i < nAlloc) {
++ /* 'Deallocate' */
++ /* segid - page not supported yet */
++ /* Reserved memory */
++ fRet = RMM_free(hNldr->rmm, 0, pSect->runAddr, pSect->size,
++ true);
++ DBC_Assert(fRet);
++ pSect = pSect->pNextSect;
++ i++;
++ }
++}
++
++/*
++ * ======== GetSymbolValue ========
++ * Find symbol in library's base image. If not there, check dependent
++ * libraries.
++ */
++static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
++ char *name, struct DBLL_Symbol **sym)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
++ struct NLDR_NODEOBJECT *hNldrNode = (struct NLDR_NODEOBJECT *)rmmHandle;
++ struct LibNode *root = (struct LibNode *)pArg;
++ u16 i;
++ bool status = false;
++
++ /* check the base image */
++ status = hNldr->dbllFxns.getAddrFxn(hNldr->baseLib, name, sym);
++ if (!status)
++ status = hNldr->dbllFxns.getCAddrFxn(hNldr->baseLib, name, sym);
++
++ /*
++ * Check in root lib itself. If the library consists of
++ * multiple object files linked together, some symbols in the
++ * library may need to be resolved.
++ */
++ if (!status) {
++ status = hNldr->dbllFxns.getAddrFxn(root->lib, name, sym);
++ if (!status) {
++ status =
++ hNldr->dbllFxns.getCAddrFxn(root->lib, name, sym);
++ }
++ }
++
++ /*
++ * Check in root lib's dependent libraries, but not dependent
++ * libraries' dependents.
++ */
++ if (!status) {
++ for (i = 0; i < root->nDepLibs; i++) {
++ status = hNldr->dbllFxns.getAddrFxn(root->pDepLibs[i].
++ lib, name, sym);
++ if (!status) {
++ status = hNldr->dbllFxns.getCAddrFxn(root->
++ pDepLibs[i].lib, name, sym);
++ }
++ if (status) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++ /*
++ * Check in persistent libraries
++ */
++ if (!status) {
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ status = hNldr->dbllFxns.getAddrFxn(hNldrNode->
++ persLib[i].lib, name, sym);
++ if (!status) {
++ status = hNldr->dbllFxns.getCAddrFxn
++ (hNldrNode->persLib[i].lib, name, sym);
++ }
++ if (status) {
++ /* Symbol found */
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== LoadLib ========
++ * Recursively load library and all its dependent libraries. The library
++ * we're loading is specified by a uuid.
++ */
++static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
++ struct LibNode *root, struct DSP_UUID uuid,
++ bool rootPersistent, struct DBLL_LibraryObj **libPath,
++ enum NLDR_PHASE phase, u16 depth)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ u16 nLibs = 0; /* Number of dependent libraries */
++ u16 nPLibs = 0; /* Number of persistent libraries */
++ u16 nLoaded = 0; /* Number of dep. libraries loaded */
++ u16 i;
++ u32 entry;
++ u32 dwBufSize = NLDR_MAXPATHLENGTH;
++ DBLL_Flags flags = DBLL_SYMB | DBLL_CODE | DBLL_DATA | DBLL_DYNAMIC;
++ struct DBLL_Attrs newAttrs;
++ char *pszFileName = NULL;
++ struct DSP_UUID *depLibUUIDs = NULL;
++ bool *persistentDepLibs = NULL;
++ DSP_STATUS status = DSP_SOK;
++ bool fStatus = false;
++ struct LibNode *pDepLib;
++
++ if (depth > MAXDEPTH) {
++ /* Error */
++ DBC_Assert(false);
++ }
++ root->lib = NULL;
++ /* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */
++ pszFileName = MEM_Calloc(DBLL_MAXPATHLENGTH, MEM_PAGED);
++ if (pszFileName == NULL)
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the name of the library */
++ if (depth == 0) {
++ status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
++ &uuid, pszFileName, &dwBufSize, phase,
++ hNldrNode->pfPhaseSplit);
++ } else {
++ /* Dependent libraries are registered with a phase */
++ status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
++ &uuid, pszFileName, &dwBufSize, NLDR_NOPHASE,
++ NULL);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Open the library, don't load symbols */
++ status = hNldr->dbllFxns.openFxn(hNldr->dbll, pszFileName,
++ DBLL_NOLOAD, &root->lib);
++ }
++ /* Done with file name */
++ if (pszFileName)
++ MEM_Free(pszFileName);
++
++ /* Check to see if library not already loaded */
++ if (DSP_SUCCEEDED(status) && rootPersistent) {
++ fStatus = findInPersistentLibArray(hNldrNode, root->lib);
++ /* Close library */
++ if (fStatus) {
++ hNldr->dbllFxns.closeFxn(root->lib);
++ return DSP_SALREADYLOADED;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check for circular dependencies. */
++ for (i = 0; i < depth; i++) {
++ if (root->lib == libPath[i]) {
++ /* This condition could be checked by a
++ * tool at build time. */
++ status = DSP_EDYNLOAD;
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Add library to current path in dependency tree */
++ libPath[depth] = root->lib;
++ depth++;
++ /* Get number of dependent libraries */
++ status = DCD_GetNumDepLibs(hNldrNode->pNldr->hDcdMgr, &uuid,
++ &nLibs, &nPLibs, phase);
++ }
++ DBC_Assert(nLibs >= nPLibs);
++ if (DSP_SUCCEEDED(status)) {
++ if (!(*hNldrNode->pfPhaseSplit))
++ nPLibs = 0;
++
++ /* nLibs = #of dependent libraries */
++ root->nDepLibs = nLibs - nPLibs;
++ if (nLibs > 0) {
++ depLibUUIDs = MEM_Calloc(sizeof(struct DSP_UUID) *
++ nLibs, MEM_PAGED);
++ persistentDepLibs =
++ MEM_Calloc(sizeof(bool) * nLibs, MEM_PAGED);
++ if (!depLibUUIDs || !persistentDepLibs)
++ status = DSP_EMEMORY;
++
++ if (root->nDepLibs > 0) {
++ /* Allocate arrays for dependent lib UUIDs,
++ * lib nodes */
++ root->pDepLibs = MEM_Calloc
++ (sizeof(struct LibNode) *
++ (root->nDepLibs), MEM_PAGED);
++ if (!(root->pDepLibs))
++ status = DSP_EMEMORY;
++
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the dependent library UUIDs */
++ status = DCD_GetDepLibs(hNldrNode->pNldr->
++ hDcdMgr, &uuid, nLibs, depLibUUIDs,
++ persistentDepLibs, phase);
++ }
++ }
++ }
++
++ /*
++ * Recursively load dependent libraries.
++ */
++ if (DSP_SUCCEEDED(status) && persistentDepLibs) {
++ for (i = 0; i < nLibs; i++) {
++ /* If root library is NOT persistent, and dep library
++ * is, then record it. If root library IS persistent,
++ * the deplib is already included */
++ if (!rootPersistent && persistentDepLibs[i] &&
++ *hNldrNode->pfPhaseSplit) {
++ if ((hNldrNode->nPersLib) > MAXLIBS) {
++ status = DSP_EDYNLOAD;
++ break;
++ }
++
++ /* Allocate library outside of phase */
++ pDepLib = &hNldrNode->persLib[hNldrNode->
++ nPersLib];
++ } else {
++ if (rootPersistent)
++ persistentDepLibs[i] = true;
++
++
++ /* Allocate library within phase */
++ pDepLib = &root->pDepLibs[nLoaded];
++ }
++
++ if (depLibUUIDs) {
++ status = LoadLib(hNldrNode, pDepLib,
++ depLibUUIDs[i],
++ persistentDepLibs[i], libPath,
++ phase,
++ depth);
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if ((status != DSP_SALREADYLOADED) &&
++ !rootPersistent && persistentDepLibs[i] &&
++ *hNldrNode->pfPhaseSplit) {
++ (hNldrNode->nPersLib)++;
++ } else {
++ if (!persistentDepLibs[i] ||
++ !(*hNldrNode->pfPhaseSplit)) {
++ nLoaded++;
++ }
++ }
++ } else {
++ break;
++ }
++ }
++ }
++
++ /* Now we can load the root library */
++ if (DSP_SUCCEEDED(status)) {
++ newAttrs = hNldr->dbllAttrs;
++ newAttrs.symArg = root;
++ newAttrs.rmmHandle = hNldrNode;
++ newAttrs.wHandle = hNldrNode->pPrivRef;
++ newAttrs.baseImage = false;
++
++ status = hNldr->dbllFxns.loadFxn(root->lib, flags, &newAttrs,
++ &entry);
++ }
++
++ /*
++ * In case of failure, unload any dependent libraries that
++ * were loaded, and close the root library.
++ * (Persistent libraries are unloaded from the very top)
++ */
++ if (DSP_FAILED(status)) {
++ if (phase != NLDR_EXECUTE) {
++ for (i = 0; i < hNldrNode->nPersLib; i++)
++ UnloadLib(hNldrNode, &hNldrNode->persLib[i]);
++
++ hNldrNode->nPersLib = 0;
++ }
++ for (i = 0; i < nLoaded; i++)
++ UnloadLib(hNldrNode, &root->pDepLibs[i]);
++
++ if (root->lib)
++ hNldr->dbllFxns.closeFxn(root->lib);
++
++ }
++
++ /* Going up one node in the dependency tree */
++ depth--;
++
++ if (depLibUUIDs) {
++ MEM_Free(depLibUUIDs);
++ depLibUUIDs = NULL;
++ }
++
++ if (persistentDepLibs) {
++ MEM_Free(persistentDepLibs);
++ persistentDepLibs = NULL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== LoadOvly ========
++ */
++static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
++ enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ struct OvlyNode *pONode = NULL;
++ struct OvlySect *pPhaseSects = NULL;
++ struct OvlySect *pOtherSects = NULL;
++ u16 i;
++ u16 nAlloc = 0;
++ u16 nOtherAlloc = 0;
++ u16 *pRefCount = NULL;
++ u16 *pOtherRef = NULL;
++ u32 nBytes;
++ struct OvlySect *pSect;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Find the node in the table */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
++ /* Found it */
++ pONode = &(hNldr->ovlyTable[i]);
++ break;
++ }
++ }
++
++ DBC_Assert(i < hNldr->nOvlyNodes);
++ switch (phase) {
++ case NLDR_CREATE:
++ pRefCount = &(pONode->createRef);
++ pOtherRef = &(pONode->otherRef);
++ pPhaseSects = pONode->pCreateSects;
++ pOtherSects = pONode->pOtherSects;
++ break;
++
++ case NLDR_EXECUTE:
++ pRefCount = &(pONode->executeRef);
++ pPhaseSects = pONode->pExecuteSects;
++ break;
++
++ case NLDR_DELETE:
++ pRefCount = &(pONode->deleteRef);
++ pPhaseSects = pONode->pDeleteSects;
++ break;
++
++ default:
++ DBC_Assert(false);
++ break;
++ }
++
++ DBC_Assert(pRefCount != NULL);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (pRefCount == NULL)
++ goto func_end;
++
++ if (*pRefCount != 0)
++ goto func_end;
++
++ /* 'Allocate' memory for overlay sections of this phase */
++ pSect = pPhaseSects;
++ while (pSect) {
++ /* allocate */ /* page not supported yet */
++ /* reserve */ /* align */
++ status = RMM_alloc(hNldr->rmm, 0, pSect->size, 0,
++ &(pSect->runAddr), true);
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pSect->pNextSect;
++ nAlloc++;
++ } else {
++ break;
++ }
++ }
++ if (pOtherRef && *pOtherRef == 0) {
++ /* 'Allocate' memory for other overlay sections
++ * (create phase) */
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pOtherSects;
++ while (pSect) {
++ /* page not supported */ /* align */
++ /* reserve */
++ status = RMM_alloc(hNldr->rmm, 0, pSect->size,
++ 0, &(pSect->runAddr), true);
++ if (DSP_SUCCEEDED(status)) {
++ pSect = pSect->pNextSect;
++ nOtherAlloc++;
++ } else {
++ break;
++ }
++ }
++ }
++ }
++ if (*pRefCount == 0) {
++ if (DSP_SUCCEEDED(status)) {
++ /* Load sections for this phase */
++ pSect = pPhaseSects;
++ while (pSect && DSP_SUCCEEDED(status)) {
++ nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
++ pSect->runAddr, pSect->loadAddr,
++ pSect->size, pSect->page);
++ if (nBytes != pSect->size)
++ status = DSP_EFAIL;
++
++ pSect = pSect->pNextSect;
++ }
++ }
++ }
++ if (pOtherRef && *pOtherRef == 0) {
++ if (DSP_SUCCEEDED(status)) {
++ /* Load other sections (create phase) */
++ pSect = pOtherSects;
++ while (pSect && DSP_SUCCEEDED(status)) {
++ nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
++ pSect->runAddr, pSect->loadAddr,
++ pSect->size, pSect->page);
++ if (nBytes != pSect->size)
++ status = DSP_EFAIL;
++
++ pSect = pSect->pNextSect;
++ }
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* 'Deallocate' memory */
++ FreeSects(hNldr, pPhaseSects, nAlloc);
++ FreeSects(hNldr, pOtherSects, nOtherAlloc);
++ }
++func_end:
++ if (DSP_SUCCEEDED(status) && (pRefCount != NULL)) {
++ *pRefCount += 1;
++ if (pOtherRef)
++ *pOtherRef += 1;
++
++ }
++
++ return status;
++}
++
++/*
++ * ======== RemoteAlloc ========
++ */
++static DSP_STATUS RemoteAlloc(void **pRef, u16 space, u32 size,
++ u32 align, u32 *dspAddr,
++ OPTIONAL s32 segmentId, OPTIONAL s32 req,
++ bool reserve)
++{
++ struct NLDR_NODEOBJECT *hNode = (struct NLDR_NODEOBJECT *)pRef;
++ struct NLDR_OBJECT *hNldr;
++ struct RMM_TargetObj *rmm;
++ u16 memPhaseBit = MAXFLAGS;
++ u16 segid = 0;
++ u16 i;
++ u16 memType;
++ u32 nWords;
++ struct RMM_Addr *pRmmAddr = (struct RMM_Addr *)dspAddr;
++ bool fReq = false;
++ DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
++ DBC_Require(MEM_IsValidHandle(hNode, NLDR_NODESIGNATURE));
++ DBC_Require(space == DBLL_CODE || space == DBLL_DATA ||
++ space == DBLL_BSS);
++ hNldr = hNode->pNldr;
++ rmm = hNldr->rmm;
++ /* Convert size to DSP words */
++ nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
++ /* Modify memory 'align' to account for DSP cache line size */
++ align = findLcm(GEM_CACHE_LINE_SIZE, align);
++ GT_1trace(NLDR_debugMask, GT_7CLASS,
++ "RemoteAlloc: memory align to 0x%x \n", align);
++ if (segmentId != -1) {
++ pRmmAddr->segid = segmentId;
++ segid = segmentId;
++ fReq = req;
++ } else {
++ switch (hNode->phase) {
++ case NLDR_CREATE:
++ memPhaseBit = CREATEDATAFLAGBIT;
++ break;
++ case NLDR_DELETE:
++ memPhaseBit = DELETEDATAFLAGBIT;
++ break;
++ case NLDR_EXECUTE:
++ memPhaseBit = EXECUTEDATAFLAGBIT;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ if (space == DBLL_CODE)
++ memPhaseBit++;
++
++ if (memPhaseBit < MAXFLAGS)
++ segid = hNode->segId[memPhaseBit];
++
++ /* Determine if there is a memory loading requirement */
++ if ((hNode->codeDataFlagMask >> memPhaseBit) & 0x1)
++ fReq = true;
++
++ }
++ memType = (space == DBLL_CODE) ? DYNM_CODE : DYNM_DATA;
++
++ /* Find an appropriate segment based on space */
++ if (segid == NULLID) {
++ /* No memory requirements of preferences */
++ DBC_Assert(!fReq);
++ goto func_cont;
++ }
++ if (segid <= MAXSEGID) {
++ DBC_Assert(segid < hNldr->nSegs);
++ /* Attempt to allocate from segid first. */
++ pRmmAddr->segid = segid;
++ status = RMM_alloc(rmm, segid, nWords, align, dspAddr, false);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NLDR_debugMask, GT_6CLASS,
++ "RemoteAlloc:Unable allocate "
++ "from segment %d.\n", segid);
++ }
++ } else {
++ /* segid > MAXSEGID ==> Internal or external memory */
++ DBC_Assert(segid == MEMINTERNALID || segid == MEMEXTERNALID);
++ /* Check for any internal or external memory segment,
++ * depending on segid.*/
++ memType |= segid == MEMINTERNALID ?
++ DYNM_INTERNAL : DYNM_EXTERNAL;
++ for (i = 0; i < hNldr->nSegs; i++) {
++ if ((hNldr->segTable[i] & memType) != memType)
++ continue;
++
++ status = RMM_alloc(rmm, i, nWords, align, dspAddr,
++ false);
++ if (DSP_SUCCEEDED(status)) {
++ /* Save segid for freeing later */
++ pRmmAddr->segid = i;
++ break;
++ }
++ }
++ }
++func_cont:
++ /* Haven't found memory yet, attempt to find any segment that works */
++ if (status == DSP_EMEMORY && !fReq) {
++ GT_0trace(NLDR_debugMask, GT_6CLASS,
++ "RemoteAlloc: Preferred segment "
++ "unavailable, trying another segment.\n");
++ for (i = 0; i < hNldr->nSegs; i++) {
++ /* All bits of memType must be set */
++ if ((hNldr->segTable[i] & memType) != memType)
++ continue;
++
++ status = RMM_alloc(rmm, i, nWords, align, dspAddr,
++ false);
++ if (DSP_SUCCEEDED(status)) {
++ /* Save segid */
++ pRmmAddr->segid = i;
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
++ u32 size, bool reserve)
++{
++ struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)pRef;
++ struct RMM_TargetObj *rmm;
++ u32 nWords;
++ DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
++
++ DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
++
++ rmm = hNldr->rmm;
++
++ /* Convert size to DSP words */
++ nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
++
++ if (RMM_free(rmm, space, dspAddr, nWords, reserve))
++ status = DSP_SOK;
++
++ return status;
++}
++
++/*
++ * ======== UnloadLib ========
++ */
++static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root)
++{
++ struct DBLL_Attrs newAttrs;
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ u16 i;
++
++ DBC_Assert(root != NULL);
++
++ /* Unload dependent libraries */
++ for (i = 0; i < root->nDepLibs; i++)
++ UnloadLib(hNldrNode, &root->pDepLibs[i]);
++
++ root->nDepLibs = 0;
++
++ newAttrs = hNldr->dbllAttrs;
++ newAttrs.rmmHandle = hNldr->rmm;
++ newAttrs.wHandle = hNldrNode->pPrivRef;
++ newAttrs.baseImage = false;
++ newAttrs.symArg = root;
++
++ if (root->lib) {
++ /* Unload the root library */
++ hNldr->dbllFxns.unloadFxn(root->lib, &newAttrs);
++ hNldr->dbllFxns.closeFxn(root->lib);
++ }
++
++ /* Free dependent library list */
++ if (root->pDepLibs) {
++ MEM_Free(root->pDepLibs);
++ root->pDepLibs = NULL;
++ }
++}
++
++/*
++ * ======== UnloadOvly ========
++ */
++static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
++{
++ struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
++ struct OvlyNode *pONode = NULL;
++ struct OvlySect *pPhaseSects = NULL;
++ struct OvlySect *pOtherSects = NULL;
++ u16 i;
++ u16 nAlloc = 0;
++ u16 nOtherAlloc = 0;
++ u16 *pRefCount = NULL;
++ u16 *pOtherRef = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ /* Find the node in the table */
++ for (i = 0; i < hNldr->nOvlyNodes; i++) {
++ if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
++ /* Found it */
++ pONode = &(hNldr->ovlyTable[i]);
++ break;
++ }
++ }
++
++ DBC_Assert(i < hNldr->nOvlyNodes);
++ switch (phase) {
++ case NLDR_CREATE:
++ pRefCount = &(pONode->createRef);
++ pPhaseSects = pONode->pCreateSects;
++ nAlloc = pONode->nCreateSects;
++ break;
++ case NLDR_EXECUTE:
++ pRefCount = &(pONode->executeRef);
++ pPhaseSects = pONode->pExecuteSects;
++ nAlloc = pONode->nExecuteSects;
++ break;
++ case NLDR_DELETE:
++ pRefCount = &(pONode->deleteRef);
++ pOtherRef = &(pONode->otherRef);
++ pPhaseSects = pONode->pDeleteSects;
++ /* 'Other' overlay sections are unloaded in the delete phase */
++ pOtherSects = pONode->pOtherSects;
++ nAlloc = pONode->nDeleteSects;
++ nOtherAlloc = pONode->nOtherSects;
++ break;
++ default:
++ DBC_Assert(false);
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(pRefCount && (*pRefCount > 0));
++ if (pRefCount && (*pRefCount > 0)) {
++ *pRefCount -= 1;
++ if (pOtherRef) {
++ DBC_Assert(*pOtherRef > 0);
++ *pOtherRef -= 1;
++ }
++ }
++ }
++ if (pRefCount && (*pRefCount == 0)) {
++ /* 'Deallocate' memory */
++ FreeSects(hNldr, pPhaseSects, nAlloc);
++ }
++ if (pOtherRef && *pOtherRef == 0)
++ FreeSects(hNldr, pOtherSects, nOtherAlloc);
++
++}
++
++/*
++ * ======== findInPersistentLibArray ========
++ */
++static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
++ struct DBLL_LibraryObj *lib)
++{
++ s32 i = 0;
++
++ for (i = 0; i < hNldrNode->nPersLib; i++) {
++ if (lib == hNldrNode->persLib[i].lib)
++ return true;
++
++ }
++
++ return false;
++}
++
++/*
++ * ================ Find LCM (Least Common Multiplier ===
++ */
++static u32 findLcm(u32 a, u32 b)
++{
++ u32 retVal;
++
++ retVal = a * b / findGcf(a, b);
++
++ return retVal;
++}
++
++/*
++ * ================ Find GCF (Greatest Common Factor ) ===
++ */
++static u32 findGcf(u32 a, u32 b)
++{
++ u32 c;
++
++ /* Get the GCF (Greatest common factor between the numbers,
++ * using Euclidian Algo */
++ while ((c = (a % b))) {
++ a = b;
++ b = c;
++ }
++ return b;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/node.c b/drivers/dsp/bridge/rmgr/node.c
+new file mode 100644
+index 0000000..178b802
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/node.c
+@@ -0,0 +1,3544 @@
++/*
++ * node.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== node.c ========
++ *
++ * Description:
++ * DSP/BIOS Bridge Node Manager.
++ *
++ * Public Functions:
++ * NODE_Allocate
++ * NODE_AllocMsgBuf
++ * NODE_ChangePriority
++ * NODE_Connect
++ * NODE_Create
++ * NODE_CreateMgr
++ * NODE_Delete
++ * NODE_DeleteMgr
++ * NODE_EnumNodes
++ * NODE_Exit
++ * NODE_FreeMsgBuf
++ * NODE_GetAttr
++ * NODE_GetChannelId
++ * NODE_GetMessage
++ * NODE_GetStrmMgr
++ * NODE_Init
++ * NODE_OnExit
++ * NODE_Pause
++ * NODE_PutMessage
++ * NODE_RegisterNotify
++ * NODE_Run
++ * NODE_Terminate
++ *
++ *! Revision History:
++ *! =================
++ *! 12-Apr-2004 hp Compile IVA only for 24xx
++ *! 09-Feb-2004 vp Updated to support IVA.
++ *! 07-Apr-2003 map Eliminated references to old DLDR
++ *! 26-Mar-2003 vp Commented the call to DSP deep sleep in Node_Delete
++ *! function.
++ *! 18-Feb-2003 vp Code review updates.
++ *! 06-Feb-2003 kc Fixed FreeStream to release streams correctly.
++ *! 23-Jan-2003 map Removed call to DISP_DoCinit within Write()
++ *! 03-Jan-2003 map Only unload code after phase has executed if
++ *! overlay or split dynload phases
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 06-Nov-2002 map Fixed NODE_Run on NODE_PAUSED bug
++ *! 12-Oct-2002 map Fixed DeleteNode bug in NODE_Create
++ *! 11-Sep-2002 rr DeleteNode frees the memory for strmConnect and dcd obj
++ *! 29-Aug-2002 map Modified Ovly and Write to use ARM-side copy
++ *! 22-May-2002 sg Changed use of cbData for PWR calls.
++ *! 17-May-2002 jeh Removed LoadLoaderFxns(). Get address of RMS_cinit()
++ *! function. Call DISP_DoCinit() from Write(), if .cinit.
++ *! 13-May-2002 sg Added timeout to wake/sleep calls.
++ *! 02-May-2002 sg Added wake/sleep of DSP to support "nap" mode.
++ *! 18-Apr-2002 jeh Use dynamic loader if compile flag is set.
++ *! 13-Feb-2002 jeh Get uSysStackSize from DSP_NDBPROPS.
++ *! 07-Jan-2002 ag STRMMODE_ZEROCOPY(shared memory buffer swap) enabled.
++ *! 17-Dec-2001 ag STRMMODE_RDMA(DDMA) enabled.
++ *! 12-Dec-2001 ag Check for valid stream mode in NODE_Connect().
++ *! 04-Dec-2001 jeh Check for node sufficiently connected in NODE_Create().
++ *! 15-Nov-2001 jeh Removed DBC_Require(pNode->hXlator != NULL) from
++ *! NODE_AllocMsgBuf(), and check node type != NODE_DEVICE.
++ *! 11-Sep-2001 ag Zero-copy messaging support.
++ *! 28-Aug-2001 jeh Overlay/dynamic loader infrastructure added. Removed
++ *! NODE_GetDispatcher, excess node states.
++ *! 07-Aug-2001 jeh Removed critical section for dispatcher.
++ *! 26-Jul-2001 jeh Get ZL dll name through CFG.
++ *! 05-Jun-2001 jeh Assume DSP_STRMATTRS.uBufsize in GPP bytes.
++ *! 11-May-2001 jeh Some code review cleanup.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 15-Dec-2000 sg Convert IALG_Fxn address from byte addr to word addr.
++ *! 04-Dec-2000 jeh Call MSG Get and Put functions.
++ *! 04-Dec-2000 ag Added SM support for node messaging.
++ *! 10-Nov-2000 rr: NODE_MIN/MAX Priority is defined in dspdefs.h.
++ *! 27-Oct-2000 jeh Added NODE_AllocMsgBuf(), NODE_FreeMsgBuf().
++ *! 11-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Added
++ *! NODE_CloseOrphans(). Remove NODE_RegisterNotifyAllNodes
++ *! 19-Jun-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/proc.h>
++#include <dspbridge/strm.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/ntfy.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cmm.h>
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/msg.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/disp.h>
++#include <dspbridge/rms_sh.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdioctl.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/gb.h>
++#ifdef DEBUG
++#include <dspbridge/uuidutil.h>
++#include <dspbridge/dbg.h>
++#endif
++
++/* ----------------------------------- This */
++#include <dspbridge/nodepriv.h>
++#include <dspbridge/node.h>
++
++/* Static/Dynamic Loader includes */
++#include <dspbridge/dbll.h>
++#include <dspbridge/nldr.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/drv.h>
++#include <dspbridge/drvdefs.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++
++#define NODE_SIGNATURE 0x45444f4e /* "EDON" */
++#define NODEMGR_SIGNATURE 0x52474d4e /* "RGMN" */
++
++#define HOSTPREFIX "/host"
++#define PIPEPREFIX "/dbpipe"
++
++#define MaxInputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumInputStreams)
++#define MaxOutputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumOutputStreams)
++
++#define NODE_GetPriority(h) ((h)->nPriority)
++#define NODE_SetPriority(hNode, nPriority) ((hNode)->nPriority = nPriority)
++#define NODE_SetState(hNode, state) ((hNode)->nState = state)
++
++#define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
++#define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
++
++#define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
++#define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
++
++#define MAXDEVNAMELEN 32 /* DSP_NDBPROPS.acName size */
++#define CREATEPHASE 1
++#define EXECUTEPHASE 2
++#define DELETEPHASE 3
++
++/* Define default STRM parameters */
++/*
++ * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
++ * or make defaults configurable.
++ */
++#define DEFAULTBUFSIZE 32
++#define DEFAULTNBUFS 2
++#define DEFAULTSEGID 0
++#define DEFAULTALIGNMENT 0
++#define DEFAULTTIMEOUT 10000
++
++#define RMSQUERYSERVER 0
++#define RMSCONFIGURESERVER 1
++#define RMSCREATENODE 2
++#define RMSEXECUTENODE 3
++#define RMSDELETENODE 4
++#define RMSCHANGENODEPRIORITY 5
++#define RMSREADMEMORY 6
++#define RMSWRITEMEMORY 7
++#define RMSCOPY 8
++#define MAXTIMEOUT 2000
++
++#define NUMRMSFXNS 9
++
++#define PWR_TIMEOUT 500 /* default PWR timeout in msec */
++
++#define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Address */
++
++/*
++ * ======== NODE_MGR ========
++ */
++struct NODE_MGR {
++ u32 dwSignature; /* For object validation */
++ struct DEV_OBJECT *hDevObject; /* Device object */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
++ struct DISP_OBJECT *hDisp; /* Node dispatcher */
++ struct LST_LIST *nodeList; /* List of all allocated nodes */
++ u32 uNumNodes; /* Number of nodes in nodeList */
++ u32 uNumCreated; /* Number of nodes *created* on DSP */
++ struct GB_TMap *pipeMap; /* Pipe connection bit map */
++ struct GB_TMap *pipeDoneMap; /* Pipes that are half free */
++ struct GB_TMap *chnlMap; /* Channel allocation bit map */
++ struct GB_TMap *dmaChnlMap; /* DMA Channel allocation bit map */
++ struct GB_TMap *zChnlMap; /* Zero-Copy Channel alloc bit map */
++ struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++ u32 ulFxnAddrs[NUMRMSFXNS]; /* RMS function addresses */
++ struct MSG_MGR *hMsg;
++
++ /* Processor properties needed by Node Dispatcher */
++ u32 ulNumChnls; /* Total number of channels */
++ u32 ulChnlOffset; /* Offset of chnl ids rsvd for RMS */
++ u32 ulChnlBufSize; /* Buffer size for data to RMS */
++ DSP_PROCFAMILY procFamily; /* eg, 5000 */
++ DSP_PROCTYPE procType; /* eg, 5510 */
++ u32 uDSPWordSize; /* Size of DSP word on host bytes */
++ u32 uDSPDataMauSize; /* Size of DSP data MAU */
++ u32 uDSPMauSize; /* Size of MAU */
++ s32 nMinPri; /* Minimum runtime priority for node */
++ s32 nMaxPri; /* Maximum runtime priority for node */
++
++ struct STRM_MGR *hStrmMgr; /* STRM manager */
++
++ /* Loader properties */
++ struct NLDR_OBJECT *hNldr; /* Handle to loader */
++ struct NLDR_FXNS nldrFxns; /* Handle to loader functions */
++ bool fLoaderInit; /* Loader Init function succeeded? */
++};
++
++/*
++ * ======== CONNECTTYPE ========
++ */
++enum CONNECTTYPE {
++ NOTCONNECTED = 0,
++ NODECONNECT,
++ HOSTCONNECT,
++ DEVICECONNECT,
++} ;
++
++/*
++ * ======== STREAM ========
++ */
++struct STREAM {
++ enum CONNECTTYPE type; /* Type of stream connection */
++ u32 devId; /* pipe or channel id */
++};
++
++/*
++ * ======== NODE_OBJECT ========
++ */
++struct NODE_OBJECT {
++ struct LST_ELEM listElem;
++ u32 dwSignature; /* For object validation */
++ struct NODE_MGR *hNodeMgr; /* The manager of this node */
++ struct PROC_OBJECT *hProcessor; /* Back pointer to processor */
++ struct DSP_UUID nodeId; /* Node's ID */
++ s32 nPriority; /* Node's current priority */
++ u32 uTimeout; /* Timeout for blocking NODE calls */
++ u32 uHeapSize; /* Heap Size */
++ u32 uDSPHeapVirtAddr; /* Heap Size */
++ u32 uGPPHeapVirtAddr; /* Heap Size */
++ enum NODE_TYPE nType; /* Type of node: message, task, etc */
++ enum NODE_STATE nState; /* NODE_ALLOCATED, NODE_CREATED, ... */
++ u32 uNumInputs; /* Current number of inputs */
++ u32 uNumOutputs; /* Current number of outputs */
++ u32 uMaxInputIndex; /* Current max input stream index */
++ u32 uMaxOutputIndex; /* Current max output stream index */
++ struct STREAM *inputs; /* Node's input streams */
++ struct STREAM *outputs; /* Node's output streams */
++ struct NODE_CREATEARGS createArgs; /* Args for node create function */
++ NODE_ENV nodeEnv; /* Environment returned by RMS */
++ struct DCD_GENERICOBJ dcdProps; /* Node properties from DCD */
++ struct DSP_CBDATA *pArgs; /* Optional args to pass to node */
++ struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
++ char *pstrDevName; /* device name, if device node */
++ struct SYNC_OBJECT *hSyncDone; /* Synchronize NODE_Terminate */
++ s32 nExitStatus; /* execute function return status */
++
++ /* Information needed for NODE_GetAttr() */
++ DSP_HNODE hDeviceOwner; /* If dev node, task that owns it */
++ u32 uNumGPPInputs; /* Current # of from GPP streams */
++ u32 uNumGPPOutputs; /* Current # of to GPP streams */
++ /* Current stream connections */
++ struct DSP_STREAMCONNECT *streamConnect;
++
++ /* Message queue */
++ struct MSG_QUEUE *hMsgQueue;
++
++ /* These fields used for SM messaging */
++ struct CMM_XLATOROBJECT *hXlator; /* Node's SM address translator */
++
++ /* Handle to pass to dynamic loader */
++ struct NLDR_NODEOBJECT *hNldrNode;
++ bool fLoaded; /* Code is (dynamically) loaded */
++ bool fPhaseSplit; /* Phases split in many libs or ovly */
++
++} ;
++
++/* Default buffer attributes */
++static struct DSP_BUFFERATTR NODE_DFLTBUFATTRS = {
++ 0, /* cbStruct */
++ 1, /* uSegment */
++ 0, /* uAlignment */
++};
++
++static void DeleteNode(struct NODE_OBJECT *hNode);
++static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr);
++static void FillStreamConnect(struct NODE_OBJECT *hNode1,
++ struct NODE_OBJECT *hNode2, u32 uStream1,
++ u32 uStream2);
++static void FillStreamDef(struct NODE_OBJECT *hNode,
++ struct NODE_STRMDEF *pstrmDef,
++ struct DSP_STRMATTR *pAttrs);
++static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream);
++static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
++ u32 uPhase);
++static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
++ struct NODE_OBJECT *hNode,
++ CONST struct DSP_UUID *pNodeId,
++ struct DCD_GENERICOBJ *pdcdProps);
++static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
++ struct DEV_OBJECT *hDevObject);
++static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr);
++static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace);
++static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace);
++
++#if GT_TRACE
++static struct GT_Mask NODE_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++#ifdef DSP_DMM_DEBUG
++extern u32 DMM_MemMapDump(struct DMM_OBJECT *hDmmMgr);
++#endif
++
++static u32 cRefs; /* module reference count */
++
++/* Dynamic loader functions. */
++static struct NLDR_FXNS nldrFxns = {
++ NLDR_Allocate,
++ NLDR_Create,
++ NLDR_Delete,
++ NLDR_Exit,
++ NLDR_Free,
++ NLDR_GetFxnAddr,
++ NLDR_Init,
++ NLDR_Load,
++ NLDR_Unload,
++};
++
++enum NODE_STATE NODE_GetState(HANDLE hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetState:hNode 0x%x\n", pNode);
++ return -1;
++ } else
++ return pNode->nState;
++
++}
++
++/*
++ * ======== NODE_Allocate ========
++ * Purpose:
++ * Allocate GPP resources to manage a node on the DSP.
++ */
++DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OPTIONAL IN CONST struct DSP_CBDATA *pArgs,
++ OPTIONAL IN CONST struct DSP_NODEATTRIN *pAttrIn,
++ OUT struct NODE_OBJECT **phNode)
++{
++ struct NODE_MGR *hNodeMgr;
++ struct DEV_OBJECT *hDevObject;
++ struct NODE_OBJECT *pNode = NULL;
++ enum NODE_TYPE nodeType = NODE_TASK;
++ struct NODE_MSGARGS *pmsgArgs;
++ struct NODE_TASKARGS *ptaskArgs;
++ u32 uNumStreams;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
++ u32 procId;
++ char *label;
++ u32 pulValue;
++ u32 dynextBase;
++ u32 offSet = 0;
++ u32 ulStackSegAddr, ulStackSegVal;
++ u32 ulGppMemBase;
++ struct CFG_HOSTRES hostRes;
++ u32 pMappedAddr = 0;
++ u32 mapAttrs = 0x0;
++ struct DSP_PROCESSORSTATE procStatus;
++#ifdef DSP_DMM_DEBUG
++ struct DMM_OBJECT *hDmmMgr;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++#endif
++
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDrvObject;
++ HANDLE nodeRes;
++ u32 hProcess;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hProcessor != NULL);
++ DBC_Require(phNode != NULL);
++ DBC_Require(pNodeId != NULL);
++
++ GT_5trace(NODE_debugMask, GT_ENTER, "NODE_Allocate: \thProcessor: "
++ "0x%x\tpNodeId: 0x%x\tpArgs: 0x%x\tpAttrIn: "
++ "0x%x\tphNode: 0x%x\n", hProcessor, pNodeId, pArgs, pAttrIn,
++ phNode);
++
++ *phNode = NULL;
++
++ status = PROC_GetProcessorId(hProcessor, &procId);
++
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
++ if (hNodeMgr == NULL)
++ status = DSP_EFAIL;
++
++ }
++ if (procId != DSP_UNIT)
++ goto func_cont;
++
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++
++ /* Assuming that 0 is not a valid function address */
++ if (hNodeMgr->ulFxnAddrs[0] == 0) {
++ /* No RMS on target - we currently can't handle this */
++ GT_0trace(NODE_debugMask, GT_5CLASS, "No RMS functions in base "
++ "image. Node allocation fails.\n");
++ status = DSP_EFAIL;
++ } else {
++ /* Validate pAttrIn fields, if non-NULL */
++ if (pAttrIn) {
++ /* Check if pAttrIn->iPriority is within range */
++ if (pAttrIn->iPriority < hNodeMgr->nMinPri ||
++ pAttrIn->iPriority > hNodeMgr->nMaxPri)
++ status = DSP_ERANGE;
++ }
++ }
++func_cont:
++ /* Allocate node object and fill in */
++ if (DSP_FAILED(status))
++ goto func_cont2;
++
++ MEM_AllocObject(pNode, struct NODE_OBJECT, NODE_SIGNATURE);
++ if (pNode == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont1;
++ }
++ pNode->hNodeMgr = hNodeMgr;
++ /* This critical section protects GetNodeProps */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (procId != DSP_UNIT)
++ goto func_cont3;
++
++ /* Get DSP_NDBPROPS from node database */
++ status = GetNodeProps(hNodeMgr->hDcdMgr, pNode, pNodeId,
++ &(pNode->dcdProps));
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ pNode->nodeId = *pNodeId;
++ pNode->hProcessor = hProcessor;
++ pNode->nType = pNode->dcdProps.objData.nodeObj.ndbProps.uNodeType;
++ pNode->uTimeout = pNode->dcdProps.objData.nodeObj.ndbProps.uTimeout;
++ pNode->nPriority = pNode->dcdProps.objData.nodeObj.ndbProps.iPriority;
++
++ /* Currently only C64 DSP builds support Node Dynamic * heaps */
++ /* Allocate memory for node heap */
++ pNode->createArgs.asa.taskArgs.uHeapSize = 0;
++ pNode->createArgs.asa.taskArgs.uDSPHeapAddr = 0;
++ pNode->createArgs.asa.taskArgs.uDSPHeapResAddr = 0;
++ pNode->createArgs.asa.taskArgs.uGPPHeapAddr = 0;
++ if (!pAttrIn)
++ goto func_cont3;
++
++ /* Check if we have a user allocated node heap */
++ if (!(pAttrIn->pGPPVirtAddr))
++ goto func_cont3;
++
++ /* check for page aligned Heap size */
++ if (((pAttrIn->uHeapSize) & (PG_SIZE_4K - 1))) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "NODE_Allocate: node heap page size"
++ " not aligned to 4K page, size=0x%x \n",
++ pAttrIn->uHeapSize);
++ status = DSP_EINVALIDARG;
++ } else {
++ pNode->createArgs.asa.taskArgs.uHeapSize = pAttrIn->uHeapSize;
++ pNode->createArgs.asa.taskArgs.uGPPHeapAddr =
++ (u32)pAttrIn->pGPPVirtAddr;
++ }
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ status = PROC_ReserveMemory(hProcessor,
++ pNode->createArgs.asa.taskArgs.uHeapSize + PAGE_SIZE,
++ (void **)&(pNode->createArgs.asa.taskArgs.
++ uDSPHeapResAddr));
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate:Failed to reserve "
++ "memory for Heap: 0x%x\n", status);
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: DSPProcessor_Reserve"
++ " Memory successful: 0x%x\n", status);
++ }
++#ifdef DSP_DMM_DEBUG
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_SUCCEEDED(status))
++ DMM_MemMapDump(hDmmMgr);
++#endif
++ if (DSP_FAILED(status))
++ goto func_cont3;
++
++ mapAttrs |= DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPVIRTUALADDR;
++ status = PROC_Map(hProcessor, (void *)pAttrIn->pGPPVirtAddr,
++ pNode->createArgs.asa.taskArgs.uHeapSize,
++ (void *)pNode->createArgs.asa.taskArgs.uDSPHeapResAddr,
++ (void **)&pMappedAddr, mapAttrs);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to map memory"
++ " for Heap: 0x%x\n", status);
++ } else {
++ pNode->createArgs.asa.taskArgs.uDSPHeapAddr =
++ (u32) pMappedAddr;
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate:DSPProcessor_Map"
++ " successful: 0x%x\n", status);
++ }
++
++func_cont3:
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_cont1:
++ if (pAttrIn != NULL) {
++ /* Overrides of NBD properties */
++ pNode->uTimeout = pAttrIn->uTimeout;
++ pNode->nPriority = pAttrIn->iPriority;
++ }
++func_cont2:
++ /* Create object to manage notifications */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pNode->hNtfy);
++
++ if (DSP_SUCCEEDED(status)) {
++ nodeType = NODE_GetType(pNode);
++ /* Allocate DSP_STREAMCONNECT array for device, task, and
++ * dais socket nodes. */
++ if (nodeType != NODE_MESSAGE) {
++ uNumStreams = MaxInputs(pNode) + MaxOutputs(pNode);
++ pNode->streamConnect = MEM_Calloc(uNumStreams *
++ sizeof(struct DSP_STREAMCONNECT),
++ MEM_PAGED);
++ if (uNumStreams > 0 && pNode->streamConnect == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status) && (nodeType == NODE_TASK ||
++ nodeType == NODE_DAISSOCKET)) {
++ /* Allocate arrays for maintainig stream connections */
++ pNode->inputs =
++ MEM_Calloc(MaxInputs(pNode) *
++ sizeof(struct STREAM), MEM_PAGED);
++ pNode->outputs =
++ MEM_Calloc(MaxOutputs(pNode) *
++ sizeof(struct STREAM), MEM_PAGED);
++ ptaskArgs = &(pNode->createArgs.asa.taskArgs);
++ ptaskArgs->strmInDef =
++ MEM_Calloc(MaxInputs(pNode) *
++ sizeof(struct NODE_STRMDEF),
++ MEM_PAGED);
++ ptaskArgs->strmOutDef =
++ MEM_Calloc(MaxOutputs(pNode) *
++ sizeof(struct NODE_STRMDEF),
++ MEM_PAGED);
++ if ((MaxInputs(pNode) > 0 && (pNode->inputs == NULL ||
++ ptaskArgs->strmInDef == NULL)) ||
++ (MaxOutputs(pNode) > 0 && (pNode->outputs == NULL ||
++ ptaskArgs->strmOutDef == NULL)))
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status) && (nodeType != NODE_DEVICE)) {
++ /* Create an event that will be posted when RMS_EXIT is
++ * received. */
++ status = SYNC_OpenEvent(&pNode->hSyncDone, NULL);
++ if (DSP_SUCCEEDED(status)) {
++ /*Get the shared mem mgr for this nodes dev object */
++ status = CMM_GetHandle(hProcessor, &hCmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to"
++ " get CMM Mgr handle: 0x%x\n", status);
++ } else {
++ /* Allocate a SM addr translator for this node
++ * w/ deflt attr */
++ status = CMM_XlatorCreate(&pNode->hXlator,
++ hCmmMgr, NULL);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed"
++ " to create SM translator: 0x%x\n",
++ status);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in message args */
++ if ((pArgs != NULL) && (pArgs->cbData > 0)) {
++ pmsgArgs = &(pNode->createArgs.asa.msgArgs);
++ pmsgArgs->pData = MEM_Calloc(pArgs->cbData,
++ MEM_PAGED);
++ if (pmsgArgs->pData == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ pmsgArgs->uArgLength = pArgs->cbData;
++ memcpy(pmsgArgs->pData, pArgs->cData,
++ pArgs->cbData);
++ }
++ }
++ }
++ }
++
++ if (DSP_SUCCEEDED(status) && nodeType != NODE_DEVICE) {
++ /* Create a message queue for this node */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgCreateQueue)(hNodeMgr->hMsg,
++ &pNode->hMsgQueue, 0,
++ pNode->createArgs.asa.msgArgs.uMaxMessages,
++ pNode);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Create object for dynamic loading */
++
++ status = hNodeMgr->nldrFxns.pfnAllocate(hNodeMgr->hNldr,
++ (void *) pNode,
++ &pNode->dcdProps.objData.nodeObj,
++ &pNode->hNldrNode,
++ &pNode->fPhaseSplit);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to "
++ "allocate NLDR node: 0x%x\n", status);
++ }
++ }
++
++ /* Comapare value read from Node Properties and check if it is same as
++ * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
++ * GPP Address, Read the value in that address and override the
++ * uStackSeg value in task args */
++ if (DSP_SUCCEEDED(status) &&
++ (char *)pNode->dcdProps.objData.nodeObj.ndbProps.uStackSegName !=
++ NULL) {
++ label = MEM_Calloc(sizeof(STACKSEGLABEL)+1, MEM_PAGED);
++ strncpy(label, STACKSEGLABEL, sizeof(STACKSEGLABEL)+1);
++
++ if (strcmp((char *)pNode->dcdProps.objData.nodeObj.
++ ndbProps.uStackSegName, label) == 0) {
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
++ hNldrNode, "DYNEXT_BEG", &dynextBase);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get Address for "
++ "DYNEXT_BEG: 0x%x\n", status);
++ }
++
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
++ hNldrNode, "L1DSRAM_HEAP", &pulValue);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get Address for "
++ "L1DSRAM_HEAP: 0x%x\n", status);
++ }
++
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension(), &hostRes);
++
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Allocate: Failed to get host resource "
++ "0x%x\n", status);
++ }
++
++ ulGppMemBase = hostRes.dwMemBase[1];
++ offSet = pulValue - dynextBase;
++ ulStackSegAddr = ulGppMemBase + offSet;
++ ulStackSegVal = (u32)*((REG_UWORD32 *)
++ ((u32)(ulStackSegAddr)));
++
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "StackSegVal =0x%x\n", ulStackSegVal);
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "ulStackSegAddr = 0x%x\n", ulStackSegAddr);
++
++ pNode->createArgs.asa.taskArgs.uStackSeg =
++ ulStackSegVal;
++
++ }
++
++ if (label)
++ MEM_Free(label);
++
++ }
++
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Add the node to the node manager's list of allocated
++ * nodes. */
++ LST_InitElem((struct LST_ELEM *)pNode);
++ NODE_SetState(pNode, NODE_ALLOCATED);
++
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ LST_PutTail(hNodeMgr->nodeList,
++ (struct LST_ELEM *) pNode);
++ ++(hNodeMgr->uNumNodes);
++ }
++
++ /* Exit critical section */
++ (void) SYNC_LeaveCS(hNodeMgr->hSync);
++
++ /* Preset this to assume phases are split
++ * (for overlay and dll) */
++ pNode->fPhaseSplit = true;
++
++ if (DSP_SUCCEEDED(status))
++ *phNode = pNode;
++
++
++ /* Notify all clients registered for DSP_NODESTATECHANGE. */
++ PROC_NotifyAllClients(hProcessor, DSP_NODESTATECHANGE);
++ } else {
++ /* Cleanup */
++ if (pNode)
++ DeleteNode(pNode);
++
++ }
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_SUCCEEDED(status)) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt, *phNode, 0);
++ if (pPctxt == NULL) {
++ DRV_InsertProcContext(
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt);
++ if (pPctxt != NULL) {
++ DRV_ProcUpdatestate(pPctxt,
++ PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ pPctxt->hProcessor =
++ (DSP_HPROCESSOR)hProcessor;
++ }
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject,
++ &pPctxt, *phNode, 0);
++ if (pPctxt != NULL) {
++ DRV_InsertNodeResElement(*phNode, &nodeRes,
++ pPctxt);
++ DRV_ProcNodeUpdateHeapStatus(nodeRes, true);
++ DRV_ProcNodeUpdateStatus(nodeRes, true);
++ }
++ }
++ }
++#endif
++ DBC_Ensure((DSP_FAILED(status) && (*phNode == NULL)) ||
++ (DSP_SUCCEEDED(status)
++ && MEM_IsValidHandle((*phNode), NODE_SIGNATURE)));
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_AllocMsgBuf ========
++ * Purpose:
++ * Allocates buffer for zero copy messaging.
++ */
++DBAPI NODE_AllocMsgBuf(struct NODE_OBJECT *hNode, u32 uSize,
++ OPTIONAL IN OUT struct DSP_BUFFERATTR *pAttr,
++ OUT u8 **pBuffer)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ DSP_STATUS status = DSP_SOK;
++ bool bVirtAddr = false;
++ bool bSetInfo;
++ u32 procId;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuffer != NULL);
++
++ DBC_Require(uSize > 0);
++
++ GT_4trace(NODE_debugMask, GT_ENTER,
++ "NODE_AllocMsgBuf: hNode: 0x%x\tuSize:"
++ " 0x%x\tpAttr: 0x%x\tpBuffer: %d\n", pNode, uSize, pAttr,
++ pBuffer);
++
++ if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ if (NODE_GetType(pNode) == NODE_DEVICE)
++ status = DSP_ENODETYPE;
++
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (pAttr == NULL)
++ pAttr = &NODE_DFLTBUFATTRS; /* set defaults */
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (procId != DSP_UNIT) {
++ DBC_Assert(NULL);
++ goto func_end;
++ }
++ /* If segment ID includes MEM_SETVIRTUALSEGID then pBuffer is a
++ * virt address, so set this info in this node's translator
++ * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
++ * virtual address from node's translator. */
++ if ((pAttr->uSegment & MEM_SETVIRTUALSEGID) ||
++ (pAttr->uSegment & MEM_GETVIRTUALSEGID)) {
++ bVirtAddr = true;
++ bSetInfo = (pAttr->uSegment & MEM_SETVIRTUALSEGID) ?
++ true : false;
++ pAttr->uSegment &= ~MEM_MASKVIRTUALSEGID; /* clear mask bits */
++ /* Set/get this node's translators virtual address base/size */
++ status = CMM_XlatorInfo(pNode->hXlator, pBuffer, uSize,
++ pAttr->uSegment, bSetInfo);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "NODE_AllocMsgBuf "
++ "failed: 0x%lx\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status) && (!bVirtAddr)) {
++ if (pAttr->uSegment != 1) {
++ /* Node supports single SM segment only. */
++ status = DSP_EBADSEGID;
++ }
++ /* Arbitrary SM buffer alignment not supported for host side
++ * allocs, but guaranteed for the following alignment
++ * values. */
++ switch (pAttr->uAlignment) {
++ case 0:
++ case 1:
++ case 2:
++ case 4:
++ break;
++ default:
++ /* alignment value not suportted */
++ status = DSP_EALIGNMENT;
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* allocate physical buffer from segId in node's
++ * translator */
++ (void)CMM_XlatorAllocBuf(pNode->hXlator, pBuffer,
++ uSize);
++ if (*pBuffer == NULL) {
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_AllocMsgBuf: "
++ "ERROR: Out of shared memory.\n");
++ status = DSP_EMEMORY;
++ }
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_ChangePriority ========
++ * Purpose:
++ * Change the priority of a node in the allocated state, or that is
++ * currently running or paused on the target.
++ */
++DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode, s32 nPriority)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(NODE_debugMask, GT_ENTER, "NODE_ChangePriority: "
++ "hNode: 0x%x\tnPriority: %d\n", hNode, nPriority);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_7CLASS,
++ "Invalid NODE Handle: 0x%x\n", hNode);
++ status = DSP_EHANDLE;
++ } else {
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ else if (nPriority < hNodeMgr->nMinPri ||
++ nPriority > hNodeMgr->nMaxPri)
++ status = DSP_ERANGE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ state = NODE_GetState(hNode);
++ if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
++ NODE_SetPriority(hNode, nPriority);
++ } else {
++ if (state != NODE_RUNNING) {
++ status = DSP_EWRONGSTATE;
++ goto func_cont;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetProcessorId(pNode->hProcessor,
++ &procId);
++ if (procId == DSP_UNIT) {
++ status = DISP_NodeChangePriority(hNodeMgr->
++ hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
++ hNode->nodeEnv, nPriority);
++ }
++ if (DSP_SUCCEEDED(status))
++ NODE_SetPriority(hNode, nPriority);
++
++ }
++ }
++func_cont:
++ /* Leave critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Connect ========
++ * Purpose:
++ * Connect two nodes on the DSP, or a node on the DSP to the GPP.
++ */
++DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1, u32 uStream1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream2, OPTIONAL IN struct DSP_STRMATTR *pAttrs,
++ OPTIONAL IN struct DSP_CBDATA *pConnParam)
++{
++ struct NODE_MGR *hNodeMgr;
++ char *pstrDevName = NULL;
++ enum NODE_TYPE node1Type = NODE_TASK;
++ enum NODE_TYPE node2Type = NODE_TASK;
++ struct NODE_STRMDEF *pstrmDef;
++ struct NODE_STRMDEF *pInput = NULL;
++ struct NODE_STRMDEF *pOutput = NULL;
++ struct NODE_OBJECT *hDevNode;
++ struct NODE_OBJECT *hNode;
++ struct STREAM *pStream;
++ GB_BitNum pipeId = GB_NOBITS;
++ GB_BitNum chnlId = GB_NOBITS;
++ CHNL_MODE uMode;
++ u32 dwLength;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ GT_5trace(NODE_debugMask, GT_ENTER,
++ "NODE_Connect: hNode1: 0x%x\tuStream1:"
++ " %d\thNode2: 0x%x\tuStream2: %d\tpAttrs: 0x%x\n", hNode1,
++ uStream1, hNode2, uStream2, pAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ if ((hNode1 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
++ !MEM_IsValidHandle(hNode1, NODE_SIGNATURE)) ||
++ (hNode2 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
++ !MEM_IsValidHandle(hNode2, NODE_SIGNATURE)))
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* The two nodes must be on the same processor */
++ if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
++ hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
++ hNode1->hNodeMgr != hNode2->hNodeMgr)
++ status = DSP_EFAIL;
++ /* Cannot connect a node to itself */
++ if (hNode1 == hNode2)
++ status = DSP_EFAIL;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* NODE_GetType() will return NODE_GPP if hNode =
++ * DSP_HGPPNODE. */
++ node1Type = NODE_GetType(hNode1);
++ node2Type = NODE_GetType(hNode2);
++ /* Check stream indices ranges */
++ if ((node1Type != NODE_GPP && node1Type != NODE_DEVICE &&
++ uStream1 >= MaxOutputs(hNode1)) || (node2Type != NODE_GPP &&
++ node2Type != NODE_DEVICE && uStream2 >= MaxInputs(hNode2)))
++ status = DSP_EVALUE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Only the following types of connections are allowed:
++ * task/dais socket < == > task/dais socket
++ * task/dais socket < == > device
++ * task/dais socket < == > GPP
++ *
++ * ie, no message nodes, and at least one task or dais
++ * socket node.
++ */
++ if (node1Type == NODE_MESSAGE || node2Type == NODE_MESSAGE ||
++ (node1Type != NODE_TASK && node1Type != NODE_DAISSOCKET &&
++ node2Type != NODE_TASK && node2Type != NODE_DAISSOCKET))
++ status = DSP_EFAIL;
++ }
++ /*
++ * Check stream mode. Default is STRMMODE_PROCCOPY.
++ */
++ if (DSP_SUCCEEDED(status) && pAttrs) {
++ if (pAttrs->lMode != STRMMODE_PROCCOPY)
++ status = DSP_ESTRMMODE; /* illegal stream mode */
++
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (node1Type != NODE_GPP) {
++ hNodeMgr = hNode1->hNodeMgr;
++ } else {
++ DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
++ hNodeMgr = hNode2->hNodeMgr;
++ }
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Nodes must be in the allocated state */
++ if (node1Type != NODE_GPP && NODE_GetState(hNode1) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (node2Type != NODE_GPP && NODE_GetState(hNode2) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Check that stream indices for task and dais socket nodes
++ * are not already be used. (Device nodes checked later) */
++ if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
++ pOutput = &(hNode1->createArgs.asa.taskArgs.
++ strmOutDef[uStream1]);
++ if (pOutput->szDevice != NULL)
++ status = DSP_EALREADYCONNECTED;
++
++ }
++ if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
++ pInput = &(hNode2->createArgs.asa.taskArgs.
++ strmInDef[uStream2]);
++ if (pInput->szDevice != NULL)
++ status = DSP_EALREADYCONNECTED;
++
++ }
++ }
++ /* Connecting two task nodes? */
++ if (DSP_SUCCEEDED(status) && ((node1Type == NODE_TASK ||
++ node1Type == NODE_DAISSOCKET) && (node2Type == NODE_TASK ||
++ node2Type == NODE_DAISSOCKET))) {
++ /* Find available pipe */
++ pipeId = GB_findandset(hNodeMgr->pipeMap);
++ if (pipeId == GB_NOBITS) {
++ status = DSP_ENOMORECONNECTIONS;
++ } else {
++ hNode1->outputs[uStream1].type = NODECONNECT;
++ hNode2->inputs[uStream2].type = NODECONNECT;
++ hNode1->outputs[uStream1].devId = pipeId;
++ hNode2->inputs[uStream2].devId = pipeId;
++ pOutput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
++ MEM_PAGED);
++ pInput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
++ MEM_PAGED);
++ if (pOutput->szDevice == NULL ||
++ pInput->szDevice == NULL) {
++ /* Undo the connection */
++ if (pOutput->szDevice)
++ MEM_Free(pOutput->szDevice);
++
++ if (pInput->szDevice)
++ MEM_Free(pInput->szDevice);
++
++ pOutput->szDevice = NULL;
++ pInput->szDevice = NULL;
++ GB_clear(hNodeMgr->pipeMap, pipeId);
++ status = DSP_EMEMORY;
++ } else {
++ /* Copy "/dbpipe<pipId>" name to device names */
++ sprintf(pOutput->szDevice, "%s%d",
++ PIPEPREFIX, pipeId);
++ strcpy(pInput->szDevice, pOutput->szDevice);
++ }
++ }
++ }
++ /* Connecting task node to host? */
++ if (DSP_SUCCEEDED(status) && (node1Type == NODE_GPP ||
++ node2Type == NODE_GPP)) {
++ if (node1Type == NODE_GPP) {
++ uMode = CHNL_MODETODSP;
++ } else {
++ DBC_Assert(node2Type == NODE_GPP);
++ uMode = CHNL_MODEFROMDSP;
++ }
++ /* Reserve a channel id. We need to put the name "/host<id>"
++ * in the node's createArgs, but the host
++ * side channel will not be opened until DSPStream_Open is
++ * called for this node. */
++ if (pAttrs) {
++ if (pAttrs->lMode == STRMMODE_RDMA) {
++ chnlId = GB_findandset(hNodeMgr->dmaChnlMap);
++ /* dma chans are 2nd transport chnl set
++ * ids(e.g. 16-31)*/
++ (chnlId != GB_NOBITS) ?
++ (chnlId = chnlId + hNodeMgr->ulNumChnls) :
++ chnlId;
++ } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
++ chnlId = GB_findandset(hNodeMgr->zChnlMap);
++ /* zero-copy chans are 3nd transport set
++ * (e.g. 32-47) */
++ (chnlId != GB_NOBITS) ? (chnlId = chnlId +
++ (2 * hNodeMgr->ulNumChnls)) : chnlId;
++ } else { /* must be PROCCOPY */
++ DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
++ chnlId = GB_findandset(hNodeMgr->chnlMap);
++ /* e.g. 0-15 */
++ }
++ } else {
++ /* default to PROCCOPY */
++ chnlId = GB_findandset(hNodeMgr->chnlMap);
++ }
++ if (chnlId == GB_NOBITS) {
++ status = DSP_ENOMORECONNECTIONS;
++ goto func_cont2;
++ }
++ pstrDevName = MEM_Calloc(HOSTNAMELEN + 1, MEM_PAGED);
++ if (pstrDevName != NULL)
++ goto func_cont2;
++
++ if (pAttrs) {
++ if (pAttrs->lMode == STRMMODE_RDMA) {
++ GB_clear(hNodeMgr->dmaChnlMap, chnlId -
++ hNodeMgr->ulNumChnls);
++ } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
++ GB_clear(hNodeMgr->zChnlMap, chnlId -
++ (2*hNodeMgr->ulNumChnls));
++ } else {
++ DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
++ GB_clear(hNodeMgr->chnlMap, chnlId);
++ }
++ } else {
++ GB_clear(hNodeMgr->chnlMap, chnlId);
++ }
++ status = DSP_EMEMORY;
++func_cont2:
++ if (DSP_SUCCEEDED(status)) {
++ if (hNode1 == (struct NODE_OBJECT *) DSP_HGPPNODE) {
++ hNode2->inputs[uStream2].type = HOSTCONNECT;
++ hNode2->inputs[uStream2].devId = chnlId;
++ pInput->szDevice = pstrDevName;
++ } else {
++ hNode1->outputs[uStream1].type = HOSTCONNECT;
++ hNode1->outputs[uStream1].devId = chnlId;
++ pOutput->szDevice = pstrDevName;
++ }
++ sprintf(pstrDevName, "%s%d", HOSTPREFIX, chnlId);
++ }
++ }
++ /* Connecting task node to device node? */
++ if (DSP_SUCCEEDED(status) && ((node1Type == NODE_DEVICE) ||
++ (node2Type == NODE_DEVICE))) {
++ if (node2Type == NODE_DEVICE) {
++ /* node1 == > device */
++ hDevNode = hNode2;
++ hNode = hNode1;
++ pStream = &(hNode1->outputs[uStream1]);
++ pstrmDef = pOutput;
++ } else {
++ /* device == > node2 */
++ hDevNode = hNode1;
++ hNode = hNode2;
++ pStream = &(hNode2->inputs[uStream2]);
++ pstrmDef = pInput;
++ }
++ /* Set up create args */
++ pStream->type = DEVICECONNECT;
++ dwLength = strlen(hDevNode->pstrDevName);
++ if (pConnParam != NULL) {
++ pstrmDef->szDevice = MEM_Calloc(dwLength + 1 +
++ (u32) pConnParam->cbData,
++ MEM_PAGED);
++ } else {
++ pstrmDef->szDevice = MEM_Calloc(dwLength + 1,
++ MEM_PAGED);
++ }
++ if (pstrmDef->szDevice == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Copy device name */
++ strncpy(pstrmDef->szDevice, hDevNode->pstrDevName,
++ dwLength);
++ if (pConnParam != NULL) {
++ strncat(pstrmDef->szDevice,
++ (char *)pConnParam->cData,
++ (u32)pConnParam->cbData);
++ }
++ hDevNode->hDeviceOwner = hNode;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in create args */
++ if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
++ hNode1->createArgs.asa.taskArgs.uNumOutputs++;
++ FillStreamDef(hNode1, pOutput, pAttrs);
++ }
++ if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
++ hNode2->createArgs.asa.taskArgs.uNumInputs++;
++ FillStreamDef(hNode2, pInput, pAttrs);
++ }
++ /* Update hNode1 and hNode2 streamConnect */
++ if (node1Type != NODE_GPP && node1Type != NODE_DEVICE) {
++ hNode1->uNumOutputs++;
++ if (uStream1 > hNode1->uMaxOutputIndex)
++ hNode1->uMaxOutputIndex = uStream1;
++
++ }
++ if (node2Type != NODE_GPP && node2Type != NODE_DEVICE) {
++ hNode2->uNumInputs++;
++ if (uStream2 > hNode2->uMaxInputIndex)
++ hNode2->uMaxInputIndex = uStream2;
++
++ }
++ FillStreamConnect(hNode1, hNode2, uStream1, uStream2);
++ }
++func_cont:
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Create ========
++ * Purpose:
++ * Create a node on the DSP by remotely calling the node's create function.
++ */
++DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulCreateFxn;
++ enum NODE_TYPE nodeType;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ bool bJustWokeDSP = false;
++ struct DSP_CBDATA cbData;
++ u32 procId = 255;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Create: hNode: 0x%x\n",
++ hNode);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to create
++ new node */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ /* create struct DSP_CBDATA struct for PWR calls */
++ cbData.cbData = PWR_TIMEOUT;
++ nodeType = NODE_GetType(hNode);
++ hNodeMgr = hNode->hNodeMgr;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Get access to node dispatcher */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Check node state */
++ if (NODE_GetState(hNode) != NODE_ALLOCATED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status))
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_FAILED(status))
++ goto func_cont2;
++
++ if (procId != DSP_UNIT)
++ goto func_cont2;
++
++ /* Make sure streams are properly connected */
++ if ((hNode->uNumInputs && hNode->uMaxInputIndex >
++ hNode->uNumInputs - 1) ||
++ (hNode->uNumOutputs && hNode->uMaxOutputIndex >
++ hNode->uNumOutputs - 1))
++ status = DSP_ENOTCONNECTED;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* If node's create function is not loaded, load it */
++ /* Boost the OPP level to max level that DSP can be requested */
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq) {
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP3]);
++
++ if (pdata->dsp_get_opp) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
++ "after setting to VDD1_OPP3 is %d\n",
++ (*pdata->dsp_get_opp)());
++ }
++ }
++#endif
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
++ NLDR_CREATE);
++ /* Get address of node's create function */
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ if (nodeType != NODE_DEVICE) {
++ status = GetFxnAddress(hNode, &ulCreateFxn,
++ CREATEPHASE);
++ }
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Create: failed to load"
++ " create code: 0x%x\n", status);
++ }
++ /* Request the lowest OPP level*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq) {
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
++
++ if (pdata->dsp_get_opp) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "opp level"
++ "after setting to VDD1_OPP1 is %d\n",
++ (*pdata->dsp_get_opp)());
++ }
++ }
++#endif
++ /* Get address of iAlg functions, if socket node */
++ if (DSP_SUCCEEDED(status)) {
++ if (nodeType == NODE_DAISSOCKET) {
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr
++ (hNode->hNldrNode, hNode->dcdProps.
++ objData.nodeObj.pstrIAlgName,
++ &hNode->createArgs.asa.taskArgs.
++ ulDaisArg);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (nodeType != NODE_DEVICE) {
++ status = DISP_NodeCreate(hNodeMgr->hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCREATENODE],
++ ulCreateFxn, &(hNode->createArgs),
++ &(hNode->nodeEnv));
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the message queue id to the node env
++ * pointer */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ (*pIntfFxns->pfnMsgSetQueueId)(hNode->hMsgQueue,
++ hNode->nodeEnv);
++ }
++ }
++ }
++ /* Phase II/Overlays: Create, execute, delete phases possibly in
++ * different files/sections. */
++ if (hNode->fLoaded && hNode->fPhaseSplit) {
++ /* If create code was dynamically loaded, we can now unload
++ * it. */
++ status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
++ NLDR_CREATE);
++ hNode->fLoaded = false;
++ }
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Create: Failed to unload "
++ "create code: 0x%x\n", status1);
++ }
++func_cont2:
++ /* Update node state and node manager state */
++ if (DSP_SUCCEEDED(status)) {
++ NODE_SetState(hNode, NODE_CREATED);
++ hNodeMgr->uNumCreated++;
++ goto func_cont;
++ }
++ if (status != DSP_EWRONGSTATE) {
++ /* Put back in NODE_ALLOCATED state if error occurred */
++ NODE_SetState(hNode, NODE_ALLOCATED);
++ }
++ if (procId == DSP_UNIT) {
++ /* If node create failed, see if should sleep DSP now */
++ if (bJustWokeDSP == true) {
++ /* Check to see if partial create happened on DSP */
++ if (hNode->nodeEnv == (u32)NULL) {
++ /* No environment allocated on DSP, re-sleep
++ * DSP now */
++ PROC_Ctrl(hNode->hProcessor, WMDIOCTL_DEEPSLEEP,
++ &cbData);
++ } else {
++ /* Increment count, sleep later when node fully
++ * deleted */
++ hNodeMgr->uNumCreated++;
++ }
++ }
++ }
++func_cont:
++ /* Free access to node dispatcher */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++func_end:
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++
++ return status;
++}
++
++/*
++ * ======== NODE_CreateMgr ========
++ * Purpose:
++ * Create a NODE Manager object.
++ */
++DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ u32 i;
++ struct NODE_MGR *pNodeMgr = NULL;
++ struct DISP_ATTRS dispAttrs;
++ char *szZLFile = "";
++ struct NLDR_ATTRS nldrAttrs;
++ DSP_STATUS status = DSP_SOK;
++ u32 devType;
++ DBC_Require(cRefs > 0);
++ DBC_Require(phNodeMgr != NULL);
++ DBC_Require(hDevObject != NULL);
++ GT_2trace(NODE_debugMask, GT_ENTER, "NODE_CreateMgr: phNodeMgr: 0x%x\t"
++ "hDevObject: 0x%x\n", phNodeMgr, hDevObject);
++ *phNodeMgr = NULL;
++ /* Allocate Node manager object */
++ MEM_AllocObject(pNodeMgr, struct NODE_MGR, NODEMGR_SIGNATURE);
++ if (pNodeMgr) {
++ pNodeMgr->hDevObject = hDevObject;
++ pNodeMgr->nodeList = LST_Create();
++ pNodeMgr->pipeMap = GB_create(MAXPIPES);
++ pNodeMgr->pipeDoneMap = GB_create(MAXPIPES);
++ if (pNodeMgr->nodeList == NULL || pNodeMgr->pipeMap == NULL ||
++ pNodeMgr->pipeDoneMap == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Memory "
++ "allocation failed\n");
++ } else {
++ status = NTFY_Create(&pNodeMgr->hNtfy);
++ }
++ pNodeMgr->uNumCreated = 0;
++ } else {
++ GT_0trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ /* get devNodeType */
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevType(hDevObject, &devType);
++
++ /* Create the DCD Manager */
++ if (DSP_SUCCEEDED(status)) {
++ status = DCD_CreateManager(szZLFile, &pNodeMgr->hDcdMgr);
++ if (DSP_SUCCEEDED(status))
++ status = GetProcProps(pNodeMgr, hDevObject);
++
++ }
++ /* Create NODE Dispatcher */
++ if (DSP_SUCCEEDED(status)) {
++ dispAttrs.ulChnlOffset = pNodeMgr->ulChnlOffset;
++ dispAttrs.ulChnlBufSize = pNodeMgr->ulChnlBufSize;
++ dispAttrs.procFamily = pNodeMgr->procFamily;
++ dispAttrs.procType = pNodeMgr->procType;
++ status = DISP_Create(&pNodeMgr->hDisp, hDevObject, &dispAttrs);
++ }
++ /* Create a STRM Manager */
++ if (DSP_SUCCEEDED(status))
++ status = STRM_Create(&pNodeMgr->hStrmMgr, hDevObject);
++
++ if (DSP_SUCCEEDED(status)) {
++ DEV_GetIntfFxns(hDevObject, &pNodeMgr->pIntfFxns);
++ /* Get MSG queue manager */
++ DEV_GetMsgMgr(hDevObject, &pNodeMgr->hMsg);
++ status = SYNC_InitializeCS(&pNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pNodeMgr->chnlMap = GB_create(pNodeMgr->ulNumChnls);
++ /* dma chnl map. ulNumChnls is # per transport */
++ pNodeMgr->dmaChnlMap = GB_create(pNodeMgr->ulNumChnls);
++ pNodeMgr->zChnlMap = GB_create(pNodeMgr->ulNumChnls);
++ if ((pNodeMgr->chnlMap == NULL) ||
++ (pNodeMgr->dmaChnlMap == NULL) ||
++ (pNodeMgr->zChnlMap == NULL)) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Block out reserved channels */
++ for (i = 0; i < pNodeMgr->ulChnlOffset; i++)
++ GB_set(pNodeMgr->chnlMap, i);
++
++ /* Block out channels reserved for RMS */
++ GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset);
++ GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset + 1);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* NO RM Server on the IVA */
++ if (devType != IVA_UNIT) {
++ /* Get addresses of any RMS functions loaded */
++ status = GetRMSFxns(pNodeMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Failed to"
++ " get RMS functions: status = 0x%x", status);
++ }
++ }
++ }
++
++ /* Get loader functions and create loader */
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_1CLASS,
++ "NODE_CreateMgr: using dynamic loader\n");
++ pNodeMgr->nldrFxns = nldrFxns; /* Dynamic loader functions */
++ }
++ if (DSP_SUCCEEDED(status)) {
++ nldrAttrs.pfnOvly = Ovly;
++ nldrAttrs.pfnWrite = Write;
++ nldrAttrs.usDSPWordSize = pNodeMgr->uDSPWordSize;
++ nldrAttrs.usDSPMauSize = pNodeMgr->uDSPMauSize;
++ pNodeMgr->fLoaderInit = pNodeMgr->nldrFxns.pfnInit();
++ status = pNodeMgr->nldrFxns.pfnCreate(&pNodeMgr->hNldr,
++ hDevObject, &nldrAttrs);
++ if (DSP_FAILED(status)) {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_CreateMgr: Failed to "
++ "create loader: status = 0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ *phNodeMgr = pNodeMgr;
++ else
++ DeleteNodeMgr(pNodeMgr);
++
++ DBC_Ensure((DSP_FAILED(status) && (*phNodeMgr == NULL)) ||
++ (DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle((*phNodeMgr), NODEMGR_SIGNATURE)));
++
++ return status;
++}
++
++/*
++ * ======== NODE_Delete ========
++ * Purpose:
++ * Delete a node on the DSP by remotely calling the node's delete function.
++ * Loads the node's delete function if necessary. Free GPP side resources
++ * after node's delete function returns.
++ */
++DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ struct PROC_OBJECT *hProcessor;
++ struct DISP_OBJECT *hDisp;
++ u32 ulDeleteFxn;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++ struct DSP_CBDATA cbData;
++ u32 procId;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE nodeRes;
++ HANDLE hDrvObject;
++ struct PROCESS_CONTEXT *pCtxt = NULL;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++ struct DSP_PROCESSORSTATE procStatus;
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Delete: hNode: 0x%x\n",
++ hNode);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ /* create struct DSP_CBDATA struct for PWR call */
++ cbData.cbData = PWR_TIMEOUT;
++ hNodeMgr = hNode->hNodeMgr;
++ hProcessor = hNode->hProcessor;
++ hDisp = hNodeMgr->hDisp;
++ nodeType = NODE_GetType(hNode);
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ state = NODE_GetState(hNode);
++ /* Execute delete phase code for non-device node in all cases
++ * except when the node was only allocated. Delete phase must be
++ * executed even if create phase was executed, but failed.
++ * If the node environment pointer is non-NULL, the delete phase
++ * code must be executed. */
++ if (!(state == NODE_ALLOCATED && hNode->nodeEnv == (u32)NULL) &&
++ nodeType != NODE_DEVICE) {
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (DSP_FAILED(status))
++ goto func_cont1;
++
++ if (procId == DSP_UNIT || procId == IVA_UNIT) {
++ /* If node has terminated, execute phase code will
++ * have already been unloaded in NODE_OnExit(). If the
++ * node is PAUSED, the execute phase is loaded, and it
++ * is now ok to unload it. If the node is running, we
++ * will unload the execute phase only after deleting
++ * the node. */
++ if (state == NODE_PAUSED && hNode->fLoaded &&
++ hNode->fPhaseSplit) {
++ /* Ok to unload execute code as long as node
++ * is not * running */
++ status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->
++ hNldrNode, NLDR_EXECUTE);
++ hNode->fLoaded = false;
++ NODE_SetState(hNode, NODE_DONE);
++ }
++ /* Load delete phase code if not loaded or if haven't
++ * * unloaded EXECUTE phase */
++ if ((!(hNode->fLoaded) || (state == NODE_RUNNING)) &&
++ hNode->fPhaseSplit) {
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->
++ hNldrNode, NLDR_DELETE);
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to "
++ "load delete code: 0x%x\n",
++ status);
++ }
++ }
++ }
++func_cont1:
++ if (DSP_SUCCEEDED(status)) {
++ /* Unblock a thread trying to terminate the node */
++ (void)SYNC_SetEvent(hNode->hSyncDone);
++ if (procId == DSP_UNIT) {
++ /* ulDeleteFxn = address of node's delete
++ * function */
++ status = GetFxnAddress(hNode, &ulDeleteFxn,
++ DELETEPHASE);
++ } else if (procId == IVA_UNIT)
++ ulDeleteFxn = (u32)hNode->nodeEnv;
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Delete: proc Status "
++ "0x%x\n", procStatus.iState);
++ if (procStatus.iState != PROC_ERROR) {
++ status = DISP_NodeDelete(hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSDELETENODE],
++ ulDeleteFxn, hNode->nodeEnv);
++ } else
++ NODE_SetState(hNode, NODE_DONE);
++
++ /* Unload execute, if not unloaded, and delete
++ * function */
++ if (state == NODE_RUNNING &&
++ hNode->fPhaseSplit) {
++ status1 = hNodeMgr->nldrFxns.pfnUnload(
++ hNode->hNldrNode, NLDR_EXECUTE);
++ }
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to"
++ "unload execute code: 0x%x\n",
++ status1);
++ }
++ status1 = hNodeMgr->nldrFxns.pfnUnload(
++ hNode->hNldrNode, NLDR_DELETE);
++ hNode->fLoaded = false;
++ if (DSP_FAILED(status1)) {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Delete: failed to"
++ "unload delete code: 0x%x\n",
++ status1);
++ }
++ }
++ }
++ }
++ /* Free host side resources even if a failure occurred */
++ /* Remove node from hNodeMgr->nodeList */
++ LST_RemoveElem(hNodeMgr->nodeList, (struct LST_ELEM *) hNode);
++ hNodeMgr->uNumNodes--;
++ /* Decrement count of nodes created on DSP */
++ if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
++ (hNode->nodeEnv != (u32) NULL)))
++ hNodeMgr->uNumCreated--;
++ /* Free host-side resources allocated by NODE_Create()
++ * DeleteNode() fails if SM buffers not freed by client! */
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_cont;
++ DRV_GetProcContext(0, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, hNode, 0);
++ if (pCtxt == NULL)
++ goto func_cont;
++ if (DRV_GetNodeResElement(hNode, &nodeRes, pCtxt) != DSP_ENOTFOUND) {
++ GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete12:\n");
++ DRV_ProcNodeUpdateStatus(nodeRes, false);
++ }
++#endif
++func_cont:
++ GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete13:\n ");
++ DeleteNode(hNode);
++#ifndef RES_CLEANUP_DISABLE
++ GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete2:\n ");
++ if (pCtxt != NULL)
++ DRV_RemoveNodeResElement(nodeRes, (HANDLE)pCtxt);
++#endif
++ GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete3:\n ");
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ PROC_NotifyClients(hProcessor, DSP_NODESTATECHANGE);
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_DeleteMgr ========
++ * Purpose:
++ * Delete the NODE Manager.
++ */
++DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
++
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_DeleteMgr: hNodeMgr: 0x%x\n",
++ hNodeMgr);
++ DeleteNodeMgr(hNodeMgr);
++
++ return status;
++}
++
++/*
++ * ======== NODE_EnumNodes ========
++ * Purpose:
++ * Enumerate currently allocated nodes.
++ */
++DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr, IN DSP_HNODE *aNodeTab,
++ u32 uNodeTabSize, OUT u32 *puNumNodes,
++ OUT u32 *puAllocated)
++{
++ struct NODE_OBJECT *hNode;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
++ DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(puAllocated != NULL);
++ GT_5trace(NODE_debugMask, GT_ENTER, "NODE_EnumNodes: hNodeMgr: 0x%x\t"
++ "aNodeTab: %d\tuNodeTabSize: 0x%x\tpuNumNodes: 0x%x\t"
++ "puAllocated\n", hNodeMgr, aNodeTab, uNodeTabSize, puNumNodes,
++ puAllocated);
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ if (hNodeMgr->uNumNodes > uNodeTabSize) {
++ *puAllocated = hNodeMgr->uNumNodes;
++ *puNumNodes = 0;
++ status = DSP_ESIZE;
++ } else {
++ hNode = (struct NODE_OBJECT *)LST_First(hNodeMgr->
++ nodeList);
++ for (i = 0; i < hNodeMgr->uNumNodes; i++) {
++ DBC_Assert(MEM_IsValidHandle(hNode,
++ NODE_SIGNATURE));
++ aNodeTab[i] = hNode;
++ hNode = (struct NODE_OBJECT *)LST_Next
++ (hNodeMgr->nodeList,
++ (struct LST_ELEM *)hNode);
++ }
++ *puAllocated = *puNumNodes = hNodeMgr->uNumNodes;
++ }
++ }
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ return status;
++}
++
++/*
++ * ======== NODE_Exit ========
++ * Purpose:
++ * Discontinue usage of NODE module.
++ */
++void NODE_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "Entered NODE_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== NODE_FreeMsgBuf ========
++ * Purpose:
++ * Frees the message buffer.
++ */
++DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode, IN u8 *pBuffer,
++ OPTIONAL struct DSP_BUFFERATTR *pAttr)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuffer != NULL);
++ DBC_Require(pNode != NULL);
++ DBC_Require(pNode->hXlator != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER, "NODE_FreeMsgBuf: hNode: 0x%x\t"
++ "pBuffer: 0x%x\tpAttr: 0x%x\n", hNode, pBuffer, pAttr);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++ if (procId == DSP_UNIT) {
++ if (DSP_SUCCEEDED(status)) {
++ if (pAttr == NULL) {
++ /* set defaults */
++ pAttr = &NODE_DFLTBUFATTRS;
++ }
++ /* Node supports single SM segment only */
++ if (pAttr->uSegment != 1)
++ status = DSP_EBADSEGID;
++
++ /* pBuffer is clients Va. */
++ status = CMM_XlatorFreeBuf(pNode->hXlator, pBuffer);
++ if (DSP_FAILED(status))
++ status = DSP_EFAIL;
++ else
++ status = DSP_SOK;
++
++ }
++ } else {
++ DBC_Assert(NULL); /* BUG */
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetAttr ========
++ * Purpose:
++ * Copy the current attributes of the specified node into a DSP_NODEATTR
++ * structure.
++ */
++DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
++ OUT struct DSP_NODEATTR *pAttr, u32 uAttrSize)
++{
++ struct NODE_MGR *hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(cRefs > 0);
++ DBC_Require(pAttr != NULL);
++ DBC_Require(uAttrSize >= sizeof(struct DSP_NODEATTR));
++ GT_3trace(NODE_debugMask, GT_ENTER, "NODE_GetAttr: hNode: "
++ "0x%x\tpAttr: 0x%x \tuAttrSize: 0x%x\n", hNode, pAttr,
++ uAttrSize);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ hNodeMgr = hNode->hNodeMgr;
++ /* Enter hNodeMgr critical section (since we're accessing
++ * data that could be changed by NODE_ChangePriority() and
++ * NODE_Connect(). */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ pAttr->cbStruct = sizeof(struct DSP_NODEATTR);
++ /* DSP_NODEATTRIN */
++ pAttr->inNodeAttrIn.cbStruct =
++ sizeof(struct DSP_NODEATTRIN);
++ pAttr->inNodeAttrIn.iPriority = hNode->nPriority;
++ pAttr->inNodeAttrIn.uTimeout = hNode->uTimeout;
++ pAttr->inNodeAttrIn.uHeapSize =
++ hNode->createArgs.asa.taskArgs.uHeapSize;
++ pAttr->inNodeAttrIn.pGPPVirtAddr = (void *)
++ hNode->createArgs.asa.taskArgs.uGPPHeapAddr;
++ pAttr->uInputs = hNode->uNumGPPInputs;
++ pAttr->uOutputs = hNode->uNumGPPOutputs;
++ /* DSP_NODEINFO */
++ GetNodeInfo(hNode, &(pAttr->iNodeInfo));
++ }
++ /* end of SYNC_EnterCS */
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetChannelId ========
++ * Purpose:
++ * Get the channel index reserved for a stream connection between the
++ * host and a node.
++ */
++DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
++ OUT u32 *pulId)
++{
++ enum NODE_TYPE nodeType;
++ DSP_STATUS status = DSP_EVALUE;
++ DBC_Require(cRefs > 0);
++ DBC_Require(uDir == DSP_TONODE || uDir == DSP_FROMNODE);
++ DBC_Require(pulId != NULL);
++ GT_4trace(NODE_debugMask, GT_ENTER, "NODE_GetChannelId: hNode: "
++ "0x%x\tuDir: %d\tuIndex: %d\tpulId: 0x%x\n", hNode, uDir,
++ uIndex, pulId);
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ return status;
++ }
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET) {
++ status = DSP_ENODETYPE;
++ return status;
++ }
++ if (uDir == DSP_TONODE) {
++ if (uIndex < MaxInputs(hNode)) {
++ if (hNode->inputs[uIndex].type == HOSTCONNECT) {
++ *pulId = hNode->inputs[uIndex].devId;
++ status = DSP_SOK;
++ }
++ }
++ } else {
++ DBC_Assert(uDir == DSP_FROMNODE);
++ if (uIndex < MaxOutputs(hNode)) {
++ if (hNode->outputs[uIndex].type == HOSTCONNECT) {
++ *pulId = hNode->outputs[uIndex].devId;
++ status = DSP_SOK;
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_GetMessage ========
++ * Purpose:
++ * Retrieve a message from a node on the DSP.
++ */
++DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode, OUT struct DSP_MSG *pMsg,
++ u32 uTimeout)
++{
++ struct NODE_MGR *hNodeMgr;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pMsg != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_GetMessage: hNode: 0x%x\tpMsg: "
++ "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to get the
++ message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_GetMessage:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
++ nodeType != NODE_DAISSOCKET) {
++ status = DSP_ENODETYPE;
++ goto func_end;
++ }
++ /* This function will block unless a message is available. Since
++ * DSPNode_RegisterNotify() allows notification when a message
++ * is available, the system can be designed so that
++ * DSPNode_GetMessage() is only called when a message is
++ * available. */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgGet)(hNode->hMsgQueue, pMsg, uTimeout);
++ /* Check if message contains SM descriptor */
++ if (DSP_FAILED(status) || !(pMsg->dwCmd & DSP_RMSBUFDESC))
++ goto func_end;
++
++ /* Translate DSP byte addr to GPP Va. */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
++ (void *)(pMsg->dwArg1 * hNode->hNodeMgr->uDSPWordSize),
++ CMM_DSPPA2PA);
++ if (pTmpBuf != NULL) {
++ /* now convert this GPP Pa to Va */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator, pTmpBuf,
++ CMM_PA2VA);
++ if (pTmpBuf != NULL) {
++ /* Adjust SM size in msg */
++ pMsg->dwArg1 = (u32) pTmpBuf;
++ pMsg->dwArg2 *= hNode->hNodeMgr->uDSPWordSize;
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: "
++ "Failed SM translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: Failed "
++ "SM Pa/Pa translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_GetNldrObj ========
++ */
++DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
++ struct NLDR_OBJECT **phNldrObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct NODE_MGR *pNodeMgr = hNodeMgr;
++ DBC_Require(phNldrObj != NULL);
++ GT_2trace(NODE_debugMask, GT_ENTER,
++ "Entered NODE_GetNldrObj, hNodeMgr: "
++ "0x%x\n\tphNldrObj: 0x%x\n", hNodeMgr, phNldrObj);
++ if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
++ status = DSP_EHANDLE;
++ else
++ *phNldrObj = pNodeMgr->hNldr;
++
++ GT_2trace(NODE_debugMask, GT_ENTER,
++ "Exit NODE_GetNldrObj: status 0x%x\n\t"
++ "phNldrObj: 0x%x\n", status, *phNldrObj);
++ DBC_Ensure(DSP_SUCCEEDED(status) || ((phNldrObj != NULL) &&
++ (*phNldrObj == NULL)));
++ return status;
++}
++
++/*
++ * ======== NODE_GetStrmMgr ========
++ * Purpose:
++ * Returns the Stream manager.
++ */
++DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
++ struct STRM_MGR **phStrmMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else
++ *phStrmMgr = hNode->hNodeMgr->hStrmMgr;
++
++ return status;
++}
++
++/*
++ * ======== NODE_GetLoadType ========
++ */
++enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode)
++{
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetLoadType: Failed. hNode:"
++ " 0x%x\n", hNode);
++ return -1;
++ } else
++ return hNode->dcdProps.objData.nodeObj.usLoadType;
++}
++
++/*
++ * ======== NODE_GetTimeout ========
++ * Purpose:
++ * Returns the timeout value for this node.
++ */
++u32 NODE_GetTimeout(struct NODE_OBJECT *hNode)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetTimeout: Failed. hNode:"
++ " 0x%x\n", hNode);
++ return 0;
++ } else
++ return hNode->uTimeout;
++}
++
++/*
++ * ======== NODE_GetType ========
++ * Purpose:
++ * Returns the node type.
++ */
++enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode)
++{
++ enum NODE_TYPE nodeType;
++
++ if (hNode == (struct NODE_OBJECT *) DSP_HGPPNODE)
++ nodeType = NODE_GPP;
++ else {
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ nodeType = -1;
++ else
++ nodeType = hNode->nType;
++ }
++ return nodeType;
++}
++
++/*
++ * ======== NODE_Init ========
++ * Purpose:
++ * Initialize the NODE module.
++ */
++bool NODE_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!NODE_debugMask.flags);
++ GT_create(&NODE_debugMask, "NO"); /* "NO" for NOde */
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(NODE_debugMask, GT_5CLASS, "NODE_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++ return fRetVal;
++}
++
++/*
++ * ======== NODE_OnExit ========
++ * Purpose:
++ * Gets called when RMS_EXIT is received for a node.
++ */
++void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus)
++{
++ DBC_Assert(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ /* Set node state to done */
++ NODE_SetState(hNode, NODE_DONE);
++ hNode->nExitStatus = nStatus;
++ if (hNode->fLoaded && hNode->fPhaseSplit) {
++ (void)hNode->hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
++ NLDR_EXECUTE);
++ hNode->fLoaded = false;
++ }
++ /* Unblock call to NODE_Terminate */
++ (void) SYNC_SetEvent(hNode->hSyncDone);
++ /* Notify clients */
++ PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++}
++
++/*
++ * ======== NODE_Pause ========
++ * Purpose:
++ * Suspend execution of a node currently running on the DSP.
++ */
++DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ struct NODE_MGR *hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Pause: hNode: 0x%x\n", hNode);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++
++ }
++
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (procId == IVA_UNIT)
++ status = DSP_ENOTIMPL;
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr = hNode->hNodeMgr;
++
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ /* Check node state */
++ if (state != NODE_RUNNING)
++ status = DSP_EWRONGSTATE;
++
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Pause: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DISP_NodeChangePriority(hNodeMgr->
++ hDisp, hNode,
++ hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
++ hNode->nodeEnv, NODE_SUSPENDEDPRI);
++ }
++
++ /* Update state */
++ if (DSP_SUCCEEDED(status)) {
++ NODE_SetState(hNode, NODE_PAUSED);
++ } else {
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "NODE_Pause: Failed. hNode:"
++ " 0x%x\n", hNode);
++ }
++ }
++ /* End of SYNC_EnterCS */
++ /* Leave critical section */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor,
++ DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_PutMessage ========
++ * Purpose:
++ * Send a message to a message node, task node, or XDAIS socket node. This
++ * function will block until the message stream can accommodate the
++ * message, or a timeout occurs.
++ */
++DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
++ IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ enum NODE_STATE state;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf;
++ struct DSP_MSG newMsg;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pMsg != NULL);
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_PutMessage: hNode: 0x%x\tpMsg: "
++ "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in bad state then don't attempt sending the
++ message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_PutMessage:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else {
++ hNodeMgr = hNode->hNodeMgr;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
++ nodeType != NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check node state. Can't send messages to a node after
++ * we've sent the RMS_EXIT command. There is still the
++ * possibility that NODE_Terminate can be called after we've
++ * checked the state. Could add another SYNC object to
++ * prevent this (can't use hNodeMgr->hSync, since we don't
++ * want to block other NODE functions). However, the node may
++ * still exit on its own, before this message is sent. */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ if (state == NODE_TERMINATING || state == NODE_DONE)
++ status = DSP_EWRONGSTATE;
++
++ }
++ /* end of SYNC_EnterCS */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* assign pMsg values to new msg */
++ newMsg = *pMsg;
++ /* Now, check if message contains a SM buffer descriptor */
++ if (pMsg->dwCmd & DSP_RMSBUFDESC) {
++ /* Translate GPP Va to DSP physical buf Ptr. */
++ pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
++ (void *)newMsg.dwArg1, CMM_VA2DSPPA);
++ if (pTmpBuf != NULL) {
++ /* got translation, convert to MAUs in msg */
++ if (hNode->hNodeMgr->uDSPWordSize != 0) {
++ newMsg.dwArg1 =
++ (u32)pTmpBuf /
++ hNode->hNodeMgr->uDSPWordSize;
++ /* MAUs */
++ newMsg.dwArg2 /= hNode->hNodeMgr->uDSPWordSize;
++ } else {
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_PutMessage: "
++ "uDSPWordSize is zero!\n");
++ status = DSP_EFAIL; /* bad DSPWordSize */
++ }
++ } else { /* failed to translate buffer address */
++ GT_0trace(NODE_debugMask, GT_7CLASS,
++ "NODE_PutMessage: Failed to"
++ " translate SM address\n");
++ status = DSP_ETRANSLATE;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue,
++ &newMsg, uTimeout);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this node.
++ */
++DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hNotification != NULL);
++
++ GT_4trace(NODE_debugMask, GT_ENTER,
++ "NODE_RegisterNotify: hNode: 0x%x\t"
++ "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
++ hNode, uEventMask, uNotifyType, hNotification);
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ /* Check if event mask is a valid node related event */
++ if (uEventMask & ~(DSP_NODESTATECHANGE |
++ DSP_NODEMESSAGEREADY))
++ status = DSP_EVALUE;
++
++ /* Check if notify type is valid */
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_EVALUE;
++
++ /* Only one Notification can be registered at a
++ * time - Limitation */
++ if (uEventMask == (DSP_NODESTATECHANGE |
++ DSP_NODEMESSAGEREADY))
++ status = DSP_EVALUE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (uEventMask == DSP_NODESTATECHANGE) {
++ status = NTFY_Register(hNode->hNtfy, hNotification,
++ uEventMask & DSP_NODESTATECHANGE, uNotifyType);
++ } else {
++ /* Send Message part of event mask to MSG */
++ pIntfFxns = hNode->hNodeMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnMsgRegisterNotify)
++ (hNode->hMsgQueue,
++ uEventMask & DSP_NODEMESSAGEREADY, uNotifyType,
++ hNotification);
++ }
++
++ }
++ return status;
++}
++
++/*
++ * ======== NODE_Run ========
++ * Purpose:
++ * Start execution of a node's execute phase, or resume execution of a node
++ * that has been suspended (via NODE_NodePause()) on the DSP. Load the
++ * node's execute function if necessary.
++ */
++DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr;
++ enum NODE_TYPE nodeType;
++ enum NODE_STATE state;
++ u32 ulExecuteFxn;
++ u32 ulFxnAddr;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct DSP_PROCESSORSTATE procStatus;
++ struct PROC_OBJECT *hProcessor;
++
++ DBC_Require(cRefs > 0);
++ GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Run: hNode: 0x%x\n", hNode);
++ hProcessor = hNode->hProcessor;
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt to run the node */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Run:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType == NODE_DEVICE)
++ status = DSP_ENODETYPE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ hNodeMgr = hNode->hNodeMgr;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ /* Enter critical section */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ state = NODE_GetState(hNode);
++ if (state != NODE_CREATED && state != NODE_PAUSED)
++ status = DSP_EWRONGSTATE;
++
++ if (DSP_SUCCEEDED(status))
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_FAILED(status))
++ goto func_cont1;
++
++ if ((procId != DSP_UNIT) && (procId != IVA_UNIT))
++ goto func_cont1;
++
++ if (state == NODE_CREATED) {
++ /* If node's execute function is not loaded, load it */
++ if (!(hNode->fLoaded) && hNode->fPhaseSplit) {
++ status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
++ NLDR_EXECUTE);
++ if (DSP_SUCCEEDED(status)) {
++ hNode->fLoaded = true;
++ } else {
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Run: failed to load "
++ "execute code:0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get address of node's execute function */
++ if (procId == IVA_UNIT)
++ ulExecuteFxn = (u32) hNode->nodeEnv;
++ else {
++ status = GetFxnAddress(hNode, &ulExecuteFxn,
++ EXECUTEPHASE);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSEXECUTENODE];
++ status = DISP_NodeRun(hNodeMgr->hDisp, hNode, ulFxnAddr,
++ ulExecuteFxn, hNode->nodeEnv);
++ }
++ } else if (state == NODE_PAUSED) {
++ ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY];
++ status = DISP_NodeChangePriority(hNodeMgr->hDisp, hNode,
++ ulFxnAddr, hNode->nodeEnv,
++ NODE_GetPriority(hNode));
++ } else {
++ /* We should never get here */
++ DBC_Assert(false);
++ }
++func_cont1:
++ /* Update node state. */
++ if (DSP_SUCCEEDED(status))
++ NODE_SetState(hNode, NODE_RUNNING);
++ else /* Set state back to previous value */
++ NODE_SetState(hNode, state);
++ /*End of SYNC_EnterCS */
++ /* Exit critical section */
++func_cont:
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ PROC_NotifyClients(hNode->hProcessor,
++ DSP_NODESTATECHANGE);
++ NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== NODE_Terminate ========
++ * Purpose:
++ * Signal a node running on the DSP that it should exit its execute phase
++ * function.
++ */
++DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode, OUT DSP_STATUS *pStatus)
++{
++ struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
++ struct NODE_MGR *hNodeMgr = NULL;
++ enum NODE_TYPE nodeType;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ enum NODE_STATE state;
++ struct DSP_MSG msg, killmsg;
++ DSP_STATUS status = DSP_SOK;
++ u32 procId, killTimeOut;
++ struct DEH_MGR *hDehMgr;
++ struct DSP_PROCESSORSTATE procStatus;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pStatus != NULL);
++
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Terminate: hNode: 0x%x\n", hNode);
++
++ if (pNode->hProcessor == NULL) {
++ GT_1trace(NODE_debugMask, GT_4CLASS,
++ "NODE_Terminate: pNode->hProcessor = 0x%x\n",
++ pNode->hProcessor);
++ goto func_end;
++ }
++ status = PROC_GetProcessorId(pNode->hProcessor, &procId);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr = hNode->hNodeMgr;
++
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
++ status = DSP_EHANDLE;
++ else {
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_TASK && nodeType !=
++ NODE_DAISSOCKET)
++ status = DSP_ENODETYPE;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Check node state */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ state = NODE_GetState(hNode);
++ if (state != NODE_RUNNING) {
++ status = DSP_EWRONGSTATE;
++ /* Set the exit status if node terminated on
++ * its own. */
++ if (state == NODE_DONE)
++ *pStatus = hNode->nExitStatus;
++
++ } else {
++ NODE_SetState(hNode, NODE_TERMINATING);
++ }
++ }
++ /* end of SYNC_EnterCS */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /*
++ * Send exit message. Do not change state to NODE_DONE
++ * here. That will be done in callback.
++ */
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_Terminate: env = 0x%x\n", hNode->nodeEnv);
++
++ status = PROC_GetState(pNode->hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_cont;
++ /* If processor is in error state then don't attempt to send
++ * A kill task command */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Terminate:"
++ " proc Status 0x%x\n", procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_cont;
++ }
++
++ msg.dwCmd = RMS_EXIT;
++ msg.dwArg1 = hNode->nodeEnv;
++ killmsg.dwCmd = RMS_KILLTASK;
++ killmsg.dwArg1 = hNode->nodeEnv;
++ pIntfFxns = hNodeMgr->pIntfFxns;
++
++ if (hNode->uTimeout > MAXTIMEOUT)
++ killTimeOut = MAXTIMEOUT;
++ else
++ killTimeOut = (hNode->uTimeout)*2;
++
++ status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue, &msg,
++ hNode->uTimeout);
++ if (DSP_SUCCEEDED(status)) {
++ /* Wait on synchronization object that will be
++ * posted in the callback on receiving RMS_EXIT
++ * message, or by NODE_Delete. Check for valid hNode,
++ * in case posted by NODE_Delete(). */
++ status = SYNC_WaitOnEvent(hNode->hSyncDone,
++ killTimeOut/2);
++ if (DSP_FAILED(status)) {
++ if (status == DSP_ETIMEOUT) {
++ status = (*pIntfFxns->pfnMsgPut)
++ (hNode->hMsgQueue, &killmsg,
++ hNode->uTimeout);
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_WaitOnEvent
++ (hNode->hSyncDone,
++ killTimeOut/2);
++ if (DSP_FAILED(status)) {
++ /* Here it goes the part
++ * of the simulation of
++ * the DSP exception */
++ DEV_GetDehMgr(hNodeMgr->
++ hDevObject, &hDehMgr);
++ if (hDehMgr) {
++ (*pIntfFxns->
++ pfnDehNotify)(hDehMgr,
++ DSP_SYSERROR,
++ DSP_EXCEPTIONABORT);
++ status = DSP_EFAIL;
++ }
++ } else
++ status = DSP_SOK;
++ }
++ } else
++ status = DSP_EFAIL;
++ } else /* Convert SYNC status to DSP status */
++ status = DSP_SOK;
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Enter CS before getting exit status, in case node was
++ * deleted. */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++ /* Make sure node wasn't deleted while we blocked */
++ if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
++ status = DSP_EFAIL;
++ } else {
++ *pStatus = hNode->nExitStatus;
++ GT_1trace(NODE_debugMask, GT_ENTER,
++ "NODE_Terminate: env = 0x%x "
++ "succeeded.\n", hNode->nodeEnv);
++ }
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ } /*End of SYNC_EnterCS */
++func_end:
++ return status;
++}
++
++/*
++ * ======== DeleteNode ========
++ * Purpose:
++ * Free GPP resources allocated in NODE_Allocate() or NODE_Connect().
++ */
++static void DeleteNode(struct NODE_OBJECT *hNode)
++{
++ struct NODE_MGR *hNodeMgr;
++ struct CMM_XLATOROBJECT *hXlator;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 i;
++ enum NODE_TYPE nodeType;
++ struct STREAM stream;
++ struct NODE_MSGARGS msgArgs;
++ struct NODE_TASKARGS taskArgs;
++#ifdef DSP_DMM_DEBUG
++ struct DMM_OBJECT *hDmmMgr;
++ struct PROC_OBJECT *pProcObject =
++ (struct PROC_OBJECT *)hNode->hProcessor;
++#endif
++ DSP_STATUS status;
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ hNodeMgr = hNode->hNodeMgr;
++ if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
++ return;
++ hXlator = hNode->hXlator;
++ nodeType = NODE_GetType(hNode);
++ if (nodeType != NODE_DEVICE) {
++ msgArgs = hNode->createArgs.asa.msgArgs;
++ if (msgArgs.pData)
++ MEM_Free(msgArgs.pData);
++
++ /* Free MSG queue */
++ if (hNode->hMsgQueue) {
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ (*pIntfFxns->pfnMsgDeleteQueue) (hNode->hMsgQueue);
++ hNode->hMsgQueue = NULL;
++
++ }
++ if (hNode->hSyncDone)
++ (void) SYNC_CloseEvent(hNode->hSyncDone);
++
++ /* Free all stream info */
++ if (hNode->inputs) {
++ for (i = 0; i < MaxInputs(hNode); i++) {
++ stream = hNode->inputs[i];
++ FreeStream(hNodeMgr, stream);
++ }
++ MEM_Free(hNode->inputs);
++ hNode->inputs = NULL;
++ }
++ if (hNode->outputs) {
++ for (i = 0; i < MaxOutputs(hNode); i++) {
++ stream = hNode->outputs[i];
++ FreeStream(hNodeMgr, stream);
++ }
++ MEM_Free(hNode->outputs);
++ hNode->outputs = NULL;
++ }
++ taskArgs = hNode->createArgs.asa.taskArgs;
++ if (taskArgs.strmInDef) {
++ for (i = 0; i < MaxInputs(hNode); i++) {
++ if (taskArgs.strmInDef[i].szDevice) {
++ MEM_Free(taskArgs.strmInDef[i].
++ szDevice);
++ taskArgs.strmInDef[i].szDevice = NULL;
++ }
++ }
++ MEM_Free(taskArgs.strmInDef);
++ taskArgs.strmInDef = NULL;
++ }
++ if (taskArgs.strmOutDef) {
++ for (i = 0; i < MaxOutputs(hNode); i++) {
++ if (taskArgs.strmOutDef[i].szDevice) {
++ MEM_Free(taskArgs.strmOutDef[i].
++ szDevice);
++ taskArgs.strmOutDef[i].szDevice = NULL;
++ }
++ }
++ MEM_Free(taskArgs.strmOutDef);
++ taskArgs.strmOutDef = NULL;
++ }
++ if (taskArgs.uDSPHeapResAddr) {
++ status = PROC_UnMap(hNode->hProcessor,
++ (void *)taskArgs.uDSPHeapAddr);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnMap succeeded.\n");
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnMap failed."
++ " Status = 0x%x\n", (u32)status);
++ }
++ status = PROC_UnReserveMemory(hNode->hProcessor,
++ (void *)taskArgs.uDSPHeapResAddr);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnReserveMemory "
++ "succeeded.\n");
++ } else {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "DSPProcessor_UnReserveMemory "
++ "failed. Status = 0x%x\n",
++ (u32)status);
++ }
++#ifdef DSP_DMM_DEBUG
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_SUCCEEDED(status))
++ DMM_MemMapDump(hDmmMgr);
++#endif
++ }
++ }
++ if (nodeType != NODE_MESSAGE) {
++ if (hNode->streamConnect) {
++ MEM_Free(hNode->streamConnect);
++ hNode->streamConnect = NULL;
++ }
++ }
++ if (hNode->pstrDevName) {
++ MEM_Free(hNode->pstrDevName);
++ hNode->pstrDevName = NULL;
++ }
++
++ if (hNode->hNtfy) {
++ NTFY_Delete(hNode->hNtfy);
++ hNode->hNtfy = NULL;
++ }
++
++ /* These were allocated in DCD_GetObjectDef (via NODE_Allocate) */
++ if (hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn);
++ hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn = NULL;
++ }
++
++ if (hNode->dcdProps.objData.nodeObj.pstrIAlgName) {
++ MEM_Free(hNode->dcdProps.objData.nodeObj.pstrIAlgName);
++ hNode->dcdProps.objData.nodeObj.pstrIAlgName = NULL;
++ }
++
++ /* Free all SM address translator resources */
++ if (hXlator) {
++ (void) CMM_XlatorDelete(hXlator, TRUE); /* force free */
++ hXlator = NULL;
++ }
++
++ if (hNode->hNldrNode) {
++ hNodeMgr->nldrFxns.pfnFree(hNode->hNldrNode);
++ hNode->hNldrNode = NULL;
++ }
++
++ MEM_FreeObject(hNode);
++ hNode = NULL;
++}
++
++/*
++ * ======== DeleteNodeMgr ========
++ * Purpose:
++ * Frees the node manager.
++ */
++static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr)
++{
++ struct NODE_OBJECT *hNode;
++
++ if (MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE)) {
++ /* Free resources */
++ if (hNodeMgr->hDcdMgr)
++ DCD_DestroyManager(hNodeMgr->hDcdMgr);
++
++ /* Remove any elements remaining in lists */
++ if (hNodeMgr->nodeList) {
++ while ((hNode =
++ (struct NODE_OBJECT *)LST_GetHead(hNodeMgr->
++ nodeList)))
++ DeleteNode(hNode);
++
++ DBC_Assert(LST_IsEmpty(hNodeMgr->nodeList));
++ LST_Delete(hNodeMgr->nodeList);
++ }
++ if (hNodeMgr->hNtfy)
++ NTFY_Delete(hNodeMgr->hNtfy);
++
++ if (hNodeMgr->pipeMap)
++ GB_delete(hNodeMgr->pipeMap);
++
++ if (hNodeMgr->pipeDoneMap)
++ GB_delete(hNodeMgr->pipeDoneMap);
++
++ if (hNodeMgr->chnlMap)
++ GB_delete(hNodeMgr->chnlMap);
++
++ if (hNodeMgr->dmaChnlMap)
++ GB_delete(hNodeMgr->dmaChnlMap);
++
++ if (hNodeMgr->zChnlMap)
++ GB_delete(hNodeMgr->zChnlMap);
++
++ if (hNodeMgr->hDisp)
++ DISP_Delete(hNodeMgr->hDisp);
++
++ if (hNodeMgr->hSync)
++ SYNC_DeleteCS(hNodeMgr->hSync);
++
++ if (hNodeMgr->hStrmMgr)
++ STRM_Delete(hNodeMgr->hStrmMgr);
++
++ /* Delete the loader */
++ if (hNodeMgr->hNldr)
++ hNodeMgr->nldrFxns.pfnDelete(hNodeMgr->hNldr);
++
++ if (hNodeMgr->fLoaderInit)
++ hNodeMgr->nldrFxns.pfnExit();
++
++ MEM_FreeObject(hNodeMgr);
++ }
++}
++
++/*
++ * ======== FillStreamConnect ========
++ * Purpose:
++ * Fills stream information.
++ */
++static void FillStreamConnect(struct NODE_OBJECT *hNode1,
++ struct NODE_OBJECT *hNode2,
++ u32 uStream1, u32 uStream2)
++{
++ u32 uStrmIndex;
++ struct DSP_STREAMCONNECT *pStrm1 = NULL;
++ struct DSP_STREAMCONNECT *pStrm2 = NULL;
++ enum NODE_TYPE node1Type = NODE_TASK;
++ enum NODE_TYPE node2Type = NODE_TASK;
++
++ node1Type = NODE_GetType(hNode1);
++ node2Type = NODE_GetType(hNode2);
++ if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
++
++ if (node1Type != NODE_DEVICE) {
++ uStrmIndex = hNode1->uNumInputs +
++ hNode1->uNumOutputs - 1;
++ pStrm1 = &(hNode1->streamConnect[uStrmIndex]);
++ pStrm1->cbStruct = sizeof(struct DSP_STREAMCONNECT);
++ pStrm1->uThisNodeStreamIndex = uStream1;
++ }
++
++ if (hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
++ /* NODE == > NODE */
++ if (node1Type != NODE_DEVICE) {
++ pStrm1->hConnectedNode = hNode2;
++ pStrm1->uiConnectedNodeID = hNode2->nodeId;
++ pStrm1->uConnectedNodeStreamIndex = uStream2;
++ pStrm1->lType = CONNECTTYPE_NODEOUTPUT;
++ }
++ if (node2Type != NODE_DEVICE) {
++ uStrmIndex = hNode2->uNumInputs +
++ hNode2->uNumOutputs - 1;
++ pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
++ pStrm2->cbStruct =
++ sizeof(struct DSP_STREAMCONNECT);
++ pStrm2->uThisNodeStreamIndex = uStream2;
++ pStrm2->hConnectedNode = hNode1;
++ pStrm2->uiConnectedNodeID = hNode1->nodeId;
++ pStrm2->uConnectedNodeStreamIndex = uStream1;
++ pStrm2->lType = CONNECTTYPE_NODEINPUT;
++ }
++ } else if (node1Type != NODE_DEVICE)
++ pStrm1->lType = CONNECTTYPE_GPPOUTPUT;
++ } else {
++ /* GPP == > NODE */
++ DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
++ uStrmIndex = hNode2->uNumInputs + hNode2->uNumOutputs - 1;
++ pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
++ pStrm2->cbStruct = sizeof(struct DSP_STREAMCONNECT);
++ pStrm2->uThisNodeStreamIndex = uStream2;
++ pStrm2->lType = CONNECTTYPE_GPPINPUT;
++ }
++}
++
++/*
++ * ======== FillStreamDef ========
++ * Purpose:
++ * Fills Stream attributes.
++ */
++static void FillStreamDef(struct NODE_OBJECT *hNode,
++ struct NODE_STRMDEF *pstrmDef,
++ struct DSP_STRMATTR *pAttrs)
++{
++ struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
++
++ if (pAttrs != NULL) {
++ pstrmDef->uNumBufs = pAttrs->uNumBufs;
++ pstrmDef->uBufsize = pAttrs->uBufsize / hNodeMgr->
++ uDSPDataMauSize;
++ pstrmDef->uSegid = pAttrs->uSegid;
++ pstrmDef->uAlignment = pAttrs->uAlignment;
++ pstrmDef->uTimeout = pAttrs->uTimeout;
++ } else {
++ pstrmDef->uNumBufs = DEFAULTNBUFS;
++ pstrmDef->uBufsize = DEFAULTBUFSIZE / hNodeMgr->
++ uDSPDataMauSize;
++ pstrmDef->uSegid = DEFAULTSEGID;
++ pstrmDef->uAlignment = DEFAULTALIGNMENT;
++ pstrmDef->uTimeout = DEFAULTTIMEOUT;
++ }
++}
++
++/*
++ * ======== FreeStream ========
++ * Purpose:
++ * Updates the channel mask and frees the pipe id.
++ */
++static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream)
++{
++ /* Free up the pipe id unless other node has not yet been deleted. */
++ if (stream.type == NODECONNECT) {
++ if (GB_test(hNodeMgr->pipeDoneMap, stream.devId)) {
++ /* The other node has already been deleted */
++ GB_clear(hNodeMgr->pipeDoneMap, stream.devId);
++ GB_clear(hNodeMgr->pipeMap, stream.devId);
++ } else {
++ /* The other node has not been deleted yet */
++ GB_set(hNodeMgr->pipeDoneMap, stream.devId);
++ }
++ } else if (stream.type == HOSTCONNECT) {
++ if (stream.devId < hNodeMgr->ulNumChnls) {
++ GB_clear(hNodeMgr->chnlMap, stream.devId);
++ } else if (stream.devId < (2 * hNodeMgr->ulNumChnls)) {
++ /* dsp-dma */
++ GB_clear(hNodeMgr->dmaChnlMap, stream.devId -
++ (1 * hNodeMgr->ulNumChnls));
++ } else if (stream.devId < (3 * hNodeMgr->ulNumChnls)) {
++ /* zero-copy */
++ GB_clear(hNodeMgr->zChnlMap, stream.devId -
++ (2 * hNodeMgr->ulNumChnls));
++ }
++ }
++}
++
++/*
++ * ======== GetFxnAddress ========
++ * Purpose:
++ * Retrieves the address for create, execute or delete phase for a node.
++ */
++static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
++ u32 uPhase)
++{
++ char *pstrFxnName = NULL;
++ struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
++ DSP_STATUS status = DSP_SOK;
++ DBC_Require(NODE_GetType(hNode) == NODE_TASK ||
++ NODE_GetType(hNode) == NODE_DAISSOCKET ||
++ NODE_GetType(hNode) == NODE_MESSAGE);
++
++ switch (uPhase) {
++ case CREATEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrCreatePhaseFxn;
++ break;
++ case EXECUTEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrExecutePhaseFxn;
++ break;
++ case DELETEPHASE:
++ pstrFxnName = hNode->dcdProps.objData.nodeObj.
++ pstrDeletePhaseFxn;
++ break;
++ default:
++ /* Should never get here */
++ DBC_Assert(false);
++ break;
++ }
++
++ status = hNodeMgr->nldrFxns.pfnGetFxnAddr(hNode->hNldrNode, pstrFxnName,
++ pulFxnAddr);
++
++ return status;
++}
++
++/*
++ * ======== GetNodeInfo ========
++ * Purpose:
++ * Retrieves the node information.
++ */
++void GetNodeInfo(struct NODE_OBJECT *hNode, struct DSP_NODEINFO *pNodeInfo)
++{
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ DBC_Require(pNodeInfo != NULL);
++
++ pNodeInfo->cbStruct = sizeof(struct DSP_NODEINFO);
++ pNodeInfo->nbNodeDatabaseProps = hNode->dcdProps.objData.nodeObj.
++ ndbProps;
++ pNodeInfo->uExecutionPriority = hNode->nPriority;
++ pNodeInfo->hDeviceOwner = hNode->hDeviceOwner;
++ pNodeInfo->uNumberStreams = hNode->uNumInputs + hNode->uNumOutputs;
++ pNodeInfo->uNodeEnv = hNode->nodeEnv;
++
++ pNodeInfo->nsExecutionState = NODE_GetState(hNode);
++
++ /* Copy stream connect data */
++ for (i = 0; i < hNode->uNumInputs + hNode->uNumOutputs; i++)
++ pNodeInfo->scStreamConnection[i] = hNode->streamConnect[i];
++
++}
++
++/*
++ * ======== GetNodeProps ========
++ * Purpose:
++ * Retrieve node properties.
++ */
++static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
++ struct NODE_OBJECT *hNode,
++ CONST struct DSP_UUID *pNodeId,
++ struct DCD_GENERICOBJ *pdcdProps)
++{
++ u32 uLen;
++ struct NODE_MSGARGS *pMsgArgs;
++ struct NODE_TASKARGS *pTaskArgs;
++ enum NODE_TYPE nodeType = NODE_TASK;
++ struct DSP_NDBPROPS *pndbProps = &(pdcdProps->objData.nodeObj.ndbProps);
++ DSP_STATUS status = DSP_SOK;
++#ifdef DEBUG
++ char szUuid[MAXUUIDLEN];
++#endif
++
++ status = DCD_GetObjectDef(hDcdMgr, (struct DSP_UUID *)pNodeId,
++ DSP_DCDNODETYPE, pdcdProps);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNode->nType = nodeType = pndbProps->uNodeType;
++
++#ifdef DEBUG
++ /* Create UUID value to set in registry. */
++ UUID_UuidToString((struct DSP_UUID *)pNodeId, szUuid,
++ MAXUUIDLEN);
++ DBG_Trace(DBG_LEVEL7, "\n** (node) UUID: %s\n", szUuid);
++#endif
++
++ /* Fill in message args that come from NDB */
++ if (nodeType != NODE_DEVICE) {
++ pMsgArgs = &(hNode->createArgs.asa.msgArgs);
++ pMsgArgs->uSegid = pdcdProps->objData.nodeObj.uMsgSegid;
++ pMsgArgs->uNotifyType = pdcdProps->objData.nodeObj.
++ uMsgNotifyType;
++ pMsgArgs->uMaxMessages = pndbProps->uMessageDepth;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (node) Max Number of Messages: 0x%x\n",
++ pMsgArgs->uMaxMessages);
++#endif
++ } else {
++ /* Copy device name */
++ DBC_Require(pndbProps->acName);
++ uLen = strlen(pndbProps->acName);
++ DBC_Assert(uLen < MAXDEVNAMELEN);
++ hNode->pstrDevName = MEM_Calloc(uLen + 1, MEM_PAGED);
++ if (hNode->pstrDevName == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ strncpy(hNode->pstrDevName,
++ pndbProps->acName, uLen);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in create args that come from NDB */
++ if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
++ pTaskArgs = &(hNode->createArgs.asa.taskArgs);
++ pTaskArgs->nPriority = pndbProps->iPriority;
++ pTaskArgs->uStackSize = pndbProps->uStackSize;
++ pTaskArgs->uSysStackSize = pndbProps->uSysStackSize;
++ pTaskArgs->uStackSeg = pndbProps->uStackSeg;
++#ifdef DEBUG
++ DBG_Trace(DBG_LEVEL7,
++ "** (node) Priority: 0x%x\n" "** (node) Stack"
++ " Size: 0x%x words\n" "** (node) System Stack"
++ " Size: 0x%x words\n" "** (node) Stack"
++ " Segment: 0x%x\n\n",
++ "** (node) profile count : 0x%x \n \n",
++ pTaskArgs->nPriority, pTaskArgs->uStackSize,
++ pTaskArgs->uSysStackSize,
++ pTaskArgs->uStackSeg,
++ pndbProps->uCountProfiles);
++#endif
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== GetProcProps ========
++ * Purpose:
++ * Retrieve the processor properties.
++ */
++static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ struct CFG_DEVNODE *hDevNode;
++ struct CFG_HOSTRES hostRes;
++ DSP_STATUS status = DSP_SOK;
++
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++ if (DSP_SUCCEEDED(status))
++ status = CFG_GetHostResources(hDevNode, &hostRes);
++
++ if (DSP_SUCCEEDED(status)) {
++ hNodeMgr->ulChnlOffset = hostRes.dwChnlOffset;
++ hNodeMgr->ulChnlBufSize = hostRes.dwChnlBufSize;
++ hNodeMgr->ulNumChnls = hostRes.dwNumChnls;
++
++ /*
++ * PROC will add an API to get DSP_PROCESSORINFO.
++ * Fill in default values for now.
++ */
++ /* TODO -- Instead of hard coding, take from registry */
++ hNodeMgr->procFamily = 6000;
++ hNodeMgr->procType = 6410;
++ hNodeMgr->nMinPri = DSP_NODE_MIN_PRIORITY;
++ hNodeMgr->nMaxPri = DSP_NODE_MAX_PRIORITY;
++ hNodeMgr->uDSPWordSize = DSPWORDSIZE;
++ hNodeMgr->uDSPDataMauSize = DSPWORDSIZE;
++ hNodeMgr->uDSPMauSize = 1;
++
++ }
++ return status;
++}
++
++
++
++/*
++ * ======== NODE_GetUUIDProps ========
++ * Purpose:
++ * Fetch Node UUID properties from DCD/DOF file.
++ */
++DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
++ IN CONST struct DSP_UUID *pNodeId,
++ OUT struct DSP_NDBPROPS *pNodeProps)
++{
++ struct NODE_MGR *hNodeMgr = NULL;
++ struct DEV_OBJECT *hDevObject;
++ DSP_STATUS status = DSP_SOK;
++ struct DCD_NODEPROPS dcdNodeProps;
++ struct DSP_PROCESSORSTATE procStatus;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hProcessor != NULL);
++ DBC_Require(pNodeId != NULL);
++
++ if (hProcessor == NULL || pNodeId == NULL) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ status = PROC_GetState(hProcessor, &procStatus,
++ sizeof(struct DSP_PROCESSORSTATE));
++ if (DSP_FAILED(status))
++ goto func_end;
++ /* If processor is in error state then don't attempt
++ to send the message */
++ if (procStatus.iState == PROC_ERROR) {
++ GT_1trace(NODE_debugMask, GT_5CLASS,
++ "NODE_GetUUIDProps: proc Status 0x%x\n",
++ procStatus.iState);
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++
++ GT_3trace(NODE_debugMask, GT_ENTER,
++ "NODE_GetUUIDProps: " "\thProcessor: "
++ "0x%x\tpNodeId: 0x%x" "\tpNodeProps: 0x%x\n", hProcessor,
++ pNodeId, pNodeProps);
++
++ status = PROC_GetDevObject(hProcessor, &hDevObject);
++ if (DSP_SUCCEEDED(status) && hDevObject != NULL) {
++ status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
++ if (hNodeMgr == NULL) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ }
++
++ /*
++ * Enter the critical section. This is needed because
++ * DCD_GetObjectDef will ultimately end up calling DBLL_open/close,
++ * which needs to be protected in order to not corrupt the zlib manager
++ * (COD).
++ */
++ status = SYNC_EnterCS(hNodeMgr->hSync);
++
++ if (DSP_SUCCEEDED(status)) {
++ dcdNodeProps.pstrCreatePhaseFxn = NULL;
++ dcdNodeProps.pstrExecutePhaseFxn = NULL;
++ dcdNodeProps.pstrDeletePhaseFxn = NULL;
++ dcdNodeProps.pstrIAlgName = NULL;
++
++ status = DCD_GetObjectDef(hNodeMgr->hDcdMgr,
++ (struct DSP_UUID *) pNodeId,
++ DSP_DCDNODETYPE,
++ (struct DCD_GENERICOBJ *) &dcdNodeProps);
++ if (DSP_SUCCEEDED(status)) {
++ *pNodeProps = dcdNodeProps.ndbProps;
++ if (dcdNodeProps.pstrCreatePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrCreatePhaseFxn);
++
++ if (dcdNodeProps.pstrExecutePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrExecutePhaseFxn);
++
++ if (dcdNodeProps.pstrDeletePhaseFxn)
++ MEM_Free(dcdNodeProps.pstrDeletePhaseFxn);
++
++ if (dcdNodeProps.pstrIAlgName)
++ MEM_Free(dcdNodeProps.pstrIAlgName);
++ }
++ /* Leave the critical section, we're done. */
++ (void)SYNC_LeaveCS(hNodeMgr->hSync);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== GetRMSFxns ========
++ * Purpose:
++ * Retrieve the RMS functions.
++ */
++static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr)
++{
++ s32 i;
++ struct DEV_OBJECT *hDev = hNodeMgr->hDevObject;
++ DSP_STATUS status = DSP_SOK;
++
++ static char *pszFxns[NUMRMSFXNS] = {
++ "RMS_queryServer", /* RMSQUERYSERVER */
++ "RMS_configureServer", /* RMSCONFIGURESERVER */
++ "RMS_createNode", /* RMSCREATENODE */
++ "RMS_executeNode", /* RMSEXECUTENODE */
++ "RMS_deleteNode", /* RMSDELETENODE */
++ "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
++ "RMS_readMemory", /* RMSREADMEMORY */
++ "RMS_writeMemory", /* RMSWRITEMEMORY */
++ "RMS_copy", /* RMSCOPY */
++ };
++
++ for (i = 0; i < NUMRMSFXNS; i++) {
++ status = DEV_GetSymbol(hDev, pszFxns[i],
++ &(hNodeMgr->ulFxnAddrs[i]));
++ if (DSP_FAILED(status)) {
++ if (status == COD_E_SYMBOLNOTFOUND) {
++ /*
++ * May be loaded dynamically (in the future),
++ * but return an error for now.
++ */
++ GT_1trace(NODE_debugMask, GT_6CLASS,
++ "RMS function: %s "
++ "currently not loaded\n", pszFxns[i]);
++ } else {
++ GT_2trace(NODE_debugMask, GT_6CLASS,
++ "GetRMSFxns: Symbol not "
++ "found: %s\tstatus = 0x%x\n",
++ pszFxns[i], status);
++ break;
++ }
++ }
++ }
++
++ return status;
++}
++
++/*
++ * ======== Ovly ========
++ * Purpose:
++ * Called during overlay.Sends command to RMS to copy a block of data.
++ */
++static u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct NODE_OBJECT *hNode = (struct NODE_OBJECT *)pPrivRef;
++ struct NODE_MGR *hNodeMgr;
++ u32 ulBytes = 0;
++ u32 ulSize;
++ u32 ulTimeout;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++
++ hNodeMgr = hNode->hNodeMgr;
++
++ ulSize = ulNumBytes / hNodeMgr->uDSPWordSize;
++ ulTimeout = hNode->uTimeout;
++
++ /* Call new MemCopy function */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
++ status = (*pIntfFxns->pfnBrdMemCopy)(hWmdContext, ulDspRunAddr,
++ ulDspLoadAddr, ulNumBytes, (u32) nMemSpace);
++
++ if (DSP_SUCCEEDED(status))
++ ulBytes = ulNumBytes;
++
++ return ulBytes;
++}
++
++/*
++ * ======== Write ========
++ */
++static u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
++ u32 ulNumBytes, u32 nMemSpace)
++{
++ struct NODE_OBJECT *hNode = (struct NODE_OBJECT *) pPrivRef;
++ struct NODE_MGR *hNodeMgr;
++ u16 memType;
++ u32 ulTimeout;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++
++ DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
++ DBC_Require(nMemSpace & DBLL_CODE || nMemSpace & DBLL_DATA);
++
++ hNodeMgr = hNode->hNodeMgr;
++
++ ulTimeout = hNode->uTimeout;
++ memType = (nMemSpace & DBLL_CODE) ? RMS_CODE : RMS_DATA;
++
++ /* Call new MemWrite function */
++ pIntfFxns = hNodeMgr->pIntfFxns;
++ status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
++ status = (*pIntfFxns->pfnBrdMemWrite) (hWmdContext, pBuf, ulDspAddr,
++ ulNumBytes, memType);
++
++ return ulNumBytes;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/proc.c b/drivers/dsp/bridge/rmgr/proc.c
+new file mode 100644
+index 0000000..332e01a
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/proc.c
+@@ -0,0 +1,1985 @@
++/*
++ * proc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== proc.c ========
++ * Description:
++ * Processor interface at the driver level.
++ *
++ * Public Functions:
++ * PROC_Attach
++ * PROC_Ctrl
++ * PROC_Detach
++ * PROC_EnumNodes
++ * PROC_GetResourceInfo
++ * PROC_Exit
++ * PROC_FlushMemory
++ * PROC_GetState
++ * PROC_GetProcessorId
++ * PROC_GetTrace
++ * PROC_Init
++ * PROC_Load
++ * PROC_Map
++ * PROC_NotifyClients
++ * PROC_RegisterNotify
++ * PROC_ReserveMemory
++ * PROC_Start
++ * PROC_UnMap
++ * PROC_UnReserveMemory
++ * PROC_InvalidateMemory
++
++ *! Revision History
++ *! ======== ========
++ *! 04-Apr-2007 sh Added PROC_InvalidateMemory API
++ *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
++ *! Used MEM_FlushCache instead of OS specific API
++ *! Integrated Alan's code review updates
++ *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
++ *! 08-Mar-2004 vp Added g_pszLastCoff member to PROC_OBJECT.
++ *! This is required for multiprocessor environment.
++ *! 09-Feb-2004 vp Added PROC_GetProcessorID function
++ *! 22-Apr-2003 vp Fixed issue with the string that stores coff file name
++ *! 03-Apr-2003 sb Fix DEH deregistering bug
++ *! 26-Mar-2003 vp Commented the call to DSP deep sleep in PROC_Start function.
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 22-May-2002 sg Do IOCTL-to-PWR translation before calling PWR_SleepDSP.
++ *! 14-May-2002 sg Use CSL_Atoi() instead of atoi().
++ *! 13-May-2002 sg Propagate PWR return codes upwards.
++ *! 07-May-2002 sg Added check for, and call to PWR functions in PROC_Ctrl.
++ *! 02-May-2002 sg Added "nap" mode: put DSP to sleep once booted.
++ *! 01-Apr-2002 jeh Assume word addresses in PROC_GetTrace().
++ *! 29-Nov-2001 jeh Don't call DEH function if hDehMgr == NULL.
++ *! 05-Nov-2001 kc: Updated PROC_RegisterNotify and PROC_GetState to support
++ *! DEH module.
++ *! 09-Oct-2001 jeh Fix number of bytes calculated in PROC_GetTrace().
++ *! 11-Sep-2001 jeh Delete MSG manager in PROC_Monitor() to fix memory leak.
++ *! 29-Aug-2001 rr: DCD_AutoRegister and IOOnLoaded moved before COD_LoadBase
++ *! to facilitate the external loading.
++ *! 14-Aug-2001 ag DCD_AutoRegister() now called before IOOnLoaded() fxn.
++ *! 21-Jun-2001 rr: MSG_Create is done only the first time.
++ *! 02-May-2001 jeh Return failure in PROC_Load if IOOnLoaded function returns
++ *! error other than E_NOTIMPL.
++ *! 03-Apr-2001 sg: Changed DSP_DCD_ENOAUTOREGISTER to DSP_EDCDNOAUTOREGISTER.
++ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
++ *! 05-Jan-2001 rr: PROC_LOAD MSG_Create error is checked.
++ *! 15-Dec-2000 rr: IoOnLoaded is checked for WSX_STATUS. We fail to load
++ *! if DEV_Create2 fails; ie, no non-RMS targets can be
++ *! loaded.
++ *! 12-Dec-2000 rr: PROC_Start's DEV_Create2 is checked for WSX_STATUS.
++ *! 28-Nov-2000 jeh Added call to IO OnLoaded function to PROC_Load().
++ *! 29-Nov-2000 rr: Incorporated code review changes.
++ *! 03-Nov-2000 rr: Auto_Register happens after PROC_Load.
++ *! 06-Oct-2000 rr: Updated to ver 0.9. PROC_Start calls DEV_Create2 and
++ *! WMD_BRD_STOP is always followed by DEV_Destroy2.
++ *! 05-Sep-2000 rr: PROC_GetTrace calculates the Trace symbol for 55 in a
++ *! different way.
++ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
++ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
++ *! WMD fxns are checked for WSX_STATUS.
++ *! PROC_Attach does not alter the state of the BRD.
++ *! PROC_Run removed.
++ *! 04-Aug-2000 rr: All the functions return DSP_EHANDLE if proc handle is
++ *! invalid
++ *! 27-Jul-2000 rr: PROC_GetTrace and PROC_Load implemented. Updated to
++ *! ver 0.8 API.
++ *! 06-Jul-2000 rr: Created.
++ */
++
++/* ------------------------------------ Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/sync.h>
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/procpriv.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/mgr.h>
++#include <dspbridge/node.h>
++#include <dspbridge/nldr.h>
++#include <dspbridge/rmm.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbdcd.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/msg.h>
++#include <dspbridge/wmdioctl.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/proc.h>
++#include <dspbridge/pwr.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/resourcecleanup.h>
++#endif
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define PROC_SIGNATURE 0x434F5250 /* "PROC" (in reverse). */
++#define MAXCMDLINELEN 255
++#define PROC_ENVPROCID "PROC_ID=%d"
++#define MAXPROCIDLEN (8 + 5)
++#define PROC_DFLT_TIMEOUT 10000 /* Time out in milliseconds */
++#define PWR_TIMEOUT 500 /* Sleep/wake timout in msec */
++#define EXTEND "_EXT_END" /* Extmem end addr in DSP binary */
++
++extern char *iva_img;
++/* The PROC_OBJECT structure. */
++struct PROC_OBJECT {
++ struct LST_ELEM link; /* Link to next PROC_OBJECT */
++ u32 dwSignature; /* Used for object validation */
++ struct DEV_OBJECT *hDevObject; /* Device this PROC represents */
++ u32 hProcess; /* Process owning this Processor */
++ struct MGR_OBJECT *hMgrObject; /* Manager Object Handle */
++ u32 uAttachCount; /* Processor attach count */
++ u32 uProcessor; /* Processor number */
++ u32 uTimeout; /* Time out count */
++ enum DSP_PROCSTATE sState; /* Processor state */
++ u32 ulUnit; /* DDSP unit number */
++ bool bIsAlreadyAttached; /*
++ * True if the Device below has
++ * GPP Client attached
++ */
++ struct NTFY_OBJECT *hNtfy; /* Manages notifications */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ char *g_pszLastCoff;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask PROC_DebugMask = { NULL, NULL }; /* WCD MGR Mask */
++#endif
++
++static u32 cRefs;
++
++struct SYNC_CSOBJECT *hProcLock; /* For critical sections */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcessor);
++static s32 GetEnvpCount(char **envp);
++static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
++ char *szVar);
++
++
++/*
++ * ======== PROC_Attach ========
++ * Purpose:
++ * Prepare for communication with a particular DSP processor, and return
++ * a handle to the processor object.
++ */
++DSP_STATUS
++PROC_Attach(u32 uProcessor, OPTIONAL CONST struct DSP_PROCESSORATTRIN *pAttrIn,
++ OUT DSP_HPROCESSOR *phProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEV_OBJECT *hDevObject;
++ struct PROC_OBJECT *pProcObject = NULL;
++ struct MGR_OBJECT *hMgrObject = NULL;
++ struct DRV_OBJECT *hDrvObject = NULL;
++ u32 devType;
++
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDRVObject;
++ u32 hProcess;
++ DSP_STATUS res_status = DSP_SOK;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phProcessor != NULL);
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Attach, args:\n\t"
++ "uProcessor: 0x%x\n\tpAttrIn: 0x%x\n\tphProcessor:"
++ "0x%x\n", uProcessor, pAttrIn, phProcessor);
++ /* Get the Driver and Manager Object Handles */
++ status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetObject((u32 *)&hMgrObject, REG_MGR_OBJECT);
++ if (DSP_FAILED(status)) {
++ /* don't propogate CFG errors from this PROC function */
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: DSP_FAILED to get"
++ "the Manager Object.\n", status);
++ }
++ } else {
++ /* don't propogate CFG errors from this PROC function */
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get the"
++ " DriverObject, 0x%x!\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the Device Object */
++ status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get"
++ " DevObject, 0x%x!\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDevType(hDevObject, &devType);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to get"
++ " DevType, 0x%x!\n", status);
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* If we made it this far, create the Proceesor object: */
++ MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
++ /* Fill out the Processor Object: */
++ if (pProcObject == NULL) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach:Out of memeory \n");
++ status = DSP_EFAIL;
++ goto func_end;
++ }
++ pProcObject->hDevObject = hDevObject;
++ pProcObject->hMgrObject = hMgrObject;
++ pProcObject->uProcessor = devType;
++ /* Get Caller Process and store it */
++ /* Return PID instead of process handle */
++ pProcObject->hProcess = current->pid;
++
++ if (pAttrIn)
++ pProcObject->uTimeout = pAttrIn->uTimeout;
++ else
++ pProcObject->uTimeout = PROC_DFLT_TIMEOUT;
++
++ status = DEV_GetIntfFxns(hDevObject, &pProcObject->pIntfFxns);
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetWMDContext(hDevObject,
++ &pProcObject->hWmdContext);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach Could not"
++ " get the WMD Context.\n", status);
++ MEM_FreeObject(pProcObject);
++ }
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach Could not get"
++ " the DEV_ Interface fxns.\n", status);
++ MEM_FreeObject(pProcObject);
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Create the Notification Object */
++ /* This is created with no event mask, no notify mask
++ * and no valid handle to the notification. They all get
++ * filled up when PROC_RegisterNotify is called */
++ status = NTFY_Create(&pProcObject->hNtfy);
++ if (DSP_SUCCEEDED(status)) {
++ /* Insert the Processor Object into the DEV List.
++ * Return handle to this Processor Object:
++ * Find out if the Device is already attached to a
++ * Processor. If so, return AlreadyAttached status */
++ LST_InitElem(&pProcObject->link);
++ status = DEV_InsertProcObject(pProcObject->hDevObject,
++ (u32)pProcObject,
++ &pProcObject->bIsAlreadyAttached);
++ if (DSP_SUCCEEDED(status)) {
++ if (pProcObject->bIsAlreadyAttached) {
++ status = DSP_SALREADYATTACHED;
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Attach: Processor "
++ "Already Attached!\n");
++ }
++ } else {
++ if (pProcObject->hNtfy)
++ NTFY_Delete(pProcObject->hNtfy);
++
++ MEM_FreeObject(pProcObject);
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: failed to insert "
++ "Proc Object into DEV, 0x%x!\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ *phProcessor = (DSP_HPROCESSOR)pProcObject;
++ (void)PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORATTACH);
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Attach: Processor "
++ "Attach Success!\n");
++ }
++ } else {
++ /* Don't leak memory if DSP_FAILED */
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Attach: Could not allocate "
++ "storage for notification \n");
++ MEM_FreeObject(pProcObject);
++ }
++func_end:
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_cont;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDRVObject,
++ &pPctxt, NULL, 0);
++ if (pPctxt == NULL) {
++ DRV_InsertProcContext((struct DRV_OBJECT *)hDRVObject, &pPctxt);
++ if (pPctxt != NULL) {
++ DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
++ DRV_ProcSetPID(pPctxt, hProcess);
++ }
++ }
++func_cont:
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDRVObject, &pPctxt,
++ NULL, 0);
++ if (pPctxt != NULL)
++ pPctxt->hProcessor = (DSP_HPROCESSOR)*phProcessor;
++
++ }
++#endif
++ DBC_Ensure((status == DSP_EFAIL && *phProcessor == NULL) ||
++ (DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) ||
++ (status == DSP_SALREADYATTACHED &&
++ MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)));
++ GT_2trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Attach, results:\n\t"
++ "status: 0x%x\n\thProcessor: 0x%x\n", status, *phProcessor);
++
++ return status;
++}
++
++static DSP_STATUS GetExecFile(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject,
++ u32 size, char *execFile)
++{
++ s32 devType;
++ s32 len;
++
++ DEV_GetDevType(hDevObject, (u32 *) &devType);
++ if (devType == DSP_UNIT) {
++ return CFG_GetExecFile(hDevNode, size, execFile);
++ } else if (devType == IVA_UNIT) {
++ if (iva_img) {
++ len = strlen(iva_img);
++ strncpy(execFile, iva_img, len + 1);
++ return DSP_SOK;
++ }
++ }
++ return DSP_EFILE;
++}
++
++/*
++ * ======== PROC_AutoStart ======== =
++ * Purpose:
++ * A Particular device gets loaded with the default image
++ * if the AutoStart flag is set.
++ * Parameters:
++ * hDevObject: Handle to the Device
++ * Returns:
++ * DSP_SOK: On Successful Loading
++ * DSP_EFAIL General Failure
++ * Requires:
++ * hDevObject != NULL
++ * Ensures:
++ */
++DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ u32 dwAutoStart = 0; /* autostart flag */
++ struct PROC_OBJECT *pProcObject;
++ struct PROC_OBJECT *hProcObject;
++ char szExecFile[MAXCMDLINELEN];
++ char *argv[2];
++ struct MGR_OBJECT *hMgrObject = NULL;
++ s32 devType;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hDevNode != NULL);
++ DBC_Require(hDevObject != NULL);
++
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_AutoStart, args:\n\t"
++ "hDevNode: 0x%x\thDevObject: 0x%x\n", hDevNode, hDevObject);
++ /* Create a Dummy PROC Object */
++ if (DSP_FAILED(CFG_GetObject((u32 *)&hMgrObject,
++ REG_MGR_OBJECT))) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED to "
++ "Get MGR Object\n");
++ goto func_end;
++ }
++ MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
++ if (pProcObject == NULL) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED "
++ "to Create a dummy Processor\n");
++ goto func_end;
++ }
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "NTFY Created \n");
++ pProcObject->hDevObject = hDevObject;
++ pProcObject->hMgrObject = hMgrObject;
++ hProcObject = pProcObject;
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ &pProcObject->pIntfFxns))) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ &pProcObject->hWmdContext))) {
++ status = DSP_SOK;
++ } else {
++ MEM_FreeObject(hProcObject);
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: Failed "
++ "to get WMD Context \n");
++ }
++ } else {
++ MEM_FreeObject(hProcObject);
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: Failed to "
++ "get IntFxns \n");
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Stop the Device, put it into standby mode */
++ status = PROC_Stop(hProcObject);
++ if (DSP_FAILED(CFG_GetAutoStart(hDevNode, &dwAutoStart)) ||
++ !dwAutoStart) {
++ status = DSP_EFAIL;
++ /* DSP_FAILED to Get s32 Fxn or Wmd Context */
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_AutoStart: "
++ "CFG_GetAutoStart DSP_FAILED \n");
++ goto func_cont;
++ }
++ /* Get the default executable for this board... */
++ DEV_GetDevType(hDevObject, (u32 *)&devType);
++ pProcObject->uProcessor = devType;
++ if (DSP_SUCCEEDED(GetExecFile(hDevNode, hDevObject,
++ sizeof(szExecFile), szExecFile))) {
++ argv[0] = szExecFile;
++ argv[1] = NULL;
++ /* ...and try to load it: */
++ status = PROC_Load(hProcObject, 1, (CONST char **)argv, NULL);
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_Start(hProcObject);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_AutoStart: Processor started "
++ "running\n");
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED To "
++ "Start \n");
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_AutoStart: DSP_FAILED to Load\n");
++ }
++ } else {
++ status = DSP_EFILE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_AutoStart: "
++ "No Exec file found \n");
++ }
++func_cont:
++ MEM_FreeObject(hProcObject);
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_AutoStart, status:0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== PROC_Ctrl ========
++ * Purpose:
++ * Pass control information to the GPP device driver managing the
++ * DSP processor.
++ *
++ * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
++ * application developer's API.
++ * Call the WMD_ICOTL Fxn with the Argument This is a Synchronous
++ * Operation. arg can be null.
++ */
++DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor, u32 dwCmd,
++ IN struct DSP_CBDATA *arg)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = hProcessor;
++ u32 timeout = 0;
++
++ DBC_Require(cRefs > 0);
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_Ctrl, args:\n\thProcessor:"
++ " 0x%x\n\tdwCmd: 0x%x\n\targ: 0x%x\n", hProcessor, dwCmd, arg);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* intercept PWR deep sleep command */
++ if (dwCmd == WMDIOCTL_DEEPSLEEP) {
++ timeout = arg->cbData;
++ status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
++ }
++ /* intercept PWR emergency sleep command */
++ else if (dwCmd == WMDIOCTL_EMERGENCYSLEEP) {
++ timeout = arg->cbData;
++ status = PWR_SleepDSP(PWR_EMERGENCYDEEPSLEEP, timeout);
++ } else if (dwCmd == PWR_DEEPSLEEP) {
++ /* timeout = arg->cbData; */
++ status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
++ }
++ /* intercept PWR wake commands */
++ else if (dwCmd == WMDIOCTL_WAKEUP) {
++ timeout = arg->cbData;
++ status = PWR_WakeDSP(timeout);
++ } else if (dwCmd == PWR_WAKEUP) {
++ /* timeout = arg->cbData; */
++ status = PWR_WakeDSP(timeout);
++ } else
++ if (DSP_SUCCEEDED
++ ((*pProcObject->pIntfFxns->pfnDevCntrl)
++ (pProcObject->hWmdContext, dwCmd, arg))) {
++ status = DSP_SOK;
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Ctrl: Failed \n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Ctrl: InValid Processor Handle \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Ctrl, 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_Detach ========
++ * Purpose:
++ * Destroys the Processor Object. Removes the notification from the Dev
++ * List.
++ */
++DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++#ifndef RES_CLEANUP_DISABLE
++ HANDLE hDRVObject;
++ u32 hProcess;
++ DSP_STATUS res_status = DSP_SOK;
++ struct PROCESS_CONTEXT *pPctxt = NULL;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Detach, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* Notify the Client */
++ NTFY_Notify(pProcObject->hNtfy, DSP_PROCESSORDETACH);
++ /* Remove the notification memory */
++ if (pProcObject->hNtfy)
++ NTFY_Delete(pProcObject->hNtfy);
++
++ if (pProcObject->g_pszLastCoff) {
++ MEM_Free(pProcObject->g_pszLastCoff);
++ pProcObject->g_pszLastCoff = NULL;
++ }
++
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDRVObject, &pPctxt,
++ NULL, 0);
++ if (pPctxt != NULL) {
++ DRV_ProcFreeDMMRes(pPctxt);
++ pPctxt->hProcessor = NULL;
++ }
++ }
++#endif
++
++ /* Remove the Proc from the DEV List */
++ (void)DEV_RemoveProcObject(pProcObject->hDevObject,
++ (u32)pProcObject);
++ /* Free the Processor Object */
++ MEM_FreeObject(pProcObject);
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Detach: InValid Processor Handle \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Detach, 0x%x\n",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_EnumNodes ========
++ * Purpose:
++ * Enumerate and get configuration information about nodes allocated
++ * on a DSP processor.
++ */
++DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor, OUT DSP_HNODE *aNodeTab,
++ IN u32 uNodeTabSize, OUT u32 *puNumNodes,
++ OUT u32 *puAllocated)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct NODE_MGR *hNodeMgr = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
++ DBC_Require(puNumNodes != NULL);
++ DBC_Require(puAllocated != NULL);
++
++ GT_5trace(PROC_DebugMask, GT_ENTER, "Entered PROC_EnumNodes, args:\n\t"
++ "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
++ " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n",
++ hProcessor, aNodeTab, uNodeTabSize, puNumNodes,
++ puAllocated);
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ if (DSP_SUCCEEDED(DEV_GetNodeManager(pProcObject->hDevObject,
++ &hNodeMgr))) {
++ if (hNodeMgr) {
++ status = NODE_EnumNodes(hNodeMgr, aNodeTab,
++ uNodeTabSize,
++ puNumNodes,
++ puAllocated);
++ }
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_EnumNodes: "
++ "InValid Processor Handle \n");
++ }
++ GT_6trace(PROC_DebugMask, GT_ENTER, "Exit PROC_EnumNodes, args:\n\t"
++ "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
++ " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n\t "
++ "status: 0x%x \n", hProcessor, aNodeTab, uNodeTabSize,
++ puNumNodes, puAllocated, status);
++
++ return status;
++}
++
++/*
++ * ======== PROC_FlushMemory ========
++ * Purpose:
++ * Flush cache
++ */
++DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
++ u32 ulSize, u32 ulFlags)
++{
++ /* Keep STATUS here for future additions to this function */
++ DSP_STATUS status = DSP_SOK;
++ enum DSP_FLUSHTYPE FlushMemType = PROC_WRITEBACK_INVALIDATE_MEM;
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_FlushMemory, args:\n\t"
++ "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x, ulFlags 0x%x\n",
++ hProcessor, pMpuAddr, ulSize, ulFlags);
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
++ (void)SYNC_LeaveCS(hProcLock);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_FlushMemory [0x%x]",
++ status);
++ return status;
++}
++
++
++/*
++ * ======== PROC_InvalidateMemory ========
++ * Purpose:
++ * Invalidates the memory specified
++ */
++DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
++ u32 ulSize)
++{
++ /* Keep STATUS here for future additions to this function */
++ DSP_STATUS status = DSP_SOK;
++ enum DSP_FLUSHTYPE FlushMemType = PROC_INVALIDATE_MEM;
++ DBC_Require(cRefs > 0);
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_InvalidateMemory, args:\n\t"
++ "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x\n", hProcessor,
++ pMpuAddr, ulSize);
++ (void)SYNC_EnterCS(hProcLock);
++ MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
++ (void)SYNC_LeaveCS(hProcLock);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_InvalidateMemory [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_GetResourceInfo ========
++ * Purpose:
++ * Enumerate the resources currently available on a processor.
++ */
++DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor, u32 uResourceType,
++ OUT struct DSP_RESOURCEINFO *pResourceInfo,
++ u32 uResourceInfoSize)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct NODE_MGR *hNodeMgr = NULL;
++ struct NLDR_OBJECT *hNldr = NULL;
++ struct RMM_TargetObj *rmm = NULL;
++ struct IO_MGR *hIOMgr = NULL; /* IO manager handle */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pResourceInfo != NULL);
++ DBC_Require(uResourceInfoSize >= sizeof(struct DSP_RESOURCEINFO));
++
++ GT_4trace(PROC_DebugMask, GT_ENTER, "Entered PROC_GetResourceInfo,\n\t"
++ "hProcessor: 0x%x\n\tuResourceType: 0x%x\n\tpResourceInfo:"
++ " 0x%x\n\t uResourceInfoSize 0x%x\n", hProcessor,
++ uResourceType, pResourceInfo, uResourceInfoSize);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetResourceInfo: InValid "
++ "Processor Handle \n");
++ goto func_end;
++ }
++ switch (uResourceType) {
++ case DSP_RESOURCE_DYNDARAM:
++ case DSP_RESOURCE_DYNSARAM:
++ case DSP_RESOURCE_DYNEXTERNAL:
++ case DSP_RESOURCE_DYNSRAM:
++ if (DSP_FAILED(DEV_GetNodeManager(pProcObject->hDevObject,
++ &hNodeMgr)))
++ goto func_end;
++
++ if (DSP_SUCCEEDED(NODE_GetNldrObj(hNodeMgr, &hNldr))) {
++ if (DSP_SUCCEEDED(NLDR_GetRmmManager(hNldr, &rmm))) {
++ DBC_Assert(rmm != NULL);
++ status = DSP_EVALUE;
++ if (RMM_stat(rmm,
++ (enum DSP_MEMTYPE)uResourceType,
++ (struct DSP_MEMSTAT *)&(pResourceInfo->
++ result.memStat)))
++ status = DSP_SOK;
++ }
++ }
++ break;
++ case DSP_RESOURCE_PROCLOAD:
++ status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
++ status = pProcObject->pIntfFxns->pfnIOGetProcLoad(hIOMgr,
++ (struct DSP_PROCLOADSTAT *)&(pResourceInfo->
++ result.procLoadStat));
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Error in procLoadStat function 0x%x\n", status);
++ }
++ break;
++ default:
++ status = DSP_EFAIL;
++ break;
++ }
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_GetResourceInfo, "
++ "status 0x%x\n", status);
++ return status;
++}
++
++/*
++ * ======== PROC_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count is
++ * 0.
++ */
++void PROC_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ if (hProcLock)
++ (void)SYNC_DeleteCS(hProcLock);
++
++ cRefs--;
++
++ GT_1trace(PROC_DebugMask, GT_5CLASS,
++ "Entered PROC_Exit, ref count:0x%x\n", cRefs);
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== PROC_GetDevObject ========
++ * Purpose:
++ * Return the Dev Object handle for a given Processor.
++ *
++ */
++DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
++ struct DEV_OBJECT **phDevObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phDevObject != NULL);
++
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ *phDevObject = pProcObject->hDevObject;
++ status = DSP_SOK;
++ } else {
++ *phDevObject = NULL;
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && *phDevObject != NULL) ||
++ (DSP_FAILED(status) && *phDevObject == NULL));
++
++ return status;
++}
++
++/*
++ * ======== PROC_GetState ========
++ * Purpose:
++ * Report the state of the specified DSP processor.
++ */
++DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
++ OUT struct DSP_PROCESSORSTATE *pProcStatus,
++ u32 uStateInfoSize)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ BRD_STATUS brdStatus;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pProcStatus != NULL);
++ DBC_Require(uStateInfoSize >= sizeof(struct DSP_PROCESSORSTATE));
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "Entering PROC_GetState, args:\n\t"
++ "pProcStatus: 0x%x\n\thProcessor: 0x%x\n\t uStateInfoSize"
++ " 0x%x\n", pProcStatus, hProcessor, uStateInfoSize);
++ if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ /* First, retrieve BRD state information */
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &brdStatus))) {
++ switch (brdStatus) {
++ case BRD_STOPPED:
++ pProcStatus->iState = PROC_STOPPED;
++ break;
++ case BRD_DSP_HIBERNATION:
++ /* Fall through */
++ case BRD_RUNNING:
++ pProcStatus->iState = PROC_RUNNING;
++ break;
++ case BRD_LOADED:
++ pProcStatus->iState = PROC_LOADED;
++ break;
++ case BRD_ERROR:
++ pProcStatus->iState = PROC_ERROR;
++ break;
++ default:
++ pProcStatus->iState = 0xFF;
++ status = DSP_EFAIL;
++ break;
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: General Failure"
++ " to read the PROC Status \n");
++ }
++ /* Next, retrieve error information, if any */
++ status = DEV_GetDehMgr(pProcObject->hDevObject, &hDehMgr);
++ if (DSP_SUCCEEDED(status) && hDehMgr) {
++ status = (*pProcObject->pIntfFxns->pfnDehGetInfo)
++ (hDehMgr, &(pProcStatus->errInfo));
++ if (DSP_FAILED(status)) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: Failed "
++ "retrieve exception info.\n");
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState: Failed to "
++ "retrieve DEH handle.\n");
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_GetState:InValid Processor Handle \n");
++ }
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_GetState, results:\n\t"
++ "status: 0x%x\n\tpProcStatus: 0x%x\n", status,
++ pProcStatus->iState);
++ return status;
++}
++
++/*
++ * ======== PROC_GetTrace ========
++ * Purpose:
++ * Retrieve the current contents of the trace buffer, located on the
++ * Processor. Predefined symbols for the trace buffer must have been
++ * configured into the DSP executable.
++ * Details:
++ * We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
++ * trace buffer, only. Treat it as an undocumented feature.
++ * This call is destructive, meaning the processor is placed in the monitor
++ * state as a result of this function.
++ */
++DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf, u32 uMaxSize)
++{
++ DSP_STATUS status;
++ status = DSP_ENOTIMPL;
++ return status;
++}
++
++/*
++ * ======== PROC_Init ========
++ * Purpose:
++ * Initialize PROC's private state, keeping a reference count on each call
++ */
++bool PROC_Init(void)
++{
++ bool fRetval = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ /* Set the Trace mask */
++ DBC_Assert(!PROC_DebugMask.flags);
++ GT_create(&PROC_DebugMask, "PR"); /* "PR" for Processor */
++
++ (void)SYNC_InitializeCS(&hProcLock);
++ }
++
++ if (fRetval)
++ cRefs++;
++
++ GT_1trace(PROC_DebugMask, GT_5CLASS,
++ "Entered PROC_Init, ref count:0x%x\n", cRefs);
++ DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
++
++ return fRetval;
++}
++
++/*
++ * ======== PROC_Load ========
++ * Purpose:
++ * Reset a processor and load a new base program image.
++ * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
++ * application developer's API.
++ */
++DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor, IN CONST s32 iArgc,
++ IN CONST char **aArgv, IN CONST char **aEnvp)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct IO_MGR *hIOMgr; /* IO manager handle */
++ struct MSG_MGR *hMsgMgr;
++ struct COD_MANAGER *hCodMgr; /* Code manager handle */
++ char *pargv0; /* temp argv[0] ptr */
++ char **newEnvp; /* Updated envp[] array. */
++ char szProcID[MAXPROCIDLEN]; /* Size of "PROC_ID=<n>" */
++ s32 cEnvp; /* Num elements in envp[]. */
++ s32 cNewEnvp; /* " " in newEnvp[] */
++ s32 nProcID = 0; /* Anticipate MP version. */
++ struct DCD_MANAGER *hDCDHandle;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 dwExtEnd;
++ u32 uProcId;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ struct timeval tv1;
++ struct timeval tv2;
++#endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(iArgc > 0);
++ DBC_Require(aArgv != NULL);
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ do_gettimeofday(&tv1);
++#endif
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++ GT_2trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Load, args:\n\t"
++ "hProcessor: 0x%x\taArgv: 0x%x\n", hProcessor, aArgv[0]);
++ /* Call the WMD_BRD_Load Fxn */
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Load: Invalid Processor Handle..\n");
++ goto func_end;
++ }
++ if (pProcObject->bIsAlreadyAttached) {
++ status = DSP_EATTACHED;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load Abort becuase a GPP "
++ "Client is already attached status 0x%x \n", status);
++ goto func_end;
++ }
++ if (DSP_FAILED(DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr))) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: DSP_FAILED in "
++ "DEV_GetCodMgr status 0x%x \n", status);
++ goto func_end;
++ }
++ status = PROC_Stop(hProcessor);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED to Place the"
++ " Processor in Stop Mode(PROC_STOP) status 0x%x \n",
++ status);
++ goto func_end;
++ }
++ /* Place the board in the monitor state. */
++ status = PROC_Monitor(hProcessor);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED to Place the"
++ " Processor in Monitor Mode(PROC_IDLE) status 0x%x\n",
++ status);
++ goto func_end;
++ }
++ /* Save ptr to original argv[0]. */
++ pargv0 = (char *)aArgv[0];
++ /*Prepend "PROC_ID=<nProcID>"to envp array for target.*/
++ cEnvp = GetEnvpCount((char **)aEnvp);
++ cNewEnvp = (cEnvp ? (cEnvp + 1) : (cEnvp + 2));
++ newEnvp = MEM_Calloc(cNewEnvp * sizeof(char **), MEM_PAGED);
++ if (newEnvp) {
++ status = snprintf(szProcID, MAXPROCIDLEN, PROC_ENVPROCID,
++ nProcID);
++ if (status == -1) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: "
++ "Proc ID string overflow \n");
++ status = DSP_EFAIL;
++ } else {
++ newEnvp = PrependEnvp(newEnvp, (char **)aEnvp, cEnvp,
++ cNewEnvp, szProcID);
++ /* Get the DCD Handle */
++ status = MGR_GetDCDHandle(pProcObject->hMgrObject,
++ (u32 *)&hDCDHandle);
++ if (DSP_SUCCEEDED(status)) {
++ /* Before proceeding with new load,
++ * check if a previously registered COFF
++ * exists.
++ * If yes, unregister nodes in previously
++ * registered COFF. If any error occurred,
++ * set previously registered COFF to NULL. */
++ if (pProcObject->g_pszLastCoff != NULL) {
++ status = DCD_AutoUnregister(hDCDHandle,
++ pProcObject->g_pszLastCoff);
++ /* Regardless of auto unregister status,
++ * free previously allocated
++ * memory. */
++ MEM_Free(pProcObject->g_pszLastCoff);
++ pProcObject->g_pszLastCoff = NULL;
++ }
++ }
++ /* On success, do COD_OpenBase() */
++ status = COD_OpenBase(hCodMgr, (char *)aArgv[0],
++ COD_SYMB);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: COD_OpenBase "
++ "failed (0x%x)\n", status);
++ }
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ " PROC_Load:Out of Memory \n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Auto-register data base */
++ /* Get the DCD Handle */
++ status = MGR_GetDCDHandle(pProcObject->hMgrObject,
++ (u32 *)&hDCDHandle);
++ if (DSP_SUCCEEDED(status)) {
++ /* Auto register nodes in specified COFF
++ * file. If registration did not fail,
++ * (status = DSP_SOK or DSP_EDCDNOAUTOREGISTER)
++ * save the name of the COFF file for
++ * de-registration in the future. */
++ status = DCD_AutoRegister(hDCDHandle, (char *)aArgv[0]);
++ if (status == DSP_EDCDNOAUTOREGISTER) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: No Auto "
++ "Register section. Proceeding..\n");
++ status = DSP_SOK;
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed to "
++ "Auto Register..\n");
++ } else {
++ DBC_Assert(pProcObject->g_pszLastCoff == NULL);
++ /* Allocate memory for pszLastCoff */
++ pProcObject->g_pszLastCoff = MEM_Calloc(
++ (strlen((char *)aArgv[0]) + 1),
++ MEM_PAGED);
++ /* If memory allocated, save COFF file name*/
++ if (pProcObject->g_pszLastCoff) {
++ strncpy(pProcObject->g_pszLastCoff,
++ (char *)aArgv[0],
++ (strlen((char *)aArgv[0]) + 1));
++ }
++ }
++ }
++ }
++ /* Update shared memory address and size */
++ if (DSP_SUCCEEDED(status)) {
++ /* Create the message manager. This must be done
++ * before calling the IOOnLoaded function. */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (!hMsgMgr) {
++ status = MSG_Create(&hMsgMgr, pProcObject->hDevObject,
++ (MSG_ONEXIT)NODE_OnExit);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ DEV_SetMsgMgr(pProcObject->hDevObject, hMsgMgr);
++ }
++ if (status == DSP_ENOTIMPL) {
++ /* It's OK not to have a message manager */
++ status = DSP_SOK;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Device object's message manager */
++ status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ status = (*pProcObject->pIntfFxns->pfnIOOnLoaded)(hIOMgr);
++ if (status == DSP_ENOTIMPL) {
++ /* Ok not to implement this function */
++ status = DSP_SOK;
++ } else {
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed to get shared "
++ "memory or message buffer address "
++ "from COFF status 0x%x\n", status);
++ status = DSP_EFAIL;
++ }
++ }
++ } else {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED in "
++ "MSG_Create status 0x%x\n", status);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Now, attempt to load an exec: */
++
++ /* Boost the OPP level to Maximum level supported by baseport*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq)
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP5]);
++#endif
++ status = COD_LoadBase(hCodMgr, iArgc, (char **)aArgv,
++ DEV_BrdWriteFxn,
++ pProcObject->hDevObject, NULL);
++ if (DSP_FAILED(status)) {
++ if (status == COD_E_OPENFAILED) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load:Failure to Load the EXE\n");
++ }
++ if (status == COD_E_SYMBOLNOTFOUND) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load:Could not parse the file\n");
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: DSP_FAILED in "
++ "COD_Load status 0x%x \n", status);
++ }
++ }
++ /* Requesting the lowest opp supported*/
++#if defined(CONFIG_BRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
++ if (pdata->cpu_set_freq)
++ (*pdata->cpu_set_freq)(pdata->mpu_speed[VDD1_OPP1]);
++#endif
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the Processor status to loaded */
++ status = (*pProcObject->pIntfFxns->pfnBrdSetState)
++ (pProcObject->hWmdContext, BRD_LOADED);
++ if (DSP_SUCCEEDED(status)) {
++ pProcObject->sState = PROC_LOADED;
++ if (pProcObject->hNtfy) {
++ PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORSTATECHANGE);
++ }
++ } else {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load, pfnBrdSetState "
++ "failed: 0x%x\n", status);
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = PROC_GetProcessorId(hProcessor, &uProcId);
++ if (uProcId == DSP_UNIT) {
++ /* Use all available DSP address space after EXTMEM
++ * for DMM */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMgr, EXTEND,
++ &dwExtEnd);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Load: Failed on "
++ "COD_GetSymValue %s.\n",
++ EXTEND);
++ }
++ }
++ /* Reset DMM structs and add an initial free chunk*/
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetDmmMgr(pProcObject->hDevObject,
++ &hDmmMgr);
++ if (DSP_SUCCEEDED(status)) {
++ /* Set dwExtEnd to DMM START u8
++ * address */
++ dwExtEnd = (dwExtEnd + 1) * DSPWORDSIZE;
++ /* DMM memory is from EXT_END */
++ status = DMM_CreateTables(hDmmMgr,
++ dwExtEnd, DMMPOOLSIZE);
++ }
++ }
++ }
++ }
++ /* Restore the original argv[0] */
++ MEM_Free(newEnvp);
++ aArgv[0] = pargv0;
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Load: Processor Loaded\n");
++ DBC_Assert(uBrdState == BRD_LOADED);
++ }
++ }
++#endif
++func_end:
++#ifdef DEBUG
++ if (DSP_FAILED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Load: "
++ "Processor Load Failed.\n");
++
++ }
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Load, status: 0x%x\n", status);
++ DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState == PROC_LOADED)
++ || DSP_FAILED(status));
++#ifdef OPT_LOAD_TIME_INSTRUMENTATION
++ do_gettimeofday(&tv2);
++ if (tv2.tv_usec < tv1.tv_usec) {
++ tv2.tv_usec += 1000000;
++ tv2.tv_sec--;
++ }
++ GT_2trace(PROC_DebugMask, GT_1CLASS,
++ "Proc_Load: time to load %d sec and %d usec \n",
++ tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
++#endif
++ return status;
++}
++
++/*
++ * ======== PROC_Map ========
++ * Purpose:
++ * Maps a MPU buffer to DSP address space.
++ */
++DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor, void *pMpuAddr, u32 ulSize,
++ void *pReqAddr, void **ppMapAddr, u32 ulMapAttr)
++{
++ u32 vaAlign;
++ u32 paAlign;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 sizeAlign;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE dmmRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++ GT_6trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Map, args:\n\t"
++ "hProcessor %x, pMpuAddr %x, ulSize %x, pReqAddr %x, "
++ "ulMapAttr %x, ppMapAddr %x\n", hProcessor, pMpuAddr, ulSize,
++ pReqAddr, ulMapAttr, ppMapAddr);
++ /* Calculate the page-aligned PA, VA and size */
++ vaAlign = PG_ALIGN_LOW((u32) pReqAddr, PG_SIZE_4K);
++ paAlign = PG_ALIGN_LOW((u32) pMpuAddr, PG_SIZE_4K);
++ sizeAlign = PG_ALIGN_HIGH(ulSize + (u32)pMpuAddr - paAlign,
++ PG_SIZE_4K);
++
++ GT_3trace(PROC_DebugMask, GT_ENTER, "PROC_Map: vaAlign %x, paAlign %x, "
++ "sizeAlign %x\n", vaAlign, paAlign, sizeAlign);
++
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Map: Failed to get DMM Mgr "
++ "handle: 0x%x\n", status);
++ } else {
++ status = DMM_MapMemory(hDmmMgr, vaAlign, sizeAlign);
++ }
++ /* Add mapping to the page tables. */
++ if (DSP_SUCCEEDED(status)) {
++
++ status = (*pProcObject->pIntfFxns->pfnBrdMemMap)
++ (pProcObject->hWmdContext, paAlign, vaAlign, sizeAlign,
++ ulMapAttr);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Mapped address = MSB of VA | LSB of PA */
++ *ppMapAddr = (void *) (vaAlign | ((u32) pMpuAddr &
++ (PG_SIZE_4K - 1)));
++ } else {
++ DMM_UnMapMemory(hDmmMgr, vaAlign, &sizeAlign);
++ }
++ (void)SYNC_LeaveCS(hProcLock);
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject,
++ REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ if (DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt, NULL,
++ (u32)pMpuAddr) != DSP_ENOTFOUND) {
++ DRV_InsertDMMResElement(&dmmRes, pCtxt);
++ DRV_UpdateDMMResElement(dmmRes, (u32)pMpuAddr,
++ ulSize, (u32)pReqAddr,
++ (u32)*ppMapAddr, hProcessor);
++ }
++ }
++ }
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_Map [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_RegisterNotify ========
++ * Purpose:
++ * Register to be notified of specific processor events.
++ */
++DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor, u32 uEventMask,
++ u32 uNotifyType, struct DSP_NOTIFICATION
++ *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(hNotification != NULL);
++ DBC_Require(cRefs > 0);
++
++ GT_4trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_RegisterNotify, args:\n\t"
++ "hProcessor: 0x%x\n\tuEventMask: 0x%x\n\tuNotifyMask:"
++ " 0x%x\n\t hNotification 0x%x\n", hProcessor, uEventMask,
++ uNotifyType, hNotification);
++
++ /* Check processor handle */
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_RegsiterNotify Invalid "
++ "ProcessorHandle 0x%x\n", hProcessor);
++ goto func_end;
++ }
++ /* Check if event mask is a valid processor related event */
++ if (uEventMask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
++ DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | DSP_MMUFAULT |
++ DSP_SYSERROR))
++ status = DSP_EVALUE;
++
++ /* Check if notify type is valid */
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_EVALUE;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* * If event mask is not DSP_SYSERROR or DSP_MMUFAULT,
++ * then register event immediately. */
++ if (uEventMask & ~(DSP_SYSERROR | DSP_MMUFAULT)) {
++ status = NTFY_Register(pProcObject->hNtfy,
++ hNotification, uEventMask, uNotifyType);
++ /* * Special case alert, special case alert!
++ * If we're trying to *deregister* (i.e. uEventMask
++ * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
++ * we have to deregister with the DEH manager.
++ * There's no way to know, based on uEventMask which
++ * manager the notification event was registered with,
++ * so if we're trying to deregister and NTFY_Register
++ * failed, we'll give the deh manager a shot.
++ */
++ if ((uEventMask == 0) && DSP_FAILED(status)) {
++ status = DEV_GetDehMgr(pProcObject->hDevObject,
++ &hDehMgr);
++ DBC_Assert(pProcObject->pIntfFxns->
++ pfnDehRegisterNotify);
++ status = (*pProcObject->pIntfFxns->
++ pfnDehRegisterNotify)
++ (hDehMgr, uEventMask, uNotifyType,
++ hNotification);
++ }
++ } else {
++ status = DEV_GetDehMgr(pProcObject->hDevObject,
++ &hDehMgr);
++ DBC_Assert(pProcObject->pIntfFxns->
++ pfnDehRegisterNotify);
++ status = (*pProcObject->pIntfFxns->pfnDehRegisterNotify)
++ (hDehMgr, uEventMask, uNotifyType,
++ hNotification);
++ if (DSP_FAILED(status))
++ status = DSP_EFAIL;
++
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== PROC_ReserveMemory ========
++ * Purpose:
++ * Reserve a virtually contiguous region of DSP address space.
++ */
++DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
++ void **ppRsvAddr)
++{
++ struct DMM_OBJECT *hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ GT_3trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_ReserveMemory, args:\n\t"
++ "hProcessor: 0x%x ulSize: 0x%x ppRsvAddr: 0x%x\n", hProcessor,
++ ulSize, ppRsvAddr);
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_ReserveMemory: "
++ "Failed to get DMM Mgr handle: 0x%x\n", status);
++ } else
++ status = DMM_ReserveMemory(hDmmMgr, ulSize, (u32 *)ppRsvAddr);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_ReserveMemory [0x%x]",
++ status);
++ return status;
++}
++
++/*
++ * ======== PROC_Start ========
++ * Purpose:
++ * Start a processor running.
++ */
++DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct COD_MANAGER *hCodMgr; /* Code manager handle */
++ u32 dwDspAddr; /* Loaded code's entry point. */
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Start, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start :InValid Handle \n");
++ goto func_end;
++ }
++ /* Call the WMD_BRD_Start */
++ if (pProcObject->sState != PROC_LOADED) {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start :Wrong state \n");
++ status = DSP_EWRONGSTATE;
++ goto func_end;
++ }
++ status = DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Processor Start DSP_FAILED "
++ "in Getting DEV_GetCodMgr status 0x%x\n", status);
++ goto func_cont;
++ }
++ status = COD_GetEntry(hCodMgr, &dwDspAddr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Processor Start DSP_FAILED in "
++ "Getting COD_GetEntry status 0x%x\n", status);
++ goto func_cont;
++ }
++ status = (*pProcObject->pIntfFxns->pfnBrdStart)
++ (pProcObject->hWmdContext, dwDspAddr);
++ if (DSP_FAILED(status)) {
++ status = DSP_EFAIL;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Start Failed to Start the board\n");
++ goto func_cont;
++ }
++ /* Call DEV_Create2 */
++ status = DEV_Create2(pProcObject->hDevObject);
++ if (DSP_SUCCEEDED(status)) {
++ pProcObject->sState = PROC_RUNNING;
++ /* Deep sleep switces off the peripheral clocks.
++ * we just put the DSP CPU in idle in the idle loop.
++ * so there is no need to send a command to DSP */
++
++ if (pProcObject->hNtfy) {
++ PROC_NotifyClients(pProcObject,
++ DSP_PROCESSORSTATECHANGE);
++ }
++ GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Start: Processor "
++ "Started and running \n");
++ } else {
++ /* Failed to Create Node Manager and DISP Object
++ * Stop the Processor from running. Put it in STOPPED State */
++ (void)(*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
++ hWmdContext);
++ status = DSP_EFAIL;
++ pProcObject->sState = PROC_STOPPED;
++ GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Start "
++ "Failed to Create the Node Manager\n");
++ }
++func_cont:
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Start: Processor State is RUNNING \n");
++ DBC_Assert(uBrdState != BRD_HIBERNATION);
++ }
++ }
++#endif
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Start, status 0x%x\n", status);
++ DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState ==
++ PROC_RUNNING) || DSP_FAILED(status));
++ return status;
++}
++
++/*
++ * ======== PROC_Stop ========
++ * Purpose:
++ * Stop a processor running.
++ */
++DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct MSG_MGR *hMsgMgr;
++ struct NODE_MGR *hNodeMgr;
++ DSP_HNODE hNode;
++ u32 uNodeTabSize = 1;
++ u32 uNumNodes = 0;
++ u32 uNodesAllocated = 0;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++ DBC_Require(cRefs > 0);
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Stop, args:\n\t"
++ "hProcessor: 0x%x\n", hProcessor);
++ if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop :InValid Handle \n");
++ goto func_end;
++ }
++ /* check if there are any running nodes */
++ status = DEV_GetNodeManager(pProcObject->hDevObject, &hNodeMgr);
++ if (DSP_SUCCEEDED(status) && hNodeMgr) {
++ status = NODE_EnumNodes(hNodeMgr, &hNode, uNodeTabSize,
++ &uNumNodes, &uNodesAllocated);
++ if ((status == DSP_ESIZE) || (uNodesAllocated > 0)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "Can't stop device, Active "
++ "nodes = 0x%x \n", uNodesAllocated);
++ return DSP_EWRONGSTATE;
++ }
++ }
++ /* Call the WMD_BRD_Stop */
++ /* It is OK to stop a device that does n't have nodes OR not started */
++ status = (*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
++ hWmdContext);
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Stop: Processor Stopped, "
++ "i.e in standby mode \n");
++ pProcObject->sState = PROC_STOPPED;
++ /* Destory the Node Manager, MSG Manager */
++ if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
++ /* Destroy the MSG by calling MSG_Delete */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (hMsgMgr) {
++ MSG_Delete(hMsgMgr);
++ DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->
++ pfnBrdStatus)(pProcObject->hWmdContext,
++ &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Monitor:Processor Stopped \n");
++ DBC_Assert(uBrdState == BRD_STOPPED);
++ }
++#endif
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop Couldn't delete node manager \n");
++ }
++ } else {
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Stop Failed to Stop the processor/device \n");
++ }
++func_end:
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Stop, status 0x%x\n",
++ status);
++
++ return status;
++}
++
++/*
++ * ======== PROC_UnMap ========
++ * Purpose:
++ * Removes a MPU buffer mapping from the DSP address space.
++ */
++DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++ struct DMM_OBJECT *hDmmMgr;
++ u32 vaAlign;
++ u32 sizeAlign;
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE dmmRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_UnMap, args:\n\thProcessor:"
++ "0x%x pMapAddr: 0x%x\n", hProcessor, pMapAddr);
++
++ vaAlign = PG_ALIGN_LOW((u32) pMapAddr, PG_SIZE_4K);
++
++ status = DMM_GetHandle(hProcessor, &hDmmMgr);
++ /* Critical section */
++ (void)SYNC_EnterCS(hProcLock);
++ if (DSP_FAILED(status)) {
++ GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
++ "Failed to get DMM Mgr handle: 0x%x\n", status);
++ } else {
++ /* Update DMM structures. Get the size to unmap.
++ This function returns error if the VA is not mapped */
++ status = DMM_UnMapMemory(hDmmMgr, (u32) vaAlign, &sizeAlign);
++ }
++ /* Remove mapping from the page tables. */
++ if (DSP_SUCCEEDED(status)) {
++ status = (*pProcObject->pIntfFxns->pfnBrdMemUnMap)
++ (pProcObject->hWmdContext, vaAlign, sizeAlign);
++ }
++ (void)SYNC_LeaveCS(hProcLock);
++#ifndef RES_CLEANUP_DISABLE
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "PROC_UnMap DRV_GetDMMResElement "
++ "pMapAddr:[0x%x]", pMapAddr);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, (u32)pMapAddr);
++ if (pCtxt != NULL) {
++ if (DRV_GetDMMResElement((u32)pMapAddr, &dmmRes, pCtxt) !=
++ DSP_ENOTFOUND)
++ DRV_RemoveDMMResElement(dmmRes, pCtxt);
++ }
++func_end:
++#endif
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_UnMap [0x%x]", status);
++ return status;
++}
++
++/*
++ * ======== PROC_UnReserveMemory ========
++ * Purpose:
++ * Frees a previously reserved region of DSP address space.
++ */
++DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
++{
++ struct DMM_OBJECT *hDmmMgr;
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
++
++ GT_2trace(PROC_DebugMask, GT_ENTER,
++ "Entered PROC_UnReserveMemory, args:\n\t"
++ "hProcessor: 0x%x pRsvAddr: 0x%x\n", hProcessor, pRsvAddr);
++
++ status = DMM_GetHandle(pProcObject, &hDmmMgr);
++ if (DSP_FAILED(status))
++ GT_1trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_UnReserveMemory: Failed to get DMM Mgr "
++ "handle: 0x%x\n", status);
++ else
++ status = DMM_UnReserveMemory(hDmmMgr, (u32) pRsvAddr);
++
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Leaving PROC_UnReserveMemory [0x%x]",
++ status);
++
++ return status;
++}
++
++/*
++ * ======== = PROC_Monitor ======== ==
++ * Purpose:
++ * Place the Processor in Monitor State. This is an internal
++ * function and a requirement before Processor is loaded.
++ * This does a WMD_BRD_Stop, DEV_Destroy2 and WMD_BRD_Monitor.
++ * In DEV_Destroy2 we delete the node manager.
++ * Parameters:
++ * hProcObject: Handle to Processor Object
++ * Returns:
++ * DSP_SOK: Processor placed in monitor mode.
++ * !DSP_SOK: Failed to place processor in monitor mode.
++ * Requires:
++ * Valid Processor Handle
++ * Ensures:
++ * Success: ProcObject state is PROC_IDLE
++ */
++static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcObject)
++{
++ DSP_STATUS status = DSP_EFAIL;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcObject;
++ struct MSG_MGR *hMsgMgr;
++#ifdef DEBUG
++ BRD_STATUS uBrdState;
++#endif
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++
++ GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Monitor, args:\n\t"
++ "hProcessor: 0x%x\n", hProcObject);
++ /* This is needed only when Device is loaded when it is
++ * already 'ACTIVE' */
++ /* Destory the Node Manager, MSG Manager */
++ if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
++ /* Destroy the MSG by calling MSG_Delete */
++ DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
++ if (hMsgMgr) {
++ MSG_Delete(hMsgMgr);
++ DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
++ }
++ }
++ /* Place the Board in the Monitor State */
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdMonitor)
++ (pProcObject->hWmdContext))) {
++ status = DSP_SOK;
++#ifdef DEBUG
++ if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
++ (pProcObject->hWmdContext, &uBrdState))) {
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_Monitor:Processor in "
++ "Monitor State\n");
++ DBC_Assert(uBrdState == BRD_IDLE);
++ }
++#endif
++ } else {
++ /* Monitor Failure */
++ GT_0trace(PROC_DebugMask, GT_7CLASS,
++ "PROC_Monitor: Processor Could not"
++ "be put in Monitor mode \n");
++ }
++ GT_1trace(PROC_DebugMask, GT_ENTER,
++ "Exiting PROC_Monitor, status 0x%x\n",
++ status);
++#ifdef DEBUG
++ DBC_Ensure((DSP_SUCCEEDED(status) && uBrdState == BRD_IDLE) ||
++ DSP_FAILED(status));
++#endif
++ return status;
++}
++
++/*
++ * ======== GetEnvpCount ========
++ * Purpose:
++ * Return the number of elements in the envp array, including the
++ * terminating NULL element.
++ */
++static s32 GetEnvpCount(char **envp)
++{
++ s32 cRetval = 0;
++ if (envp) {
++ while (*envp++)
++ cRetval++;
++
++ cRetval += 1; /* Include the terminating NULL in the count. */
++ }
++
++ return cRetval;
++}
++
++/*
++ * ======== PrependEnvp ========
++ * Purpose:
++ * Prepend an environment variable=value pair to the new envp array, and
++ * copy in the existing var=value pairs in the old envp array.
++ */
++static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
++ char *szVar)
++{
++ char **ppEnvp = newEnvp;
++
++ DBC_Require(newEnvp);
++
++ /* Prepend new environ var=value string */
++ *newEnvp++ = szVar;
++
++ /* Copy user's environment into our own. */
++ while (cEnvp--)
++ *newEnvp++ = *envp++;
++
++ /* Ensure NULL terminates the new environment strings array. */
++ if (cEnvp == 0)
++ *newEnvp = NULL;
++
++ return ppEnvp;
++}
++
++/*
++ * ======== PROC_NotifyClients ========
++ * Purpose:
++ * Notify the processor the events.
++ */
++DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc, u32 uEvents)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++ DBC_Require(IsValidProcEvent(uEvents));
++ DBC_Require(cRefs > 0);
++
++ NTFY_Notify(pProcObject->hNtfy, uEvents);
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_NotifyClients :Signaled. \n");
++
++ return status;
++}
++
++/*
++ * ======== PROC_NotifyAllClients ========
++ * Purpose:
++ * Notify the processor the events. This includes notifying all clients
++ * attached to a particulat DSP.
++ */
++DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc, u32 uEvents)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
++ DBC_Require(IsValidProcEvent(uEvents));
++ DBC_Require(cRefs > 0);
++
++ DEV_NotifyClients(pProcObject->hDevObject, uEvents);
++
++ GT_0trace(PROC_DebugMask, GT_1CLASS,
++ "PROC_NotifyAllClients :Signaled. \n");
++
++ return status;
++}
++
++/*
++ * ======== PROC_GetProcessorId ========
++ * Purpose:
++ * Retrieves the processor ID.
++ */
++DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProc, u32 *procID)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
++
++ *procID = pProcObject->uProcessor;
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/pwr.c b/drivers/dsp/bridge/rmgr/pwr.c
+new file mode 100644
+index 0000000..50a3f79
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/pwr.c
+@@ -0,0 +1,184 @@
++/*
++ * pwr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== PWR.c ========
++ * PWR API for controlling DSP power states.
++ *
++ * Public Functions:
++ * PWR_SleepDSP
++ * PWR_WakeDSP
++ *
++ *! Revision History
++ *! ================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 22-May-2002 sg Do PWR-to-IOCTL code mapping in PWR_SleepDSP.
++ *! 29-Apr-2002 sg Initial.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/pwr.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/devdefs.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmdioctl.h>
++
++/*
++ * ======== PWR_SleepDSP ========
++ * Send command to DSP to enter sleep state.
++ */
++DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode, IN CONST u32 timeout)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 ioctlcode = 0;
++ u32 arg = timeout;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject =
++ (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_FAILED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ continue;
++ }
++ if (DSP_FAILED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ continue;
++ }
++ if (sleepCode == PWR_DEEPSLEEP)
++ ioctlcode = WMDIOCTL_DEEPSLEEP;
++ else if (sleepCode == PWR_EMERGENCYDEEPSLEEP)
++ ioctlcode = WMDIOCTL_EMERGENCYSLEEP;
++ else
++ status = DSP_EINVALIDARG;
++
++ if (status != DSP_EINVALIDARG) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ ioctlcode, (void *)&arg);
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_WakeDSP ========
++ * Send command to DSP to wake it from sleep.
++ */
++DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg = timeout;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_WAKEUP, (void *)&arg);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_PM_PreScale========
++ * Sends pre-notification message to DSP.
++ */
++DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg[2];
++
++ arg[0] = voltage_domain;
++ arg[1] = level;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_PRESCALE_NOTIFY,
++ (void *)&arg);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== PWR_PM_PostScale========
++ * Sends post-notification message to DSP.
++ */
++DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain, u32 level)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct WMD_DEV_CONTEXT *dwContext;
++ DSP_STATUS status = DSP_EFAIL;
++ struct DEV_OBJECT *hDevObject = NULL;
++ u32 arg[2];
++
++ arg[0] = voltage_domain;
++ arg[1] = level;
++
++ for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
++ hDevObject != NULL;
++ hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
++ ((u32)hDevObject)) {
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
++ (struct WMD_DEV_CONTEXT **)&dwContext))) {
++ if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
++ (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
++ status = (*pIntfFxns->pfnDevCntrl)(dwContext,
++ WMDIOCTL_POSTSCALE_NOTIFY,
++ (void *)&arg);
++ }
++ }
++ }
++ return status;
++
++}
++
++
+diff --git a/drivers/dsp/bridge/rmgr/rmm.c b/drivers/dsp/bridge/rmgr/rmm.c
+new file mode 100644
+index 0000000..575f675
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/rmm.c
+@@ -0,0 +1,604 @@
++/*
++ * rmm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== rmm.c ========
++ * Description:
++ *
++ * This memory manager provides general heap management and arbitrary
++ * alignment for any number of memory segments.
++ *
++ * Notes:
++ *
++ * Memory blocks are allocated from the end of the first free memory
++ * block large enough to satisfy the request. Alignment requirements
++ * are satisfied by "sliding" the block forward until its base satisfies
++ * the alignment specification; if this is not possible then the next
++ * free block large enough to hold the request is tried.
++ *
++ * Since alignment can cause the creation of a new free block - the
++ * unused memory formed between the start of the original free block
++ * and the start of the allocated block - the memory manager must free
++ * this memory to prevent a memory leak.
++ *
++ * Overlay memory is managed by reserving through RMM_alloc, and freeing
++ * it through RMM_free. The memory manager prevents DSP code/data that is
++ * overlayed from being overwritten as long as the memory it runs at has
++ * been allocated, and not yet freed.
++ *
++ *! Revision History
++ *! ================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux Platform.
++ *! 24-Sep-2002 map Updated from Code Review
++ *! 25-Jun-2002 jeh Free from segid passed to RMM_free().
++ *! 24-Apr-2002 jeh Determine segid based on address in RMM_free(). (No way
++ *! to keep track of segid with dynamic loader library.)
++ *! 16-Oct-2001 jeh Based on gen tree rm.c. Added support for overlays.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/rmm.h>
++
++#define RMM_TARGSIGNATURE 0x544d4d52 /* "TMMR" */
++
++/*
++ * ======== RMM_Header ========
++ * This header is used to maintain a list of free memory blocks.
++ */
++struct RMM_Header {
++ struct RMM_Header *next; /* form a free memory link list */
++ u32 size; /* size of the free memory */
++ u32 addr; /* DSP address of memory block */
++} ;
++
++/*
++ * ======== RMM_OvlySect ========
++ * Keeps track of memory occupied by overlay section.
++ */
++struct RMM_OvlySect {
++ struct LST_ELEM listElem;
++ u32 addr; /* Start of memory section */
++ u32 size; /* Length (target MAUs) of section */
++ s32 page; /* Memory page */
++};
++
++/*
++ * ======== RMM_TargetObj ========
++ */
++struct RMM_TargetObj {
++ u32 dwSignature;
++ struct RMM_Segment *segTab;
++ struct RMM_Header **freeList;
++ u32 numSegs;
++ struct LST_LIST *ovlyList; /* List of overlay memory in use */
++};
++
++#if GT_TRACE
++static struct GT_Mask RMM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr);
++static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
++ u32 size);
++
++/*
++ * ======== RMM_alloc ========
++ */
++DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr, bool reserve)
++{
++ struct RMM_OvlySect *sect;
++ struct RMM_OvlySect *prevSect = NULL;
++ struct RMM_OvlySect *newSect;
++ u32 addr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++ DBC_Require(dspAddr != NULL);
++ DBC_Require(size > 0);
++ DBC_Require(reserve || (target->numSegs > 0));
++ DBC_Require(cRefs > 0);
++
++ GT_6trace(RMM_debugMask, GT_ENTER,
++ "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
++ "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr,
++ reserve);
++ if (!reserve) {
++ if (!allocBlock(target, segid, size, align, dspAddr)) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Increment the number of allocated blocks in this
++ * segment */
++ target->segTab[segid].number++;
++ }
++ goto func_end;
++ }
++ /* An overlay section - See if block is already in use. If not,
++ * insert into the list in ascending address size. */
++ addr = *dspAddr;
++ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
++ /* Find place to insert new list element. List is sorted from
++ * smallest to largest address. */
++ while (sect != NULL) {
++ if (addr <= sect->addr) {
++ /* Check for overlap with sect */
++ if ((addr + size > sect->addr) || (prevSect &&
++ (prevSect->addr + prevSect->size > addr))) {
++ status = DSP_EOVERLAYMEMORY;
++ }
++ break;
++ }
++ prevSect = sect;
++ sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* No overlap - allocate list element for new section. */
++ newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED);
++ if (newSect == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ LST_InitElem((struct LST_ELEM *)newSect);
++ newSect->addr = addr;
++ newSect->size = size;
++ newSect->page = segid;
++ if (sect == NULL) {
++ /* Put new section at the end of the list */
++ LST_PutTail(target->ovlyList,
++ (struct LST_ELEM *)newSect);
++ } else {
++ /* Put new section just before sect */
++ LST_InsertBefore(target->ovlyList,
++ (struct LST_ELEM *)newSect,
++ (struct LST_ELEM *)sect);
++ }
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== RMM_create ========
++ */
++DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
++ struct RMM_Segment segTab[], u32 numSegs)
++{
++ struct RMM_Header *hptr;
++ struct RMM_Segment *sptr, *tmp;
++ struct RMM_TargetObj *target;
++ s32 i;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(pTarget != NULL);
++ DBC_Require(numSegs == 0 || segTab != NULL);
++
++ GT_3trace(RMM_debugMask, GT_ENTER,
++ "RMM_create(0x%lx, 0x%lx, 0x%lx)\n",
++ pTarget, segTab, numSegs);
++
++ /* Allocate DBL target object */
++ MEM_AllocObject(target, struct RMM_TargetObj, RMM_TARGSIGNATURE);
++
++ if (target == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ target->numSegs = numSegs;
++ if (!(numSegs > 0))
++ goto func_cont;
++
++ /* Allocate the memory for freelist from host's memory */
++ target->freeList = MEM_Calloc(numSegs * sizeof(struct RMM_Header *),
++ MEM_PAGED);
++ if (target->freeList == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ /* Allocate headers for each element on the free list */
++ for (i = 0; i < (s32) numSegs; i++) {
++ target->freeList[i] =
++ MEM_Calloc(sizeof(struct RMM_Header),
++ MEM_PAGED);
++ if (target->freeList[i] == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory "
++ "allocation failed\n");
++ status = DSP_EMEMORY;
++ break;
++ }
++ }
++ /* Allocate memory for initial segment table */
++ target->segTab = MEM_Calloc(numSegs *
++ sizeof(struct RMM_Segment), MEM_PAGED);
++ if (target->segTab == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ } else {
++ /* Initialize segment table and free list */
++ sptr = target->segTab;
++ for (i = 0, tmp = segTab; numSegs > 0; numSegs--, i++) {
++ *sptr = *tmp;
++ hptr = target->freeList[i];
++ hptr->addr = tmp->base;
++ hptr->size = tmp->length;
++ hptr->next = NULL;
++ tmp++;
++ sptr++;
++ }
++ }
++ }
++func_cont:
++ /* Initialize overlay memory list */
++ if (DSP_SUCCEEDED(status)) {
++ target->ovlyList = LST_Create();
++ if (target->ovlyList == NULL) {
++ GT_0trace(RMM_debugMask, GT_6CLASS,
++ "RMM_create: Memory allocation failed\n");
++ status = DSP_EMEMORY;
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ *pTarget = target;
++ } else {
++ *pTarget = NULL;
++ if (target)
++ RMM_delete(target);
++
++ }
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle((*pTarget),
++ RMM_TARGSIGNATURE)) || (DSP_FAILED(status) && *pTarget ==
++ NULL));
++
++ return status;
++}
++
++/*
++ * ======== RMM_delete ========
++ */
++void RMM_delete(struct RMM_TargetObj *target)
++{
++ struct RMM_OvlySect *pSect;
++ struct RMM_Header *hptr;
++ struct RMM_Header *next;
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++
++ GT_1trace(RMM_debugMask, GT_ENTER, "RMM_delete(0x%lx)\n", target);
++
++ if (target->segTab != NULL)
++ MEM_Free(target->segTab);
++
++ if (target->ovlyList) {
++ while ((pSect = (struct RMM_OvlySect *)LST_GetHead
++ (target->ovlyList))) {
++ MEM_Free(pSect);
++ }
++ DBC_Assert(LST_IsEmpty(target->ovlyList));
++ LST_Delete(target->ovlyList);
++ }
++
++ if (target->freeList != NULL) {
++ /* Free elements on freelist */
++ for (i = 0; i < target->numSegs; i++) {
++ hptr = next = target->freeList[i];
++ while (next) {
++ hptr = next;
++ next = hptr->next;
++ MEM_Free(hptr);
++ }
++ }
++ MEM_Free(target->freeList);
++ }
++
++ MEM_FreeObject(target);
++}
++
++/*
++ * ======== RMM_exit ========
++ */
++void RMM_exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(RMM_debugMask, GT_5CLASS, "RMM_exit() ref count: 0x%x\n",
++ cRefs);
++
++ if (cRefs == 0)
++ MEM_Exit();
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== RMM_free ========
++ */
++bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size,
++ bool reserved)
++
++{
++ struct RMM_OvlySect *sect;
++ bool retVal = true;
++
++ DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
++
++ DBC_Require(reserved || segid < target->numSegs);
++ DBC_Require(reserved || (addr >= target->segTab[segid].base &&
++ (addr + size) <= (target->segTab[segid].base +
++ target->segTab[segid].length)));
++
++ GT_5trace(RMM_debugMask, GT_ENTER,
++ "RMM_free(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
++ "0x%lx)\n", target, segid, addr, size, reserved);
++ /*
++ * Free or unreserve memory.
++ */
++ if (!reserved) {
++ retVal = freeBlock(target, segid, addr, size);
++ if (retVal)
++ target->segTab[segid].number--;
++
++ } else {
++ /* Unreserve memory */
++ sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
++ while (sect != NULL) {
++ if (addr == sect->addr) {
++ DBC_Assert(size == sect->size);
++ /* Remove from list */
++ LST_RemoveElem(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ MEM_Free(sect);
++ break;
++ }
++ sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
++ (struct LST_ELEM *)sect);
++ }
++ if (sect == NULL)
++ retVal = false;
++
++ }
++ return retVal;
++}
++
++/*
++ * ======== RMM_init ========
++ */
++bool RMM_init(void)
++{
++ bool retVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ DBC_Assert(!RMM_debugMask.flags);
++ GT_create(&RMM_debugMask, "RM"); /* "RM" for RMm */
++
++ retVal = MEM_Init();
++
++ if (!retVal)
++ MEM_Exit();
++
++ }
++
++ if (retVal)
++ cRefs++;
++
++ GT_1trace(RMM_debugMask, GT_5CLASS,
++ "RMM_init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
++
++ return retVal;
++}
++
++/*
++ * ======== RMM_stat ========
++ */
++bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
++ struct DSP_MEMSTAT *pMemStatBuf)
++{
++ struct RMM_Header *head;
++ bool retVal = false;
++ u32 maxFreeSize = 0;
++ u32 totalFreeSize = 0;
++ u32 freeBlocks = 0;
++
++ DBC_Require(pMemStatBuf != NULL);
++ DBC_Assert(target != NULL);
++
++ if ((u32) segid < target->numSegs) {
++ head = target->freeList[segid];
++
++ /* Collect data from freeList */
++ while (head != NULL) {
++ maxFreeSize = max(maxFreeSize, head->size);
++ totalFreeSize += head->size;
++ freeBlocks++;
++ head = head->next;
++ }
++
++ /* ulSize */
++ pMemStatBuf->ulSize = target->segTab[segid].length;
++
++ /* ulNumFreeBlocks */
++ pMemStatBuf->ulNumFreeBlocks = freeBlocks;
++
++ /* ulTotalFreeSize */
++ pMemStatBuf->ulTotalFreeSize = totalFreeSize;
++
++ /* ulLenMaxFreeBlock */
++ pMemStatBuf->ulLenMaxFreeBlock = maxFreeSize;
++
++ /* ulNumAllocBlocks */
++ pMemStatBuf->ulNumAllocBlocks = target->segTab[segid].number;
++
++ retVal = true;
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== balloc ========
++ * This allocation function allocates memory from the lowest addresses
++ * first.
++ */
++static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
++ u32 align, u32 *dspAddr)
++{
++ struct RMM_Header *head;
++ struct RMM_Header *prevhead = NULL;
++ struct RMM_Header *next;
++ u32 tmpalign;
++ u32 alignbytes;
++ u32 hsize;
++ u32 allocsize;
++ u32 addr;
++
++ alignbytes = (align == 0) ? 1 : align;
++ prevhead = NULL;
++ head = target->freeList[segid];
++
++ do {
++ hsize = head->size;
++ next = head->next;
++
++ addr = head->addr; /* alloc from the bottom */
++
++ /* align allocation */
++ (tmpalign = (u32) addr % alignbytes);
++ if (tmpalign != 0)
++ tmpalign = alignbytes - tmpalign;
++
++ allocsize = size + tmpalign;
++
++ if (hsize >= allocsize) { /* big enough */
++ if (hsize == allocsize && prevhead != NULL) {
++ prevhead->next = next;
++ MEM_Free(head);
++ } else {
++ head->size = hsize - allocsize;
++ head->addr += allocsize;
++ }
++
++ /* free up any hole created by alignment */
++ if (tmpalign)
++ freeBlock(target, segid, addr, tmpalign);
++
++ *dspAddr = addr + tmpalign;
++ return true;
++ }
++
++ prevhead = head;
++ head = next;
++
++ } while (head != NULL);
++
++ return false;
++}
++
++/*
++ * ======== freeBlock ========
++ * TO DO: freeBlock() allocates memory, which could result in failure.
++ * Could allocate an RMM_Header in RMM_alloc(), to be kept in a pool.
++ * freeBlock() could use an RMM_Header from the pool, freeing as blocks
++ * are coalesced.
++ */
++static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
++ u32 size)
++{
++ struct RMM_Header *head;
++ struct RMM_Header *thead;
++ struct RMM_Header *rhead;
++ bool retVal = true;
++
++ /* Create a memory header to hold the newly free'd block. */
++ rhead = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED);
++ if (rhead == NULL) {
++ retVal = false;
++ } else {
++ /* search down the free list to find the right place for addr */
++ head = target->freeList[segid];
++
++ if (addr >= head->addr) {
++ while (head->next != NULL && addr > head->next->addr)
++ head = head->next;
++
++ thead = head->next;
++
++ head->next = rhead;
++ rhead->next = thead;
++ rhead->addr = addr;
++ rhead->size = size;
++ } else {
++ *rhead = *head;
++ head->next = rhead;
++ head->addr = addr;
++ head->size = size;
++ thead = rhead->next;
++ }
++
++ /* join with upper block, if possible */
++ if (thead != NULL && (rhead->addr + rhead->size) ==
++ thead->addr) {
++ head->next = rhead->next;
++ thead->size = size + thead->size;
++ thead->addr = addr;
++ MEM_Free(rhead);
++ rhead = thead;
++ }
++
++ /* join with the lower block, if possible */
++ if ((head->addr + head->size) == rhead->addr) {
++ head->next = rhead->next;
++ head->size = head->size + rhead->size;
++ MEM_Free(rhead);
++ }
++ }
++
++ return retVal;
++}
++
+diff --git a/drivers/dsp/bridge/rmgr/strm.c b/drivers/dsp/bridge/rmgr/strm.c
+new file mode 100644
+index 0000000..bd55fd3
+--- /dev/null
++++ b/drivers/dsp/bridge/rmgr/strm.c
+@@ -0,0 +1,1066 @@
++/*
++ * strm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== strm.c ========
++ * Description:
++ * DSP/BIOS Bridge Stream Manager.
++ *
++ * Public Functions:
++ * STRM_AllocateBuffer
++ * STRM_Close
++ * STRM_Create
++ * STRM_Delete
++ * STRM_Exit
++ * STRM_FreeBuffer
++ * STRM_GetEventHandle
++ * STRM_GetInfo
++ * STRM_Idle
++ * STRM_Init
++ * STRM_Issue
++ * STRM_Open
++ * STRM_PrepareBuffer
++ * STRM_Reclaim
++ * STRM_RegisterNotify
++ * STRM_Select
++ * STRM_UnprepareBuffer
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Feb-2003 vp Code review updates.
++ *! 18-Oct-2002 vp Ported to Linux platform.
++ *! 13-Mar-2002 map pStrm init'd to NULL in STRM_Open to prevent error
++ *! 12-Mar-2002 map Changed return var to WSX "wStatus" instead of "status"
++ *! in DEV and CMM function calls to avoid confusion.
++ *! Return DSP_SOK instead of S_OK from API fxns.
++ *! 12-Mar-2002 map Changed FAILED(..) to DSP_FAILED(..)
++ *! 25-Jan-2002 ag Allow neg seg ids(e.g. DSP_SHMSEG0) to denote SM.
++ *! 15-Nov-2001 ag Added STRMMODE & SM for DMA/ZCopy streaming.
++ *! Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
++ *! Use strm timeout value for dma flush timeout.
++ *! 09-May-2001 jeh Code review cleanup.
++ *! 06-Feb-2001 kc Updated DBC_Ensure in STRM_Select to check timeout.
++ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open() for DLL
++ *! tests to pass.
++ *! 25-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmd.h>
++
++/* ----------------------------------- Resource Manager */
++#include <dspbridge/nodepriv.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/cmm.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/strm.h>
++
++#ifndef RES_CLEANUP_DISABLE
++#include <dspbridge/cfg.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/resourcecleanup.h>
++#endif
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define STRM_SIGNATURE 0x4d525453 /* "MRTS" */
++#define STRMMGR_SIGNATURE 0x5254534d /* "RTSM" */
++
++#define DEFAULTTIMEOUT 10000
++#define DEFAULTNUMBUFS 2
++
++/*
++ * ======== STRM_MGR ========
++ * The STRM_MGR contains device information needed to open the underlying
++ * channels of a stream.
++ */
++struct STRM_MGR {
++ u32 dwSignature;
++ struct DEV_OBJECT *hDev; /* Device for this processor */
++ struct CHNL_MGR *hChnlMgr; /* Channel manager */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++} ;
++
++/*
++ * ======== STRM_OBJECT ========
++ * This object is allocated in STRM_Open().
++ */
++ struct STRM_OBJECT {
++ u32 dwSignature;
++ struct STRM_MGR *hStrmMgr;
++ struct CHNL_OBJECT *hChnl;
++ u32 uDir; /* DSP_TONODE or DSP_FROMNODE */
++ u32 uTimeout;
++ u32 uNumBufs; /* Max # of bufs allowed in stream */
++ u32 uNBufsInStrm; /* Current # of bufs in stream */
++ u32 ulNBytes; /* bytes transferred since idled */
++ enum DSP_STREAMSTATE strmState; /* STREAM_IDLE, STREAM_READY, ... */
++ HANDLE hUserEvent; /* Saved for STRM_GetInfo() */
++ enum DSP_STRMMODE lMode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
++ u32 uDMAChnlId; /* DMA chnl id */
++ u32 uDMAPriority; /* DMA priority:DMAPRI_[LOW][HIGH] */
++ u32 uSegment; /* >0 is SM segment.=0 is local heap */
++ u32 uAlignment; /* Alignment for stream bufs */
++ struct CMM_XLATOROBJECT *hXlator; /* Stream's SM address translator */
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask STRM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++static u32 cRefs; /* module reference count */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm);
++static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr);
++
++/*
++ * ======== STRM_AllocateBuffer ========
++ * Purpose:
++ * Allocates buffers for a stream.
++ */
++DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm, u32 uSize,
++ OUT u8 **apBuffer, u32 uNumBufs)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 uAllocated = 0;
++ u32 i;
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(apBuffer != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER, "STRM_AllocateBuffer: hStrm: 0x%x\t"
++ "uSize: 0x%x\tapBuffer: 0x%x\tuNumBufs: 0x%x\n",
++ hStrm, uSize, apBuffer, uNumBufs);
++ if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ /*
++ * Allocate from segment specified at time of stream open.
++ */
++ if (uSize == 0)
++ status = DSP_ESIZE;
++
++ }
++ if (DSP_FAILED(status)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ for (i = 0; i < uNumBufs; i++) {
++ DBC_Assert(hStrm->hXlator != NULL);
++ (void)CMM_XlatorAllocBuf(hStrm->hXlator, &apBuffer[i], uSize);
++ if (apBuffer[i] == NULL) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_AllocateBuffer: "
++ "DSP_FAILED to alloc shared memory.\n");
++ status = DSP_EMEMORY;
++ uAllocated = i;
++ break;
++ }
++ }
++ if (DSP_FAILED(status))
++ STRM_FreeBuffer(hStrm, apBuffer, uAllocated);
++
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcUpdateSTRMRes(uNumBufs, hSTRMRes, pCtxt);
++ }
++ }
++#endif
++func_end:
++ return status;
++}
++
++/*
++ * ======== STRM_Close ========
++ * Purpose:
++ * Close a stream opened with STRM_Open().
++ */
++DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_INFO chnlInfo;
++ DSP_STATUS status = DSP_SOK;
++
++
++#ifndef RES_CLEANUP_DISABLE
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ DSP_STATUS res_status = DSP_SOK;
++#endif
++
++
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Close: hStrm: 0x%x\n", hStrm);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ /* Have all buffers been reclaimed? If not, return
++ * DSP_EPENDING */
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
++ DBC_Assert(DSP_SUCCEEDED(status));
++
++ if (chnlInfo.cIOCs > 0 || chnlInfo.cIOReqs > 0) {
++ status = DSP_EPENDING;
++ } else {
++
++ status = DeleteStrm(hStrm);
++
++ if (DSP_FAILED(status)) {
++ /* we already validated the handle. */
++ DBC_Assert(status != DSP_EHANDLE);
++
++ /* make sure we return a documented result */
++ status = DSP_EFAIL;
++ }
++ }
++ }
++#ifndef RES_CLEANUP_DISABLE
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_FAILED(res_status))
++ goto func_end;
++
++ DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)hDrvObject,
++ &pCtxt, NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcRemoveSTRMResElement(hSTRMRes, pCtxt);
++ }
++ }
++func_end:
++#endif
++ DBC_Ensure(status == DSP_SOK || status == DSP_EHANDLE ||
++ status == DSP_EPENDING || status == DSP_EFAIL);
++
++ return status;
++}
++
++/*
++ * ======== STRM_Create ========
++ * Purpose:
++ * Create a STRM manager object.
++ */
++DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr, struct DEV_OBJECT *hDev)
++{
++ struct STRM_MGR *pStrmMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(phStrmMgr != NULL);
++ DBC_Require(hDev != NULL);
++
++ GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Create: phStrmMgr: "
++ "0x%x\thDev: 0x%x\n", phStrmMgr, hDev);
++ *phStrmMgr = NULL;
++ /* Allocate STRM manager object */
++ MEM_AllocObject(pStrmMgr, struct STRM_MGR, STRMMGR_SIGNATURE);
++ if (pStrmMgr == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
++ "MEM_AllocObject() failed!\n ");
++ } else {
++ pStrmMgr->hDev = hDev;
++ }
++ /* Get Channel manager and WMD function interface */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetChnlMgr(hDev, &(pStrmMgr->hChnlMgr));
++ if (DSP_SUCCEEDED(status)) {
++ (void) DEV_GetIntfFxns(hDev, &(pStrmMgr->pIntfFxns));
++ DBC_Assert(pStrmMgr->pIntfFxns != NULL);
++ } else {
++ GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
++ "Failed to get channel manager! status = "
++ "0x%x\n", status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pStrmMgr->hSync);
++
++ if (DSP_SUCCEEDED(status))
++ *phStrmMgr = pStrmMgr;
++ else
++ DeleteStrmMgr(pStrmMgr);
++
++ DBC_Ensure(DSP_SUCCEEDED(status) &&
++ (MEM_IsValidHandle((*phStrmMgr), STRMMGR_SIGNATURE) ||
++ (DSP_FAILED(status) && *phStrmMgr == NULL)));
++
++ return status;
++}
++
++/*
++ * ======== STRM_Delete ========
++ * Purpose:
++ * Delete the STRM Manager Object.
++ */
++void STRM_Delete(struct STRM_MGR *hStrmMgr)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
++
++ GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Delete: hStrmMgr: 0x%x\n",
++ hStrmMgr);
++
++ DeleteStrmMgr(hStrmMgr);
++
++ DBC_Ensure(!MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
++}
++
++/*
++ * ======== STRM_Exit ========
++ * Purpose:
++ * Discontinue usage of STRM module.
++ */
++void STRM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ cRefs--;
++
++ GT_1trace(STRM_debugMask, GT_5CLASS,
++ "Entered STRM_Exit, ref count: 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== STRM_FreeBuffer ========
++ * Purpose:
++ * Frees the buffers allocated for a stream.
++ */
++DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm, u8 **apBuffer,
++ u32 uNumBufs)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 i = 0;
++
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes = NULL;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(apBuffer != NULL);
++
++ GT_3trace(STRM_debugMask, GT_ENTER, "STRM_FreeBuffer: hStrm: 0x%x\t"
++ "apBuffer: 0x%x\tuNumBufs: 0x%x\n", hStrm, apBuffer, uNumBufs);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE))
++ status = DSP_EHANDLE;
++
++ if (DSP_SUCCEEDED(status)) {
++ for (i = 0; i < uNumBufs; i++) {
++ DBC_Assert(hStrm->hXlator != NULL);
++ status = CMM_XlatorFreeBuf(hStrm->hXlator, apBuffer[i]);
++ if (DSP_FAILED(status)) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_FreeBuffer: DSP_FAILED"
++ " to free shared memory.\n");
++ break;
++ }
++ apBuffer[i] = NULL;
++ }
++ }
++#ifndef RES_CLEANUP_DISABLE
++ /* Update the node and stream resource status */
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt,
++ NULL, 0);
++ if (pCtxt != NULL) {
++ if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pCtxt) !=
++ DSP_ENOTFOUND) {
++ DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes,
++ pCtxt);
++ }
++ }
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== STRM_GetInfo ========
++ * Purpose:
++ * Retrieves information about a stream.
++ */
++DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
++ OUT struct STRM_INFO *pStreamInfo,
++ u32 uStreamInfoSize)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_INFO chnlInfo;
++ DSP_STATUS status = DSP_SOK;
++ void *pVirtBase = NULL; /* NULL if no SM used */
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pStreamInfo != NULL);
++ DBC_Require(uStreamInfoSize >= sizeof(struct STRM_INFO));
++
++ GT_3trace(STRM_debugMask, GT_ENTER, "STRM_GetInfo: hStrm: 0x%x\t"
++ "pStreamInfo: 0x%x\tuStreamInfoSize: 0x%x\n", hStrm,
++ pStreamInfo, uStreamInfoSize);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ if (uStreamInfoSize < sizeof(struct STRM_INFO)) {
++ /* size of users info */
++ status = DSP_ESIZE;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ if (hStrm->hXlator) {
++ /* We have a translator */
++ DBC_Assert(hStrm->uSegment > 0);
++ CMM_XlatorInfo(hStrm->hXlator, (u8 **)&pVirtBase, 0,
++ hStrm->uSegment, false);
++ }
++ pStreamInfo->uSegment = hStrm->uSegment;
++ pStreamInfo->lMode = hStrm->lMode;
++ pStreamInfo->pVirtBase = pVirtBase;
++ pStreamInfo->pUser->uNumberBufsAllowed = hStrm->uNumBufs;
++ pStreamInfo->pUser->uNumberBufsInStream = chnlInfo.cIOCs +
++ chnlInfo.cIOReqs;
++ /* # of bytes transferred since last call to DSPStream_Idle() */
++ pStreamInfo->pUser->ulNumberBytes = chnlInfo.cPosition;
++ pStreamInfo->pUser->hSyncObjectHandle = chnlInfo.hEvent;
++ /* Determine stream state based on channel state and info */
++ if (chnlInfo.dwState & CHNL_STATEEOS) {
++ pStreamInfo->pUser->ssStreamState = STREAM_DONE;
++ } else {
++ if (chnlInfo.cIOCs > 0)
++ pStreamInfo->pUser->ssStreamState = STREAM_READY;
++ else if (chnlInfo.cIOReqs > 0)
++ pStreamInfo->pUser->ssStreamState = STREAM_PENDING;
++ else
++ pStreamInfo->pUser->ssStreamState = STREAM_IDLE;
++
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== STRM_Idle ========
++ * Purpose:
++ * Idles a particular stream.
++ */
++DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Idle: hStrm: 0x%x\t"
++ "fFlush: 0x%x\n", hStrm, fFlush);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlIdle) (hStrm->hChnl,
++ hStrm->uTimeout, fFlush);
++ }
++ return status;
++}
++
++/*
++ * ======== STRM_Init ========
++ * Purpose:
++ * Initialize the STRM module.
++ */
++bool STRM_Init(void)
++{
++ bool fRetVal = true;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++#if GT_TRACE
++ DBC_Assert(!STRM_debugMask.flags);
++ GT_create(&STRM_debugMask, "ST"); /* "ST" for STrm */
++#endif
++ }
++
++ if (fRetVal)
++ cRefs++;
++
++ GT_1trace(STRM_debugMask, GT_5CLASS, "STRM_Init(), ref count: 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
++
++ return fRetVal;
++}
++
++/*
++ * ======== STRM_Issue ========
++ * Purpose:
++ * Issues a buffer on a stream
++ */
++DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf, u32 ulBytes,
++ u32 ulBufSize, u32 dwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBuf != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER, "STRM_Issue: hStrm: 0x%x\tpBuf: "
++ "0x%x\tulBytes: 0x%x\tdwArg: 0x%x\n", hStrm, pBuf, ulBytes,
++ dwArg);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ if (hStrm->uSegment != 0) {
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ (void *)pBuf, CMM_VA2DSPPA);
++ if (pTmpBuf == NULL)
++ status = DSP_ETRANSLATE;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = (*pIntfFxns->pfnChnlAddIOReq)
++ (hStrm->hChnl, pBuf, ulBytes, ulBufSize,
++ (u32) pTmpBuf, dwArg);
++ }
++ if (DSP_FAILED(status)) {
++ if (status == CHNL_E_NOIORPS)
++ status = DSP_ESTREAMFULL;
++ else
++ status = DSP_EFAIL;
++
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== STRM_Open ========
++ * Purpose:
++ * Open a stream for sending/receiving data buffers to/from a task or
++ * XDAIS socket node on the DSP.
++ */
++DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
++ IN struct STRM_ATTR *pAttr, OUT struct STRM_OBJECT **phStrm)
++{
++ struct STRM_MGR *hStrmMgr;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ u32 ulChnlId;
++ struct STRM_OBJECT *pStrm = NULL;
++ CHNL_MODE uMode;
++ struct CHNL_ATTRS chnlAttrs;
++ DSP_STATUS status = DSP_SOK;
++ struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
++
++ #ifndef RES_CLEANUP_DISABLE
++ DSP_STATUS res_status = DSP_SOK;
++ u32 hProcess;
++ HANDLE pCtxt = NULL;
++ HANDLE hDrvObject;
++ HANDLE hSTRMRes;
++ #endif
++ DBC_Require(cRefs > 0);
++ DBC_Require(phStrm != NULL);
++ DBC_Require(pAttr != NULL);
++ GT_5trace(STRM_debugMask, GT_ENTER,
++ "STRM_Open: hNode: 0x%x\tuDir: 0x%x\t"
++ "uIndex: 0x%x\tpAttr: 0x%x\tphStrm: 0x%x\n",
++ hNode, uDir, uIndex, pAttr, phStrm);
++ *phStrm = NULL;
++ if (uDir != DSP_TONODE && uDir != DSP_FROMNODE) {
++ status = DSP_EDIRECTION;
++ } else {
++ /* Get the channel id from the node (set in NODE_Connect()) */
++ status = NODE_GetChannelId(hNode, uDir, uIndex, &ulChnlId);
++ }
++ if (DSP_SUCCEEDED(status))
++ status = NODE_GetStrmMgr(hNode, &hStrmMgr);
++
++ if (DSP_SUCCEEDED(status)) {
++ MEM_AllocObject(pStrm, struct STRM_OBJECT, STRM_SIGNATURE);
++ if (pStrm == NULL) {
++ status = DSP_EMEMORY;
++ GT_0trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: MEM_AllocObject() failed!\n ");
++ } else {
++ pStrm->hStrmMgr = hStrmMgr;
++ pStrm->uDir = uDir;
++ pStrm->strmState = STREAM_IDLE;
++ pStrm->hUserEvent = pAttr->hUserEvent;
++ if (pAttr->pStreamAttrIn != NULL) {
++ pStrm->uTimeout = pAttr->pStreamAttrIn->
++ uTimeout;
++ pStrm->uNumBufs = pAttr->pStreamAttrIn->
++ uNumBufs;
++ pStrm->lMode = pAttr->pStreamAttrIn->lMode;
++ pStrm->uSegment = pAttr->pStreamAttrIn->
++ uSegment;
++ pStrm->uAlignment = pAttr->pStreamAttrIn->
++ uAlignment;
++ pStrm->uDMAChnlId = pAttr->pStreamAttrIn->
++ uDMAChnlId;
++ pStrm->uDMAPriority = pAttr->pStreamAttrIn->
++ uDMAPriority;
++ chnlAttrs.uIOReqs = pAttr->pStreamAttrIn->
++ uNumBufs;
++ } else {
++ pStrm->uTimeout = DEFAULTTIMEOUT;
++ pStrm->uNumBufs = DEFAULTNUMBUFS;
++ pStrm->lMode = STRMMODE_PROCCOPY;
++ pStrm->uSegment = 0; /* local memory */
++ pStrm->uAlignment = 0;
++ pStrm->uDMAChnlId = 0;
++ pStrm->uDMAPriority = 0;
++ chnlAttrs.uIOReqs = DEFAULTNUMBUFS;
++ }
++ chnlAttrs.hReserved1 = NULL;
++ /* DMA chnl flush timeout */
++ chnlAttrs.hReserved2 = pStrm->uTimeout;
++ chnlAttrs.hEvent = NULL;
++ if (pAttr->hUserEvent != NULL)
++ chnlAttrs.hEvent = pAttr->hUserEvent;
++
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ if ((pAttr->pVirtBase == NULL) || !(pAttr->ulVirtSize > 0))
++ goto func_cont;
++
++ DBC_Assert(pStrm->lMode != STRMMODE_LDMA); /* no System DMA */
++ /* Get the shared mem mgr for this streams dev object */
++ status = DEV_GetCmmMgr(hStrmMgr->hDev, &hCmmMgr);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Open: Failed to get "
++ "CMM Mgr handle: 0x%x\n", status);
++ } else {
++ /*Allocate a SM addr translator for this strm.*/
++ status = CMM_XlatorCreate(&pStrm->hXlator, hCmmMgr, NULL);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: Failed to "
++ "create SM translator: 0x%x\n", status);
++ } else {
++ DBC_Assert(pStrm->uSegment > 0);
++ /* Set translators Virt Addr attributes */
++ status = CMM_XlatorInfo(pStrm->hXlator,
++ (u8 **)&pAttr->pVirtBase, pAttr->ulVirtSize,
++ pStrm->uSegment, true);
++ if (status != DSP_SOK) {
++ GT_0trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: ERROR: "
++ "in setting CMM_XlatorInfo.\n");
++ }
++ }
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Open channel */
++ uMode = (uDir == DSP_TONODE) ?
++ CHNL_MODETODSP : CHNL_MODEFROMDSP;
++ pIntfFxns = hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlOpen) (&(pStrm->hChnl),
++ hStrmMgr->hChnlMgr, uMode, ulChnlId, &chnlAttrs);
++ if (DSP_FAILED(status)) {
++ /*
++ * over-ride non-returnable status codes so we return
++ * something documented
++ */
++ if (status != DSP_EMEMORY && status !=
++ DSP_EINVALIDARG && status != DSP_EFAIL) {
++ /*
++ * We got a status that's not return-able.
++ * Assert that we got something we were
++ * expecting (DSP_EHANDLE isn't acceptable,
++ * hStrmMgr->hChnlMgr better be valid or we
++ * assert here), and then return DSP_EFAIL.
++ */
++ DBC_Assert(status == CHNL_E_OUTOFSTREAMS ||
++ status == CHNL_E_BADCHANID ||
++ status == CHNL_E_CHANBUSY ||
++ status == CHNL_E_NOIORPS);
++ status = DSP_EFAIL;
++ }
++ GT_2trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Open: Channel open failed, "
++ "chnl id = %d, status = 0x%x\n", ulChnlId,
++ status);
++ }
++ }
++ if (DSP_SUCCEEDED(status))
++ *phStrm = pStrm;
++ else
++ (void)DeleteStrm(pStrm);
++
++#ifndef RES_CLEANUP_DISABLE
++ /* Return PID instead of process handle */
++ hProcess = current->pid;
++
++ res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
++ if (DSP_SUCCEEDED(res_status)) {
++ DRV_GetProcContext(hProcess,
++ (struct DRV_OBJECT *)hDrvObject, &pCtxt,
++ hNode, 0);
++ if (pCtxt != NULL)
++ DRV_ProcInsertSTRMResElement(*phStrm, &hSTRMRes, pCtxt);
++
++ }
++#endif
++
++ /* ensure we return a documented error code */
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle((*phStrm), STRM_SIGNATURE)) ||
++ (*phStrm == NULL && (status == DSP_EHANDLE ||
++ status == DSP_EDIRECTION || status == DSP_EVALUE ||
++ status == DSP_EFAIL)));
++ return status;
++}
++
++/*
++ * ======== STRM_Reclaim ========
++ * Purpose:
++ * Relcaims a buffer from a stream.
++ */
++DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm, OUT u8 **pBufPtr,
++ u32 *pulBytes, u32 *pulBufSize, u32 *pdwArg)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct CHNL_IOC chnlIOC;
++ DSP_STATUS status = DSP_SOK;
++ void *pTmpBuf = NULL;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(pBufPtr != NULL);
++ DBC_Require(pulBytes != NULL);
++ DBC_Require(pdwArg != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_Reclaim: hStrm: 0x%x\tpBufPtr: 0x%x"
++ "\tpulBytes: 0x%x\tpdwArg: 0x%x\n", hStrm, pBufPtr, pulBytes,
++ pdwArg);
++
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlGetIOC)(hStrm->hChnl, hStrm->uTimeout,
++ &chnlIOC);
++ if (DSP_FAILED(status)) {
++ GT_1trace(STRM_debugMask, GT_6CLASS,
++ "STRM_Reclaim: GetIOC failed! "
++ "Status = 0x%x\n", status);
++ } else {
++ *pulBytes = chnlIOC.cBytes;
++ if (pulBufSize)
++ *pulBufSize = chnlIOC.cBufSize;
++
++ *pdwArg = chnlIOC.dwArg;
++ if (!CHNL_IsIOComplete(chnlIOC)) {
++ if (CHNL_IsTimedOut(chnlIOC)) {
++ status = DSP_ETIMEOUT;
++ } else {
++ /* Allow reclaims after idle to succeed */
++ if (!CHNL_IsIOCancelled(chnlIOC))
++ status = DSP_EFAIL;
++
++ }
++ }
++ /* Translate zerocopy buffer if channel not canceled. */
++ if (DSP_SUCCEEDED(status) && (!CHNL_IsIOCancelled(chnlIOC)) &&
++ (hStrm->lMode == STRMMODE_ZEROCOPY)) {
++ /*
++ * This is a zero-copy channel so chnlIOC.pBuf
++ * contains the DSP address of SM. We need to
++ * translate it to a virtual address for the user
++ * thread to access.
++ * Note: Could add CMM_DSPPA2VA to CMM in the future.
++ */
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ chnlIOC.pBuf, CMM_DSPPA2PA);
++ if (pTmpBuf != NULL) {
++ /* now convert this GPP Pa to Va */
++ pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
++ pTmpBuf, CMM_PA2VA);
++ }
++ if (pTmpBuf == NULL) {
++ GT_0trace(STRM_debugMask, GT_7CLASS,
++ "STRM_Reclaim: Failed "
++ "SM translation!\n");
++ status = DSP_ETRANSLATE;
++ }
++ chnlIOC.pBuf = pTmpBuf;
++ }
++ *pBufPtr = chnlIOC.pBuf;
++ }
++func_end:
++ /* ensure we return a documented return code */
++ DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
++ status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
++ status == DSP_EFAIL);
++ return status;
++}
++
++/*
++ * ======== STRM_RegisterNotify ========
++ * Purpose:
++ * Register to be notified on specific events for this stream.
++ */
++DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm, u32 uEventMask,
++ u32 uNotifyType, struct DSP_NOTIFICATION
++ *hNotification)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(hNotification != NULL);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_RegisterNotify: hStrm: 0x%x\t"
++ "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
++ hStrm, uEventMask, uNotifyType, hNotification);
++ if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if ((uEventMask & ~((DSP_STREAMIOCOMPLETION) |
++ DSP_STREAMDONE)) != 0) {
++ status = DSP_EVALUE;
++ } else {
++ if (uNotifyType != DSP_SIGNALEVENT)
++ status = DSP_ENOTIMPL;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++
++ status = (*pIntfFxns->pfnChnlRegisterNotify)(hStrm->hChnl,
++ uEventMask, uNotifyType, hNotification);
++ }
++ /* ensure we return a documented return code */
++ DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
++ status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
++ status == DSP_ENOTIMPL || status == DSP_EFAIL);
++ return status;
++}
++
++/*
++ * ======== STRM_Select ========
++ * Purpose:
++ * Selects a ready stream.
++ */
++DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab, u32 nStrms,
++ OUT u32 *pMask, u32 uTimeout)
++{
++ u32 uIndex;
++ struct CHNL_INFO chnlInfo;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct SYNC_OBJECT **hSyncEvents = NULL;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(cRefs > 0);
++ DBC_Require(aStrmTab != NULL);
++ DBC_Require(pMask != NULL);
++ DBC_Require(nStrms > 0);
++
++ GT_4trace(STRM_debugMask, GT_ENTER,
++ "STRM_Select: aStrmTab: 0x%x \tnStrms: "
++ "0x%x\tpMask: 0x%x\tuTimeout: 0x%x\n", aStrmTab,
++ nStrms, pMask, uTimeout);
++ *pMask = 0;
++ for (i = 0; i < nStrms; i++) {
++ if (!MEM_IsValidHandle(aStrmTab[i], STRM_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ break;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Determine which channels have IO ready */
++ for (i = 0; i < nStrms; i++) {
++ pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo)(aStrmTab[i]->hChnl,
++ &chnlInfo);
++ if (DSP_FAILED(status)) {
++ break;
++ } else {
++ if (chnlInfo.cIOCs > 0)
++ *pMask |= (1 << i);
++
++ }
++ }
++ if (DSP_SUCCEEDED(status) && uTimeout > 0 && *pMask == 0) {
++ /* Non-zero timeout */
++ hSyncEvents = (struct SYNC_OBJECT **)MEM_Alloc(nStrms *
++ sizeof(struct SYNC_OBJECT *), MEM_PAGED);
++ if (hSyncEvents == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ for (i = 0; i < nStrms; i++) {
++ pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
++ status = (*pIntfFxns->pfnChnlGetInfo)
++ (aStrmTab[i]->hChnl, &chnlInfo);
++ if (DSP_FAILED(status))
++ break;
++ else
++ hSyncEvents[i] = chnlInfo.hSyncEvent;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_WaitOnMultipleEvents(hSyncEvents, nStrms,
++ uTimeout, &uIndex);
++ if (DSP_SUCCEEDED(status)) {
++ /* Since we waited on the event, we have to
++ * reset it */
++ SYNC_SetEvent(hSyncEvents[uIndex]);
++ *pMask = 1 << uIndex;
++ }
++ }
++ }
++func_end:
++ if (hSyncEvents)
++ MEM_Free(hSyncEvents);
++
++ DBC_Ensure((DSP_SUCCEEDED(status) && (*pMask != 0 || uTimeout == 0)) ||
++ (DSP_FAILED(status) && *pMask == 0));
++
++ return status;
++}
++
++/*
++ * ======== DeleteStrm ========
++ * Purpose:
++ * Frees the resources allocated for a stream.
++ */
++static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm)
++{
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ DSP_STATUS status = DSP_SOK;
++
++ if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
++ if (hStrm->hChnl) {
++ pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
++ /* Channel close can fail only if the channel handle
++ * is invalid. */
++ status = (*pIntfFxns->pfnChnlClose) (hStrm->hChnl);
++ /* Free all SM address translator resources */
++ if (DSP_SUCCEEDED(status)) {
++ if (hStrm->hXlator) {
++ /* force free */
++ (void)CMM_XlatorDelete(hStrm->hXlator,
++ true);
++ }
++ }
++ }
++ MEM_FreeObject(hStrm);
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== DeleteStrmMgr ========
++ * Purpose:
++ * Frees stream manager.
++ */
++static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr)
++{
++ if (MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE)) {
++
++ if (hStrmMgr->hSync)
++ SYNC_DeleteCS(hStrmMgr->hSync);
++
++ MEM_FreeObject(hStrmMgr);
++ }
++}
++
+diff --git a/drivers/dsp/bridge/services/cfg.c b/drivers/dsp/bridge/services/cfg.c
+new file mode 100644
+index 0000000..67656bf
+--- /dev/null
++++ b/drivers/dsp/bridge/services/cfg.c
+@@ -0,0 +1,483 @@
++/*
++ * cfg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cfgce.c ========
++ * Purpose:
++ * Implementation of platform specific config services.
++ *
++ * Private Functions:
++ * CFG_Exit
++ * CFG_GetAutoStart
++ * CFG_GetDevObject
++ * CFG_GetDSPResources
++ * CFG_GetExecFile
++ * CFG_GetHostResources
++ * CFG_GetObject
++ * CFG_Init
++ * CFG_SetDevObject
++ * CFG_SetObject
++ *
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Arp-2004 hp Support for handling more than one Device.
++ *! 26-Feb-2003 kc Removed unused CFG fxns.
++ *! 10-Nov-2000 rr: CFG_GetBoardName local var initialized.
++ *! 30-Oct-2000 kc: Changed local var. names to use Hungarian notation.
++ *! 10-Aug-2000 rr: Cosmetic changes.
++ *! 26-Jul-2000 rr: Added CFG_GetDCDName. CFG_Get/SetObject(based on a flag)
++ *! replaces CFG_GetMgrObject & CFG_SetMgrObject.
++ *! 17-Jul-2000 rr: Added CFG_GetMgrObject & CFG_SetMgrObject.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 31-Jan-2000 rr: Comments and bugfixes: modified after code review
++ *! 07-Jan-2000 rr: CFG_GetBoardName Ensure class checks strlen of the
++ *! read value from the registry against the passed in BufSize;
++ *! CFG_GetZLFile,CFG_GetWMDFileName and
++ *! CFG_GetExecFile also modified same way.
++ *! 06-Jan-2000 rr: CFG_GetSearchPath & CFG_GetWinBRIDGEDir removed.
++ *! 09-Dec-1999 rr: CFG_SetDevObject stores the DevNodeString pointer.
++ *! 03-Dec-1999 rr: CFG_GetDevObject reads stored DevObject from Registry.
++ *! CFG_GetDevNode reads the Devnodestring from the registry.
++ *! CFG_SetDevObject stores the registry path as
++ *! DevNodestring in the registry.
++ *! 02-Dec-1999 rr: CFG_debugMask is declared static now. stdwin.h included
++ *! 22-Nov-1999 kc: Added windows.h to remove warnings.
++ *! 25-Oct-1999 rr: CFG_GetHostResources reads the HostResource structure
++ *! from the registry which was set by the DRV Request
++ *! Resources.
++ *! 15-Oct-1999 rr: Changes in CFG_SetPrivateDword & HostResources reflecting
++ *! changes for drv.h resource structure and wsxreg.h new
++ *! entry(DevObject) Hard coded entries removed for those items
++ *! 08-Oct-1999 rr: CFG_SetPrivateDword modified. it sets devobject into the
++ *! registry. CFG_Get HostResources modified for opening up
++ *! two mem winodws.
++ *! 24-Sep-1999 rr: CFG_GetHostResources uses hardcoded Registry calls,uses NT
++ *! type of Resource Structure.
++ *! 19-Jul-1999 a0216266: Stubbed from cfgnt.c.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/reg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/cfg.h>
++#include <dspbridge/list.h>
++
++struct DRV_EXT {
++ struct LST_ELEM link;
++ char szString[MAXREGPATHLENGTH];
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CFG_debugMask = { NULL, NULL }; /* CFG debug Mask */
++#endif
++
++/*
++ * ======== CFG_Exit ========
++ * Purpose:
++ * Discontinue usage of the CFG module.
++ */
++void CFG_Exit(void)
++{
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Exit\n");
++}
++
++/*
++ * ======== CFG_GetAutoStart ========
++ * Purpose:
++ * Retreive the autostart mask, if any, for this board.
++ */
++DSP_STATUS CFG_GetAutoStart(struct CFG_DEVNODE *hDevNode,
++ OUT u32 *pdwAutoStart)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetAutoStart: \n\thDevNode:"
++ "0x%x\n\tpdwAutoStart: 0x%x\n", hDevNode, pdwAutoStart);
++ dwBufSize = sizeof(*pdwAutoStart);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++ if (!pdwAutoStart)
++ status = CFG_E_INVALIDPOINTER;
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, (char *)hDevNode, AUTOSTART,
++ (u8 *)pdwAutoStart, &dwBufSize);
++ if (DSP_FAILED(status))
++ status = CFG_E_RESOURCENOTAVAIL;
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetAutoStart SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetAutoStart Failed \n");
++ }
++#endif
++ DBC_Ensure((status == DSP_SOK &&
++ (*pdwAutoStart == 0 || *pdwAutoStart == 1))
++ || status != DSP_SOK);
++ return status;
++}
++
++/*
++ * ======== CFG_GetDevObject ========
++ * Purpose:
++ * Retrieve the Device Object handle for a given devnode.
++ */
++DSP_STATUS CFG_GetDevObject(struct CFG_DEVNODE *hDevNode, OUT u32 *pdwValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER, "Entered CFG_GetDevObject, args: "
++ "\n\thDevNode: 0x%x\n\tpdwValue: 0x%x\n", hDevNode,
++ *pdwValue);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pdwValue)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ dwBufSize = sizeof(pdwValue);
++ if (DSP_SUCCEEDED(status)) {
++
++ /* check the device string and then call the REG_SetValue*/
++ if (!(strcmp((char *)((struct DRV_EXT *)hDevNode)->szString,
++ "TIOMAP1510"))) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "Fetching DSP Device from "
++ "Registry \n");
++ status = REG_GetValue(NULL, (char *)hDevNode,
++ "DEVICE_DSP",
++ (u8 *)pdwValue, &dwBufSize);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "Failed to Identify the Device to Fetch \n");
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetDevObject SUCCESS DevObject"
++ ": 0x%x\n ", *pdwValue);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetDevObject Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetDSPResources ========
++ * Purpose:
++ * Get the DSP resources available to a given device.
++ */
++DSP_STATUS CFG_GetDSPResources(struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_DSPRES *pDSPResTable)
++{
++ DSP_STATUS status = DSP_SOK; /* return value */
++ u32 dwResSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetDSPResources, args: "
++ "\n\thDevNode: 0x%x\n\tpDSPResTable: 0x%x\n",
++ hDevNode, pDSPResTable);
++ if (!hDevNode) {
++ status = CFG_E_INVALIDHDEVNODE;
++ } else if (!pDSPResTable) {
++ status = CFG_E_INVALIDPOINTER;
++ } else {
++ status = REG_GetValue(NULL, CONFIG, DSPRESOURCES,
++ (u8 *)pDSPResTable,
++ &dwResSize);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetDSPResources SUCCESS\n");
++ } else {
++ status = CFG_E_RESOURCENOTAVAIL;
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetDSPResources Failed \n");
++ }
++#ifdef DEBUG
++ /* assert that resource values are reasonable */
++ DBC_Assert(pDSPResTable->uChipType < 256);
++ DBC_Assert(pDSPResTable->uWordSize > 0);
++ DBC_Assert(pDSPResTable->uWordSize < 32);
++ DBC_Assert(pDSPResTable->cChips > 0);
++ DBC_Assert(pDSPResTable->cChips < 256);
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetExecFile ========
++ * Purpose:
++ * Retreive the default executable, if any, for this board.
++ */
++DSP_STATUS CFG_GetExecFile(struct CFG_DEVNODE *hDevNode, u32 ulBufSize,
++ OUT char *pstrExecFile)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 cExecSize = ulBufSize;
++ GT_3trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetExecFile:\n\tthDevNode: "
++ "0x%x\n\tulBufSize: 0x%x\n\tpstrExecFile: 0x%x\n", hDevNode,
++ ulBufSize, pstrExecFile);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pstrExecFile)
++ status = CFG_E_INVALIDPOINTER;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = REG_GetValue(NULL, (char *)hDevNode, DEFEXEC,
++ (u8 *)pstrExecFile, &cExecSize);
++ if (DSP_FAILED(status))
++ status = CFG_E_RESOURCENOTAVAIL;
++ else if (cExecSize > ulBufSize)
++ status = DSP_ESIZE;
++
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetExecFile SUCCESS Exec File"
++ "name : %s\n ", pstrExecFile);
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetExecFile Failed \n");
++ }
++#endif
++ DBC_Ensure(((status == DSP_SOK) &&
++ (strlen(pstrExecFile) <= ulBufSize)) || (status != DSP_SOK));
++ return status;
++}
++
++/*
++ * ======== CFG_GetHostResources ========
++ * Purpose:
++ * Get the Host allocated resources assigned to a given device.
++ */
++DSP_STATUS CFG_GetHostResources(struct CFG_DEVNODE *hDevNode,
++ OUT struct CFG_HOSTRES *pHostResTable)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBufSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetHostResources, args:\n\t"
++ "pHostResTable: 0x%x\n\thDevNode: 0x%x\n",
++ pHostResTable, hDevNode);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ if (!pHostResTable)
++ status = CFG_E_INVALIDPOINTER;
++
++ if (DSP_SUCCEEDED(status)) {
++ dwBufSize = sizeof(struct CFG_HOSTRES);
++ if (DSP_FAILED(REG_GetValue(NULL, (char *)hDevNode,
++ CURRENTCONFIG,
++ (u8 *)pHostResTable, &dwBufSize))) {
++ status = CFG_E_RESOURCENOTAVAIL;
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetHostResources SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_GetHostResources Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_GetObject ========
++ * Purpose:
++ * Retrieve the Object handle from the Registry
++ */
++DSP_STATUS CFG_GetObject(OUT u32 *pdwValue, u32 dwType)
++{
++ DSP_STATUS status = DSP_EINVALIDARG;
++ u32 dwBufSize;
++ DBC_Require(pdwValue != NULL);
++ GT_1trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_GetObject, args:pdwValue: "
++ "0x%x\n", *pdwValue);
++ dwBufSize = sizeof(pdwValue);
++ switch (dwType) {
++ case (REG_DRV_OBJECT):
++ status = REG_GetValue(NULL, CONFIG, DRVOBJECT,
++ (u8 *)pdwValue,
++ &dwBufSize);
++ break;
++ case (REG_MGR_OBJECT):
++ status = REG_GetValue(NULL, CONFIG, MGROBJECT,
++ (u8 *)pdwValue,
++ &dwBufSize);
++ break;
++ default:
++ break;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ GT_1trace(CFG_debugMask, GT_1CLASS,
++ "CFG_GetObject SUCCESS DrvObject: "
++ "0x%x\n ", *pdwValue);
++ } else {
++ status = CFG_E_RESOURCENOTAVAIL;
++ *pdwValue = 0;
++ GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_GetObject Failed \n");
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && *pdwValue != 0) ||
++ (DSP_FAILED(status) && *pdwValue == 0));
++ return status;
++}
++
++/*
++ * ======== CFG_Init ========
++ * Purpose:
++ * Initialize the CFG module's private state.
++ */
++bool CFG_Init(void)
++{
++ struct CFG_DSPRES dspResources;
++ GT_create(&CFG_debugMask, "CF"); /* CF for ConFig */
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Entered CFG_Init\n");
++ GT_0trace(CFG_debugMask, GT_5CLASS, "Intializing DSP Registry Info \n");
++
++ dspResources.uChipType = DSPTYPE_64;
++ dspResources.cChips = 1;
++ dspResources.uWordSize = DSPWORDSIZE;
++ dspResources.cMemTypes = 0;
++ dspResources.aMemDesc[0].uMemType = 0;
++ dspResources.aMemDesc[0].ulMin = 0;
++ dspResources.aMemDesc[0].ulMax = 0;
++ if (DSP_SUCCEEDED(REG_SetValue(NULL, CONFIG, DSPRESOURCES, REG_BINARY,
++ (u8 *)&dspResources, sizeof(struct CFG_DSPRES)))) {
++ GT_0trace(CFG_debugMask, GT_5CLASS,
++ "Initialized DSP resources in "
++ "Registry \n");
++ } else
++ GT_0trace(CFG_debugMask, GT_5CLASS,
++ "Failed to Initialize DSP resources"
++ " in Registry \n");
++ return true;
++}
++
++/*
++ * ======== CFG_SetDevObject ========
++ * Purpose:
++ * Store the Device Object handle and devNode pointer for a given devnode.
++ */
++DSP_STATUS CFG_SetDevObject(struct CFG_DEVNODE *hDevNode, u32 dwValue)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 dwBuffSize;
++ GT_2trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_SetDevObject, args: \n\t"
++ "hDevNode: 0x%x\n\tdwValue: 0x%x\n", hDevNode, dwValue);
++ if (!hDevNode)
++ status = CFG_E_INVALIDHDEVNODE;
++
++ dwBuffSize = sizeof(dwValue);
++ if (DSP_SUCCEEDED(status)) {
++ /* Store the WCD device object in the Registry */
++
++ if (!(strcmp((char *)hDevNode, "TIOMAP1510"))) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "Registering the DSP Device \n");
++ status = REG_SetValue(NULL, (char *)hDevNode,
++ "DEVICE_DSP", REG_DWORD,\
++ (u8 *)&dwValue, dwBuffSize);
++ if (DSP_SUCCEEDED(status)) {
++ dwBuffSize = sizeof(hDevNode);
++ status = REG_SetValue(NULL,
++ (char *)hDevNode, "DEVNODESTRING_DSP",
++ REG_DWORD, (u8 *)&hDevNode,
++ dwBuffSize);
++ }
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "Failed to Register Device \n");
++ }
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status)) {
++ GT_0trace(CFG_debugMask, GT_1CLASS,
++ "CFG_SetDevObject SUCCESS \n");
++ } else {
++ GT_0trace(CFG_debugMask, GT_6CLASS,
++ "CFG_SetDevObject Failed \n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== CFG_SetObject ========
++ * Purpose:
++ * Store the Driver Object handle
++ */
++DSP_STATUS CFG_SetObject(u32 dwValue, u32 dwType)
++{
++ DSP_STATUS status = DSP_EINVALIDARG;
++ u32 dwBuffSize;
++ GT_1trace(CFG_debugMask, GT_ENTER,
++ "Entered CFG_SetObject, args: dwValue: "
++ "0x%x\n", dwValue);
++ dwBuffSize = sizeof(dwValue);
++ switch (dwType) {
++ case (REG_DRV_OBJECT):
++ status = REG_SetValue(NULL, CONFIG, DRVOBJECT, REG_DWORD,
++ (u8 *)&dwValue, dwBuffSize);
++ break;
++ case (REG_MGR_OBJECT):
++ status = REG_SetValue(NULL, CONFIG, MGROBJECT, REG_DWORD,
++ (u8 *) &dwValue, dwBuffSize);
++ break;
++ default:
++ break;
++ }
++#ifdef DEBUG
++ if (DSP_SUCCEEDED(status))
++ GT_0trace(CFG_debugMask, GT_1CLASS, "CFG_SetObject SUCCESS \n");
++ else
++ GT_0trace(CFG_debugMask, GT_6CLASS, "CFG_SetObject Failed \n");
++
++#endif
++ return status;
++}
+diff --git a/drivers/dsp/bridge/services/clk.c b/drivers/dsp/bridge/services/clk.c
+new file mode 100644
+index 0000000..b499b14
+--- /dev/null
++++ b/drivers/dsp/bridge/services/clk.c
+@@ -0,0 +1,375 @@
++/*
++ * clk.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== clk.c ========
++ * Purpose:
++ * Clock and Timer services.
++ *
++ * Public Functions:
++ * CLK_Exit
++ * CLK_Init
++ * CLK_Enable
++ * CLK_Disable
++ * CLK_GetRate
++ * CLK_Set_32KHz
++ *! Revision History:
++ *! ================
++ *! 08-May-2007 rg: moved all clock functions from sync module.
++ * And added CLK_Set_32KHz, CLK_Set_SysClk.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/clk.h>
++#include <dspbridge/util.h>
++
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++
++typedef volatile unsigned long REG_UWORD32;
++
++#define SSI_Base 0x48058000
++
++#define SSI_BASE IO_ADDRESS(SSI_Base)
++
++
++struct SERVICES_Clk_t {
++ struct clk *clk_handle;
++ const char *clk_name;
++ int id;
++};
++
++/* The row order of the below array needs to match with the clock enumerations
++ * 'SERVICES_ClkId' provided in the header file.. any changes in the
++ * enumerations needs to be fixed in the array as well */
++static struct SERVICES_Clk_t SERVICES_Clks[] = {
++ {NULL, "iva2_ck", -1},
++ {NULL, "mailboxes_ick", -1},
++ {NULL, "gpt5_fck", -1},
++ {NULL, "gpt5_ick", -1},
++ {NULL, "gpt6_fck", -1},
++ {NULL, "gpt6_ick", -1},
++ {NULL, "gpt7_fck", -1},
++ {NULL, "gpt7_ick", -1},
++ {NULL, "gpt8_fck", -1},
++ {NULL, "gpt8_ick", -1},
++ {NULL, "wdt_fck", 3},
++ {NULL, "wdt_ick", 3},
++ {NULL, "mcbsp_fck", 1},
++ {NULL, "mcbsp_ick", 1},
++ {NULL, "mcbsp_fck", 2},
++ {NULL, "mcbsp_ick", 2},
++ {NULL, "mcbsp_fck", 3},
++ {NULL, "mcbsp_ick", 3},
++ {NULL, "mcbsp_fck", 4},
++ {NULL, "mcbsp_ick", 4},
++ {NULL, "mcbsp_fck", 5},
++ {NULL, "mcbsp_ick", 5},
++ {NULL, "ssi_ssr_sst_fck", -1},
++ {NULL, "ssi_ick", -1},
++ {NULL, "omap_32k_fck", -1},
++ {NULL, "sys_ck", -1},
++ {NULL, ""}
++};
++
++/* Generic TIMER object: */
++struct TIMER_OBJECT {
++ struct timer_list timer;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CLK_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/*
++ * ======== CLK_Exit ========
++ * Purpose:
++ * Cleanup CLK module.
++ */
++void CLK_Exit(void)
++{
++ int i = 0;
++
++ GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Exit\n");
++ /* Relinquish the clock handles */
++ while (i < SERVICESCLK_NOT_DEFINED) {
++ if (SERVICES_Clks[i].clk_handle)
++ clk_put(SERVICES_Clks[i].clk_handle);
++
++ SERVICES_Clks[i].clk_handle = NULL;
++ i++;
++ }
++
++}
++
++/*
++ * ======== CLK_Init ========
++ * Purpose:
++ * Initialize CLK module.
++ */
++bool CLK_Init(void)
++{
++ static struct platform_device dspbridge_device;
++ struct clk *clk_handle;
++ int i = 0;
++ GT_create(&CLK_debugMask, "CK"); /* CK for CLK */
++ GT_0trace(CLK_debugMask, GT_5CLASS, "CLK_Init\n");
++
++ dspbridge_device.dev.bus = &platform_bus_type;
++
++ /* Get the clock handles from base port and store locally */
++ while (i < SERVICESCLK_NOT_DEFINED) {
++ /* get the handle from BP */
++ dspbridge_device.id = SERVICES_Clks[i].id;
++
++ clk_handle = clk_get(&dspbridge_device.dev,
++ SERVICES_Clks[i].clk_name);
++
++ if (!clk_handle) {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_Init: failed to get Clk handle %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[i].clk_name,
++ SERVICES_Clks[i].id);
++ /* should we fail here?? */
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_Init: PASS and Clk handle %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[i].clk_name,
++ SERVICES_Clks[i].id);
++ }
++ SERVICES_Clks[i].clk_handle = clk_handle;
++ i++;
++ }
++
++ return true;
++}
++
++/*
++ * ======== CLK_Enable ========
++ * Purpose:
++ * Enable Clock .
++ *
++*/
++DSP_STATUS CLK_Enable(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Enable: CLK %s, "
++ "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ if (clk_enable(pClk) == 0x0) {
++ /* Success ? */
++ } else {
++ pr_err("CLK_Enable: failed to Enable CLK %s, "
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ } else {
++ pr_err("CLK_Enable: failed to get CLK %s, CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ /* The SSI module need to configured not to have the Forced idle for
++ * master interface. If it is set to forced idle, the SSI module is
++ * transitioning to standby thereby causing the client in the DSP hang
++ * waiting for the SSI module to be active after enabling the clocks
++ */
++ if (clk_id == SERVICESCLK_ssi_fck)
++ SSI_Clk_Prepare(true);
++
++ return status;
++}
++/*
++ * ======== CLK_Set_32KHz ========
++ * Purpose:
++ * To Set parent of a clock to 32KHz.
++ */
++
++DSP_STATUS CLK_Set_32KHz(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ struct clk *pClkParent;
++ enum SERVICES_ClkId sys_32k_id = SERVICESCLK_sys_32k_ck;
++ pClkParent = SERVICES_Clks[sys_32k_id].clk_handle;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Set_32KHz: CLK %s, "
++ "CLK dev id = %d is setting to 32KHz \n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ if (!(clk_set_parent(pClk, pClkParent) == 0x0)) {
++ GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_Set_32KHz: "
++ "Failed to set to 32KHz %s, CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== CLK_Disable ========
++ * Purpose:
++ * Disable the clock.
++ *
++*/
++DSP_STATUS CLK_Disable(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ s32 clkUseCnt;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ GT_2trace(CLK_debugMask, GT_6CLASS, "CLK_Disable: CLK %s, "
++ "CLK dev id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++
++ clkUseCnt = CLK_Get_UseCnt(clk_id);
++ if (clkUseCnt == -1) {
++ pr_err("CLK_Disable: failed to get CLK Use count for CLK %s,"
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ } else if (clkUseCnt == 0) {
++ pr_err("CLK_Disable: CLK %s, CLK dev id= %d is already"
++ "disabled\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ return status;
++ }
++ if (clk_id == SERVICESCLK_ssi_ick)
++ SSI_Clk_Prepare(false);
++
++ if (pClk) {
++ clk_disable(pClk);
++ } else {
++ pr_err("CLK_Disable: failed to get CLK %s,"
++ "CLK dev id = %d\n",
++ SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++/*
++ * ======== CLK_GetRate ========
++ * Purpose:
++ * GetClock Speed.
++ *
++ */
++
++DSP_STATUS CLK_GetRate(IN enum SERVICES_ClkId clk_id, u32 *speedKhz)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ u32 clkSpeedHz;
++
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++ *speedKhz = 0x0;
++
++ GT_2trace(CLK_debugMask, GT_7CLASS, "CLK_GetRate: CLK %s, "
++ "CLK dev Id = %d \n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++ if (pClk) {
++ clkSpeedHz = clk_get_rate(pClk);
++ *speedKhz = clkSpeedHz / 1000;
++ GT_2trace(CLK_debugMask, GT_6CLASS,
++ "CLK_GetRate: clkSpeedHz = %d , "
++ "speedinKhz=%d\n", clkSpeedHz, *speedKhz);
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_GetRate: failed to get CLK %s, "
++ "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return status;
++}
++
++s32 CLK_Get_UseCnt(IN enum SERVICES_ClkId clk_id)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct clk *pClk;
++ s32 useCount = -1;
++ DBC_Require(clk_id < SERVICESCLK_NOT_DEFINED);
++
++ pClk = SERVICES_Clks[clk_id].clk_handle;
++
++ if (pClk) {
++ useCount = pClk->usecount; /* FIXME: usecount shouldn't be used */
++ } else {
++ GT_2trace(CLK_debugMask, GT_7CLASS,
++ "CLK_GetRate: failed to get CLK %s, "
++ "CLK dev Id = %d\n", SERVICES_Clks[clk_id].clk_name,
++ SERVICES_Clks[clk_id].id);
++ status = DSP_EFAIL;
++ }
++ return useCount;
++}
++
++void SSI_Clk_Prepare(bool FLAG)
++{
++ u32 ssi_sysconfig;
++ ssi_sysconfig = __raw_readl((SSI_BASE) + 0x10);
++
++ if (FLAG) {
++ /* Set Autoidle, SIDLEMode to smart idle, and MIDLEmode to
++ * no idle
++ */
++ ssi_sysconfig = 0x1011;
++ } else {
++ /* Set Autoidle, SIDLEMode to forced idle, and MIDLEmode to
++ * forced idle
++ */
++ ssi_sysconfig = 0x1;
++ }
++ __raw_writel((u32)ssi_sysconfig, SSI_BASE + 0x10);
++}
+diff --git a/drivers/dsp/bridge/services/csl.c b/drivers/dsp/bridge/services/csl.c
+new file mode 100644
+index 0000000..dd33c2d
+--- /dev/null
++++ b/drivers/dsp/bridge/services/csl.c
+@@ -0,0 +1,173 @@
++/*
++ * csl.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== cslce.c ========
++ * Purpose:
++ * Provides platform independent C Standard library functions.
++ *
++ * Public Functions:
++ * CSL_Atoi
++ * CSL_Exit
++ * CSL_Init
++ * CSL_NumToAscii
++ * CSL_Strtokr
++ *
++ *! Revision History:
++ *! ================
++ *! 07-Aug-2002 jeh: Added CSL_Strtokr().
++ *! 21-Sep-2001 jeh: Added CSL_Strncmp(). Alphabetized functions.
++ *! 22-Nov-2000 map: Added CSL_Atoi and CSL_Strtok
++ *! 19-Nov-2000 kc: Added CSL_ByteSwap.
++ *! 09-Nov-2000 kc: Added CSL_Strncat.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 15-Dec-1999 ag: Removed incorrect assertion CSL_NumToAscii()
++ *! 29-Oct-1999 kc: Added CSL_Wstrlen for UNICODE strings.
++ *! 30-Sep-1999 ag: Removed DBC assertion (!CSL_DebugMask.flags) in
++ * CSP_Init().
++ *! 20-Sep-1999 ag: Added CSL_WcharToAnsi().
++ *! Removed call to GT_set().
++ *! 19-Jan-1998 cr: Code review cleanup.
++ *! 29-Dec-1997 cr: Made platform independant, using MS CRT code, and
++ *! combined csl32.c csl95.c and cslnt.c into csl.c. Also
++ *! changed CSL_lowercase to CSL_Uppercase.
++ *! 21-Aug-1997 gp: Fix to CSL_strcpyn to initialize Source string, the NT way.
++ *! 25-Jun-1997 cr: Created from csl95, added CSL_strcmp.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/csl.h>
++
++/* Is character c in the string pstrDelim? */
++#define IsDelimiter(c, pstrDelim) ((c != '\0') && \
++ (strchr(pstrDelim, c) != NULL))
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask CSL_DebugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== CSL_Exit ========
++ * Purpose:
++ * Discontinue usage of the CSL module.
++ */
++void CSL_Exit(void)
++{
++ GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Exit\n");
++}
++
++/*
++ * ======== CSL_Init ========
++ * Purpose:
++ * Initialize the CSL module's private state.
++ */
++bool CSL_Init(void)
++{
++ GT_create(&CSL_DebugMask, "CS");
++
++ GT_0trace(CSL_DebugMask, GT_5CLASS, "CSL_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== CSL_NumToAscii ========
++ * Purpose:
++ * Convert a 1 or 2 digit number to a 2 digit string.
++ */
++void CSL_NumToAscii(OUT char *pstrNumber, u32 dwNum)
++{
++ char tens;
++
++ DBC_Require(dwNum < 100);
++
++ if (dwNum < 100) {
++ tens = (char) dwNum / 10;
++ dwNum = dwNum % 10;
++
++ if (tens) {
++ pstrNumber[0] = tens + '0';
++ pstrNumber[1] = (char) dwNum + '0';
++ pstrNumber[2] = '\0';
++ } else {
++ pstrNumber[0] = (char) dwNum + '0';
++ pstrNumber[1] = '\0';
++ }
++ } else {
++ pstrNumber[0] = '\0';
++ }
++}
++
++
++
++
++/*
++ * ======= CSL_Strtokr =======
++ * Purpose:
++ * Re-entrant version of strtok.
++ */
++char *CSL_Strtokr(IN char *pstrSrc, IN CONST char *szSeparators,
++ OUT char **ppstrLast)
++{
++ char *pstrTemp;
++ char *pstrToken;
++
++ DBC_Require(szSeparators != NULL);
++ DBC_Require(ppstrLast != NULL);
++ DBC_Require(pstrSrc != NULL || *ppstrLast != NULL);
++
++ /*
++ * Set string location to beginning (pstrSrc != NULL) or to the
++ * beginning of the next token.
++ */
++ pstrTemp = (pstrSrc != NULL) ? pstrSrc : *ppstrLast;
++ if (*pstrTemp == '\0') {
++ pstrToken = NULL;
++ } else {
++ pstrToken = pstrTemp;
++ while (*pstrTemp != '\0' && !IsDelimiter(*pstrTemp,
++ szSeparators)) {
++ pstrTemp++;
++ }
++ if (*pstrTemp != '\0') {
++ while (IsDelimiter(*pstrTemp, szSeparators)) {
++ /* TODO: Shouldn't we do this for
++ * only 1 char?? */
++ *pstrTemp = '\0';
++ pstrTemp++;
++ }
++ }
++
++ /* Location in string for next call */
++ *ppstrLast = pstrTemp;
++ }
++
++ return pstrToken;
++}
+diff --git a/drivers/dsp/bridge/services/dbg.c b/drivers/dsp/bridge/services/dbg.c
+new file mode 100644
+index 0000000..5e1773f
+--- /dev/null
++++ b/drivers/dsp/bridge/services/dbg.c
+@@ -0,0 +1,119 @@
++/*
++ * dbg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dbgce.c ========
++ * Purpose:
++ * Provide debugging services for DSP/BIOS Bridge Mini Drivers.
++ *
++ * Public Functions:
++ * DBG_Exit
++ * DBG_Init
++ * DBG_Trace
++ *
++ * Notes:
++ * Requires gt.h.
++ *
++ * This implementation does not create GT masks on a per WMD basis.
++ * There is currently no facility for a WMD to alter the GT mask.
++ *
++ *! Revision History:
++ *! ================
++ *! 15-Feb-2000 rr: DBG_Trace prints based on the DebugZones.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 29-Oct-1999 kc: Cleaned up for code review.
++ *! 10-Oct-1997 cr: Added DBG_Printf service.
++ *! 28-May-1997 cr: Added reference counting.
++ *! 23-May-1997 cr: Updated DBG_Trace to new gt interface.
++ *! 29-May-1996 gp: Removed WCD_ prefix.
++ *! 20-May-1996 gp: Remove DEBUG conditional compilation.
++ *! 15-May-1996 gp: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DBG_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++#if (defined(DEBUG) || defined (DDSP_DEBUG_PRODUCT)) && GT_TRACE
++
++/*
++ * ======== DBG_Init ========
++ * Purpose:
++ * Ensures trace capability is set up for link drivers.
++ */
++bool DBG_Init(void)
++{
++ GT_create(&DBG_debugMask, "WD"); /* for WmD (link driver) debug */
++
++ GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== DBG_Trace ========
++ * Purpose:
++ * Output a trace message to the debugger, if the given trace level
++ * is unmasked.
++ */
++DSP_STATUS DBG_Trace(u8 bLevel, char *pstrFormat, ...)
++{
++ s32 arg1, arg2, arg3, arg4, arg5, arg6;
++ va_list va;
++
++ va_start(va, pstrFormat);
++
++ arg1 = va_arg(va, s32);
++ arg2 = va_arg(va, s32);
++ arg3 = va_arg(va, s32);
++ arg4 = va_arg(va, s32);
++ arg5 = va_arg(va, s32);
++ arg6 = va_arg(va, s32);
++
++ va_end(va);
++
++ if (bLevel & *(DBG_debugMask).flags)
++ printk(pstrFormat, arg1, arg2, arg3, arg4, arg5, arg6);
++
++ return DSP_SOK;
++}
++
++/*
++ * ======== DBG_Exit ========
++ * Purpose:
++ * Discontinue usage of the DBG module.
++ */
++void DBG_Exit(void)
++{
++ GT_0trace(DBG_debugMask, GT_5CLASS, "DBG_Exit\n");
++}
++
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
+diff --git a/drivers/dsp/bridge/services/dpc.c b/drivers/dsp/bridge/services/dpc.c
+new file mode 100644
+index 0000000..bd608d1
+--- /dev/null
++++ b/drivers/dsp/bridge/services/dpc.c
+@@ -0,0 +1,274 @@
++/*
++ * dpc.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== dpcce.c ========
++ * Purpose:
++ * Deferred Procedure Call(DPC) Services.
++ *
++ *
++ * Public Functions:
++ * DPC_Create
++ * DPC_Destroy
++ * DPC_Exit
++ * DPC_Init
++ * DPC_Schedule
++ *
++ *! Revision History:
++ *! ================
++ *! 28-Mar-2001 ag: Added #ifdef CHNL_NOIPCINTR to set DPC thread priority
++ *! to THREAD_PRIORITY_IDLE for polling IPC.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 31-Jan-2000 rr: Changes after code review.Terminate thread,handle
++ *! modified.DPC_Destroy frees the DPC_Object only on
++ *! Successful termination of the thread and the handle.
++ *! 06-Jan-1999 ag: Format cleanup for code review.
++ *! Removed DPC_[Lower|Raise]IRQL[From|To]DispatchLevel.
++ *! 10-Dec-1999 ag: Added SetProcPermissions in DPC_DeferredProcedure().
++ *! (Needed to access client(s) CHNL buffers).
++ *! 19-Sep-1999 a0216266: Stubbed from dpcnt.c.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/dpc.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x5f435044 /* "DPC_" (in reverse). */
++
++/* The DPC object, passed to our priority event callback routine: */
++struct DPC_OBJECT {
++ u32 dwSignature; /* Used for object validation. */
++ void *pRefData; /* Argument for client's DPC. */
++ DPC_PROC pfnDPC; /* Client's DPC. */
++ u32 numRequested; /* Number of requested DPC's. */
++ u32 numScheduled; /* Number of executed DPC's. */
++ struct tasklet_struct dpc_tasklet;
++
++#ifdef DEBUG
++ u32 cEntryCount; /* Number of times DPC reentered. */
++ u32 numRequestedMax; /* Keep track of max pending DPC's. */
++#endif
++
++ spinlock_t dpc_lock;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask DPC_DebugMask = { NULL, NULL }; /* DPC Debug Mask */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static void DPC_DeferredProcedure(IN unsigned long pDeferredContext);
++
++/*
++ * ======== DPC_Create ========
++ * Purpose:
++ * Create a DPC object, allowing a client's own DPC procedure to be
++ * scheduled for a call with client reference data.
++ */
++DSP_STATUS DPC_Create(OUT struct DPC_OBJECT **phDPC, DPC_PROC pfnDPC,
++ void *pRefData)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = NULL;
++
++ if ((phDPC != NULL) && (pfnDPC != NULL)) {
++ /*
++ * Allocate a DPC object to store information allowing our DPC
++ * callback to dispatch to the client's DPC.
++ */
++ MEM_AllocObject(pDPCObject, struct DPC_OBJECT, SIGNATURE);
++ if (pDPCObject != NULL) {
++ tasklet_init(&pDPCObject->dpc_tasklet,
++ DPC_DeferredProcedure,
++ (u32) pDPCObject);
++ /* Fill out our DPC Object: */
++ pDPCObject->pRefData = pRefData;
++ pDPCObject->pfnDPC = pfnDPC;
++ pDPCObject->numRequested = 0;
++ pDPCObject->numScheduled = 0;
++#ifdef DEBUG
++ pDPCObject->numRequestedMax = 0;
++ pDPCObject->cEntryCount = 0;
++#endif
++ spin_lock_init(&pDPCObject->dpc_lock);
++ *phDPC = pDPCObject;
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Create: DSP_EMEMORY\n");
++ status = DSP_EMEMORY;
++ }
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Create: DSP_EPOINTER\n");
++ status = DSP_EPOINTER;
++ }
++ DBC_Ensure((DSP_FAILED(status) && (!phDPC || (phDPC && *phDPC == NULL)))
++ || DSP_SUCCEEDED(status));
++ return status;
++}
++
++/*
++ * ======== DPC_Destroy ========
++ * Purpose:
++ * Cancel the last scheduled DPC, and deallocate a DPC object previously
++ * allocated with DPC_Create(). Frees the Object only if the thread
++ * and the event terminated successfuly.
++ */
++DSP_STATUS DPC_Destroy(struct DPC_OBJECT *hDPC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
++
++ if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
++
++ /* Free our DPC object: */
++ if (DSP_SUCCEEDED(status)) {
++ tasklet_kill(&pDPCObject->dpc_tasklet);
++ MEM_FreeObject(pDPCObject);
++ pDPCObject = NULL;
++ GT_0trace(DPC_DebugMask, GT_2CLASS,
++ "DPC_Destroy: SUCCESS\n");
++ }
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Destroy: DSP_EHANDLE\n");
++ status = DSP_EHANDLE;
++ }
++ DBC_Ensure((DSP_SUCCEEDED(status) && pDPCObject == NULL)
++ || DSP_FAILED(status));
++ return status;
++}
++
++/*
++ * ======== DPC_Exit ========
++ * Purpose:
++ * Discontinue usage of the DPC module.
++ */
++void DPC_Exit(void)
++{
++ GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Exit\n");
++}
++
++/*
++ * ======== DPC_Init ========
++ * Purpose:
++ * Initialize the DPC module's private state.
++ */
++bool DPC_Init(void)
++{
++ GT_create(&DPC_DebugMask, "DP");
++
++ GT_0trace(DPC_DebugMask, GT_5CLASS, "Entered DPC_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== DPC_Schedule ========
++ * Purpose:
++ * Schedule a deferred procedure call to be executed at a later time.
++ * Latency and order of DPC execution is platform specific.
++ */
++DSP_STATUS DPC_Schedule(struct DPC_OBJECT *hDPC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)hDPC;
++ unsigned long flags;
++
++ GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule hDPC %x\n", hDPC);
++ if (MEM_IsValidHandle(hDPC, SIGNATURE)) {
++ /* Increment count of DPC's pending. Needs to be protected
++ * from ISRs since this function is called from process
++ * context also. */
++ spin_lock_irqsave(&hDPC->dpc_lock, flags);
++ pDPCObject->numRequested++;
++ spin_unlock_irqrestore(&hDPC->dpc_lock, flags);
++ tasklet_schedule(&(hDPC->dpc_tasklet));
++#ifdef DEBUG
++ if (pDPCObject->numRequested > pDPCObject->numScheduled +
++ pDPCObject->numRequestedMax) {
++ pDPCObject->numRequestedMax = pDPCObject->numRequested -
++ pDPCObject->numScheduled;
++ }
++#endif
++ /* If an interrupt occurs between incrementing numRequested and the
++ * assertion below, then DPC will get executed while returning from
++ * ISR, which will complete all requests and make numRequested equal
++ * to numScheduled, firing this assertion. This happens only when
++ * DPC is being scheduled in process context */
++ } else {
++ GT_0trace(DPC_DebugMask, GT_6CLASS,
++ "DPC_Schedule: DSP_EHANDLE\n");
++ status = DSP_EHANDLE;
++ }
++ GT_1trace(DPC_DebugMask, GT_ENTER, "DPC_Schedule status %x\n", status);
++ return status;
++}
++
++/*
++ * ======== DeferredProcedure ========
++ * Purpose:
++ * Main DPC routine. This is called by host OS DPC callback
++ * mechanism with interrupts enabled.
++ */
++static void DPC_DeferredProcedure(IN unsigned long pDeferredContext)
++{
++ struct DPC_OBJECT *pDPCObject = (struct DPC_OBJECT *)pDeferredContext;
++ /* read numRequested in local variable */
++ u32 requested;
++ u32 serviced;
++
++ DBC_Require(pDPCObject != NULL);
++ requested = pDPCObject->numRequested;
++ serviced = pDPCObject->numScheduled;
++
++ GT_1trace(DPC_DebugMask, GT_ENTER, "> DPC_DeferredProcedure "
++ "pDeferredContext=%x\n", pDeferredContext);
++ /* Rollover taken care of using != instead of < */
++ if (serviced != requested) {
++ if (pDPCObject->pfnDPC != NULL) {
++ /* Process pending DPC's: */
++ do {
++ /* Call client's DPC: */
++ (*(pDPCObject->pfnDPC))(pDPCObject->pRefData);
++ serviced++;
++ } while (serviced != requested);
++ }
++ pDPCObject->numScheduled = requested;
++ }
++ GT_2trace(DPC_DebugMask, GT_ENTER,
++ "< DPC_DeferredProcedure requested %d"
++ " serviced %d\n", requested, serviced);
++}
++
+diff --git a/drivers/dsp/bridge/services/kfile.c b/drivers/dsp/bridge/services/kfile.c
+new file mode 100644
+index 0000000..ba1d26f
+--- /dev/null
++++ b/drivers/dsp/bridge/services/kfile.c
+@@ -0,0 +1,338 @@
++/*
++ * kfile.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== kfilece.c ========
++ * Purpose:
++ * This module provides file i/o services.
++ *
++ * Public Functions:
++ * KFILE_Close
++ * KFILE_Exit
++ * KFILE_Init
++ * KFILE_Open
++ * KFILE_Read
++ * KFILE_Seek
++ * KFILE_Tell
++ *
++ *! Revision History
++ *! ================
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 12-Nov-1999 kc: Enabled CSL for UNICODE/ANSI string conversions.
++ *! 30-Sep-1999 ag: Changed KFILE_Read() GT level from _ENTER to _4CLASS.
++ *! Removed GT_set().
++ *! 25-Aug-1999 ag: Changed MEM_Calloc allocation type to MEM_PAGED.
++ *! 13-Jul-1999 a0216266(ww - TID): Stubbed from kfilent.c.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/kfile.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x4c49464b /* hex code of KFIL (reversed) */
++#define MAXFILENAMELENGTH 256
++#define GENERAL_FAILURE 0xffffffff /* SetFilePointer error */
++
++/* The KFILE_FileObj abstracts the true file handle from a KFILE handle. */
++struct KFILE_FileObj {
++ u32 dwSignature;
++ __kernel_pid_t owner_pid; /* PID of process that opened this file */
++ char *fileName ;
++ bool isOpen ;
++ u32 size ;
++ u32 curPos ;
++ long hInternal; /* internal handle of file */
++ struct file *fileDesc;
++
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask KFILE_debugMask = { NULL, NULL }; /* Debug mask */
++#endif
++
++/*
++ * ======== KFILE_Close ========
++ * Purpose:
++ * This function closes a file's stream.
++ */
++s32 KFILE_Close(struct KFILE_FileObj *hFile)
++{
++ s32 cRetVal = 0; /* 0 indicates success */
++ s32 fRetVal = 0;
++ __kernel_pid_t curr_pid;
++
++ GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Close: hFile 0x%x\n",
++ hFile);
++
++ /* Check for valid handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ /* Close file only if opened by the same process (id). Otherwise
++ * Linux closes all open file handles when process exits.*/
++ /* Return PID instead of process handle */
++ curr_pid = (__kernel_pid_t)current->pid;
++ fRetVal = filp_close(hFile->fileDesc, NULL) ;
++ if (fRetVal) {
++ cRetVal = E_KFILE_ERROR;
++ GT_1trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Close: sys_close "
++ "returned %d\n", fRetVal);
++ }
++ MEM_FreeObject(hFile);
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Close: "
++ "invalid file handle\n");
++ }
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Exit ========
++ * Purpose:
++ * Decrement reference count, and free resources when reference count
++ * is 0.
++ */
++void KFILE_Exit(void)
++{
++ GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Exit\n");
++}
++
++/*
++ * ======== KFILE_Init ========
++ */
++bool KFILE_Init(void)
++{
++ GT_create(&KFILE_debugMask, "KF"); /* "KF" for KFile */
++
++ GT_0trace(KFILE_debugMask, GT_5CLASS, "KFILE_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== KFILE_Open ========
++ * Purpose:
++ * Open a file for reading ONLY
++ */
++struct KFILE_FileObj *KFILE_Open(CONST char *pszFileName, CONST char *pszMode)
++{
++ struct KFILE_FileObj *hFile; /* file handle */
++ DSP_STATUS status;
++ mm_segment_t fs;
++
++ struct file*fileDesc = NULL;
++ DBC_Require(pszMode != NULL);
++ DBC_Require(pszFileName != NULL);
++
++ GT_2trace(KFILE_debugMask, GT_ENTER,
++ "KFILE_Open: pszFileName %s, pszMode "
++ "%s\n", pszFileName, pszMode);
++
++ /* create a KFILE object */
++ MEM_AllocObject(hFile, struct KFILE_FileObj, SIGNATURE);
++
++ if (hFile) {
++ fs = get_fs();
++ set_fs(get_ds());
++ /* Third argument is mode (permissions). Ignored unless creating file */
++ fileDesc = filp_open(pszFileName, O_RDONLY, 0);
++ if ((IS_ERR(fileDesc)) || (fileDesc == NULL) ||
++ (fileDesc->f_op == NULL) || (fileDesc->f_op->read == NULL)
++ || (fileDesc->f_op->llseek == NULL)) {
++ status = DSP_EFILE;
++ } else {
++ hFile->fileDesc = fileDesc;
++ hFile->fileName = (char *)pszFileName;
++ hFile->isOpen = true;
++ hFile->curPos = 0;
++ hFile->size = fileDesc->f_op->llseek(fileDesc, 0,
++ SEEK_END);
++ fileDesc->f_op->llseek(fileDesc, 0, SEEK_SET);
++ /* Return PID instead of process handle */
++ hFile->owner_pid = current->pid;
++
++ status = DSP_SOK;
++ }
++ set_fs(fs);
++ if (DSP_FAILED(status)) {
++ /* free memory, and clear handle */
++ MEM_FreeObject(hFile);
++ hFile = NULL;
++ }
++ } else {
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Open: MEM_AllocObject failed\n");
++ status = DSP_EMEMORY;
++ }
++ return hFile;
++}
++
++/*
++ * ======== KFILE_Read ========
++ * Purpose:
++ * Reads a specified number of bytes into a buffer.
++ */
++s32
++KFILE_Read(void __user*pBuffer, s32 cSize, s32 cCount,
++ struct KFILE_FileObj *hFile)
++{
++ u32 dwBytesRead = 0;
++ s32 cRetVal = 0;
++ mm_segment_t fs;
++
++ DBC_Require(pBuffer != NULL);
++
++ GT_4trace(KFILE_debugMask, GT_4CLASS,
++ "KFILE_Read: buffer 0x%x, cSize 0x%x,"
++ "cCount 0x%x, hFile 0x%x\n", pBuffer, cSize, cCount, hFile);
++
++ /* check for valid file handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ if ((cSize > 0) && (cCount > 0) && pBuffer) {
++ /* read from file */
++ fs = get_fs();
++ set_fs(get_ds());
++ dwBytesRead = hFile->fileDesc->f_op->read(hFile->
++ fileDesc, pBuffer, cSize *cCount,
++ &(hFile->fileDesc->f_pos));
++ set_fs(fs);
++ if (dwBytesRead) {
++ cRetVal = dwBytesRead / cSize;
++ hFile->curPos += dwBytesRead;
++ DBC_Assert((dwBytesRead / cSize) <= \
++ (u32)cCount);
++ } else {
++ cRetVal = E_KFILE_ERROR;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: sys_read() failed\n");
++ }
++ } else {
++ cRetVal = DSP_EINVALIDARG;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: Invalid argument(s)\n");
++ }
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Read: invalid file handle\n");
++ }
++
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Seek ========
++ * Purpose:
++ * Sets the file position indicator. NOTE: we don't support seeking
++ * beyond the boundaries of a file.
++ */
++s32 KFILE_Seek(struct KFILE_FileObj *hFile, s32 lOffset, s32 cOrigin)
++{
++ s32 cRetVal = 0; /* 0 for success */
++ u32 dwCurPos = 0;
++
++ struct file *fileDesc = NULL;
++
++ GT_3trace(KFILE_debugMask, GT_ENTER, "KFILE_Seek: hFile 0x%x, "
++ "lOffset 0x%x, cOrigin 0x%x\n",
++ hFile, lOffset, cOrigin);
++
++ /* check for valid file handle */
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++ /* based on the origin flag, move the internal pointer */
++
++ fileDesc = hFile->fileDesc;
++ switch (cOrigin) {
++ case KFILE_SEEK_SET:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_SET);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++
++ case KFILE_SEEK_CUR:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_CUR);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++ case KFILE_SEEK_END:
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->
++ fileDesc, lOffset, SEEK_END);
++ cRetVal = ((dwCurPos >= 0) ? 0 : E_KFILE_ERROR);
++ break;
++ default:
++ cRetVal = E_KFILE_BADORIGINFLAG;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:bad origin flag\n");
++ break;
++ }
++ } else {
++ cRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:invalid file handle\n");
++ }
++ return cRetVal;
++}
++
++/*
++ * ======== KFILE_Tell ========
++ * Purpose:
++ * Reports the current value of the position indicator. We did not
++ * consider 64 bit long file size, which implies a 4GB file limit
++ * (2 to 32 power).
++ */
++s32 KFILE_Tell(struct KFILE_FileObj *hFile)
++{
++ u32 dwCurPos = 0;
++ s32 lRetVal = E_KFILE_ERROR;
++
++ GT_1trace(KFILE_debugMask, GT_ENTER, "KFILE_Tell: hFile 0x%x\n", hFile);
++
++ if (MEM_IsValidHandle(hFile, SIGNATURE)) {
++
++ /* Get current position. */
++ dwCurPos = hFile->fileDesc->f_op->llseek(hFile->fileDesc, 0,
++ SEEK_CUR);
++ if (dwCurPos >= 0)
++ lRetVal = dwCurPos;
++
++ } else {
++ lRetVal = E_KFILE_INVALIDHANDLE;
++ GT_0trace(KFILE_debugMask, GT_6CLASS,
++ "KFILE_Seek:invalid file handle\n");
++ }
++ return lRetVal;
++}
++
+diff --git a/drivers/dsp/bridge/services/list.c b/drivers/dsp/bridge/services/list.c
+new file mode 100644
+index 0000000..7fa3e76
+--- /dev/null
++++ b/drivers/dsp/bridge/services/list.c
+@@ -0,0 +1,285 @@
++/*
++ * list.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== listce.c ========
++ * Purpose
++ * Provides standard circular list handling functions.
++ *
++ * Public Functions:
++ * LST_Create
++ * LST_Delete
++ * LST_Exit
++ * LST_First
++ * LST_GetHead
++ * LST_Init
++ * LST_InitElem
++ * LST_InsertBefore
++ * LST_Next
++ * LST_PutTail
++ * LST_RemoveElem
++ *
++ *! Revision History
++ *! ================
++ *! 06-Mar-2002 jeh Don't set element self to NULL in LST_RemoveElem().
++ *! 10-Aug-2000 ag: Added LST_InsertBefore().
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 10-Aug-1999 kc: Based on wsx-c18.
++ *! 16-Jun-1997 gp: Removed unnecessary enabling/disabling of interrupts around
++ *! list manipulation code.
++ *! 22-Oct-1996 gp: Added LST_RemoveElem, and LST_First/LST_Next iterators.
++ *! 10-Aug-1996 gp: Acquired from SMM for WinSPOX v. 1.1; renamed identifiers.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/list.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask LST_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== LST_Create ========
++ * Purpose:
++ * Allocates and initializes a circular list.
++ */
++struct LST_LIST *LST_Create(void)
++{
++ struct LST_LIST *pList;
++
++ GT_0trace(LST_debugMask, GT_ENTER, "LST_Create: entered\n");
++
++ pList = (struct LST_LIST *) MEM_Calloc(sizeof(struct LST_LIST),
++ MEM_NONPAGED);
++ if (pList != NULL) {
++ pList->head.next = &pList->head;
++ pList->head.prev = &pList->head;
++ pList->head.self = NULL;
++ }
++
++ return pList;
++}
++
++/*
++ * ======== LST_Delete ========
++ * Purpose:
++ * Removes a list by freeing its control structure's memory space.
++ */
++void LST_Delete(struct LST_LIST *pList)
++{
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_Delete: pList 0x%x\n", pList);
++
++ MEM_Free(pList);
++}
++
++/*
++ * ======== LST_Exit ========
++ * Purpose:
++ * Discontinue usage of the LST module.
++ */
++void LST_Exit(void)
++{
++ GT_0trace(LST_debugMask, GT_5CLASS, "LST_Exit\n");
++}
++
++/*
++ * ======== LST_First ========
++ * Purpose:
++ * Returns a pointer to the first element of the list, or NULL if the
++ * list is empty.
++ */
++struct LST_ELEM *LST_First(struct LST_LIST *pList)
++{
++ struct LST_ELEM *pElem = NULL;
++
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_First: pList 0x%x\n", pList);
++
++ if (!LST_IsEmpty(pList))
++ pElem = pList->head.next;
++
++ return pElem;
++}
++
++/*
++ * ======== LST_GetHead ========
++ * Purpose:
++ * "Pops" the head off the list and returns a pointer to it.
++ */
++struct LST_ELEM *LST_GetHead(struct LST_LIST *pList)
++{
++ struct LST_ELEM *pElem;
++
++ DBC_Require(pList != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_GetHead: pList 0x%x\n", pList);
++
++ if (LST_IsEmpty(pList))
++ return NULL;
++
++ /* pElem is always valid because the list cannot be empty
++ * at this point */
++ pElem = pList->head.next;
++ pList->head.next = pElem->next;
++ pElem->next->prev = &pList->head;
++
++ return pElem->self;
++}
++
++/*
++ * ======== LST_Init ========
++ * Purpose:
++ * Initialize LST module private state.
++ */
++bool LST_Init(void)
++{
++ GT_create(&LST_debugMask, "LS"); /* LS for LSt module */
++
++ GT_0trace(LST_debugMask, GT_5CLASS, "LST_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== LST_InitElem ========
++ * Purpose:
++ * Initializes a list element to default (cleared) values
++ */
++void LST_InitElem(struct LST_ELEM *pElem)
++{
++ DBC_Require(pElem != NULL);
++
++ GT_1trace(LST_debugMask, GT_ENTER, "LST_InitElem: pElem 0x%x\n", pElem);
++
++ if (pElem) {
++ pElem->next = NULL;
++ pElem->prev = NULL;
++ pElem->self = pElem;
++ }
++}
++
++/*
++ * ======== LST_InsertBefore ========
++ * Purpose:
++ * Insert the element before the existing element.
++ */
++void LST_InsertBefore(struct LST_LIST *pList, struct LST_ELEM *pElem,
++ struct LST_ELEM *pElemExisting)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pElem != NULL);
++ DBC_Require(pElemExisting != NULL);
++
++ GT_3trace(LST_debugMask, GT_ENTER, "LST_InsertBefore: pList 0x%x, "
++ "pElem 0x%x pElemExisting 0x%x\n", pList, pElem,
++ pElemExisting);
++
++ pElemExisting->prev->next = pElem;
++ pElem->prev = pElemExisting->prev;
++ pElem->next = pElemExisting;
++ pElemExisting->prev = pElem;
++}
++
++/*
++ * ======== LST_Next ========
++ * Purpose:
++ * Returns a pointer to the next element of the list, or NULL if the
++ * next element is the head of the list or the list is empty.
++ */
++struct LST_ELEM *LST_Next(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
++{
++ struct LST_ELEM *pNextElem = NULL;
++
++ DBC_Require(pList != NULL);
++ DBC_Require(pCurElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_Next: pList 0x%x, pCurElem 0x%x\n",
++ pList, pCurElem);
++
++ if (!LST_IsEmpty(pList)) {
++ if (pCurElem->next != &pList->head)
++ pNextElem = pCurElem->next;
++ }
++
++ return pNextElem;
++}
++
++/*
++ * ======== LST_PutTail ========
++ * Purpose:
++ * Adds the specified element to the tail of the list
++ */
++void LST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_PutTail: pList 0x%x, pElem 0x%x\n",
++ pList, pElem);
++
++ pElem->prev = pList->head.prev;
++ pElem->next = &pList->head;
++ pList->head.prev = pElem;
++ pElem->prev->next = pElem;
++
++ DBC_Ensure(!LST_IsEmpty(pList));
++}
++
++/*
++ * ======== LST_RemoveElem ========
++ * Purpose:
++ * Removes (unlinks) the given element from the list, if the list is not
++ * empty. Does not free the list element.
++ */
++void LST_RemoveElem(struct LST_LIST *pList, struct LST_ELEM *pCurElem)
++{
++ DBC_Require(pList != NULL);
++ DBC_Require(pCurElem != NULL);
++
++ GT_2trace(LST_debugMask, GT_ENTER,
++ "LST_RemoveElem: pList 0x%x, pCurElem "
++ "0x%x\n", pList, pCurElem);
++
++ if (!LST_IsEmpty(pList)) {
++ pCurElem->prev->next = pCurElem->next;
++ pCurElem->next->prev = pCurElem->prev;
++
++ /* set elem fields to NULL to prevent illegal references */
++ pCurElem->next = NULL;
++ pCurElem->prev = NULL;
++ }
++}
++
+diff --git a/drivers/dsp/bridge/services/mem.c b/drivers/dsp/bridge/services/mem.c
+new file mode 100644
+index 0000000..0a10304
+--- /dev/null
++++ b/drivers/dsp/bridge/services/mem.c
+@@ -0,0 +1,599 @@
++/*
++ * mem.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mem.c ========
++ * Purpose:
++ * Implementation of platform specific memory services.
++ *
++ * Public Functions:
++ * MEM_Alloc
++ * MEM_AllocPhysMem
++ * MEM_Calloc
++ * MEM_Exit
++ * MEM_FlushCache
++ * MEM_Free
++ * MEM_FreePhysMem
++ * MEM_Init
++ * MEM_ExtPhysPoolInit
++ *
++ *! Revision History:
++ *! =================
++ *! 18-Jan-2004 hp: Added support for External physical memory pool
++ *! 19-Apr-2004 sb: Added Alloc/Free PhysMem, FlushCache, VirtualToPhysical
++ *! 01-Sep-2001 ag: Code cleanup.
++ *! 02-May-2001 ag: MEM_[UnMap]LinearAddress revamped to align Phys to Virt.
++ *! Set PAGE_PHYSICAL if phy addr <= 512MB. Opposite uSoft doc!
++ *! 29-Aug-2000 rr: MEM_LinearAddress does not check for 512MB for non-x86.
++ *! 28-Mar-2000 rr: MEM_LinearAddress changed.Handles address larger than 512MB
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 16-Aug-1999 kc: modified for WinCE.
++ *! 20-Mar-1999 ag: SP 4 fix in MEM_UMBCalloc().
++ *! Mdl offset now ORed not added to userBuf.
++ *! 23-Dec-1997 cr: Code review changes.
++ *! 08-Dec-1997 cr: Prepared for code review.
++ *! 24-Jun-1997 cr: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/mem.h>
++#include <dspbridge/list.h>
++
++/* ----------------------------------- Defines */
++#define MEM_512MB 0x1fffffff
++#define memInfoSign 0x464E494D /* "MINF" (in reverse). */
++
++#ifdef DEBUG
++#define MEM_CHECK /* Use to detect source of memory leaks */
++#endif
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask MEM_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static u32 cRefs; /* module reference count */
++
++static bool extPhysMemPoolEnabled;
++
++struct extPhysMemPool {
++ u32 physMemBase;
++ u32 physMemSize;
++ u32 virtMemBase;
++ u32 nextPhysAllocPtr;
++};
++
++static struct extPhysMemPool extMemPool;
++
++/* Information about each element allocated on heap */
++struct memInfo {
++ struct LST_ELEM link; /* Must be first */
++ size_t size;
++ void *caller;
++ u32 dwSignature; /* Should be last */
++};
++
++#ifdef MEM_CHECK
++
++/*
++ * This structure holds a linked list to all memory elements allocated on
++ * heap by DSP/BIOS Bridge. This is used to report memory leaks and free
++ * such elements while removing the DSP/BIOS Bridge driver
++ */
++struct memMan {
++ struct LST_LIST lst;
++ spinlock_t lock;
++};
++
++static struct memMan mMan;
++
++/*
++ * These functions are similar to LST_PutTail and LST_RemoveElem and are
++ * duplicated here to make MEM independent of LST
++ */
++static inline void MLST_PutTail(struct LST_LIST *pList, struct LST_ELEM *pElem)
++{
++ pElem->prev = pList->head.prev;
++ pElem->next = &pList->head;
++ pList->head.prev = pElem;
++ pElem->prev->next = pElem;
++ pElem->self = pElem;
++}
++
++static inline void MLST_RemoveElem(struct LST_LIST *pList,
++ struct LST_ELEM *pCurElem)
++{
++ pCurElem->prev->next = pCurElem->next;
++ pCurElem->next->prev = pCurElem->prev;
++ pCurElem->next = NULL;
++ pCurElem->prev = NULL;
++}
++
++static void MEM_Check(void)
++{
++ struct memInfo *pMem;
++ struct LST_ELEM *last = &mMan.lst.head;
++ struct LST_ELEM *curr = mMan.lst.head.next;
++
++ if (!LST_IsEmpty(&mMan.lst)) {
++ GT_0trace(MEM_debugMask, GT_7CLASS, "*** MEMORY LEAK ***\n");
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "Addr Size Caller\n");
++ while (curr != last) {
++ pMem = (struct memInfo *)curr;
++ curr = curr->next;
++ if ((u32)pMem > PAGE_OFFSET &&
++ MEM_IsValidHandle(pMem, memInfoSign)) {
++ GT_3trace(MEM_debugMask, GT_7CLASS,
++ "%lx %d\t [<%p>]\n",
++ (u32) pMem + sizeof(struct memInfo),
++ pMem->size, pMem->caller);
++ MLST_RemoveElem(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ kfree(pMem);
++ } else {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "Invalid allocation or "
++ "Buffer underflow at %x\n",
++ (u32)pMem + sizeof(struct memInfo));
++ break;
++ }
++ }
++ }
++ DBC_Ensure(LST_IsEmpty(&mMan.lst));
++}
++
++#endif
++
++void MEM_ExtPhysPoolInit(u32 poolPhysBase, u32 poolSize)
++{
++ u32 poolVirtBase;
++
++ /* get the virtual address for the physical memory pool passed */
++ poolVirtBase = (u32)ioremap(poolPhysBase, poolSize);
++
++ if ((void **)poolVirtBase == NULL) {
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "[PHYS_POOL]Mapping External "
++ "physical memory to virt failed \n");
++ extPhysMemPoolEnabled = false;
++ } else {
++ extMemPool.physMemBase = poolPhysBase;
++ extMemPool.physMemSize = poolSize;
++ extMemPool.virtMemBase = poolVirtBase;
++ extMemPool.nextPhysAllocPtr = poolPhysBase;
++ extPhysMemPoolEnabled = true;
++ GT_3trace(MEM_debugMask, GT_1CLASS,
++ "ExtMemory Pool details " "Pool"
++ "Physical mem base = %0x " "Pool Physical mem size "
++ "= %0x" "Pool Virtual mem base = %0x \n",
++ poolPhysBase, poolSize, poolVirtBase);
++ }
++}
++
++static void MEM_ExtPhysPoolRelease(void)
++{
++ GT_0trace(MEM_debugMask, GT_1CLASS,
++ "Releasing External memory pool \n");
++ if (extPhysMemPoolEnabled) {
++ iounmap((void *)(extMemPool.virtMemBase));
++ extPhysMemPoolEnabled = false;
++ }
++}
++
++/*
++ * ======== MEM_ExtPhysMemAlloc ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory from external memory pool
++ */
++
++static void *MEM_ExtPhysMemAlloc(u32 bytes, u32 align, OUT u32 *pPhysAddr)
++{
++ u32 newAllocPtr;
++ u32 offset;
++ u32 virtAddr;
++
++ GT_2trace(MEM_debugMask, GT_1CLASS,
++ "Ext Memory Allocation" "bytes=0x%x , "
++ "align=0x%x \n", bytes, align);
++ if (align == 0) {
++ GT_0trace(MEM_debugMask, GT_7CLASS,
++ "ExtPhysical Memory Allocation "
++ "No alignment request in allocation call !! \n");
++ align = 1;
++ }
++ if (bytes > ((extMemPool.physMemBase + extMemPool.physMemSize)
++ - extMemPool.nextPhysAllocPtr)) {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "ExtPhysical Memory Allocation "
++ "unable to allocate memory for bytes = 0x%x \n",
++ bytes);
++ pPhysAddr = NULL;
++ return NULL;
++ } else {
++ offset = (extMemPool.nextPhysAllocPtr & (align - 1));
++ if (offset == 0)
++ newAllocPtr = extMemPool.nextPhysAllocPtr;
++ else
++ newAllocPtr = (extMemPool.nextPhysAllocPtr) +
++ (align - offset);
++ if ((newAllocPtr + bytes) <=
++ (extMemPool.physMemBase + extMemPool.physMemSize)) {
++ /* we can allocate */
++ *pPhysAddr = newAllocPtr;
++ extMemPool.nextPhysAllocPtr = newAllocPtr + bytes;
++ virtAddr = extMemPool.virtMemBase + (newAllocPtr -
++ extMemPool.physMemBase);
++ GT_2trace(MEM_debugMask, GT_1CLASS,
++ "Ext Memory Allocation succedded "
++ "phys address=0x%x , virtaddress=0x%x \n",
++ newAllocPtr, virtAddr);
++ return (void *)virtAddr;
++ } else {
++ *pPhysAddr = 0;
++ return NULL;
++ }
++ }
++}
++
++/*
++ * ======== MEM_Alloc ========
++ * Purpose:
++ * Allocate memory from the paged or non-paged pools.
++ */
++void *MEM_Alloc(u32 cBytes, enum MEM_POOLATTRS type)
++{
++ struct memInfo *pMem = NULL;
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_Alloc: cBytes 0x%x\ttype 0x%x\n", cBytes, type);
++ if (cBytes > 0) {
++ switch (type) {
++ case MEM_NONPAGED:
++ /* If non-paged memory required, see note at top of file. */
++ case MEM_PAGED:
++#ifndef MEM_CHECK
++ pMem = kmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++#else
++ pMem = kmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem) {
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *)pMem);
++ spin_unlock(&mMan.lock);
++
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ case MEM_LARGEVIRTMEM:
++#ifndef MEM_CHECK
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++#else
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc((cBytes + sizeof(struct memInfo)),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem) {
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++
++ default:
++ GT_0trace(MEM_debugMask, GT_6CLASS,
++ "MEM_Alloc: unexpected "
++ "MEM_POOLATTRS value\n");
++ break;
++ }
++ }
++
++ return pMem;
++}
++
++/*
++ * ======== MEM_AllocPhysMem ========
++ * Purpose:
++ * Allocate physically contiguous, uncached memory
++ */
++void *MEM_AllocPhysMem(u32 cBytes, u32 ulAlign, OUT u32 *pPhysicalAddress)
++{
++ void *pVaMem = NULL;
++ dma_addr_t paMem;
++
++ DBC_Require(cRefs > 0);
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_AllocPhysMem: cBytes 0x%x\tulAlign"
++ "0x%x\n", cBytes, ulAlign);
++
++ if (cBytes > 0) {
++ if (extPhysMemPoolEnabled) {
++ pVaMem = MEM_ExtPhysMemAlloc(cBytes, ulAlign,
++ (u32 *)&paMem);
++ } else
++ pVaMem = dma_alloc_coherent(NULL, cBytes, &paMem,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pVaMem == NULL) {
++ *pPhysicalAddress = 0;
++ GT_1trace(MEM_debugMask, GT_6CLASS,
++ "MEM_AllocPhysMem failed: "
++ "0x%x\n", pVaMem);
++ } else {
++ *pPhysicalAddress = paMem;
++ }
++ }
++ return pVaMem;
++}
++
++/*
++ * ======== MEM_Calloc ========
++ * Purpose:
++ * Allocate zero-initialized memory from the paged or non-paged pools.
++ */
++void *MEM_Calloc(u32 cBytes, enum MEM_POOLATTRS type)
++{
++ struct memInfo *pMem = NULL;
++
++ GT_2trace(MEM_debugMask, GT_ENTER,
++ "MEM_Calloc: cBytes 0x%x\ttype 0x%x\n",
++ cBytes, type);
++
++ if (cBytes > 0) {
++ switch (type) {
++ case MEM_NONPAGED:
++ /* If non-paged memory required, see note at top of file. */
++ case MEM_PAGED:
++#ifndef MEM_CHECK
++ pMem = kmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem)
++ memset(pMem, 0, cBytes);
++
++#else
++ pMem = kmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL);
++ if (pMem) {
++ memset((void *)((u32)pMem +
++ sizeof(struct memInfo)), 0, cBytes);
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ case MEM_LARGEVIRTMEM:
++#ifndef MEM_CHECK
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes,
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem)
++ memset(pMem, 0, cBytes);
++
++#else
++ /* FIXME - Replace with 'vmalloc' after BP fix */
++ pMem = __vmalloc(cBytes + sizeof(struct memInfo),
++ (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL, PAGE_KERNEL);
++ if (pMem) {
++ memset((void *)((u32)pMem +
++ sizeof(struct memInfo)), 0, cBytes);
++ pMem->size = cBytes;
++ pMem->caller = __builtin_return_address(0);
++ pMem->dwSignature = memInfoSign;
++ spin_lock(&mMan.lock);
++ MLST_PutTail(&mMan.lst, (struct LST_ELEM *)
++ pMem);
++ spin_unlock(&mMan.lock);
++ pMem = (void *)((u32)pMem +
++ sizeof(struct memInfo));
++ }
++#endif
++ break;
++ default:
++ GT_1trace(MEM_debugMask, GT_6CLASS,
++ "MEM_Calloc: unexpected "
++ "MEM_POOLATTRS value 0x%x\n", type);
++ break;
++ }
++ }
++
++ return pMem;
++}
++
++/*
++ * ======== MEM_Exit ========
++ * Purpose:
++ * Discontinue usage of the MEM module.
++ */
++void MEM_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Exit: cRefs 0x%x\n", cRefs);
++
++ cRefs--;
++#ifdef MEM_CHECK
++ if (cRefs == 0)
++ MEM_Check();
++
++#endif
++ MEM_ExtPhysPoolRelease();
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== MEM_FlushCache ========
++ * Purpose:
++ * Flush cache
++ */
++void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType)
++{
++ DBC_Require(cRefs > 0);
++
++ switch (FlushType) {
++ /* invalidate only */
++ case PROC_INVALIDATE_MEM:
++ dmac_inv_range(pMemBuf, pMemBuf + cBytes);
++ outer_inv_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ /* writeback only */
++ case PROC_WRITEBACK_MEM:
++ dmac_clean_range(pMemBuf, pMemBuf + cBytes);
++ outer_clean_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ /* writeback and invalidate */
++ case PROC_WRITEBACK_INVALIDATE_MEM:
++ dmac_flush_range(pMemBuf, pMemBuf + cBytes);
++ outer_flush_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
++ cBytes));
++ break;
++ default:
++ GT_1trace(MEM_debugMask, GT_6CLASS, "MEM_FlushCache: invalid "
++ "FlushMemType 0x%x\n", FlushType);
++ break;
++ }
++
++}
++
++
++/*
++ * ======== MEM_Free ========
++ * Purpose:
++ * Free the given block of system memory.
++ */
++void MEM_Free(IN void *pMemBuf)
++{
++#ifdef MEM_CHECK
++ struct memInfo *pMem = (void *)((u32)pMemBuf - sizeof(struct memInfo));
++#endif
++
++ DBC_Require(pMemBuf != NULL);
++
++ GT_1trace(MEM_debugMask, GT_ENTER, "MEM_Free: pMemBufs 0x%x\n",
++ pMemBuf);
++
++ if (pMemBuf) {
++#ifndef MEM_CHECK
++ kfree(pMemBuf);
++#else
++ if (pMem) {
++ if (pMem->dwSignature == memInfoSign) {
++ spin_lock(&mMan.lock);
++ MLST_RemoveElem(&mMan.lst,
++ (struct LST_ELEM *) pMem);
++ spin_unlock(&mMan.lock);
++ pMem->dwSignature = 0;
++ kfree(pMem);
++ } else {
++ GT_1trace(MEM_debugMask, GT_7CLASS,
++ "Invalid allocation or "
++ "Buffer underflow at %x\n",
++ (u32) pMem + sizeof(struct memInfo));
++ }
++ }
++#endif
++ }
++}
++
++/*
++ * ======== MEM_FreePhysMem ========
++ * Purpose:
++ * Free the given block of physically contiguous memory.
++ */
++void MEM_FreePhysMem(void *pVirtualAddress, u32 pPhysicalAddress,
++ u32 cBytes)
++{
++ DBC_Require(cRefs > 0);
++ DBC_Require(pVirtualAddress != NULL);
++
++ GT_1trace(MEM_debugMask, GT_ENTER, "MEM_FreePhysMem: pVirtualAddress "
++ "0x%x\n", pVirtualAddress);
++
++ if (!extPhysMemPoolEnabled)
++ dma_free_coherent(NULL, cBytes, pVirtualAddress,
++ pPhysicalAddress);
++}
++
++/*
++ * ======== MEM_Init ========
++ * Purpose:
++ * Initialize MEM module private state.
++ */
++bool MEM_Init(void)
++{
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++ GT_create(&MEM_debugMask, "MM"); /* MM for MeM module */
++
++#ifdef MEM_CHECK
++ mMan.lst.head.next = &mMan.lst.head;
++ mMan.lst.head.prev = &mMan.lst.head;
++ mMan.lst.head.self = NULL;
++ spin_lock_init(&mMan.lock);
++#endif
++
++ }
++
++ cRefs++;
++
++ GT_1trace(MEM_debugMask, GT_5CLASS, "MEM_Init: cRefs 0x%x\n", cRefs);
++
++ DBC_Ensure(cRefs > 0);
++
++ return true;
++}
+diff --git a/drivers/dsp/bridge/services/ntfy.c b/drivers/dsp/bridge/services/ntfy.c
+new file mode 100644
+index 0000000..2eff3eb
+--- /dev/null
++++ b/drivers/dsp/bridge/services/ntfy.c
+@@ -0,0 +1,329 @@
++/*
++ * ntfy.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ntfyce.c ========
++ * Purpose:
++ * Manage lists of notification events.
++ *
++ * Public Functions:
++ * NTFY_Create
++ * NTFY_Delete
++ * NTFY_Exit
++ * NTFY_Init
++ * NTFY_Notify
++ * NTFY_Register
++ *
++ *! Revision History:
++ *! =================
++ *! 06-Feb-2003 kc Removed DSP_POSTMESSAGE related code.
++ *! 05-Nov-2001 kc Updated DSP_HNOTIFICATION structure.
++ *! 10-May-2001 jeh Removed SERVICES module init/exit from NTFY_Init/Exit.
++ *! NTFY_Register() returns DSP_ENOTIMPL for all but
++ *! DSP_SIGNALEVENT.
++ *! 12-Oct-2000 jeh Use MEM_IsValidHandle().
++ *! 07-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/ntfy.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define NTFY_SIGNATURE 0x5946544e /* "YFTN" */
++
++/*
++ * ======== NTFY_OBJECT ========
++ */
++struct NTFY_OBJECT {
++ u32 dwSignature; /* For object validation */
++ struct LST_LIST *notifyList; /* List of NOTIFICATION objects */
++ struct SYNC_CSOBJECT *hSync; /* For critical sections */
++};
++
++/*
++ * ======== NOTIFICATION ========
++ * This object will be created when a client registers for events.
++ */
++struct NOTIFICATION {
++ struct LST_ELEM listElem;
++ u32 uEventMask; /* Events to be notified about */
++ u32 uNotifyType; /* Type of notification to be sent */
++
++ /*
++ * We keep a copy of the event name to check if the event has
++ * already been registered. (SYNC also keeps a copy of the name).
++ */
++ char *pstrName; /* Name of event */
++ HANDLE hEvent; /* Handle for notification */
++ struct SYNC_OBJECT *hSync;
++};
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask NTFY_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/* ----------------------------------- Function Prototypes */
++static void DeleteNotify(struct NOTIFICATION *pNotify);
++
++/*
++ * ======== NTFY_Create ========
++ * Purpose:
++ * Create an empty list of notifications.
++ */
++DSP_STATUS NTFY_Create(struct NTFY_OBJECT **phNtfy)
++{
++ struct NTFY_OBJECT *pNtfy;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phNtfy != NULL);
++
++ *phNtfy = NULL;
++ MEM_AllocObject(pNtfy, struct NTFY_OBJECT, NTFY_SIGNATURE);
++
++ if (pNtfy) {
++
++ status = SYNC_InitializeDPCCS(&pNtfy->hSync);
++ if (DSP_SUCCEEDED(status)) {
++ pNtfy->notifyList = LST_Create();
++ if (pNtfy->notifyList == NULL) {
++ (void) SYNC_DeleteCS(pNtfy->hSync);
++ MEM_FreeObject(pNtfy);
++ status = DSP_EMEMORY;
++ } else {
++ *phNtfy = pNtfy;
++ }
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ DBC_Ensure((DSP_FAILED(status) && *phNtfy == NULL) ||
++ (DSP_SUCCEEDED(status) && MEM_IsValidHandle((*phNtfy),
++ NTFY_SIGNATURE)));
++
++ return status;
++}
++
++/*
++ * ======== NTFY_Delete ========
++ * Purpose:
++ * Free resources allocated in NTFY_Create.
++ */
++void NTFY_Delete(struct NTFY_OBJECT *hNtfy)
++{
++ struct NOTIFICATION *pNotify;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ /* Remove any elements remaining in list */
++ if (hNtfy->notifyList) {
++ while ((pNotify = (struct NOTIFICATION *)LST_GetHead(hNtfy->
++ notifyList))) {
++ DeleteNotify(pNotify);
++ }
++ DBC_Assert(LST_IsEmpty(hNtfy->notifyList));
++ LST_Delete(hNtfy->notifyList);
++ }
++ if (hNtfy->hSync)
++ (void)SYNC_DeleteCS(hNtfy->hSync);
++
++ MEM_FreeObject(hNtfy);
++}
++
++/*
++ * ======== NTFY_Exit ========
++ * Purpose:
++ * Discontinue usage of NTFY module.
++ */
++void NTFY_Exit(void)
++{
++ GT_0trace(NTFY_debugMask, GT_5CLASS, "Entered NTFY_Exit\n");
++}
++
++/*
++ * ======== NTFY_Init ========
++ * Purpose:
++ * Initialize the NTFY module.
++ */
++bool NTFY_Init(void)
++{
++ GT_create(&NTFY_debugMask, "NY"); /* "NY" for NtfY */
++
++ GT_0trace(NTFY_debugMask, GT_5CLASS, "NTFY_Init()\n");
++
++ return true;
++}
++
++/*
++ * ======== NTFY_Notify ========
++ * Purpose:
++ * Execute notify function (signal event) for every
++ * element in the notification list that is to be notified about the
++ * event specified in uEventMask.
++ */
++void NTFY_Notify(struct NTFY_OBJECT *hNtfy, u32 uEventMask)
++{
++ struct NOTIFICATION *pNotify;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ /*
++ * Go through notifyList and notify all clients registered for
++ * uEventMask events.
++ */
++
++ (void) SYNC_EnterCS(hNtfy->hSync);
++
++ pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
++ while (pNotify != NULL) {
++ if (pNotify->uEventMask & uEventMask) {
++ /* Notify */
++ if (pNotify->uNotifyType == DSP_SIGNALEVENT)
++ (void)SYNC_SetEvent(pNotify->hSync);
++
++ }
++ pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ }
++
++ (void) SYNC_LeaveCS(hNtfy->hSync);
++}
++
++/*
++ * ======== NTFY_Register ========
++ * Purpose:
++ * Add a notification element to the list. If the notification is already
++ * registered, and uEventMask != 0, the notification will get posted for
++ * events specified in the new event mask. If the notification is already
++ * registered and uEventMask == 0, the notification will be unregistered.
++ */
++DSP_STATUS NTFY_Register(struct NTFY_OBJECT *hNtfy,
++ struct DSP_NOTIFICATION *hNotification,
++ u32 uEventMask, u32 uNotifyType)
++{
++ struct NOTIFICATION *pNotify;
++ struct SYNC_ATTRS syncAttrs;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE));
++
++ if (hNotification == NULL)
++ status = DSP_EHANDLE;
++
++ /* Return DSP_ENOTIMPL if uNotifyType is not supported */
++ if (DSP_SUCCEEDED(status)) {
++ if (!IsValidNotifyMask(uNotifyType))
++ status = DSP_ENOTIMPL;
++
++ }
++
++ if (DSP_FAILED(status))
++ return status;
++
++ (void)SYNC_EnterCS(hNtfy->hSync);
++
++ pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList);
++ while (pNotify != NULL) {
++ /* If there is more than one notification type, each
++ * type may require its own handler code. */
++
++ if (hNotification->handle == pNotify->hSync) {
++ /* found */
++ break;
++ }
++ pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ }
++ if (pNotify == NULL) {
++ /* Not registered */
++ if (uEventMask == 0) {
++ status = DSP_EVALUE;
++ } else {
++ /* Allocate NOTIFICATION object, add to list */
++ pNotify = MEM_Calloc(sizeof(struct NOTIFICATION),
++ MEM_PAGED);
++ if (pNotify == NULL)
++ status = DSP_EMEMORY;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ LST_InitElem((struct LST_ELEM *) pNotify);
++ /* If there is more than one notification type, each
++ * type may require its own handler code. */
++ status = SYNC_OpenEvent(&pNotify->hSync, &syncAttrs);
++ hNotification->handle = pNotify->hSync;
++
++ if (DSP_SUCCEEDED(status)) {
++ pNotify->uEventMask = uEventMask;
++ pNotify->uNotifyType = uNotifyType;
++ LST_PutTail(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ } else {
++ DeleteNotify(pNotify);
++ }
++ }
++ } else {
++ /* Found in list */
++ if (uEventMask == 0) {
++ /* Remove from list and free */
++ LST_RemoveElem(hNtfy->notifyList,
++ (struct LST_ELEM *)pNotify);
++ DeleteNotify(pNotify);
++ } else {
++ /* Update notification mask (type shouldn't change) */
++ pNotify->uEventMask = uEventMask;
++ }
++ }
++ (void)SYNC_LeaveCS(hNtfy->hSync);
++ return status;
++}
++
++/*
++ * ======== DeleteNotify ========
++ * Purpose:
++ * Free the notification object.
++ */
++static void DeleteNotify(struct NOTIFICATION *pNotify)
++{
++ if (pNotify->hSync)
++ (void) SYNC_CloseEvent(pNotify->hSync);
++
++ if (pNotify->pstrName)
++ MEM_Free(pNotify->pstrName);
++
++ MEM_Free(pNotify);
++}
++
+diff --git a/drivers/dsp/bridge/services/reg.c b/drivers/dsp/bridge/services/reg.c
+new file mode 100644
+index 0000000..0d85f41
+--- /dev/null
++++ b/drivers/dsp/bridge/services/reg.c
+@@ -0,0 +1,196 @@
++/*
++ * reg.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regce.c ========
++ * Purpose:
++ * Provide registry functions.
++ *
++ * Public Functions:
++ * REG_DeleteValue
++ * REG_EnumValue
++ * REG_Exit
++ * REG_GetValue
++ * REG_Init
++ * REG_SetValue
++ *
++ *! Revision History:
++ *! ================
++ *
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/reg.h>
++#include <regsup.h>
++
++#if GT_TRACE
++struct GT_Mask REG_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++/*
++ * ======== REG_DeleteValue ========
++ * Deletes a registry entry value. NOTE: A registry entry value is not the
++ * same as * a registry key.
++ */
++DSP_STATUS REG_DeleteValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue)
++{
++ DSP_STATUS status;
++ DBC_Require(pstrSubkey && pstrValue);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_DeleteValue: entered\n");
++
++ /* Note that we don't use phKey */
++ if (regsupDeleteValue(pstrSubkey, pstrValue) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== REG_EnumValue ========
++ * Enumerates a registry key and retrieve values stored under the key.
++ * We will assume the input pdwValueSize is smaller than
++ * REG_MAXREGPATHLENGTH for implementation purposes.
++ */
++DSP_STATUS REG_EnumValue(IN HANDLE *phKey, IN u32 dwIndex,
++ IN CONST char *pstrKey, IN OUT char *pstrValue,
++ IN OUT u32 *pdwValueSize, IN OUT char *pstrData,
++ IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrKey && pstrValue && pdwValueSize && pstrData &&
++ pdwDataSize);
++ DBC_Require(*pdwValueSize <= REG_MAXREGPATHLENGTH);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrKey) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_EnumValue: entered\n");
++
++ status = regsupEnumValue(dwIndex, pstrKey, pstrValue, pdwValueSize,
++ pstrData, pdwDataSize);
++
++ return status;
++}
++
++/*
++ * ======== REG_Exit ========
++ * Discontinue usage of the REG module.
++ */
++void REG_Exit(void)
++{
++ GT_0trace(REG_debugMask, GT_5CLASS, "REG_Exit\n");
++
++ regsupExit();
++}
++
++/*
++ * ======== REG_GetValue ========
++ * Retrieve a value from the registry.
++ */
++DSP_STATUS REG_GetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue, OUT u8 *pbData,
++ IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrSubkey && pstrValue && pbData);
++ DBC_Require(phKey == NULL);
++ DBC_Require(strlen(pstrSubkey) < REG_MAXREGPATHLENGTH);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ GT_0trace(REG_debugMask, GT_ENTER, "REG_GetValue: entered\n");
++
++ /* We need to use regsup calls... */
++ /* ...for now we don't need the key handle or */
++ /* the subkey, all we need is the value to lookup. */
++ if (regsupGetValue((char *)pstrValue, pbData, pdwDataSize) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
++/*
++ * ======== REG_Init ========
++ * Initialize the REG module's private state.
++ */
++bool REG_Init(void)
++{
++ bool fInit;
++
++ GT_create(&REG_debugMask, "RG"); /* RG for ReG */
++
++ fInit = regsupInit();
++
++ GT_0trace(REG_debugMask, GT_5CLASS, "REG_Init\n");
++
++ return fInit;
++}
++
++/*
++ * ======== REG_SetValue ========
++ * Set a value in the registry.
++ */
++DSP_STATUS REG_SetValue(OPTIONAL IN HANDLE *phKey, IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue, IN CONST u32 dwType,
++ IN u8 *pbData, IN u32 dwDataSize)
++{
++ DSP_STATUS status;
++
++ DBC_Require(pstrValue && pbData);
++ DBC_Require(phKey == NULL);
++ DBC_Require(dwDataSize > 0);
++ DBC_Require(strlen(pstrValue) < REG_MAXREGPATHLENGTH);
++
++ /* We need to use regsup calls... */
++ /* ...for now we don't need the key handle or */
++ /* the subkey, all we need is the value to lookup. */
++ if (regsupSetValue((char *)pstrValue, pbData, dwDataSize) == DSP_SOK)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++
++ return status;
++}
++
+diff --git a/drivers/dsp/bridge/services/regsup.c b/drivers/dsp/bridge/services/regsup.c
+new file mode 100644
+index 0000000..5251b68
+--- /dev/null
++++ b/drivers/dsp/bridge/services/regsup.c
+@@ -0,0 +1,368 @@
++/*
++ * regsup.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regsup.c ========
++ * Purpose:
++ * Provide registry support functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 28-May-2002 map: Integrated PSI's dspimage update mechanism
++ *! 11-May-2002 gp: Turned PERF "on".
++ *! 21-May-2002 map: Fixed bug in SetValue - if resizing datasize, set
++ *! new size too
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/csl.h>
++
++/* ----------------------------------- This */
++#include <regsup.h>
++
++struct RegValueStruct {
++ char name[BRIDGE_MAX_NAME_SIZE]; /* Name of a given value entry */
++ u32 dataSize; /* Size of the data */
++ void *pData; /* Pointer to the actual data */
++};
++
++struct RegKeyStruct {
++ /*The current number of value entries this key has*/
++ u32 numValueEntries;
++ /* Array of value entries */
++ struct RegValueStruct values[BRIDGE_MAX_NUM_REG_ENTRIES];
++};
++
++
++/* Pointer to the registry support key */
++static struct RegKeyStruct *pRegKey;
++
++#if GT_TRACE
++extern struct GT_Mask REG_debugMask; /* GT trace var. */
++/*
++ * ======== printS ========
++ * Purpose:
++ * Displays printable characters in pBuf, if any.
++ */
++static inline void printS(void *pBuf)
++{
++ int pos = 0;
++ if (*(REG_debugMask).flags & (GT_2CLASS)) {
++ while (*(u8 *)((pBuf)+pos) >= ' ' &&
++ *(u8 *)((pBuf)+pos) <= '~') {
++ GT_1trace(REG_debugMask, GT_2CLASS, "%c",
++ *(u8 *)((pBuf) + pos++));
++ }
++
++ GT_0trace(REG_debugMask, GT_2CLASS, "\n");
++ }
++}
++#else
++#define printS(pBuf)
++#endif
++
++/*
++ * ======== regsupInit ========
++ * Purpose:
++ * Initialize the Registry Support module's private state.
++ */
++bool regsupInit(void)
++{
++ if (pRegKey != NULL)
++ return true;
++
++ /* Need to allocate and setup our registry. */
++ pRegKey = MEM_Calloc(sizeof(struct RegKeyStruct), MEM_NONPAGED);
++ if (pRegKey == NULL)
++ return false;
++
++ return true;
++}
++
++/*
++ * ======== regsupExit ========
++ * Purpose:
++ * Release all registry support allocations.
++ */
++void regsupExit(void)
++{
++ u32 i;
++
++ /* Make sure data has actually been allocated. */
++ if (pRegKey == NULL) {
++ /* Nothing initialized.return! */
++ return;
++ }
++
++ GT_1trace(REG_debugMask, GT_2CLASS, "pRegKey->numValueEntries %d\n",
++ pRegKey->numValueEntries);
++
++ /* Now go through each entry and free all resources. */
++ for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
++ (i < pRegKey->numValueEntries)); i++) {
++ if (pRegKey->values[i].name[0] != '\0') {
++ /* We have a valid entry.free it up! */
++ if (pRegKey->values[i].pData != NULL) {
++ GT_3trace(REG_debugMask, GT_2CLASS,
++ "E %d\t %s DATA %x ", i,
++ pRegKey->values[i].name,
++ *(u32 *)pRegKey->values[i].pData);
++ printS((u8 *)(pRegKey->values[i].pData));
++ MEM_Free(pRegKey->values[i].pData);
++ }
++ pRegKey->values[i].pData = NULL;
++ pRegKey->values[i].dataSize = 0;
++ pRegKey->values[i].name[0] = '\0';
++ }
++ }
++
++ /* Now that all of the resources are freed up, free the main one! */
++ MEM_Free(pRegKey);
++
++ /* Don't forget to NULL out the global entry! */
++ pRegKey = NULL;
++}
++
++/*
++ * ======== regsupGetValue ========
++ * Purpose:
++ * Get the value of the entry having the given name.
++ */
++DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if (strncmp(pRegKey->values[i].name, valName,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++
++ /* We have a match! Copy out the data. */
++ memcpy(pBuf, pRegKey->values[i].pData,
++ pRegKey->values[i].dataSize);
++
++ /* Get the size for the caller. */
++ *dataSize = pRegKey->values[i].dataSize;
++
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ if (DSP_SUCCEEDED(retVal)) {
++ GT_2trace(REG_debugMask, GT_2CLASS, "G %s DATA %x ", valName,
++ *(u32 *)pBuf);
++ printS((u8 *)pBuf);
++ } else {
++ GT_1trace(REG_debugMask, GT_3CLASS, "G %s FAILED\n", valName);
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== regsupSetValue ========
++ * Purpose:
++ * Sets the value of the entry having the given name.
++ */
++DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ GT_2trace(REG_debugMask, GT_2CLASS, "S %s DATA %x ", valName,
++ *(u32 *)pBuf);
++ printS((u8 *)pBuf);
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if (strncmp(pRegKey->values[i].name, valName,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++ /* Make sure the new data size is the same. */
++ if (dataSize != pRegKey->values[i].dataSize) {
++ /* The caller needs a different data size! */
++ MEM_Free(pRegKey->values[i].pData);
++ pRegKey->values[i].pData = MEM_Alloc(dataSize,
++ MEM_NONPAGED);
++ if (pRegKey->values[i].pData == NULL)
++ break;
++
++ }
++
++ /* We have a match! Copy out the data. */
++ memcpy(pRegKey->values[i].pData, pBuf, dataSize);
++
++ /* Reset datasize - overwrite if new or same */
++ pRegKey->values[i].dataSize = dataSize;
++
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ /* See if we found a match or if this is a new entry */
++ if (i == pRegKey->numValueEntries) {
++ /* No match, need to make a new entry */
++ /* First check to see if we can make any more entries. */
++ if (pRegKey->numValueEntries < BRIDGE_MAX_NUM_REG_ENTRIES) {
++ strncpy(pRegKey->values[pRegKey->numValueEntries].name,
++ valName, BRIDGE_MAX_NAME_SIZE);
++ pRegKey->values[pRegKey->numValueEntries].pData =
++ MEM_Alloc(dataSize, MEM_NONPAGED);
++ if (pRegKey->values[pRegKey->numValueEntries].pData !=
++ NULL) {
++ memcpy(pRegKey->
++ values[pRegKey->numValueEntries].pData,
++ pBuf, dataSize);
++ pRegKey->
++ values[pRegKey->numValueEntries].dataSize =
++ dataSize;
++ pRegKey->numValueEntries++;
++ retVal = DSP_SOK;
++ }
++ } else {
++ GT_0trace(REG_debugMask, GT_7CLASS,
++ "MAX NUM REG ENTRIES REACHED\n");
++ }
++ }
++
++ return retVal;
++}
++
++/*
++ * ======== regsupEnumValue ========
++ * Purpose:
++ * Returns registry "values" and their "data" under a (sub)key.
++ */
++DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData, IN OUT u32 *pdwDataSize)
++{
++ DSP_STATUS retVal = REG_E_INVALIDSUBKEY;
++ u32 i;
++ u32 dwKeyLen;
++ u32 count = 0;
++
++ DBC_Require(pstrKey);
++ dwKeyLen = strlen(pstrKey);
++
++ /* Need to search through the entries looking for the right one. */
++ for (i = 0; i < pRegKey->numValueEntries; i++) {
++ /* See if the name matches. */
++ if ((strncmp(pRegKey->values[i].name, pstrKey,
++ dwKeyLen) == 0) && count++ == dwIndex) {
++ /* We have a match! Copy out the data. */
++ memcpy(pstrData, pRegKey->values[i].pData,
++ pRegKey->values[i].dataSize);
++ /* Get the size for the caller. */
++ *pdwDataSize = pRegKey->values[i].dataSize;
++ *pdwValueSize = strlen(&(pRegKey->
++ values[i].name[dwKeyLen]));
++ strncpy(pstrValue,
++ &(pRegKey->values[i].name[dwKeyLen]),
++ *pdwValueSize + 1);
++ GT_3trace(REG_debugMask, GT_2CLASS,
++ "E Key %s, Value %s, Data %x ",
++ pstrKey, pstrValue, *(u32 *)pstrData);
++ printS((u8 *)pstrData);
++ /* Set our status to good and exit. */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++
++ if (count && DSP_FAILED(retVal))
++ retVal = REG_E_NOMOREITEMS;
++
++ return retVal;
++}
++
++/*
++ * ======== regsupDeleteValue ========
++ */
++DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue)
++{
++ DSP_STATUS retVal = DSP_EFAIL;
++ u32 i;
++
++ for (i = 0; ((i < BRIDGE_MAX_NUM_REG_ENTRIES) &&
++ (i < pRegKey->numValueEntries)); i++) {
++ /* See if the name matches... */
++ if (strncmp(pRegKey->values[i].name, pstrValue,
++ BRIDGE_MAX_NAME_SIZE) == 0) {
++ /* We have a match! Delete this key. To delete a
++ * key, we free all resources associated with this
++ * key and, if we're not already the last entry in
++ * the array, we copy that entry into this deleted
++ * key.
++ */
++ MEM_Free(pRegKey->values[i].pData);
++ if ((pRegKey->numValueEntries - 1) == i) {
++ /* we're deleting the last one */
++ pRegKey->values[i].name[0] = '\0';
++ pRegKey->values[i].dataSize = 0;
++ pRegKey->values[i].pData = NULL;
++ } else {
++ /* move the last one here */
++ strncpy(pRegKey->values[i].name, pRegKey->
++ values[pRegKey->numValueEntries - 1].name,
++ BRIDGE_MAX_NAME_SIZE);
++ pRegKey->values[i].dataSize =
++ pRegKey->
++ values[pRegKey->numValueEntries-1].dataSize;
++ pRegKey->values[i].pData =
++ pRegKey->
++ values[pRegKey->numValueEntries-1].pData;
++ /* don't have to do this, but for
++ * the paranoid... */
++ pRegKey->
++ values[pRegKey->numValueEntries-1].name[0] =
++ '\0';
++ }
++
++ /* another one bites the dust. */
++ pRegKey->numValueEntries--;
++
++ /* Set our status to good and exit... */
++ retVal = DSP_SOK;
++ break;
++ }
++ }
++ return retVal;
++
++}
++
+diff --git a/drivers/dsp/bridge/services/regsup.h b/drivers/dsp/bridge/services/regsup.h
+new file mode 100644
+index 0000000..011be52
+--- /dev/null
++++ b/drivers/dsp/bridge/services/regsup.h
+@@ -0,0 +1,58 @@
++/*
++ * regsup.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== regsup.h ========
++ *
++ *! Revision History
++ *! ================
++ */
++
++#ifndef _REGSUP_H_
++#define _REGSUP_H_
++
++#define BRIDGE_MAX_NAME_SIZE MAXREGPATHLENGTH
++#define BRIDGE_MAX_NUM_REG_ENTRIES 52
++
++/* Init function. MUST be called BEFORE any calls are */
++/* made into this psuedo-registry!!! Returns TRUE/FALSE for SUCCESS/ERROR */
++extern bool regsupInit(void);
++
++/* Release all registry support allocations. */
++extern void regsupExit(void);
++
++/*
++ * ======== regsupDeleteValue ========
++ */
++extern DSP_STATUS regsupDeleteValue(IN CONST char *pstrSubkey,
++ IN CONST char *pstrValue);
++/* Get the value of the entry having the given name. Returns DSP_SOK */
++/* if an entry was found and the value retrieved. Returns DSP_EFAIL
++ * otherwise.*/
++extern DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize);
++
++/* Sets the value of the entry having the given name. Returns DSP_SOK */
++/* if an entry was found and the value set. Returns DSP_EFAIL otherwise. */
++extern DSP_STATUS regsupSetValue(char *valName, void *pBuf, u32 dataSize);
++
++/* Returns registry "values" and their "data" under a (sub)key. */
++extern DSP_STATUS regsupEnumValue(IN u32 dwIndex, IN CONST char *pstrKey,
++ IN OUT char *pstrValue, IN OUT u32 *pdwValueSize,
++ IN OUT char *pstrData, IN OUT u32 *pdwDataSize);
++
++#endif
++
+diff --git a/drivers/dsp/bridge/services/services.c b/drivers/dsp/bridge/services/services.c
+new file mode 100644
+index 0000000..346007e
+--- /dev/null
++++ b/drivers/dsp/bridge/services/services.c
+@@ -0,0 +1,193 @@
++/*
++ * services.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== services.c ========
++ * Purpose:
++ * Provide SERVICES loading.
++ *
++ * Public Functions:
++ * SERVICES_Exit
++ * SERVICES_Init
++ *
++ *
++ *! Revision History
++ *! ================
++ *! 20-Nov-2000 rr: NTFY_Init/Exit added.
++ *! 06-Jul-2000 rr: PROC prefix changed to PRCS to accomodate RM.
++ *! 01-Feb-2000 kc: Created.
++ */
++
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/dbg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/kfile.h>
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/clk.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/services.h>
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask SERVICES_debugMask = { NULL, NULL }; /* GT trace var. */
++#endif
++
++static u32 cRefs; /* SERVICES module reference count */
++
++/*
++ * ======== SERVICES_Exit ========
++ * Purpose:
++ * Discontinue usage of module; free resources when reference count
++ * reaches 0.
++ */
++void SERVICES_Exit(void)
++{
++ DBC_Require(cRefs > 0);
++
++ GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Exit: cRefs 0x%x\n",
++ cRefs);
++
++ cRefs--;
++ if (cRefs == 0) {
++ /* Uninitialize all SERVICES modules here */
++ NTFY_Exit();
++ UTIL_Exit();
++ SYNC_Exit();
++ CLK_Exit();
++ REG_Exit();
++ LST_Exit();
++ KFILE_Exit();
++ DPC_Exit();
++ DBG_Exit();
++ CSL_Exit();
++ CFG_Exit();
++ MEM_Exit();
++
++ GT_exit();
++ }
++
++ DBC_Ensure(cRefs >= 0);
++}
++
++/*
++ * ======== SERVICES_Init ========
++ * Purpose:
++ * Initializes SERVICES modules.
++ */
++bool SERVICES_Init(void)
++{
++ bool fInit = true;
++ bool fCFG, fCSL, fDBG, fDPC, fKFILE, fLST, fMEM;
++ bool fREG, fSYNC, fCLK, fUTIL, fNTFY;
++
++ DBC_Require(cRefs >= 0);
++
++ if (cRefs == 0) {
++
++ GT_init();
++ GT_create(&SERVICES_debugMask, "OS"); /* OS for OSal */
++
++ GT_0trace(SERVICES_debugMask, GT_ENTER,
++ "SERVICES_Init: entered\n");
++
++ /* Perform required initialization of SERVICES modules. */
++ fMEM = MEM_Init();
++ fREG = REG_Init();
++ fCFG = CFG_Init();
++ fCSL = CSL_Init();
++ fDBG = DBG_Init();
++ fDPC = DPC_Init();
++ fKFILE = KFILE_Init();
++ fLST = LST_Init();
++ /* fREG = REG_Init(); */
++ fSYNC = SYNC_Init();
++ fCLK = CLK_Init();
++ fUTIL = UTIL_Init();
++ fNTFY = NTFY_Init();
++
++ fInit = fCFG && fCSL && fDBG && fDPC && fKFILE &&
++ fLST && fMEM && fREG && fSYNC && fCLK && fUTIL;
++
++ if (!fInit) {
++ if (fNTFY)
++ NTFY_Exit();
++
++ if (fUTIL)
++ UTIL_Exit();
++
++ if (fSYNC)
++ SYNC_Exit();
++
++ if (fCLK)
++ CLK_Exit();
++
++ if (fREG)
++ REG_Exit();
++
++ if (fLST)
++ LST_Exit();
++
++ if (fKFILE)
++ KFILE_Exit();
++
++ if (fDPC)
++ DPC_Exit();
++
++ if (fDBG)
++ DBG_Exit();
++
++ if (fCSL)
++ CSL_Exit();
++
++ if (fCFG)
++ CFG_Exit();
++
++ if (fMEM)
++ MEM_Exit();
++
++ }
++ }
++
++ if (fInit)
++ cRefs++;
++
++ GT_1trace(SERVICES_debugMask, GT_5CLASS, "SERVICES_Init: cRefs 0x%x\n",
++ cRefs);
++
++ DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs >= 0)));
++
++ return fInit;
++}
++
+diff --git a/drivers/dsp/bridge/services/sync.c b/drivers/dsp/bridge/services/sync.c
+new file mode 100644
+index 0000000..7ab9347
+--- /dev/null
++++ b/drivers/dsp/bridge/services/sync.c
+@@ -0,0 +1,602 @@
++/*
++ * sync.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== sync.c ========
++ * Purpose:
++ * Synchronization services.
++ *
++ * Public Functions:
++ * SYNC_CloseEvent
++ * SYNC_DeleteCS
++ * SYNC_EnterCS
++ * SYNC_Exit
++ * SYNC_Init
++ * SYNC_InitializeCS
++ * SYNC_LeaveCS
++ * SYNC_OpenEvent
++ * SYNC_ResetEvent
++ * SYNC_SetEvent
++ * SYNC_WaitOnEvent
++ * SYNC_WaitOnMultipleEvents
++ *
++ *! Revision History:
++ *! ================
++ *! 05-Nov-2001 kc: Minor cosmetic changes.
++ *! 05-Oct-2000 jeh Added SYNC_WaitOnMultipleEvents().
++ *! 10-Aug-2000 rr: SYNC_PostMessage added.
++ *! 10-Jul-2000 jeh Modified SYNC_OpenEvent() to handle NULL attrs.
++ *! 03-Feb-2000 rr: Module init/exit is handled by SERVICES Init/Exit.
++ *! GT Changes.
++ *! 01-Dec-1999 ag: Added optional named event creation in SYNC_OpenEvent().
++ *! 22-Nov-1999 kc: Added changes from code review.
++ *! 22-Sep-1999 kc: Modified from sync95.c.
++ *! 05-Aug-1996 gp: Created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/mem.h>
++
++/* ----------------------------------- This */
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define SIGNATURE 0x434e5953 /* "SYNC" (in reverse) */
++
++enum wait_state {
++ wo_waiting,
++ wo_signalled
++} ;
++
++enum sync_state {
++ so_reset,
++ so_signalled
++} ;
++
++struct WAIT_OBJECT {
++ enum wait_state state;
++ struct SYNC_OBJECT *signalling_event;
++ struct semaphore sem;
++};
++
++/* Generic SYNC object: */
++struct SYNC_OBJECT {
++ u32 dwSignature; /* Used for object validation. */
++ enum sync_state state;
++ spinlock_t sync_lock;
++ struct WAIT_OBJECT *pWaitObj;
++};
++
++struct SYNC_DPCCSOBJECT {
++ u32 dwSignature; /* used for object validation */
++ spinlock_t sync_dpccs_lock;
++ s32 count;
++} ;
++
++/* ----------------------------------- Globals */
++#if GT_TRACE
++static struct GT_Mask SYNC_debugMask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++static int test_and_set(volatile void *ptr, int val)
++{
++ int ret = val;
++ asm volatile (" swp %0, %0, [%1]" : "+r" (ret) : "r"(ptr) : "memory");
++ return ret;
++}
++
++static void timeout_callback(unsigned long hWaitObj);
++
++/*
++ * ======== SYNC_CloseEvent ========
++ * Purpose:
++ * Close an existing SYNC event object.
++ */
++DSP_STATUS SYNC_CloseEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++
++ DBC_Require(pEvent != NULL && pEvent->pWaitObj == NULL);
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_CloseEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ if (pEvent->pWaitObj) {
++ status = DSP_EFAIL;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_CloseEvent: Wait object not NULL\n");
++ }
++ MEM_FreeObject(pEvent);
++
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_CloseEvent: invalid "
++ "hEvent handle 0x%x\n", hEvent);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_Exit ========
++ * Purpose:
++ * Cleanup SYNC module.
++ */
++void SYNC_Exit(void)
++{
++ GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Exit\n");
++}
++
++/*
++ * ======== SYNC_Init ========
++ * Purpose:
++ * Initialize SYNC module.
++ */
++bool SYNC_Init(void)
++{
++ GT_create(&SYNC_debugMask, "SY"); /* SY for SYnc */
++
++ GT_0trace(SYNC_debugMask, GT_5CLASS, "SYNC_Init\n");
++
++ return true;
++}
++
++/*
++ * ======== SYNC_OpenEvent ========
++ * Purpose:
++ * Open a new synchronization event object.
++ */
++DSP_STATUS SYNC_OpenEvent(OUT struct SYNC_OBJECT **phEvent,
++ IN OPTIONAL struct SYNC_ATTRS *pAttrs)
++{
++ struct SYNC_OBJECT *pEvent = NULL;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phEvent != NULL);
++
++ GT_2trace(SYNC_debugMask, GT_ENTER,
++ "SYNC_OpenEvent: phEvent 0x%x, pAttrs "
++ "0x%x\n", phEvent, pAttrs);
++
++ /* Allocate memory for sync object */
++ MEM_AllocObject(pEvent, struct SYNC_OBJECT, SIGNATURE);
++ if (pEvent != NULL) {
++ pEvent->state = so_reset;
++ pEvent->pWaitObj = NULL;
++ spin_lock_init(&pEvent->sync_lock);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_OpenEvent: MEM_AllocObject failed\n");
++ }
++
++ *phEvent = pEvent;
++
++ return status;
++}
++
++/*
++ * ======== SYNC_ResetEvent ========
++ * Purpose:
++ * Reset an event to non-signalled.
++ */
++DSP_STATUS SYNC_ResetEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_ResetEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ pEvent->state = so_reset;
++ status = DSP_SOK;
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_ResetEvent: invalid hEvent "
++ "handle 0x%x\n", hEvent);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_SetEvent ========
++ * Purpose:
++ * Set an event to signaled and unblock one waiting thread.
++ *
++ * This function is called from ISR, DPC and user context. Hence interrupts
++ * are disabled to ensure atomicity.
++ */
++
++DSP_STATUS SYNC_SetEvent(struct SYNC_OBJECT *hEvent)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++ unsigned long flags;
++
++ GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: hEvent 0x%x\n",
++ hEvent);
++
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ spin_lock_irqsave(&hEvent->sync_lock, flags);
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: pEvent->pWaitObj "
++ "= 0x%x \n", pEvent->pWaitObj);
++ if (pEvent->pWaitObj)
++ GT_1trace(SYNC_debugMask, GT_6CLASS, "SYNC_SetEvent: "
++ "pEvent->pWaitObj->state = 0x%x \n",
++ pEvent->pWaitObj->state);
++ if (pEvent->pWaitObj != NULL &&
++ test_and_set(&pEvent->pWaitObj->state,
++ wo_signalled) == wo_waiting) {
++
++ pEvent->state = so_reset;
++ pEvent->pWaitObj->signalling_event = pEvent;
++ up(&pEvent->pWaitObj->sem);
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: Unlock "
++ "Semaphore for hEvent 0x%x\n", hEvent);
++ } else {
++ pEvent->state = so_signalled;
++ }
++ spin_unlock_irqrestore(&hEvent->sync_lock, flags);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_SetEvent: invalid hEvent "
++ "handle 0x%x\n", hEvent);
++ }
++ return status;
++}
++
++/*
++ * ======== SYNC_WaitOnEvent ========
++ * Purpose:
++ * Wait for an event to be signalled, up to the specified timeout.
++ * Note: dwTimeOut must be 0xffffffff to signal infinite wait.
++ */
++DSP_STATUS SYNC_WaitOnEvent(struct SYNC_OBJECT *hEvent, u32 dwTimeout)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_OBJECT *pEvent = (struct SYNC_OBJECT *)hEvent;
++ u32 temp;
++
++ GT_2trace(SYNC_debugMask, GT_6CLASS, "SYNC_WaitOnEvent: hEvent 0x%x\n, "
++ "dwTimeOut 0x%x", hEvent, dwTimeout);
++ if (MEM_IsValidHandle(hEvent, SIGNATURE)) {
++ status = SYNC_WaitOnMultipleEvents(&pEvent, 1, dwTimeout,
++ &temp);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_WaitOnEvent: invalid hEvent"
++ "handle 0x%x\n", hEvent);
++ }
++ return status;
++}
++
++/*
++ * ======== SYNC_WaitOnMultipleEvents ========
++ * Purpose:
++ * Wait for any of an array of events to be signalled, up to the
++ * specified timeout.
++ */
++DSP_STATUS SYNC_WaitOnMultipleEvents(struct SYNC_OBJECT **hSyncEvents,
++ u32 uCount, u32 dwTimeout,
++ OUT u32 *puIndex)
++{
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 curr;
++ struct WAIT_OBJECT *Wp;
++
++ DBC_Require(uCount > 0);
++ DBC_Require(hSyncEvents != NULL);
++ DBC_Require(puIndex != NULL);
++
++ for (i = 0; i < uCount; i++)
++ DBC_Require(MEM_IsValidHandle(hSyncEvents[i], SIGNATURE));
++
++ GT_4trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_WaitOnMultipleEvents: hSyncEvents:"
++ "0x%x\tuCount: 0x%x" "\tdwTimeout: 0x%x\tpuIndex: 0x%x\n",
++ hSyncEvents, uCount, dwTimeout, puIndex);
++
++ Wp = MEM_Calloc(sizeof(struct WAIT_OBJECT), MEM_NONPAGED);
++ if (Wp == NULL)
++ return DSP_EMEMORY;
++
++ Wp->state = wo_waiting;
++ Wp->signalling_event = NULL;
++ init_MUTEX_LOCKED(&(Wp->sem));
++
++ for (curr = 0; curr < uCount; curr++) {
++ hSyncEvents[curr]->pWaitObj = Wp;
++ if (hSyncEvents[curr]->state == so_signalled) {
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "Detected signaled Event !!!\n");
++ if (test_and_set(&(Wp->state), wo_signalled) ==
++ wo_waiting) {
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "Setting Signal Event!!!\n");
++ hSyncEvents[curr]->state = so_reset;
++ Wp->signalling_event = hSyncEvents[curr];
++ }
++ curr++; /* Will try optimizing later */
++ break;
++ }
++ }
++
++ curr--; /* Will try optimizing later */
++ if (Wp->state != wo_signalled && dwTimeout > 0) {
++ struct timer_list timeout;
++ if (dwTimeout != SYNC_INFINITE) {
++ init_timer(&timeout);
++ timeout.function = timeout_callback;
++ timeout.data = (unsigned long)Wp;
++ timeout.expires = jiffies + dwTimeout * HZ / 1000;
++ add_timer(&timeout);
++ }
++ if (down_interruptible(&(Wp->sem))) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS, "SYNC: "
++ "WaitOnMultipleEvents Interrupted by signal\n");
++ status = DSP_EFAIL;
++ }
++ if (dwTimeout != SYNC_INFINITE) {
++ if (in_interrupt()) {
++ if (!del_timer(&timeout)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC: Timer expired\n");
++ }
++ } else {
++ if (!del_timer_sync(&timeout)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC: Timer expired\n");
++ }
++ }
++ }
++ }
++ for (i = 0; i <= curr; i++) {
++ if (MEM_IsValidHandle(hSyncEvents[i], SIGNATURE)) {
++ /* Memory corruption here if hSyncEvents[i] is
++ * freed before following statememt. */
++ hSyncEvents[i]->pWaitObj = NULL;
++ }
++ if (hSyncEvents[i] == Wp->signalling_event)
++ *puIndex = i;
++
++ }
++ if (Wp->signalling_event == NULL && DSP_SUCCEEDED(status)) {
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC:Signaling Event NULL!!!(:-\n");
++ status = DSP_ETIMEOUT;
++ }
++ if (Wp)
++ MEM_Free(Wp);
++ return status;
++}
++
++static void timeout_callback(unsigned long hWaitObj)
++{
++ struct WAIT_OBJECT *pWaitObj = (struct WAIT_OBJECT *)hWaitObj;
++ if (test_and_set(&pWaitObj->state, wo_signalled) == wo_waiting)
++ up(&pWaitObj->sem);
++
++}
++
++/*
++ * ======== SYNC_DeleteCS ========
++ */
++DSP_STATUS SYNC_DeleteCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_DeleteCS\n");
++
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ if (down_trylock(&pCSObj->sem) != 0) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "CS in use (locked) while "
++ "deleting! pCSObj=0x%X", pCSObj);
++ DBC_Assert(0);
++ }
++ MEM_FreeObject(hCSObj);
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ if (pDPCCSObj->count != 1) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "DPC CS in use (locked) while "
++ "deleting! pCSObj=0x%X", pCSObj);
++ DBC_Assert(0);
++ }
++ MEM_FreeObject(pDPCCSObj);
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_DeleteCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_EnterCS ========
++ */
++DSP_STATUS SYNC_EnterCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS: hCSObj %p\n",
++ hCSObj);
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ if (in_interrupt()) {
++ status = DSP_EFAIL;
++ GT_0trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_EnterCS called from "
++ "ISR/DPC or with ISR/DPC disabled!");
++ DBC_Assert(0);
++ } else if (down_interruptible(&pCSObj->sem)) {
++ GT_1trace(SYNC_debugMask, GT_7CLASS,
++ "CS interrupted by signal! "
++ "pCSObj=0x%X", pCSObj);
++ status = DSP_EFAIL;
++ }
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_EnterCS DPC\n");
++ spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
++ pDPCCSObj->count--;
++ if (pDPCCSObj->count != 0) {
++ /* FATAL ERROR : Failed to acquire DPC CS */
++ GT_2trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_EnterCS DPCCS %x locked,"
++ "count %d", pDPCCSObj, pDPCCSObj->count);
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ DBC_Assert(0);
++ }
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_EnterCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
++
++/*
++ * ======== SYNC_InitializeCS ========
++ */
++DSP_STATUS SYNC_InitializeCS(OUT struct SYNC_CSOBJECT **phCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = NULL;
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeCS\n");
++
++ /* Allocate memory for sync CS object */
++ MEM_AllocObject(pCSObj, struct SYNC_CSOBJECT, SIGNATURECS);
++ if (pCSObj != NULL) {
++ init_MUTEX(&pCSObj->sem);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_InitializeCS: MEM_AllocObject"
++ "failed\n");
++ }
++ /* return CS object */
++ *phCSObj = pCSObj;
++ DBC_Assert(DSP_FAILED(status) || (pCSObj));
++ return status;
++}
++
++DSP_STATUS SYNC_InitializeDPCCS(OUT struct SYNC_CSOBJECT **phCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_DPCCSOBJECT *pCSObj = NULL;
++
++ DBC_Require(phCSObj);
++
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS\n");
++
++ if (phCSObj) {
++ /* Allocate memory for sync CS object */
++ MEM_AllocObject(pCSObj, struct SYNC_DPCCSOBJECT,
++ SIGNATUREDPCCS);
++ if (pCSObj != NULL) {
++ pCSObj->count = 1;
++ spin_lock_init(&pCSObj->sync_dpccs_lock);
++ } else {
++ status = DSP_EMEMORY;
++ GT_0trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_InitializeDPCCS: "
++ "MEM_AllocObject failed\n");
++ }
++
++ /* return CS object */
++ *phCSObj = (struct SYNC_CSOBJECT *)pCSObj;
++ } else {
++ status = DSP_EPOINTER;
++ }
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_InitializeDPCCS "
++ "pCSObj %p\n", pCSObj);
++ DBC_Assert(DSP_FAILED(status) || (pCSObj));
++
++ return status;
++}
++
++/*
++ * ======== SYNC_LeaveCS ========
++ */
++DSP_STATUS SYNC_LeaveCS(struct SYNC_CSOBJECT *hCSObj)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct SYNC_CSOBJECT *pCSObj = (struct SYNC_CSOBJECT *)hCSObj;
++
++ GT_1trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS: hCSObj %p\n",
++ hCSObj);
++
++ if (MEM_IsValidHandle(hCSObj, SIGNATURECS)) {
++ up(&pCSObj->sem);
++ } else if (MEM_IsValidHandle(hCSObj, SIGNATUREDPCCS)) {
++ struct SYNC_DPCCSOBJECT *pDPCCSObj =
++ (struct SYNC_DPCCSOBJECT *)hCSObj;
++ pDPCCSObj->count++;
++ if (pDPCCSObj->count != 1) {
++ /* FATAL ERROR : Invalid DPC CS count */
++ GT_2trace(SYNC_debugMask, GT_7CLASS,
++ "SYNC_LeaveCS DPCCS %x, "
++ "Invalid count %d", pDPCCSObj,
++ pDPCCSObj->count);
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ DBC_Assert(0);
++ spin_lock_bh(&pDPCCSObj->sync_dpccs_lock);
++ }
++ spin_unlock_bh(&pDPCCSObj->sync_dpccs_lock);
++ GT_0trace(SYNC_debugMask, GT_ENTER, "SYNC_LeaveCS DPC\n");
++ } else {
++ status = DSP_EHANDLE;
++ GT_1trace(SYNC_debugMask, GT_6CLASS,
++ "SYNC_LeaveCS: invalid hCSObj "
++ "handle 0x%x\n", hCSObj);
++ }
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/wmd/_cmm.h b/drivers/dsp/bridge/wmd/_cmm.h
+new file mode 100644
+index 0000000..801b000
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_cmm.h
+@@ -0,0 +1,59 @@
++/*
++ * _cmm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _cmm.h ========
++ * Description:
++ * Private header file defining CMM manager objects and defines needed
++ * by IO manager to register shared memory regions when DSP base image
++ * is loaded(WMD_IO_OnLoaded).
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 24-Aug-2001 ag Created.
++ */
++
++#ifndef _CMM_
++#define _CMM_
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of the section of shared memory used for shared memory manager CMM.
++ * They are defined in the *cfg.cmd file by cdb code.
++ */
++#define SHM0_SHARED_BASE_SYM "_SHM0_BEG"
++#define SHM0_SHARED_END_SYM "_SHM0_END"
++#define SHM0_SHARED_RESERVED_BASE_SYM "_SHM0_RSVDSTRT"
++
++/*
++ * Shared Memory Region #0(SHMSEG0) is used in the following way:
++ *
++ * |(_SHM0_BEG) | (_SHM0_RSVDSTRT) | (_SHM0_END)
++ * V V V
++ * ------------------------------------------------------------
++ * | DSP-side allocations | GPP-side allocations |
++ * ------------------------------------------------------------
++ *
++ *
++ */
++
++#endif /* _CMM_ */
+diff --git a/drivers/dsp/bridge/wmd/_deh.h b/drivers/dsp/bridge/wmd/_deh.h
+new file mode 100644
+index 0000000..df281ad
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_deh.h
+@@ -0,0 +1,46 @@
++/*
++ * _deh.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _deh.h ========
++ * Description:
++ * Private header for DEH module.
++ *
++ *! Revision History:
++ *! ================
++ *! 21-Sep-2001 kc: created.
++ */
++
++#ifndef _DEH_
++#define _DEH_
++
++#include <dspbridge/dpc.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/wmd.h>
++
++#define SIGNATURE 0x5f484544 /* "DEH_" backwards */
++
++/* DEH Manager: only one created per board: */
++struct DEH_MGR {
++ u32 dwSignature; /* Used for object validation. */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context. */
++ struct NTFY_OBJECT *hNtfy; /* NTFY object */
++ struct DPC_OBJECT *hMmuFaultDpc; /* DPC object handle. */
++ struct DSP_ERRORINFO errInfo; /* DSP exception info. */
++} ;
++
++#endif /* _DEH_ */
+diff --git a/drivers/dsp/bridge/wmd/_msg_sm.h b/drivers/dsp/bridge/wmd/_msg_sm.h
+new file mode 100644
+index 0000000..fa5e9ee
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_msg_sm.h
+@@ -0,0 +1,158 @@
++/*
++ * _msg_sm.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _msg_sm.h ========
++ * Description:
++ * Private header file defining MSG manager objects and defines needed
++ * by IO manager.
++ *
++ * Public Functions:
++ * None.
++ *
++ * Notes:
++ *
++ *! Revision History:
++ *! ================
++ *! 09-May-2001 jeh Code Review cleanup.
++ *! 08-Nov-2000 jeh Created.
++ */
++
++#ifndef _MSG_SM_
++#define _MSG_SM_
++
++#include <dspbridge/list.h>
++#include <dspbridge/msgdefs.h>
++
++/*
++ * These target side symbols define the beginning and ending addresses
++ * of the section of shared memory used for messages. They are
++ * defined in the *cfg.cmd file by cdb code.
++ */
++#define MSG_SHARED_BUFFER_BASE_SYM "_MSG_BEG"
++#define MSG_SHARED_BUFFER_LIMIT_SYM "_MSG_END"
++
++#ifndef _CHNL_WORDSIZE
++#define _CHNL_WORDSIZE 4 /* default _CHNL_WORDSIZE is 2 bytes/word */
++#endif
++
++/*
++ * ======== MSG ========
++ * There is a control structure for messages to the DSP, and a control
++ * structure for messages from the DSP. The shared memory region for
++ * transferring messages is partitioned as follows:
++ *
++ * ----------------------------------------------------------
++ * |Control | Messages from DSP | Control | Messages to DSP |
++ * ----------------------------------------------------------
++ *
++ * MSG control structure for messages to the DSP is used in the following
++ * way:
++ *
++ * bufEmpty - This flag is set to FALSE by the GPP after it has output
++ * messages for the DSP. The DSP host driver sets it to
++ * TRUE after it has copied the messages.
++ * postSWI - Set to 1 by the GPP after it has written the messages,
++ * set the size, and set bufEmpty to FALSE.
++ * The DSP Host driver uses SWI_andn of the postSWI field
++ * when a host interrupt occurs. The host driver clears
++ * this after posting the SWI.
++ * size - Number of messages to be read by the DSP.
++ *
++ * For messages from the DSP:
++ * bufEmpty - This flag is set to FALSE by the DSP after it has output
++ * messages for the GPP. The DPC on the GPP sets it to
++ * TRUE after it has copied the messages.
++ * postSWI - Set to 1 the DPC on the GPP after copying the messages.
++ * size - Number of messages to be read by the GPP.
++ */
++struct MSG {
++ u32 bufEmpty; /* to/from DSP buffer is empty */
++ u32 postSWI; /* Set to "1" to post MSG SWI */
++ u32 size; /* Number of messages to/from the DSP */
++ u32 resvd;
++} ;
++
++/*
++ * ======== MSG_MGR ========
++ * The MSG_MGR maintains a list of all MSG_QUEUEs. Each NODE object can
++ * have MSG_QUEUE to hold all messages that come up from the corresponding
++ * node on the DSP. The MSG_MGR also has a shared queue of messages
++ * ready to go to the DSP.
++ */
++struct MSG_MGR {
++ /* The first two fields must match those in msgobj.h */
++ u32 dwSignature;
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD. */
++
++ struct IO_MGR *hIOMgr; /* IO manager */
++ struct LST_LIST *queueList; /* List of MSG_QUEUEs */
++ struct SYNC_CSOBJECT *hSyncCS; /* For critical sections */
++ /* Signalled when MsgFrame is available */
++ struct SYNC_OBJECT *hSyncEvent;
++ struct LST_LIST *msgFreeList; /* Free MsgFrames ready to be filled */
++ struct LST_LIST *msgUsedList; /* MsgFrames ready to go to DSP */
++ u32 uMsgsPending; /* # of queued messages to go to DSP */
++ u32 uMaxMsgs; /* Max # of msgs that fit in buffer */
++ MSG_ONEXIT onExit; /* called when RMS_EXIT is received */
++} ;
++
++/*
++ * ======== MSG_QUEUE ========
++ * Each NODE has a MSG_QUEUE for receiving messages from the
++ * corresponding node on the DSP. The MSG_QUEUE object maintains a list
++ * of messages that have been sent to the host, but not yet read (MSG_Get),
++ * and a list of free frames that can be filled when new messages arrive
++ * from the DSP.
++ * The MSG_QUEUE's hSynEvent gets posted when a message is ready.
++ */
++struct MSG_QUEUE {
++ struct LST_ELEM listElem;
++ u32 dwSignature;
++ struct MSG_MGR *hMsgMgr;
++ u32 uMaxMsgs; /* Node message depth */
++ u32 dwId; /* Node environment pointer */
++ struct LST_LIST *msgFreeList; /* Free MsgFrames ready to be filled */
++ /* Filled MsgFramess waiting to be read */
++ struct LST_LIST *msgUsedList;
++ HANDLE hArg; /* Handle passed to mgr onExit callback */
++ struct SYNC_OBJECT *hSyncEvent; /* Signalled when message is ready */
++ struct SYNC_OBJECT *hSyncDone; /* For synchronizing cleanup */
++ struct SYNC_OBJECT *hSyncDoneAck; /* For synchronizing cleanup */
++ struct NTFY_OBJECT *hNtfy; /* For notification of message ready */
++ bool fDone; /* TRUE <==> deleting the object */
++ u32 refCount; /* Number of pending MSG_get/put calls */
++};
++
++/*
++ * ======== MSG_DSPMSG ========
++ */
++struct MSG_DSPMSG {
++ struct DSP_MSG msg;
++ u32 dwId; /* Identifies the node the message goes to */
++} ;
++
++/*
++ * ======== MSG_FRAME ========
++ */
++struct MSG_FRAME {
++ struct LST_ELEM listElem;
++ struct MSG_DSPMSG msgData;
++} ;
++
++#endif /* _MSG_SM_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap.h b/drivers/dsp/bridge/wmd/_tiomap.h
+new file mode 100644
+index 0000000..815f695
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap.h
+@@ -0,0 +1,384 @@
++/*
++ * _tiomap.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== _tiomap.h ========
++ * Description:
++ * Definitions and types private to this WMD.
++ *
++ */
++
++#ifndef _TIOMAP_
++#define _TIOMAP_
++
++#include <dspbridge/devdefs.h>
++#include <hw_defs.h>
++#include <hw_mbox.h>
++#include <dspbridge/wmdioctl.h> /* for WMDIOCTL_EXTPROC defn */
++#include <dspbridge/sync.h>
++#include <dspbridge/clk.h>
++
++struct MAP_L4PERIPHERAL {
++ u32 physAddr;
++ u32 dspVirtAddr;
++} ;
++
++#define ARM_MAILBOX_START 0xfffcf000
++#define ARM_MAILBOX_LENGTH 0x800
++
++/* New Registers in OMAP3.1 */
++
++#define TESTBLOCK_ID_START 0xfffed400
++#define TESTBLOCK_ID_LENGTH 0xff
++
++/* ID Returned by OMAP1510 */
++#define TBC_ID_VALUE 0xB47002F
++
++#define SPACE_LENGTH 0x2000
++#define API_CLKM_DPLL_DMA 0xfffec000
++#define ARM_INTERRUPT_OFFSET 0xb00
++
++#define BIOS_24XX
++
++#define L4_PERIPHERAL_NULL 0x0
++#define DSPVA_PERIPHERAL_NULL 0x0
++
++#define MAX_LOCK_TLB_ENTRIES 15
++
++#define L4_PERIPHERAL_PRM 0x48306000 /*PRM L4 Peripheral */
++#define DSPVA_PERIPHERAL_PRM 0x1181e000
++#define L4_PERIPHERAL_SCM 0x48002000 /*SCM L4 Peripheral */
++#define DSPVA_PERIPHERAL_SCM 0x1181f000
++#define L4_PERIPHERAL_MMU 0x5D000000 /*MMU L4 Peripheral */
++#define DSPVA_PERIPHERAL_MMU 0x11820000
++#define L4_PERIPHERAL_CM 0x48004000 /* Core L4, Clock Management */
++#define DSPVA_PERIPHERAL_CM 0x1181c000
++#define L4_PERIPHERAL_PER 0x48005000 /* PER */
++#define DSPVA_PERIPHERAL_PER 0x1181d000
++
++#define L4_PERIPHERAL_GPIO1 0x48310000
++#define DSPVA_PERIPHERAL_GPIO1 0x11809000
++#define L4_PERIPHERAL_GPIO2 0x49050000
++#define DSPVA_PERIPHERAL_GPIO2 0x1180a000
++#define L4_PERIPHERAL_GPIO3 0x49052000
++#define DSPVA_PERIPHERAL_GPIO3 0x1180b000
++#define L4_PERIPHERAL_GPIO4 0x49054000
++#define DSPVA_PERIPHERAL_GPIO4 0x1180c000
++#define L4_PERIPHERAL_GPIO5 0x49056000
++#define DSPVA_PERIPHERAL_GPIO5 0x1180d000
++
++#define L4_PERIPHERAL_IVA2WDT 0x49030000
++#define DSPVA_PERIPHERAL_IVA2WDT 0x1180e000
++
++#define L4_PERIPHERAL_DISPLAY 0x48050000
++#define DSPVA_PERIPHERAL_DISPLAY 0x1180f000
++
++#define L4_PERIPHERAL_SSI 0x48058000
++#define DSPVA_PERIPHERAL_SSI 0x11804000
++#define L4_PERIPHERAL_GDD 0x48059000
++#define DSPVA_PERIPHERAL_GDD 0x11805000
++#define L4_PERIPHERAL_SS1 0x4805a000
++#define DSPVA_PERIPHERAL_SS1 0x11806000
++#define L4_PERIPHERAL_SS2 0x4805b000
++#define DSPVA_PERIPHERAL_SS2 0x11807000
++
++#define L4_PERIPHERAL_CAMERA 0x480BC000
++#define DSPVA_PERIPHERAL_CAMERA 0x11819000
++
++#define L4_PERIPHERAL_SDMA 0x48056000
++#define DSPVA_PERIPHERAL_SDMA 0x11810000 /*0x1181d000 conflicts with PER */
++
++#define L4_PERIPHERAL_UART1 0x4806a000
++#define DSPVA_PERIPHERAL_UART1 0x11811000
++#define L4_PERIPHERAL_UART2 0x4806c000
++#define DSPVA_PERIPHERAL_UART2 0x11812000
++#define L4_PERIPHERAL_UART3 0x49020000
++#define DSPVA_PERIPHERAL_UART3 0x11813000
++
++#define L4_PERIPHERAL_MCBSP1 0x48074000
++#define DSPVA_PERIPHERAL_MCBSP1 0x11814000
++#define L4_PERIPHERAL_MCBSP2 0x49022000
++#define DSPVA_PERIPHERAL_MCBSP2 0x11815000
++#define L4_PERIPHERAL_MCBSP3 0x49024000
++#define DSPVA_PERIPHERAL_MCBSP3 0x11816000
++#define L4_PERIPHERAL_MCBSP4 0x49026000
++#define DSPVA_PERIPHERAL_MCBSP4 0x11817000
++#define L4_PERIPHERAL_MCBSP5 0x48096000
++#define DSPVA_PERIPHERAL_MCBSP5 0x11818000
++
++#define L4_PERIPHERAL_GPTIMER5 0x49038000
++#define DSPVA_PERIPHERAL_GPTIMER5 0x11800000
++#define L4_PERIPHERAL_GPTIMER6 0x4903a000
++#define DSPVA_PERIPHERAL_GPTIMER6 0x11801000
++#define L4_PERIPHERAL_GPTIMER7 0x4903c000
++#define DSPVA_PERIPHERAL_GPTIMER7 0x11802000
++#define L4_PERIPHERAL_GPTIMER8 0x4903e000
++#define DSPVA_PERIPHERAL_GPTIMER8 0x11803000
++
++#define L4_PERIPHERAL_SPI1 0x48098000
++#define DSPVA_PERIPHERAL_SPI1 0x1181a000
++#define L4_PERIPHERAL_SPI2 0x4809a000
++#define DSPVA_PERIPHERAL_SPI2 0x1181b000
++
++#define L4_PERIPHERAL_MBOX 0x48094000
++#define DSPVA_PERIPHERAL_MBOX 0x11808000
++
++#define PM_GRPSEL_BASE 0x48307000
++#define DSPVA_GRPSEL_BASE 0x11821000
++
++#define L4_PERIPHERAL_SIDETONE_MCBSP2 0x49028000
++#define DSPVA_PERIPHERAL_SIDETONE_MCBSP2 0x11824000
++#define L4_PERIPHERAL_SIDETONE_MCBSP3 0x4902a000
++#define DSPVA_PERIPHERAL_SIDETONE_MCBSP3 0x11825000
++
++/* define a static array with L4 mappings */
++static const struct MAP_L4PERIPHERAL L4PeripheralTable[] = {
++ {L4_PERIPHERAL_MBOX, DSPVA_PERIPHERAL_MBOX},
++ {L4_PERIPHERAL_SCM, DSPVA_PERIPHERAL_SCM},
++ {L4_PERIPHERAL_MMU, DSPVA_PERIPHERAL_MMU},
++ {L4_PERIPHERAL_GPTIMER5, DSPVA_PERIPHERAL_GPTIMER5},
++ {L4_PERIPHERAL_GPTIMER6, DSPVA_PERIPHERAL_GPTIMER6},
++ {L4_PERIPHERAL_GPTIMER7, DSPVA_PERIPHERAL_GPTIMER7},
++ {L4_PERIPHERAL_GPTIMER8, DSPVA_PERIPHERAL_GPTIMER8},
++ {L4_PERIPHERAL_GPIO1, DSPVA_PERIPHERAL_GPIO1},
++ {L4_PERIPHERAL_GPIO2, DSPVA_PERIPHERAL_GPIO2},
++ {L4_PERIPHERAL_GPIO3, DSPVA_PERIPHERAL_GPIO3},
++ {L4_PERIPHERAL_GPIO4, DSPVA_PERIPHERAL_GPIO4},
++ {L4_PERIPHERAL_GPIO5, DSPVA_PERIPHERAL_GPIO5},
++ {L4_PERIPHERAL_IVA2WDT, DSPVA_PERIPHERAL_IVA2WDT},
++ {L4_PERIPHERAL_DISPLAY, DSPVA_PERIPHERAL_DISPLAY},
++ {L4_PERIPHERAL_SSI, DSPVA_PERIPHERAL_SSI},
++ {L4_PERIPHERAL_GDD, DSPVA_PERIPHERAL_GDD},
++ {L4_PERIPHERAL_SS1, DSPVA_PERIPHERAL_SS1},
++ {L4_PERIPHERAL_SS2, DSPVA_PERIPHERAL_SS2},
++ {L4_PERIPHERAL_UART1, DSPVA_PERIPHERAL_UART1},
++ {L4_PERIPHERAL_UART2, DSPVA_PERIPHERAL_UART2},
++ {L4_PERIPHERAL_UART3, DSPVA_PERIPHERAL_UART3},
++ {L4_PERIPHERAL_MCBSP1, DSPVA_PERIPHERAL_MCBSP1},
++ {L4_PERIPHERAL_MCBSP2, DSPVA_PERIPHERAL_MCBSP2},
++ {L4_PERIPHERAL_MCBSP3, DSPVA_PERIPHERAL_MCBSP3},
++ {L4_PERIPHERAL_MCBSP4, DSPVA_PERIPHERAL_MCBSP4},
++ {L4_PERIPHERAL_MCBSP5, DSPVA_PERIPHERAL_MCBSP5},
++ {L4_PERIPHERAL_CAMERA, DSPVA_PERIPHERAL_CAMERA},
++ {L4_PERIPHERAL_SPI1, DSPVA_PERIPHERAL_SPI1},
++ {L4_PERIPHERAL_SPI2, DSPVA_PERIPHERAL_SPI2},
++ {L4_PERIPHERAL_PRM, DSPVA_PERIPHERAL_PRM},
++ {L4_PERIPHERAL_CM, DSPVA_PERIPHERAL_CM},
++ {L4_PERIPHERAL_PER, DSPVA_PERIPHERAL_PER},
++ {PM_GRPSEL_BASE, DSPVA_GRPSEL_BASE},
++ {L4_PERIPHERAL_SIDETONE_MCBSP2, DSPVA_PERIPHERAL_SIDETONE_MCBSP2},
++ {L4_PERIPHERAL_SIDETONE_MCBSP3, DSPVA_PERIPHERAL_SIDETONE_MCBSP3},
++ {L4_PERIPHERAL_NULL, DSPVA_PERIPHERAL_NULL}
++};
++
++/*
++ * 15 10 0
++ * ---------------------------------
++ * |0|0|1|0|0|0|c|c|c|i|i|i|i|i|i|i|
++ * ---------------------------------
++ * | (class) | (module specific) |
++ *
++ * where c -> Externel Clock Command: Clk & Autoidle Disable/Enable
++ * i -> External Clock ID Timers 5,6,7,8, McBSP1,2 and WDT3
++ */
++
++/* MBX_PM_CLK_IDMASK: DSP External clock id mask. */
++#define MBX_PM_CLK_IDMASK 0x7F
++
++/* MBX_PM_CLK_CMDSHIFT: DSP External clock command shift. */
++#define MBX_PM_CLK_CMDSHIFT 7
++
++/* MBX_PM_CLK_CMDMASK: DSP External clock command mask. */
++#define MBX_PM_CLK_CMDMASK 7
++
++/* MBX_PM_MAX_RESOURCES: CORE 1 Clock resources. */
++#define MBX_CORE1_RESOURCES 7
++
++/* MBX_PM_MAX_RESOURCES: CORE 2 Clock Resources. */
++#define MBX_CORE2_RESOURCES 1
++
++/* MBX_PM_MAX_RESOURCES: TOTAL Clock Reosurces. */
++#define MBX_PM_MAX_RESOURCES 11
++
++/* Power Management Commands */
++enum BPWR_ExtClockCmd {
++ BPWR_DisableClock = 0,
++ BPWR_EnableClock,
++ BPWR_DisableAutoIdle,
++ BPWR_EnableAutoIdle
++} ;
++
++/* OMAP242x specific resources */
++enum BPWR_ExtClockId {
++ BPWR_GPTimer5 = 0x10,
++ BPWR_GPTimer6,
++ BPWR_GPTimer7,
++ BPWR_GPTimer8,
++ BPWR_WDTimer3,
++ BPWR_MCBSP1,
++ BPWR_MCBSP2,
++ BPWR_MCBSP3,
++ BPWR_MCBSP4,
++ BPWR_MCBSP5,
++ BPWR_SSI = 0x20
++} ;
++
++static const u32 BPWR_CLKID[] = {
++ (u32) BPWR_GPTimer5,
++ (u32) BPWR_GPTimer6,
++ (u32) BPWR_GPTimer7,
++ (u32) BPWR_GPTimer8,
++ (u32) BPWR_WDTimer3,
++ (u32) BPWR_MCBSP1,
++ (u32) BPWR_MCBSP2,
++ (u32) BPWR_MCBSP3,
++ (u32) BPWR_MCBSP4,
++ (u32) BPWR_MCBSP5,
++ (u32) BPWR_SSI
++};
++
++struct BPWR_Clk_t {
++ u32 clkId;
++ enum SERVICES_ClkId funClk;
++ enum SERVICES_ClkId intClk;
++} ;
++
++static const struct BPWR_Clk_t BPWR_Clks[] = {
++ {(u32) BPWR_GPTimer5, SERVICESCLK_gpt5_fck, SERVICESCLK_gpt5_ick},
++ {(u32) BPWR_GPTimer6, SERVICESCLK_gpt6_fck, SERVICESCLK_gpt6_ick},
++ {(u32) BPWR_GPTimer7, SERVICESCLK_gpt7_fck, SERVICESCLK_gpt7_ick},
++ {(u32) BPWR_GPTimer8, SERVICESCLK_gpt8_fck, SERVICESCLK_gpt8_ick},
++ {(u32) BPWR_WDTimer3, SERVICESCLK_wdt3_fck, SERVICESCLK_wdt3_ick},
++ {(u32) BPWR_MCBSP1, SERVICESCLK_mcbsp1_fck, SERVICESCLK_mcbsp1_ick},
++ {(u32) BPWR_MCBSP2, SERVICESCLK_mcbsp2_fck, SERVICESCLK_mcbsp2_ick},
++ {(u32) BPWR_MCBSP3, SERVICESCLK_mcbsp3_fck, SERVICESCLK_mcbsp3_ick},
++ {(u32) BPWR_MCBSP4, SERVICESCLK_mcbsp4_fck, SERVICESCLK_mcbsp4_ick},
++ {(u32) BPWR_MCBSP5, SERVICESCLK_mcbsp5_fck, SERVICESCLK_mcbsp5_ick},
++ {(u32) BPWR_SSI, SERVICESCLK_ssi_fck, SERVICESCLK_ssi_ick}
++};
++
++/* Interrupt Register Offsets */
++#define INTH_IT_REG_OFFSET 0x00 /* Interrupt register offset */
++#define INTH_MASK_IT_REG_OFFSET 0x04 /* Mask Interrupt reg offset */
++
++#define DSP_MAILBOX1_INT 10
++
++/*
++ * INTH_InterruptKind_t
++ * Identify the kind of interrupt: either FIQ/IRQ
++ */
++enum INTH_InterruptKind_t {
++ INTH_IRQ = 0,
++ INTH_FIQ = 1
++} ;
++
++enum INTH_SensitiveEdge_t {
++ FALLING_EDGE_SENSITIVE = 0,
++ LOW_LEVEL_SENSITIVE = 1
++} ;
++
++/*
++ * Bit definition of Interrupt Level Registers
++ */
++
++/* Mail Box defines */
++#define MB_ARM2DSP1_REG_OFFSET 0x00
++
++#define MB_ARM2DSP1B_REG_OFFSET 0x04
++
++#define MB_DSP2ARM1B_REG_OFFSET 0x0C
++
++#define MB_ARM2DSP1_FLAG_REG_OFFSET 0x18
++
++#define MB_ARM2DSP_FLAG 0x0001
++
++#define MBOX_ARM2DSP HW_MBOX_ID_0
++#define MBOX_DSP2ARM HW_MBOX_ID_1
++#define MBOX_ARM HW_MBOX_U0_ARM
++#define MBOX_DSP HW_MBOX_U1_DSP1
++
++#define ENABLE true
++#define DISABLE false
++
++#define HIGH_LEVEL true
++#define LOW_LEVEL false
++
++/* Macro's */
++#define REG16(A) (*(REG_UWORD16 *)(A))
++
++#define ClearBit(reg, mask) (reg &= ~mask)
++#define SetBit(reg, mask) (reg |= mask)
++
++#define SetGroupBits16(reg, position, width, value) \
++ do {\
++ reg &= ~((0xFFFF >> (16 - (width))) << (position)) ; \
++ reg |= ((value & (0xFFFF >> (16 - (width)))) << (position)); \
++ } while (0);
++
++#define ClearBitIndex(reg, index) (reg &= ~(1 << (index)))
++
++/* This mini driver's device context: */
++struct WMD_DEV_CONTEXT {
++ struct DEV_OBJECT *hDevObject; /* Handle to WCD device object. */
++ u32 dwDspBaseAddr; /* Arm's API to DSP virtual base addr */
++ /*
++ * DSP External memory prog address as seen virtually by the OS on
++ * the host side.
++ */
++ u32 dwDspExtBaseAddr; /* See the comment above */
++ u32 dwAPIRegBase; /* API memory mapped registers */
++ u32 dwDSPMmuBase; /* DSP MMU Mapped registers */
++ u32 dwMailBoxBase; /* Mail box mapped registers */
++ u32 dwAPIClkBase; /* CLK Registers */
++ u32 dwDSPClkM2Base; /* DSP Clock Module m2 */
++ u32 dwPublicRhea; /* Pub Rhea */
++ u32 dwIntAddr; /* MB INTR reg */
++ u32 dwTCEndianism; /* TC Endianism register */
++ u32 dwTestBase; /* DSP MMU Mapped registers */
++ u32 dwSelfLoop; /* Pointer to the selfloop */
++ u32 dwDSPStartAdd; /* API Boot vector */
++ u32 dwInternalSize; /* Internal memory size */
++
++ /*
++ * Processor specific info is set when prog loaded and read from DCD.
++ * [See WMD_BRD_Ctrl()] PROC info contains DSP-MMU TLB entries.
++ */
++ /* DMMU TLB entries */
++ struct WMDIOCTL_EXTPROC aTLBEntry[WMDIOCTL_NUMOFMMUTLB];
++ u32 dwBrdState; /* Last known board state. */
++ u32 ulIntMask; /* int mask */
++ u16 ioBase; /* Board I/O base */
++ u32 numTLBEntries; /* DSP MMU TLB entry counter */
++ u32 fixedTLBEntries; /* Fixed DSPMMU TLB entry count */
++
++ /* TC Settings */
++ bool tcWordSwapOn; /* Traffic Controller Word Swap */
++ struct PgTableAttrs *pPtAttrs;
++ u32 uDspPerClks;
++} ;
++
++ /*
++ * ======== WMD_TLB_DspVAToMpuPA ========
++ * Given a DSP virtual address, traverse the page table and return
++ * a corresponding MPU physical address and size.
++ */
++extern DSP_STATUS WMD_TLB_DspVAToMpuPA(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u32 ulVirtAddr,
++ OUT u32 *ulPhysAddr,
++ OUT u32 *sizeTlb);
++
++#endif /* _TIOMAP_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_mmu.h b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
+new file mode 100644
+index 0000000..6b21047
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_mmu.h
+@@ -0,0 +1,53 @@
++/*
++ * _tiomap_mmu.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_mmu.h ========
++ * Description:
++ * Definitions and types for the DSP MMU modules
++ *
++ *! Revision History
++ *! ================
++ *! 19-Apr-2004 sb: Renamed HW types. Removed dspMmuTlbEntry
++ *! 05-Jan-2004 vp: Moved the file to a platform specific folder from common.
++ *! 21-Mar-2003 sb: Added macro definition TIHEL_LARGEPAGESIZE
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_MMU_
++#define _TIOMAP_MMU_
++
++#include "_tiomap.h"
++
++/*
++ * ======== configureDspMmu ========
++ *
++ * Make DSP MMu page table entries.
++ * Note: Not utilizing Coarse / Fine page tables.
++ * SECTION = 1MB, LARGE_PAGE = 64KB, SMALL_PAGE = 4KB, TINY_PAGE = 1KB.
++ * DSP Byte address 0x40_0000 is word addr 0x20_0000.
++ */
++extern void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 dataBasePhys,
++ u32 dspBaseVirt,
++ u32 sizeInBytes,
++ s32 nEntryStart,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elemSize,
++ enum HW_MMUMixedSize_t mixedSize);
++
++#endif /* _TIOMAP_MMU_ */
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_pwr.h b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
+new file mode 100644
+index 0000000..7ebd7b5
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_pwr.h
+@@ -0,0 +1,102 @@
++/*
++ * _tiomap_pwr.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_pwr.h ========
++ * Description:
++ * Definitions and types for the DSP wake/sleep routines.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_PWR_
++#define _TIOMAP_PWR_
++
++/*
++ * ======== WakeDSP =========
++ * Wakes up the DSP from DeepSleep
++ */
++extern DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++
++/*
++ * ======== SleepDSP =========
++ * Places the DSP in DeepSleep.
++ */
++extern DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u32 dwCmd, IN void *pArgs);
++/*
++ * ========InterruptDSP========
++ * Sends an interrupt to DSP unconditionally.
++ */
++extern void InterruptDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u16 wMbVal);
++
++/*
++ * ======== WakeDSP =========
++ * Wakes up the DSP from DeepSleep
++ */
++extern DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++/*
++ * ======== handle_hibernation_fromDSP ========
++ * Handle Hibernation requested from DSP
++ */
++DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext);
++/*
++ * ======== PostScale_DSP ========
++ * Handle Post Scale notification to DSP
++ */
++DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++/*
++ * ======== PreScale_DSP ========
++ * Handle Pre Scale notification to DSP
++ */
++DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs);
++/*
++ * ======== handle_constraints_set ========
++ * Handle constraints request from DSP
++ */
++DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++/*
++ * ======== DSP_PeripheralClocks_Disable ========
++ * This function disables all the peripheral clocks that
++ * were enabled by DSP. Call this function only when
++ * DSP is entering Hibernation or when DSP is in
++ * Error state
++ */
++DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++
++/*
++ * ======== DSP_PeripheralClocks_Enable ========
++ * This function enables all the peripheral clocks that
++ * were requested by DSP.
++ */
++DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs);
++
++/*
++ * ======== DSPClkWakeupEventCtrl ========
++ * This function sets the group selction bits for while
++ * enabling/disabling.
++ */
++void DSPClkWakeupEventCtrl(u32 ClkId, bool enable);
++
++#endif /* _TIOMAP_PWR_ */
++
+diff --git a/drivers/dsp/bridge/wmd/_tiomap_util.h b/drivers/dsp/bridge/wmd/_tiomap_util.h
+new file mode 100644
+index 0000000..47e1e5d
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/_tiomap_util.h
+@@ -0,0 +1,46 @@
++/*
++ * _tiomap_util.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_util.h ========
++ * Description:
++ * Definitions and types for the utility routines.
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_UTIL_
++#define _TIOMAP_UTIL_
++
++/* Time out Values in uSeconds*/
++#define TIHELEN_ACKTIMEOUT 10000
++
++/* Time delay for HOM->SAM transition. */
++#define WAIT_SAM 1000000 /* in usec (1000 millisec) */
++
++/*
++ * ======== WaitForStart ========
++ * Wait for the singal from DSP that it has started, or time out.
++ * The argument dwSyncAddr is set to 1 before releasing the DSP.
++ * If the DSP starts running, it will clear this location.
++ */
++extern bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr);
++
++#endif /* _TIOMAP_UTIL_ */
++
+diff --git a/drivers/dsp/bridge/wmd/chnl_sm.c b/drivers/dsp/bridge/wmd/chnl_sm.c
+new file mode 100644
+index 0000000..e8ffb2f
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/chnl_sm.c
+@@ -0,0 +1,1100 @@
++/*
++ * chnl_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== chnl_sm.c ========
++ * Description:
++ * Implements upper edge functions for WMD channel module.
++ *
++ * Public Functions:
++ * WMD_CHNL_AddIOReq
++ * WMD_CHNL_CancelIO
++ * WMD_CHNL_Close
++ * WMD_CHNL_Create
++ * WMD_CHNL_Destroy
++ * WMD_CHNL_FlushIO
++ * WMD_CHNL_GetInfo
++ * WMD_CHNL_GetIOC
++ * WMD_CHNL_GetMgrInfo
++ * WMD_CHNL_Idle
++ * WMD_CHNL_Open
++ *
++ * Notes:
++ * The lower edge functions must be implemented by the WMD writer, and
++ * are declared in chnl_sm.h.
++ *
++ * Care is taken in this code to prevent simulataneous access to channel
++ * queues from
++ * 1. Threads.
++ * 2. IO_DPC(), scheduled from the IO_ISR() as an event.
++ *
++ * This is done primarily by:
++ * - Semaphores.
++ * - state flags in the channel object; and
++ * - ensuring the IO_Dispatch() routine, which is called from both
++ * CHNL_AddIOReq() and the DPC(if implemented), is not re-entered.
++ *
++ * Channel Invariant:
++ * There is an important invariant condition which must be maintained per
++ * channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
++ * which may cause timeouts and/or failure offunction SYNC_WaitOnEvent.
++ * This invariant condition is:
++ *
++ * LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is reset
++ * and
++ * !LST_Empty(pChnl->pIOCompletions) ==> pChnl->hSyncEvent is set.
++ *
++ *! Revision History:
++ *! ================
++ *! 10-Feb-2004 sb: Consolidated the MAILBOX_IRQ macro at the top of the file.
++ *! 05-Jan-2004 vp: Updated for 2.6 kernel on 24xx platform.
++ *! 23-Apr-2003 sb: Fixed mailbox deadlock
++ *! 24-Feb-2003 vp: Code Review Updates.
++ *! 18-Oct-2002 vp: Ported to Linux platform
++ *! 29-Aug-2002 rr Changed the SYNC error code return to DSP error code return
++ * in WMD_CHNL_GetIOC.
++ *! 22-Jan-2002 ag Zero-copy support added.
++ *! CMM_CallocBuf() used for SM allocations.
++ *! 04-Feb-2001 ag DSP-DMA support added.
++ *! 22-Nov-2000 kc: Updated usage of PERF_RegisterStat.
++ *! 06-Nov-2000 jeh Move ISR_Install, DPC_Create from CHNL_Create to IO_Create.
++ *! 13-Oct-2000 jeh Added dwArg parameter to WMD_CHNL_AddIOReq(), added
++ *! WMD_CHNL_Idle and WMD_CHNL_RegisterNotify for DSPStream.
++ *! Remove #ifdef DEBUG from around channel cIOCs field.
++ *! 21-Sep-2000 rr: PreOMAP chnl class library acts like a IO class library.
++ *! 25-Sep-2000 ag: MEM_[Unmap]LinearAddress added for #ifdef CHNL_PREOMAP.
++ *! 07-Sep-2000 rr: Added new channel class for PreOMAP.
++ *! 11-Jul-2000 jeh Allow NULL user event in WMD_CHNL_Open().
++ *! 06-Jul-2000 rr: Changed prefix PROC to PRCS for process module calls.
++ *! 20-Jan-2000 ag: Incorporated code review comments.
++ *! 05-Jan-2000 ag: Text format cleanup.
++ *! 07-Dec-1999 ag: Now setting ChnlMgr fSharedIRQ flag before ISR_Install().
++ *! 01-Dec-1999 ag: WMD_CHNL_Open() now accepts named sync event.
++ *! 14-Nov-1999 ag: DPC_Schedule() uncommented.
++ *! 28-Oct-1999 ag: CHNL Attrs userEvent not supported.
++ *! SM addrs taken from COFF(IO) or host resource(SM).
++ *! 25-May-1999 jg: CHNL_IOCLASS boards now get their shared memory buffer
++ *! address and length from symbols defined in the currently
++ *! loaded COFF file. See _chn_sm.h.
++ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
++ *! 22-Jan-1998 gp: Update User's pIOC struct in GetIOC at lower IRQL (NT).
++ *! 16-Jan-1998 gp: Commented out PERF stuff, since it is not all there in NT.
++ *! 13-Jan-1998 gp: Protect IOCTLs from IO_DPC by raising IRQL to DIRQL (NT).
++ *! 22-Oct-1997 gp: Call SYNC_OpenEvent in CHNL_Open, for NT support.
++ *! 18-Jun-1997 gp: Moved waiting back to ring 0 to improve performance.
++ *! 16-Jun-1997 gp: Added call into lower edge CHNL function to allow override
++ *! of the SHM window length reported by Windows CM.
++ *! 05-Jun-1997 gp: Removed unnecessary critical sections.
++ *! 18-Mar-1997 gp: Ensured CHNL_FlushIO on input leaves channel in READY state.
++ *! 06-Jan-1997 gp: ifdefed to support the IO variant of SHM channel class lib.
++ *! 21-Jan-1997 gp: CHNL_Close: set pChnl = NULL for DBC_Ensure().
++ *! 14-Jan-1997 gp: Updated based on code review feedback.
++ *! 03-Jan-1997 gp: Added CHNL_E_WAITTIMEOUT error return code to CHNL_FlushIO()
++ *! 23-Oct-1996 gp: Tag channel with ring 0 process handle.
++ *! 13-Sep-1996 gp: Added performance statistics for channel.
++ *! 09-Sep-1996 gp: Added WMD_CHNL_GetMgrInfo().
++ *! 04-Sep-1996 gp: Removed shared memory control struct offset: made zero.
++ *! 01-Aug-1996 gp: Implemented basic channel manager and channel create/delete.
++ *! 17-Jul-1996 gp: Started pseudo coding.
++ *! 11-Jul-1996 gp: Stubbed out.
++ */
++
++/* ----------------------------------- OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Mini-Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdchnl.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- Define for This */
++#define USERMODE_ADDR PAGE_OFFSET
++
++#define MAILBOX_IRQ INT_MAIL_MPU_IRQ
++
++/* ----------------------------------- Function Prototypes */
++static struct LST_LIST *CreateChirpList(u32 uChirps);
++
++static void FreeChirpList(struct LST_LIST *pList);
++
++static struct CHNL_IRP *MakeNewChirp(void);
++
++static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
++ OUT u32 *pdwChnl);
++
++/*
++ * ======== WMD_CHNL_AddIOReq ========
++ * Enqueue an I/O request for data transfer on a channel to the DSP.
++ * The direction (mode) is specified in the channel object. Note the DSP
++ * address is specified for channels opened in direct I/O mode.
++ */
++DSP_STATUS WMD_CHNL_AddIOReq(struct CHNL_OBJECT *hChnl, void *pHostBuf,
++ u32 cBytes, u32 cBufSize,
++ OPTIONAL u32 dwDspAddr, u32 dwArg)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ struct CHNL_IRP *pChirp = NULL;
++ u32 dwState;
++ bool fIsEOS;
++ struct CHNL_MGR *pChnlMgr = pChnl->pChnlMgr;
++ u8 *pHostSysBuf = NULL;
++ bool fSchedDPC = false;
++ u16 wMbVal = 0;
++
++ DBG_Trace(DBG_ENTER,
++ "> WMD_CHNL_AddIOReq pChnl %p CHNL_IsOutput %x uChnlType "
++ "%x Id %d\n", pChnl, CHNL_IsOutput(pChnl->uMode),
++ pChnl->uChnlType, pChnl->uId);
++
++ fIsEOS = (cBytes == 0) ? true : false;
++
++ if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1 && pHostBuf) {
++ if (!(pHostBuf < (void *)USERMODE_ADDR)) {
++ pHostSysBuf = pHostBuf;
++ goto func_cont;
++ }
++ /* if addr in user mode, then copy to kernel space */
++ pHostSysBuf = MEM_Alloc(cBufSize, MEM_NONPAGED);
++ if (pHostSysBuf == NULL) {
++ status = DSP_EMEMORY;
++ DBG_Trace(DBG_LEVEL7,
++ "No memory to allocate kernel buffer\n");
++ goto func_cont;
++ }
++ if (CHNL_IsOutput(pChnl->uMode)) {
++ status = copy_from_user(pHostSysBuf, pHostBuf,
++ cBufSize);
++ if (status) {
++ DBG_Trace(DBG_LEVEL7,
++ "Error copying user buffer to "
++ "kernel, %d bytes remaining.\n",
++ status);
++ MEM_Free(pHostSysBuf);
++ pHostSysBuf = NULL;
++ status = DSP_EPOINTER;
++ }
++ }
++ }
++func_cont:
++ /* Validate args: */
++ if (pHostBuf == NULL) {
++ status = DSP_EPOINTER;
++ } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if (fIsEOS && CHNL_IsInput(pChnl->uMode)) {
++ status = CHNL_E_NOEOS;
++ } else {
++ /* Check the channel state: only queue chirp if channel state
++ * allows */
++ dwState = pChnl->dwState;
++ if (dwState != CHNL_STATEREADY) {
++ if (dwState & CHNL_STATECANCEL) {
++ status = CHNL_E_CANCELLED;
++ } else if ((dwState & CHNL_STATEEOS)
++ && CHNL_IsOutput(pChnl->uMode)) {
++ status = CHNL_E_EOS;
++ } else {
++ /* No other possible states left: */
++ DBC_Assert(0);
++ }
++ }
++ }
++ /* Mailbox IRQ is disabled to avoid race condition with DMA/ZCPY
++ * channels. DPCCS is held to avoid race conditions with PCPY channels.
++ * If DPC is scheduled in process context (IO_Schedule) and any
++ * non-mailbox interrupt occurs, that DPC will run and break CS. Hence
++ * we disable ALL DPCs. We will try to disable ONLY IO DPC later. */
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ disable_irq(MAILBOX_IRQ);
++ if (pChnl->uChnlType == CHNL_PCPY) {
++ /* This is a processor-copy channel. */
++ if (DSP_SUCCEEDED(status) && CHNL_IsOutput(pChnl->uMode)) {
++ /* Check buffer size on output channels for fit. */
++ if (cBytes > IO_BufSize(pChnl->pChnlMgr->hIOMgr))
++ status = CHNL_E_BUFSIZE;
++
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get a free chirp: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pFreeList);
++ if (pChirp == NULL)
++ status = CHNL_E_NOIORPS;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Enqueue the chirp on the chnl's IORequest queue: */
++ pChirp->pHostUserBuf = pChirp->pHostSysBuf = pHostBuf;
++ if (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)
++ pChirp->pHostSysBuf = pHostSysBuf;
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Note: for dma chans dwDspAddr contains dsp address
++ * of SM buffer.*/
++ DBC_Assert(pChnlMgr->uWordSize != 0);
++ /* DSP address */
++ pChirp->uDspAddr = dwDspAddr / pChnlMgr->uWordSize;
++ pChirp->cBytes = cBytes;
++ pChirp->cBufSize = cBufSize;
++ /* Only valid for output channel */
++ pChirp->dwArg = dwArg;
++ pChirp->status = (fIsEOS ? CHNL_IOCSTATEOS :
++ CHNL_IOCSTATCOMPLETE);
++ LST_PutTail(pChnl->pIORequests, (struct LST_ELEM *)
++ pChirp);
++ pChnl->cIOReqs++;
++ DBC_Assert(pChnl->cIOReqs <= pChnl->cChirps);
++ /* If end of stream, update the channel state to prevent
++ * more IOR's: */
++ if (fIsEOS)
++ pChnl->dwState |= CHNL_STATEEOS;
++
++ {
++ /* Legacy DSM Processor-Copy */
++ DBC_Assert(pChnl->uChnlType == CHNL_PCPY);
++ /* Request IO from the DSP */
++ IO_RequestChnl(pChnlMgr->hIOMgr, pChnl,
++ (CHNL_IsInput(pChnl->uMode) ?
++ IO_INPUT : IO_OUTPUT), &wMbVal);
++ fSchedDPC = true;
++ }
++ }
++ }
++ enable_irq(MAILBOX_IRQ);
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++ if (wMbVal != 0)
++ IO_IntrDSP2(pChnlMgr->hIOMgr, wMbVal);
++
++ if (fSchedDPC == true) {
++ /* Schedule a DPC, to do the actual data transfer: */
++ IO_Schedule(pChnlMgr->hIOMgr);
++ }
++ DBG_Trace(DBG_ENTER, "< WMD_CHNL_AddIOReq pChnl %p\n", pChnl);
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_CancelIO ========
++ * Return all I/O requests to the client which have not yet been
++ * transferred. The channel's I/O completion object is
++ * signalled, and all the I/O requests are queued as IOC's, with the
++ * status field set to CHNL_IOCSTATCANCEL.
++ * This call is typically used in abort situations, and is a prelude to
++ * CHNL_Close();
++ */
++DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ u32 iChnl = -1;
++ CHNL_MODE uMode;
++ struct CHNL_IRP *pChirp;
++ struct CHNL_MGR *pChnlMgr = NULL;
++
++ /* Check args: */
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ iChnl = pChnl->uId;
++ uMode = pChnl->uMode;
++ pChnlMgr = pChnl->pChnlMgr;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ /* Mark this channel as cancelled, to prevent further IORequests or
++ * IORequests or dispatching. */
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ pChnl->dwState |= CHNL_STATECANCEL;
++ if (LST_IsEmpty(pChnl->pIORequests))
++ goto func_cont;
++
++ if (pChnl->uChnlType == CHNL_PCPY) {
++ /* Indicate we have no more buffers available for transfer: */
++ if (CHNL_IsInput(pChnl->uMode)) {
++ IO_CancelChnl(pChnlMgr->hIOMgr, iChnl);
++ } else {
++ /* Record that we no longer have output buffers
++ * available: */
++ pChnlMgr->dwOutputMask &= ~(1 << iChnl);
++ }
++ }
++ /* Move all IOR's to IOC queue: */
++ while (!LST_IsEmpty(pChnl->pIORequests)) {
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
++ if (pChirp) {
++ pChirp->cBytes = 0;
++ pChirp->status |= CHNL_IOCSTATCANCEL;
++ LST_PutTail(pChnl->pIOCompletions,
++ (struct LST_ELEM *)pChirp);
++ pChnl->cIOCs++;
++ pChnl->cIOReqs--;
++ DBC_Assert(pChnl->cIOReqs >= 0);
++ }
++ }
++func_cont:
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Close ========
++ * Purpose:
++ * Ensures all pending I/O on this channel is cancelled, discards all
++ * queued I/O completion notifications, then frees the resources allocated
++ * for this channel, and makes the corresponding logical channel id
++ * available for subsequent use.
++ */
++DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl)
++{
++ DSP_STATUS status;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++
++ /* Check args: */
++ if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ goto func_cont;
++ }
++ {
++ /* Cancel IO: this ensures no further IO requests or
++ * notifications.*/
++ status = WMD_CHNL_CancelIO(hChnl);
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Assert I/O on this channel is now cancelled: Protects
++ * from IO_DPC. */
++ DBC_Assert((pChnl->dwState & CHNL_STATECANCEL));
++ /* Invalidate channel object: Protects from
++ * CHNL_GetIOCompletion(). */
++ pChnl->dwSignature = 0x0000;
++ /* Free the slot in the channel manager: */
++ pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL;
++ pChnl->pChnlMgr->cOpenChannels -= 1;
++ if (pChnl->hNtfy) {
++ NTFY_Delete(pChnl->hNtfy);
++ pChnl->hNtfy = NULL;
++ }
++ /* Reset channel event: (NOTE: hUserEvent freed in user
++ * context.). */
++ if (pChnl->hSyncEvent) {
++ SYNC_ResetEvent(pChnl->hSyncEvent);
++ SYNC_CloseEvent(pChnl->hSyncEvent);
++ pChnl->hSyncEvent = NULL;
++ }
++ /* Free I/O request and I/O completion queues: */
++ if (pChnl->pIOCompletions) {
++ FreeChirpList(pChnl->pIOCompletions);
++ pChnl->pIOCompletions = NULL;
++ pChnl->cIOCs = 0;
++ }
++ if (pChnl->pIORequests) {
++ FreeChirpList(pChnl->pIORequests);
++ pChnl->pIORequests = NULL;
++ pChnl->cIOReqs = 0;
++ }
++ if (pChnl->pFreeList) {
++ FreeChirpList(pChnl->pFreeList);
++ pChnl->pFreeList = NULL;
++ }
++ /* Release channel object. */
++ MEM_FreeObject(pChnl);
++ pChnl = NULL;
++ }
++ DBC_Ensure(DSP_FAILED(status) ||
++ !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Create ========
++ * Create a channel manager object, responsible for opening new channels
++ * and closing old ones for a given board.
++ */
++DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CHNL_MGRATTRS *pMgrAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = NULL;
++ s32 cChannels;
++#ifdef DEBUG
++ struct CHNL_MGR *hChnlMgr;
++#endif
++ /* Check DBC requirements: */
++ DBC_Require(phChnlMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++ DBC_Require(pMgrAttrs->cChannels > 0);
++ DBC_Require(pMgrAttrs->cChannels <= CHNL_MAXCHANNELS);
++ DBC_Require(pMgrAttrs->uWordSize != 0);
++#ifdef DEBUG
++ /* This for the purposes of DBC_Require: */
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ DBC_Require(status != DSP_EHANDLE);
++ DBC_Require(hChnlMgr == NULL);
++#endif
++ if (DSP_SUCCEEDED(status)) {
++ /* Allocate channel manager object: */
++ MEM_AllocObject(pChnlMgr, struct CHNL_MGR, CHNL_MGRSIGNATURE);
++ if (pChnlMgr) {
++ /* The cChannels attr must equal the # of supported
++ * chnls for each transport(# chnls for PCPY = DDMA =
++ * ZCPY): i.e. pMgrAttrs->cChannels = CHNL_MAXCHANNELS =
++ * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS. */
++ DBC_Assert(pMgrAttrs->cChannels == CHNL_MAXCHANNELS);
++ cChannels = (CHNL_MAXCHANNELS + (CHNL_MAXCHANNELS *
++ CHNL_PCPY));
++ /* Create array of channels: */
++ pChnlMgr->apChannel = MEM_Calloc(
++ sizeof(struct CHNL_OBJECT *) *
++ cChannels, MEM_NONPAGED);
++ if (pChnlMgr->apChannel) {
++ /* Initialize CHNL_MGR object: */
++ /* Shared memory driver. */
++ pChnlMgr->dwType = CHNL_TYPESM;
++ pChnlMgr->uWordSize = pMgrAttrs->uWordSize;
++ /* total # chnls supported */
++ pChnlMgr->cChannels = cChannels;
++ pChnlMgr->cOpenChannels = 0;
++ pChnlMgr->dwOutputMask = 0;
++ pChnlMgr->dwLastOutput = 0;
++ pChnlMgr->hDevObject = hDevObject;
++ if (DSP_SUCCEEDED(status)) {
++ status = SYNC_InitializeDPCCS
++ (&pChnlMgr->hCSObj);
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ WMD_CHNL_Destroy(pChnlMgr);
++ *phChnlMgr = NULL;
++ } else {
++ /* Return channel manager object to caller... */
++ *phChnlMgr = pChnlMgr;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Destroy ========
++ * Purpose:
++ * Close all open channels, and destroy the channel manager.
++ */
++DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = hChnlMgr;
++ u32 iChnl;
++
++ if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ /* Close all open channels: */
++ for (iChnl = 0; iChnl < pChnlMgr->cChannels; iChnl++) {
++ if (DSP_SUCCEEDED
++ (WMD_CHNL_Close(pChnlMgr->apChannel[iChnl]))) {
++ DBC_Assert(pChnlMgr->apChannel[iChnl] == NULL);
++ }
++ }
++ /* release critical section */
++ if (pChnlMgr->hCSObj)
++ SYNC_DeleteCS(pChnlMgr->hCSObj);
++
++ /* Free channel manager object: */
++ if (pChnlMgr->apChannel)
++ MEM_Free(pChnlMgr->apChannel);
++
++ /* Set hChnlMgr to NULL in device object. */
++ DEV_SetChnlMgr(pChnlMgr->hDevObject, NULL);
++ /* Free this Chnl Mgr object: */
++ MEM_FreeObject(hChnlMgr);
++ } else {
++ status = DSP_EHANDLE;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_FlushIO ========
++ * purpose:
++ * Flushes all the outstanding data requests on a channel.
++ */
++DSP_STATUS WMD_CHNL_FlushIO(struct CHNL_OBJECT *hChnl, u32 dwTimeOut)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ CHNL_MODE uMode = -1;
++ struct CHNL_MGR *pChnlMgr;
++ struct CHNL_IOC chnlIOC;
++ /* Check args: */
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ if ((dwTimeOut == CHNL_IOCNOWAIT)
++ && CHNL_IsOutput(pChnl->uMode)) {
++ status = DSP_EINVALIDARG;
++ } else {
++ uMode = pChnl->uMode;
++ pChnlMgr = pChnl->pChnlMgr;
++ }
++ } else {
++ status = DSP_EHANDLE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Note: Currently, if another thread continues to add IO
++ * requests to this channel, this function will continue to
++ * flush all such queued IO requests. */
++ if (CHNL_IsOutput(uMode) && (pChnl->uChnlType == CHNL_PCPY)) {
++ /* Wait for IO completions, up to the specified
++ * timeout: */
++ while (!LST_IsEmpty(pChnl->pIORequests) &&
++ DSP_SUCCEEDED(status)) {
++ status = WMD_CHNL_GetIOC(hChnl, dwTimeOut,
++ &chnlIOC);
++ if (DSP_FAILED(status))
++ continue;
++
++ if (chnlIOC.status & CHNL_IOCSTATTIMEOUT)
++ status = CHNL_E_WAITTIMEOUT;
++
++ }
++ } else {
++ status = WMD_CHNL_CancelIO(hChnl);
++ /* Now, leave the channel in the ready state: */
++ pChnl->dwState &= ~CHNL_STATECANCEL;
++ }
++ }
++ DBC_Ensure(DSP_FAILED(status) || LST_IsEmpty(pChnl->pIORequests));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetInfo ========
++ * Purpose:
++ * Retrieve information related to a channel.
++ */
++DSP_STATUS WMD_CHNL_GetInfo(struct CHNL_OBJECT *hChnl,
++ OUT struct CHNL_INFO *pInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ if (pInfo != NULL) {
++ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ /* Return the requested information: */
++ pInfo->hChnlMgr = pChnl->pChnlMgr;
++ pInfo->hEvent = pChnl->hUserEvent;
++ pInfo->dwID = pChnl->uId;
++ pInfo->dwMode = pChnl->uMode;
++ pInfo->cPosition = pChnl->cBytesMoved;
++ pInfo->hProcess = pChnl->hProcess;
++ pInfo->hSyncEvent = pChnl->hSyncEvent;
++ pInfo->cIOCs = pChnl->cIOCs;
++ pInfo->cIOReqs = pChnl->cIOReqs;
++ pInfo->dwState = pChnl->dwState;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ } else {
++ status = DSP_EPOINTER;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetIOC ========
++ * Optionally wait for I/O completion on a channel. Dequeue an I/O
++ * completion record, which contains information about the completed
++ * I/O request.
++ * Note: Ensures Channel Invariant (see notes above).
++ */
++DSP_STATUS WMD_CHNL_GetIOC(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
++ OUT struct CHNL_IOC *pIOC)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl;
++ struct CHNL_IRP *pChirp;
++ DSP_STATUS statSync;
++ bool fDequeueIOC = true;
++ struct CHNL_IOC ioc = { NULL, 0, 0, 0, 0 };
++ u8 *pHostSysBuf = NULL;
++
++ DBG_Trace(DBG_ENTER, "> WMD_CHNL_GetIOC pChnl %p CHNL_IsOutput %x "
++ "uChnlType %x\n", pChnl, CHNL_IsOutput(pChnl->uMode),
++ pChnl->uChnlType);
++ /* Check args: */
++ if (pIOC == NULL) {
++ status = DSP_EPOINTER;
++ } else if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else if (dwTimeOut == CHNL_IOCNOWAIT) {
++ if (LST_IsEmpty(pChnl->pIOCompletions))
++ status = CHNL_E_NOIOC;
++
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ ioc.status = CHNL_IOCSTATCOMPLETE;
++ if (dwTimeOut != CHNL_IOCNOWAIT && LST_IsEmpty(pChnl->pIOCompletions)) {
++ if (dwTimeOut == CHNL_IOCINFINITE)
++ dwTimeOut = SYNC_INFINITE;
++
++ statSync = SYNC_WaitOnEvent(pChnl->hSyncEvent, dwTimeOut);
++ if (statSync == DSP_ETIMEOUT) {
++ /* No response from DSP */
++ ioc.status |= CHNL_IOCSTATTIMEOUT;
++ fDequeueIOC = false;
++ } else if (statSync == DSP_EFAIL) {
++ /* This can occur when the user mode thread is
++ * aborted (^C), or when _VWIN32_WaitSingleObject()
++ * fails due to unkown causes. */
++ /* Even though Wait failed, there may be something in
++ * the Q: */
++ if (LST_IsEmpty(pChnl->pIOCompletions)) {
++ ioc.status |= CHNL_IOCSTATCANCEL;
++ fDequeueIOC = false;
++ }
++ }
++ }
++ /* See comment in AddIOReq */
++ SYNC_EnterCS(pChnl->pChnlMgr->hCSObj);
++ disable_irq(MAILBOX_IRQ);
++ if (fDequeueIOC) {
++ /* Dequeue IOC and set pIOC; */
++ DBC_Assert(!LST_IsEmpty(pChnl->pIOCompletions));
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIOCompletions);
++ /* Update pIOC from channel state and chirp: */
++ if (pChirp) {
++ pChnl->cIOCs--;
++ /* If this is a zero-copy channel, then set IOC's pBuf
++ * to the DSP's address. This DSP address will get
++ * translated to user's virtual addr later. */
++ {
++ pHostSysBuf = pChirp->pHostSysBuf;
++ ioc.pBuf = pChirp->pHostUserBuf;
++ }
++ ioc.cBytes = pChirp->cBytes;
++ ioc.cBufSize = pChirp->cBufSize;
++ ioc.dwArg = pChirp->dwArg;
++ ioc.status |= pChirp->status;
++ /* Place the used chirp on the free list: */
++ LST_PutTail(pChnl->pFreeList, (struct LST_ELEM *)
++ pChirp);
++ } else {
++ ioc.pBuf = NULL;
++ ioc.cBytes = 0;
++ }
++ } else {
++ ioc.pBuf = NULL;
++ ioc.cBytes = 0;
++ ioc.dwArg = 0;
++ ioc.cBufSize = 0;
++ }
++ /* Ensure invariant: If any IOC's are queued for this channel... */
++ if (!LST_IsEmpty(pChnl->pIOCompletions)) {
++ /* Since DSPStream_Reclaim() does not take a timeout
++ * parameter, we pass the stream's timeout value to
++ * WMD_CHNL_GetIOC. We cannot determine whether or not
++ * we have waited in User mode. Since the stream's timeout
++ * value may be non-zero, we still have to set the event.
++ * Therefore, this optimization is taken out.
++ *
++ * if (dwTimeOut == CHNL_IOCNOWAIT) {
++ * ... ensure event is set..
++ * SYNC_SetEvent(pChnl->hSyncEvent);
++ * } */
++ SYNC_SetEvent(pChnl->hSyncEvent);
++ } else {
++ /* else, if list is empty, ensure event is reset. */
++ SYNC_ResetEvent(pChnl->hSyncEvent);
++ }
++ enable_irq(MAILBOX_IRQ);
++ SYNC_LeaveCS(pChnl->pChnlMgr->hCSObj);
++ if (fDequeueIOC && (pChnl->uChnlType == CHNL_PCPY && pChnl->uId > 1)) {
++ if (!(ioc.pBuf < (void *) USERMODE_ADDR))
++ goto func_cont;
++
++ /* If the addr is in user mode, then copy it */
++ if (!pHostSysBuf || !ioc.pBuf) {
++ status = DSP_EPOINTER;
++ DBG_Trace(DBG_LEVEL7,
++ "System buffer NULL in IO completion.\n");
++ goto func_cont;
++ }
++ if (!CHNL_IsInput(pChnl->uMode))
++ goto func_cont1;
++
++ /*pHostUserBuf */
++ status = copy_to_user(ioc.pBuf, pHostSysBuf, ioc.cBytes);
++#ifndef RES_CLEANUP_DISABLE
++ if (status) {
++ if (current->flags & PF_EXITING) {
++ DBG_Trace(DBG_LEVEL7,
++ "\n2current->flags == PF_EXITING, "
++ " current->flags;0x%x\n",
++ current->flags);
++ status = 0;
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "\n2current->flags != PF_EXITING, "
++ " current->flags;0x%x\n",
++ current->flags);
++ }
++ }
++#endif
++ if (status) {
++ DBG_Trace(DBG_LEVEL7,
++ "Error copying kernel buffer to user, %d"
++ " bytes remaining. in_interupt %d\n",
++ status, in_interrupt());
++ status = DSP_EPOINTER;
++ }
++func_cont1:
++ MEM_Free(pHostSysBuf);
++ }
++func_cont:
++ /* Update User's IOC block: */
++ *pIOC = ioc;
++func_end:
++ DBG_Trace(DBG_ENTER, "< WMD_CHNL_GetIOC pChnl %p\n", pChnl);
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_GetMgrInfo ========
++ * Retrieve information related to the channel manager.
++ */
++DSP_STATUS WMD_CHNL_GetMgrInfo(struct CHNL_MGR *hChnlMgr, u32 uChnlID,
++ OUT struct CHNL_MGRINFO *pMgrInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = (struct CHNL_MGR *)hChnlMgr;
++
++ if (pMgrInfo != NULL) {
++ if (uChnlID <= CHNL_MAXCHANNELS) {
++ if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ /* Return the requested information: */
++ pMgrInfo->hChnl = pChnlMgr->apChannel[uChnlID];
++ pMgrInfo->cOpenChannels = pChnlMgr->
++ cOpenChannels;
++ pMgrInfo->dwType = pChnlMgr->dwType;
++ /* total # of chnls */
++ pMgrInfo->cChannels = pChnlMgr->cChannels;
++ } else {
++ status = DSP_EHANDLE;
++ }
++ } else {
++ status = CHNL_E_BADCHANID;
++ }
++ } else {
++ status = DSP_EPOINTER;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Idle ========
++ * Idles a particular channel.
++ */
++DSP_STATUS WMD_CHNL_Idle(struct CHNL_OBJECT *hChnl, u32 dwTimeOut,
++ bool fFlush)
++{
++ CHNL_MODE uMode;
++ struct CHNL_MGR *pChnlMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hChnl, CHNL_SIGNATURE));
++
++ uMode = hChnl->uMode;
++ pChnlMgr = hChnl->pChnlMgr;
++
++ if (CHNL_IsOutput(uMode) && !fFlush) {
++ /* Wait for IO completions, up to the specified timeout: */
++ status = WMD_CHNL_FlushIO(hChnl, dwTimeOut);
++ } else {
++ status = WMD_CHNL_CancelIO(hChnl);
++
++ /* Reset the byte count and put channel back in ready state. */
++ hChnl->cBytesMoved = 0;
++ hChnl->dwState &= ~CHNL_STATECANCEL;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_Open ========
++ * Open a new half-duplex channel to the DSP board.
++ */
++DSP_STATUS WMD_CHNL_Open(OUT struct CHNL_OBJECT **phChnl,
++ struct CHNL_MGR *hChnlMgr, CHNL_MODE uMode,
++ u32 uChnlId, CONST IN struct CHNL_ATTRS *pAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct CHNL_MGR *pChnlMgr = hChnlMgr;
++ struct CHNL_OBJECT *pChnl = NULL;
++ struct SYNC_ATTRS *pSyncAttrs = NULL;
++ struct SYNC_OBJECT *hSyncEvent = NULL;
++ /* Ensure DBC requirements: */
++ DBC_Require(phChnl != NULL);
++ DBC_Require(pAttrs != NULL);
++ *phChnl = NULL;
++ /* Validate Args: */
++ if (pAttrs->uIOReqs == 0) {
++ status = DSP_EINVALIDARG;
++ } else {
++ if (!MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) {
++ status = DSP_EHANDLE;
++ } else {
++ if (uChnlId != CHNL_PICKFREE) {
++ if (uChnlId >= pChnlMgr->cChannels) {
++ status = CHNL_E_BADCHANID;
++ } else if (pChnlMgr->apChannel[uChnlId] !=
++ NULL) {
++ status = CHNL_E_CHANBUSY;
++ }
++ } else {
++ /* Check for free channel */
++ status = SearchFreeChannel(pChnlMgr, &uChnlId);
++ }
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_end;
++
++ DBC_Assert(uChnlId < pChnlMgr->cChannels);
++ /* Create channel object: */
++ MEM_AllocObject(pChnl, struct CHNL_OBJECT, 0x0000);
++ if (!pChnl) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ /* Protect queues from IO_DPC: */
++ pChnl->dwState = CHNL_STATECANCEL;
++ /* Allocate initial IOR and IOC queues: */
++ pChnl->pFreeList = CreateChirpList(pAttrs->uIOReqs);
++ pChnl->pIORequests = CreateChirpList(0);
++ pChnl->pIOCompletions = CreateChirpList(0);
++ pChnl->cChirps = pAttrs->uIOReqs;
++ pChnl->cIOCs = 0;
++ pChnl->cIOReqs = 0;
++ status = SYNC_OpenEvent(&hSyncEvent, pSyncAttrs);
++ if (DSP_SUCCEEDED(status)) {
++ status = NTFY_Create(&pChnl->hNtfy);
++ if (DSP_FAILED(status)) {
++ /* The only failure that could have occurred */
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ if (pChnl->pIOCompletions && pChnl->pIORequests &&
++ pChnl->pFreeList) {
++ /* Initialize CHNL object fields: */
++ pChnl->pChnlMgr = pChnlMgr;
++ pChnl->uId = uChnlId;
++ pChnl->uMode = uMode;
++ pChnl->hUserEvent = hSyncEvent; /* for Linux */
++ pChnl->hSyncEvent = hSyncEvent;
++ /* get the process handle */
++ pChnl->hProcess = current->pid;
++ pChnl->pCBArg = 0;
++ pChnl->cBytesMoved = 0;
++ /* Default to proc-copy */
++ pChnl->uChnlType = CHNL_PCPY;
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ status = DSP_EINVALIDARG;
++ }
++ if (DSP_FAILED(status)) {
++ /* Free memory */
++ if (pChnl->pIOCompletions) {
++ FreeChirpList(pChnl->pIOCompletions);
++ pChnl->pIOCompletions = NULL;
++ pChnl->cIOCs = 0;
++ }
++ if (pChnl->pIORequests) {
++ FreeChirpList(pChnl->pIORequests);
++ pChnl->pIORequests = NULL;
++ }
++ if (pChnl->pFreeList) {
++ FreeChirpList(pChnl->pFreeList);
++ pChnl->pFreeList = NULL;
++ }
++ if (hSyncEvent) {
++ SYNC_CloseEvent(hSyncEvent);
++ hSyncEvent = NULL;
++ }
++ if (pChnl->hNtfy) {
++ NTFY_Delete(pChnl->hNtfy);
++ pChnl->hNtfy = NULL;
++ }
++ MEM_FreeObject(pChnl);
++ }
++func_cont:
++ if (DSP_SUCCEEDED(status)) {
++ /* Insert channel object in channel manager: */
++ pChnlMgr->apChannel[pChnl->uId] = pChnl;
++ SYNC_EnterCS(pChnlMgr->hCSObj);
++ pChnlMgr->cOpenChannels++;
++ SYNC_LeaveCS(pChnlMgr->hCSObj);
++ /* Return result... */
++ pChnl->dwSignature = CHNL_SIGNATURE;
++ pChnl->dwState = CHNL_STATEREADY;
++ *phChnl = pChnl;
++ }
++func_end:
++ DBC_Ensure((DSP_SUCCEEDED(status) &&
++ MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) ||
++ (*phChnl == NULL));
++ return status;
++}
++
++/*
++ * ======== WMD_CHNL_RegisterNotify ========
++ * Registers for events on a particular channel.
++ */
++DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Assert(!(uEventMask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION)));
++
++ status = NTFY_Register(hChnl->hNtfy, hNotification, uEventMask,
++ uNotifyType);
++
++ return status;
++}
++
++/*
++ * ======== CreateChirpList ========
++ * Purpose:
++ * Initialize a queue of channel I/O Request/Completion packets.
++ * Parameters:
++ * uChirps: Number of Chirps to allocate.
++ * Returns:
++ * Pointer to queue of IRPs, or NULL.
++ * Requires:
++ * Ensures:
++ */
++static struct LST_LIST *CreateChirpList(u32 uChirps)
++{
++ struct LST_LIST *pChirpList;
++ struct CHNL_IRP *pChirp;
++ u32 i;
++
++ pChirpList = LST_Create();
++
++ if (pChirpList) {
++ /* Make N chirps and place on queue. */
++ for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) !=
++ NULL); i++) {
++ LST_PutTail(pChirpList, (struct LST_ELEM *)pChirp);
++ }
++
++ /* If we couldn't allocate all chirps, free those allocated: */
++ if (i != uChirps) {
++ FreeChirpList(pChirpList);
++ pChirpList = NULL;
++ }
++ }
++
++ return pChirpList;
++}
++
++/*
++ * ======== FreeChirpList ========
++ * Purpose:
++ * Free the queue of Chirps.
++ */
++static void FreeChirpList(struct LST_LIST *pChirpList)
++{
++ DBC_Require(pChirpList != NULL);
++
++ while (!LST_IsEmpty(pChirpList))
++ MEM_Free(LST_GetHead(pChirpList));
++
++ LST_Delete(pChirpList);
++}
++
++/*
++ * ======== MakeNewChirp ========
++ * Allocate the memory for a new channel IRP.
++ */
++static struct CHNL_IRP *MakeNewChirp(void)
++{
++ struct CHNL_IRP *pChirp;
++
++ pChirp = (struct CHNL_IRP *)MEM_Calloc(
++ sizeof(struct CHNL_IRP), MEM_NONPAGED);
++ if (pChirp != NULL) {
++ /* LST_InitElem only resets the list's member values. */
++ LST_InitElem(&pChirp->link);
++ }
++
++ return pChirp;
++}
++
++/*
++ * ======== SearchFreeChannel ========
++ * Search for a free channel slot in the array of channel pointers.
++ */
++static DSP_STATUS SearchFreeChannel(struct CHNL_MGR *pChnlMgr,
++ OUT u32 *pdwChnl)
++{
++ DSP_STATUS status = CHNL_E_OUTOFSTREAMS;
++ u32 i;
++
++ DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
++
++ for (i = 0; i < pChnlMgr->cChannels; i++) {
++ if (pChnlMgr->apChannel[i] == NULL) {
++ status = DSP_SOK;
++ *pdwChnl = i;
++ break;
++ }
++ }
++
++ return status;
++}
+diff --git a/drivers/dsp/bridge/wmd/io_sm.c b/drivers/dsp/bridge/wmd/io_sm.c
+new file mode 100644
+index 0000000..325f1f1
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/io_sm.c
+@@ -0,0 +1,2011 @@
++/*
++ * io_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== io_sm.c ========
++ * Description:
++ * IO dispatcher for a shared memory channel driver.
++ *
++ * Public Functions:
++ * WMD_IO_Create
++ * WMD_IO_Destroy
++ * WMD_IO_OnLoaded
++ * IO_AndSetValue
++ * IO_BufSize
++ * IO_CancelChnl
++ * IO_DPC
++ * IO_ISR
++ * IO_IVAISR
++ * IO_OrSetValue
++ * IO_ReadValue
++ * IO_ReadValueLong
++ * IO_RequestChnl
++ * IO_Schedule
++ * IO_WriteValue
++ * IO_WriteValueLong
++ *
++ * Channel Invariant:
++ * There is an important invariant condition which must be maintained per
++ * channel outside of WMD_CHNL_GetIOC() and IO_Dispatch(), violation of
++ * which may cause timeouts and/or failure of the WIN32_WaitSingleObject
++ * function (SYNC_WaitOnEvent).
++ *
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++#include <linux/workqueue.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/cfg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/sync.h>
++#include <dspbridge/reg.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- Mini Driver */
++#include <dspbridge/wmddeh.h>
++#include <dspbridge/wmdio.h>
++#include <dspbridge/wmdioctl.h>
++#include <_tiomap.h>
++#include <tiomap_io.h>
++#include <_tiomap_pwr.h>
++#include <tiomap_io.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/cod.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/chnl_sm.h>
++#include <dspbridge/dbreg.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/rms_sh.h>
++#include <dspbridge/mgr.h>
++#include <dspbridge/drv.h>
++#include "_cmm.h"
++
++/* ----------------------------------- This */
++#include <dspbridge/io_sm.h>
++#include "_msg_sm.h"
++#include <dspbridge/gt.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define OUTPUTNOTREADY 0xffff
++#define NOTENABLED 0xffff /* channel(s) not enabled */
++
++#define EXTEND "_EXT_END"
++
++#define SwapWord(x) (x)
++#define ulPageAlignSize 0x10000 /* Page Align Size */
++
++#define MAX_PM_REQS 32
++
++/* IO Manager: only one created per board: */
++struct IO_MGR {
++ /* These four fields must be the first fields in a IO_MGR_ struct: */
++ u32 dwSignature; /* Used for object validation */
++ struct WMD_DEV_CONTEXT *hWmdContext; /* WMD device context */
++ struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
++ struct DEV_OBJECT *hDevObject; /* Device this board represents */
++
++ /* These fields initialized in WMD_IO_Create(): */
++ struct CHNL_MGR *hChnlMgr;
++ struct SHM *pSharedMem; /* Shared Memory control */
++ u8 *pInput; /* Address of input channel */
++ u8 *pOutput; /* Address of output channel */
++ struct MSG_MGR *hMsgMgr; /* Message manager */
++ struct MSG *pMsgInputCtrl; /* Msg control for from DSP messages */
++ struct MSG *pMsgOutputCtrl; /* Msg control for to DSP messages */
++ u8 *pMsgInput; /* Address of input messages */
++ u8 *pMsgOutput; /* Address of output messages */
++ u32 uSMBufSize; /* Size of a shared memory I/O channel */
++ bool fSharedIRQ; /* Is this IRQ shared? */
++ struct DPC_OBJECT *hDPC; /* DPC object handle */
++ struct SYNC_CSOBJECT *hCSObj; /* Critical section object handle */
++ u32 uWordSize; /* Size in bytes of DSP word */
++ u16 wIntrVal; /* interrupt value */
++ /* private extnd proc info; mmu setup */
++ struct MGR_PROCESSOREXTINFO extProcInfo;
++ struct CMM_OBJECT *hCmmMgr; /* Shared Mem Mngr */
++ struct work_struct io_workq; /*workqueue */
++ u32 dQuePowerMbxVal[MAX_PM_REQS];
++ u32 iQuePowerHead;
++ u32 iQuePowerTail;
++#ifndef DSP_TRACEBUF_DISABLED
++ u32 ulTraceBufferBegin; /* Trace message start address */
++ u32 ulTraceBufferEnd; /* Trace message end address */
++ u32 ulTraceBufferCurrent; /* Trace message current address */
++ u32 ulGPPReadPointer; /* GPP Read pointer to Trace buffer */
++ u8 *pMsg;
++ u32 ulGppVa;
++ u32 ulDspVa;
++#endif
++} ;
++
++/* ----------------------------------- Function Prototypes */
++static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
++ IN OUT struct CHNL_OBJECT *pChnl, u32 iMode);
++static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static void IO_DispatchPM(struct work_struct *work);
++static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp);
++static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode);
++static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode);
++static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr);
++static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
++ struct CHNL_OBJECT *pChnl, u32 dwMask);
++static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize);
++static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize);
++static struct workqueue_struct *bridge_workqueue;
++#ifndef DSP_TRACEBUF_DISABLED
++void PrintDSPDebugTrace(struct IO_MGR *hIOMgr);
++#endif
++
++/* Bus Addr (cached kernel)*/
++static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
++ struct COD_MANAGER *hCodMan,
++ u32 dwGPPBasePA);
++
++#ifdef CONFIG_BRIDGE_DVFS
++/* The maximum number of OPPs that are supported */
++extern s32 dsp_max_opps;
++/* The Vdd1 opp table information */
++extern u32 vdd1_dsp_freq[6][4] ;
++#endif
++
++#if GT_TRACE
++static struct GT_Mask dsp_trace_mask = { NULL, NULL }; /* GT trace variable */
++#endif
++
++/*
++ * ======== WMD_IO_Create ========
++ * Create an IO manager object.
++ */
++DSP_STATUS WMD_IO_Create(OUT struct IO_MGR **phIOMgr,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct IO_ATTRS *pMgrAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct IO_MGR *pIOMgr = NULL;
++ struct SHM *pSharedMem = NULL;
++ struct WMD_DEV_CONTEXT *hWmdContext = NULL;
++ struct CFG_HOSTRES hostRes;
++ struct CFG_DEVNODE *hDevNode;
++ struct CHNL_MGR *hChnlMgr;
++ static int ref_count;
++ u32 devType;
++ /* Check DBC requirements: */
++ DBC_Require(phIOMgr != NULL);
++ DBC_Require(pMgrAttrs != NULL);
++ DBC_Require(pMgrAttrs->uWordSize != 0);
++ /* This for the purposes of DBC_Require: */
++ status = DEV_GetChnlMgr(hDevObject, &hChnlMgr);
++ DBC_Require(status != DSP_EHANDLE);
++ DBC_Require(hChnlMgr != NULL);
++ DBC_Require(hChnlMgr->hIOMgr == NULL);
++ /* Message manager will be created when a file is loaded, since
++ * size of message buffer in shared memory is configurable in
++ * the base image. */
++ DEV_GetWMDContext(hDevObject, &hWmdContext);
++ DBC_Assert(hWmdContext);
++ DEV_GetDevType(hDevObject, &devType);
++ /* DSP shared memory area will get set properly when
++ * a program is loaded. They are unknown until a COFF file is
++ * loaded. I chose the value -1 because it was less likely to be
++ * a valid address than 0. */
++ pSharedMem = (struct SHM *) -1;
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ /*
++ * Create a Single Threaded Work Queue
++ */
++
++ if (ref_count == 0)
++ bridge_workqueue = create_workqueue("bridge_work-queue");
++
++ if (bridge_workqueue <= 0)
++ DBG_Trace(DBG_LEVEL1, "Workque Create"
++ " failed 0x%d \n", bridge_workqueue);
++
++
++ /* Allocate IO manager object: */
++ MEM_AllocObject(pIOMgr, struct IO_MGR, IO_MGRSIGNATURE);
++ if (pIOMgr == NULL) {
++ status = DSP_EMEMORY;
++ goto func_cont;
++ }
++ /*Intializing Work Element*/
++ if (ref_count == 0) {
++ INIT_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
++ ref_count = 1;
++ } else
++ PREPARE_WORK(&pIOMgr->io_workq, (void *)IO_DispatchPM);
++
++ /* Initialize CHNL_MGR object: */
++#ifndef DSP_TRACEBUF_DISABLED
++ pIOMgr->pMsg = NULL;
++#endif
++ pIOMgr->hChnlMgr = hChnlMgr;
++ pIOMgr->uWordSize = pMgrAttrs->uWordSize;
++ pIOMgr->pSharedMem = pSharedMem;
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pIOMgr->hCSObj);
++
++ if (devType == DSP_UNIT) {
++ /* Create a DPC object: */
++ status = DPC_Create(&pIOMgr->hDPC, IO_DPC, (void *)pIOMgr);
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++
++ pIOMgr->iQuePowerHead = 0;
++ pIOMgr->iQuePowerTail = 0;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension() , &hostRes);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pIOMgr->hWmdContext = hWmdContext;
++ pIOMgr->fSharedIRQ = pMgrAttrs->fShared;
++ IO_DisableInterrupt(hWmdContext);
++ if (devType == DSP_UNIT) {
++ /* Plug the channel ISR:. */
++ if ((request_irq(INT_MAIL_MPU_IRQ, IO_ISR, 0,
++ "DspBridge\tmailbox", (void *)pIOMgr)) == 0)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(status))
++ DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
++ pIOMgr);
++ else
++ status = CHNL_E_ISR;
++ } else
++ status = CHNL_E_ISR;
++func_cont:
++ if (DSP_FAILED(status)) {
++ /* Cleanup: */
++ WMD_IO_Destroy(pIOMgr);
++ *phIOMgr = NULL;
++ } else {
++ /* Return IO manager object to caller... */
++ hChnlMgr->hIOMgr = pIOMgr;
++ *phIOMgr = pIOMgr;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_IO_Destroy ========
++ * Purpose:
++ * Disable interrupts, destroy the IO manager.
++ */
++DSP_STATUS WMD_IO_Destroy(struct IO_MGR *hIOMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *hWmdContext;
++ if (MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE)) {
++ /* Unplug IRQ: */
++ /* Disable interrupts from the board: */
++ if (DSP_SUCCEEDED(DEV_GetWMDContext(hIOMgr->hDevObject,
++ &hWmdContext)))
++ DBC_Assert(hWmdContext);
++ (void)CHNLSM_DisableInterrupt(hWmdContext);
++ destroy_workqueue(bridge_workqueue);
++ /* Linux function to uninstall ISR */
++ free_irq(INT_MAIL_MPU_IRQ, (void *)hIOMgr);
++ (void)DPC_Destroy(hIOMgr->hDPC);
++#ifndef DSP_TRACEBUF_DISABLED
++ if (hIOMgr->pMsg)
++ MEM_Free(hIOMgr->pMsg);
++#endif
++ SYNC_DeleteCS(hIOMgr->hCSObj); /* Leak Fix. */
++ /* Free this IO manager object: */
++ MEM_FreeObject(hIOMgr);
++ } else
++ status = DSP_EHANDLE;
++
++ return status;
++}
++
++/*
++ * ======== WMD_IO_OnLoaded ========
++ * Purpose:
++ * Called when a new program is loaded to get shared memory buffer
++ * parameters from COFF file. ulSharedBufferBase and ulSharedBufferLimit
++ * are in DSP address units.
++ */
++DSP_STATUS WMD_IO_OnLoaded(struct IO_MGR *hIOMgr)
++{
++ struct COD_MANAGER *hCodMan;
++ struct CHNL_MGR *hChnlMgr;
++ struct MSG_MGR *hMsgMgr;
++ u32 ulShmBase;
++ u32 ulShmBaseOffset;
++ u32 ulShmLimit;
++ u32 ulShmLength = -1;
++ u32 ulMemLength = -1;
++ u32 ulMsgBase;
++ u32 ulMsgLimit;
++ u32 ulMsgLength = -1;
++ u32 ulExtEnd;
++ u32 ulGppPa = 0;
++ u32 ulGppVa = 0;
++ u32 ulDspVa = 0;
++ u32 ulSegSize = 0;
++ u32 ulPadSize = 0;
++ u32 i;
++ DSP_STATUS status = DSP_SOK;
++ u32 uNumProcs = 0;
++ s32 ndx = 0;
++ /* DSP MMU setup table */
++ struct WMDIOCTL_EXTPROC aEProc[WMDIOCTL_NUMOFMMUTLB];
++ struct CFG_HOSTRES hostRes;
++ u32 mapAttrs;
++ u32 ulShm0End;
++ u32 ulDynExtBase;
++ u32 ulSeg1Size = 0;
++ u32 paCurr = 0;
++ u32 vaCurr = 0;
++ u32 gppVaCurr = 0;
++ u32 numBytes = 0;
++ u32 allBits = 0;
++ u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
++ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
++
++ status = DEV_GetCodMgr(hIOMgr->hDevObject, &hCodMan);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ hChnlMgr = hIOMgr->hChnlMgr;
++ /* The message manager is destroyed when the board is stopped. */
++ DEV_GetMsgMgr(hIOMgr->hDevObject, &hIOMgr->hMsgMgr);
++ hMsgMgr = hIOMgr->hMsgMgr;
++ DBC_Assert(MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE));
++ DBC_Assert(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++ if (hIOMgr->pSharedMem)
++ hIOMgr->pSharedMem = NULL;
++
++ /* Get start and length of channel part of shared memory */
++ status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_BASE_SYM,
++ &ulShmBase);
++ if (DSP_FAILED(status)) {
++ status = CHNL_E_NOMEMMAP;
++ goto func_cont1;
++ }
++ status = COD_GetSymValue(hCodMan, CHNL_SHARED_BUFFER_LIMIT_SYM,
++ &ulShmLimit);
++ if (DSP_FAILED(status)) {
++ status = CHNL_E_NOMEMMAP;
++ goto func_cont1;
++ }
++ if (ulShmLimit <= ulShmBase) {
++ status = CHNL_E_INVALIDMEMBASE;
++ } else {
++ /* get total length in bytes */
++ ulShmLength = (ulShmLimit - ulShmBase + 1) * hIOMgr->uWordSize;
++ /* Calculate size of a PROCCOPY shared memory region */
++ DBG_Trace(DBG_LEVEL7,
++ "**(proc)PROCCOPY SHMMEM SIZE: 0x%x bytes\n",
++ (ulShmLength - sizeof(struct SHM)));
++ }
++func_cont1:
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_BASE_SYM,
++ &ulMsgBase);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, MSG_SHARED_BUFFER_LIMIT_SYM,
++ &ulMsgLimit);
++ if (DSP_SUCCEEDED(status)) {
++ if (ulMsgLimit <= ulMsgBase) {
++ status = CHNL_E_INVALIDMEMBASE;
++ } else {
++ /* Length (bytes) of messaging part of shared
++ * memory */
++ ulMsgLength = (ulMsgLimit - ulMsgBase + 1) *
++ hIOMgr->uWordSize;
++ /* Total length (bytes) of shared memory:
++ * chnl + msg */
++ ulMemLength = ulShmLength + ulMsgLength;
++ }
++ } else {
++ status = CHNL_E_NOMEMMAP;
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++#ifndef DSP_TRACEBUF_DISABLED
++ status = COD_GetSymValue(hCodMan, DSP_TRACESEC_END, &ulShm0End);
++ DBG_Trace(DBG_LEVEL7, "_BRIDGE_TRACE_END value = %x \n",
++ ulShm0End);
++#else
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
++ &ulShm0End);
++ DBG_Trace(DBG_LEVEL7, "_SHM0_END = %x \n", ulShm0End);
++#endif
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, DYNEXTBASE, &ulDynExtBase);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, EXTEND, &ulExtEnd);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Get memory reserved in host resources */
++ (void)MGR_EnumProcessorInfo(0,
++ (struct DSP_PROCESSORINFO *)&hIOMgr->extProcInfo,
++ sizeof(struct MGR_PROCESSOREXTINFO), &uNumProcs);
++ CFG_GetHostResources((
++ struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &hostRes);
++ /* The first MMU TLB entry(TLB_0) in DCD is ShmBase. */
++ ndx = 0;
++ ulGppPa = hostRes.dwMemPhys[1];
++ ulGppVa = hostRes.dwMemBase[1];
++ /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED ADDRESS !!! */
++ /* Why can't we directly take the DSPVA from the symbols? */
++ ulDspVa = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt;
++ ulSegSize = (ulShm0End - ulDspVa) * hIOMgr->uWordSize;
++ ulSeg1Size = (ulExtEnd - ulDynExtBase) * hIOMgr->uWordSize;
++ ulSeg1Size = (ulSeg1Size + 0xFFF) & (~0xFFFUL); /* 4K align*/
++ ulSegSize = (ulSegSize + 0xFFFF) & (~0xFFFFUL); /* 64K align*/
++ ulPadSize = ulPageAlignSize - ((ulGppPa + ulSeg1Size) %
++ ulPageAlignSize);
++ if (ulPadSize == ulPageAlignSize)
++ ulPadSize = 0x0;
++
++ DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa %x, "
++ "ulShm0End %x, ulDynExtBase %x, ulExtEnd %x, "
++ "ulSegSize %x ulSeg1Size %x \n", ulGppPa, ulGppVa,
++ ulDspVa, ulShm0End, ulDynExtBase, ulExtEnd, ulSegSize,
++ ulSeg1Size);
++
++ if ((ulSegSize + ulSeg1Size + ulPadSize) >
++ hostRes.dwMemLength[1]) {
++ DBG_Trace(DBG_LEVEL7, "ulGppPa %x, ulGppVa %x, ulDspVa "
++ "%x, ulShm0End %x, ulDynExtBase %x, ulExtEnd "
++ "%x, ulSegSize %x, ulSeg1Size %x \n", ulGppPa,
++ ulGppVa, ulDspVa, ulShm0End, ulDynExtBase,
++ ulExtEnd, ulSegSize, ulSeg1Size);
++ DBG_Trace(DBG_LEVEL7, "Insufficient SHM Reserved 0x%x. "
++ "Required 0x%x\n", hostRes.dwMemLength[1],
++ ulSegSize + ulSeg1Size + ulPadSize);
++ status = DSP_EMEMORY;
++ }
++ }
++ if (DSP_FAILED(status))
++ goto func_cont;
++
++ paCurr = ulGppPa;
++ vaCurr = ulDynExtBase * hIOMgr->uWordSize;
++ gppVaCurr = ulGppVa;
++ numBytes = ulSeg1Size;
++
++ /*
++ * Try to fit into TLB entries. If not possible, push them to page
++ * tables. It is quite possible that if sections are not on
++ * bigger page boundary, we may end up making several small pages.
++ * So, push them onto page tables, if that is the case.
++ */
++ mapAttrs = 0x00000000;
++ mapAttrs = DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPPHYSICALADDR;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPDONOTLOCK;
++
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned */
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
++ "numBytes %x\n", allBits, paCurr, vaCurr, numBytes);
++ for (i = 0; i < 4; i++) {
++ if ((numBytes >= pgSize[i]) && ((allBits &
++ (pgSize[i] - 1)) == 0)) {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext, paCurr, vaCurr,
++ pgSize[i], mapAttrs);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ gppVaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have
++ * reached an address aligned to a bigger page
++ * size*/
++ break;
++ }
++ }
++ }
++ paCurr += ulPadSize;
++ vaCurr += ulPadSize;
++ gppVaCurr += ulPadSize;
++
++ /* configure the TLB entries for the next cacheable segment */
++ numBytes = ulSegSize;
++ vaCurr = ulDspVa * hIOMgr->uWordSize;
++ allBits = 0x0;
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned*/
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits for Seg1 %x, paCurr %x, "
++ "vaCurr %x, numBytes %x\n", allBits, paCurr, vaCurr,
++ numBytes);
++ for (i = 0; i < 4; i++) {
++ if (!(numBytes >= pgSize[i]) ||
++ !((allBits & (pgSize[i]-1)) == 0))
++ continue;
++ if (ndx < MAX_LOCK_TLB_ENTRIES) {
++ /* This is the physical address written to
++ * DSP MMU */
++ aEProc[ndx].ulGppPa = paCurr;
++ /* THIS IS THE VIRTUAL UNCACHED IOREMAPPED
++ * ADDRESS!!! */
++ aEProc[ndx].ulGppVa = gppVaCurr;
++ aEProc[ndx].ulDspVa = vaCurr / hIOMgr->
++ uWordSize;
++ aEProc[ndx].ulSize = pgSize[i];
++ aEProc[ndx].endianism = HW_LITTLE_ENDIAN;
++ aEProc[ndx].elemSize = HW_ELEM_SIZE_16BIT;
++ aEProc[ndx].mixedMode = HW_MMU_CPUES;
++ DBG_Trace(DBG_LEVEL1, "SHM MMU TLB entry PA %lx"
++ " VA %lx DSP_VA %lx Size %lx\n",
++ aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulGppVa,
++ aEProc[ndx].ulDspVa *
++ hIOMgr->uWordSize, pgSize[i]);
++ ndx++;
++ } else {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap(
++ hIOMgr->hWmdContext, paCurr, vaCurr, pgSize[i],
++ mapAttrs);
++ DBG_Trace(DBG_LEVEL1, "SHM MMU PTE entry PA %lx"
++ " VA %lx DSP_VA %lx Size %lx\n",
++ aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulGppVa,
++ aEProc[ndx].ulDspVa *
++ hIOMgr->uWordSize, pgSize[i]);
++ DBC_Assert(DSP_SUCCEEDED(status));
++ }
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ gppVaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have reached
++ an address aligned to a bigger page size*/
++ break;
++ }
++ }
++
++ /* Copy remaining entries from CDB. All entries are 1 MB and should not
++ * conflict with SHM entries on MPU or DSP side */
++ for (i = 3; i < 7 && ndx < WMDIOCTL_NUMOFMMUTLB &&
++ DSP_SUCCEEDED(status); i++) {
++ if (hIOMgr->extProcInfo.tyTlb[i].ulGppPhys == 0)
++ continue;
++
++ if ((hIOMgr->extProcInfo.tyTlb[i].ulGppPhys > ulGppPa - 0x100000
++ && hIOMgr->extProcInfo.tyTlb[i].ulGppPhys <=
++ ulGppPa + ulSegSize)
++ || (hIOMgr->extProcInfo.tyTlb[i].ulDspVirt > ulDspVa -
++ 0x100000 / hIOMgr->uWordSize && hIOMgr->
++ extProcInfo.tyTlb[i].ulDspVirt
++ <= ulDspVa + ulSegSize / hIOMgr->uWordSize)) {
++ DBG_Trace(DBG_LEVEL7, "CDB MMU entry %d conflicts with "
++ "SHM.\n\tCDB: GppPa %x, DspVa %x.\n\tSHM: "
++ "GppPa %x, DspVa %x, Bytes %x.\n", i,
++ hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
++ hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
++ ulGppPa, ulDspVa, ulSegSize);
++ status = DSP_EFAIL;
++ } else {
++ if (ndx < MAX_LOCK_TLB_ENTRIES) {
++ aEProc[ndx].ulDspVa = hIOMgr->extProcInfo.
++ tyTlb[i].ulDspVirt;
++ aEProc[ndx].ulGppPa = hIOMgr->extProcInfo.
++ tyTlb[i].ulGppPhys;
++ aEProc[ndx].ulGppVa = 0;
++ /* Can't convert, so set to zero*/
++ aEProc[ndx].ulSize = 0x100000; /* 1 MB*/
++ DBG_Trace(DBG_LEVEL1, "SHM MMU entry PA %x "
++ "DSP_VA 0x%x\n", aEProc[ndx].ulGppPa,
++ aEProc[ndx].ulDspVa);
++ ndx++;
++ } else {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext,
++ hIOMgr->extProcInfo.tyTlb[i].ulGppPhys,
++ hIOMgr->extProcInfo.tyTlb[i].ulDspVirt,
++ 0x100000, mapAttrs);
++ }
++ }
++ }
++ if (i < 7 && DSP_SUCCEEDED(status)) {
++ /* All CDB entries could not be made*/
++ status = DSP_EFAIL;
++ }
++func_cont:
++ mapAttrs = 0x00000000;
++ mapAttrs = DSP_MAPLITTLEENDIAN;
++ mapAttrs |= DSP_MAPPHYSICALADDR;
++ mapAttrs |= DSP_MAPELEMSIZE32;
++ mapAttrs |= DSP_MAPDONOTLOCK;
++
++ /* Map the L4 peripherals */
++ i = 0;
++ while (L4PeripheralTable[i].physAddr && DSP_SUCCEEDED(status)) {
++ status = hIOMgr->pIntfFxns->pfnBrdMemMap
++ (hIOMgr->hWmdContext, L4PeripheralTable[i].physAddr,
++ L4PeripheralTable[i].dspVirtAddr, HW_PAGE_SIZE_4KB,
++ mapAttrs);
++ if (DSP_FAILED(status))
++ break;
++ i++;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ for (i = ndx; i < WMDIOCTL_NUMOFMMUTLB; i++) {
++ aEProc[i].ulDspVa = 0;
++ aEProc[i].ulGppPa = 0;
++ aEProc[i].ulGppVa = 0;
++ aEProc[i].ulSize = 0;
++ }
++ /* Set the SHM physical address entry (grayed out in CDB file)
++ * to the virtual uncached ioremapped address of SHM reserved
++ * on MPU */
++ hIOMgr->extProcInfo.tyTlb[0].ulGppPhys = (ulGppVa + ulSeg1Size +
++ ulPadSize);
++ DBG_Trace(DBG_LEVEL1, "*********extProcInfo *********%x \n",
++ hIOMgr->extProcInfo.tyTlb[0].ulGppPhys);
++ /* Need SHM Phys addr. IO supports only one DSP for now:
++ * uNumProcs=1 */
++ if ((hIOMgr->extProcInfo.tyTlb[0].ulGppPhys == 0) ||
++ (uNumProcs != 1)) {
++ status = CHNL_E_NOMEMMAP;
++ DBC_Assert(false);
++ } else {
++ DBC_Assert(aEProc[0].ulDspVa <= ulShmBase);
++ /* ulShmBase may not be at ulDspVa address */
++ ulShmBaseOffset = (ulShmBase - aEProc[0].ulDspVa) *
++ hIOMgr->uWordSize;
++ /* WMD_BRD_Ctrl() will set dev context dsp-mmu info. In
++ * _BRD_Start() the MMU will be re-programed with MMU
++ * DSPVa-GPPPa pair info while DSP is in a known
++ * (reset) state. */
++ DBC_Assert(hIOMgr->pIntfFxns != NULL);
++ DBC_Assert(hIOMgr->hWmdContext != NULL);
++ status = hIOMgr->pIntfFxns->pfnDevCntrl(hIOMgr->
++ hWmdContext, WMDIOCTL_SETMMUCONFIG, aEProc);
++ ulShmBase = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
++ DBG_Trace(DBG_LEVEL1, "extProcInfo.tyTlb[0].ulGppPhys "
++ "%x \n ", hIOMgr->extProcInfo.tyTlb[0].
++ ulGppPhys);
++ ulShmBase += ulShmBaseOffset;
++ ulShmBase = (u32)MEM_LinearAddress((void *)ulShmBase,
++ ulMemLength);
++ DBC_Assert(ulShmBase != 0);
++ if (DSP_SUCCEEDED(status)) {
++ status = registerSHMSegs(hIOMgr, hCodMan,
++ aEProc[0].ulGppPa);
++ /* Register SM */
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ hIOMgr->pSharedMem = (struct SHM *)ulShmBase;
++ hIOMgr->pInput = (u8 *)hIOMgr->pSharedMem +
++ sizeof(struct SHM);
++ hIOMgr->pOutput = hIOMgr->pInput + (ulShmLength -
++ sizeof(struct SHM))/2;
++ hIOMgr->uSMBufSize = hIOMgr->pOutput - hIOMgr->pInput;
++ DBG_Trace(DBG_LEVEL3,
++ "hIOMgr: pInput %p pOutput %p ulShmLength %x\n",
++ hIOMgr->pInput, hIOMgr->pOutput, ulShmLength);
++ DBG_Trace(DBG_LEVEL3,
++ "pSharedMem %p uSMBufSize %x sizeof(SHM) %x\n",
++ hIOMgr->pSharedMem, hIOMgr->uSMBufSize,
++ sizeof(struct SHM));
++ /* Set up Shared memory addresses for messaging. */
++ hIOMgr->pMsgInputCtrl = (struct MSG *)((u8 *)
++ hIOMgr->pSharedMem +
++ ulShmLength);
++ hIOMgr->pMsgInput = (u8 *)hIOMgr->pMsgInputCtrl +
++ sizeof(struct MSG);
++ hIOMgr->pMsgOutputCtrl = (struct MSG *)((u8 *)hIOMgr->
++ pMsgInputCtrl + ulMsgLength / 2);
++ hIOMgr->pMsgOutput = (u8 *)hIOMgr->pMsgOutputCtrl +
++ sizeof(struct MSG);
++ hMsgMgr->uMaxMsgs = ((u8 *)hIOMgr->pMsgOutputCtrl -
++ hIOMgr->pMsgInput) /
++ sizeof(struct MSG_DSPMSG);
++ DBG_Trace(DBG_LEVEL7, "IO MGR SHM details : pSharedMem 0x%x, "
++ "pInput 0x%x, pOutput 0x%x, pMsgInputCtrl 0x%x, "
++ "pMsgInput 0x%x, pMsgOutputCtrl 0x%x, pMsgOutput "
++ "0x%x \n", (u8 *)hIOMgr->pSharedMem,
++ (u8 *)hIOMgr->pInput, (u8 *)hIOMgr->pOutput,
++ (u8 *)hIOMgr->pMsgInputCtrl,
++ (u8 *)hIOMgr->pMsgInput,
++ (u8 *)hIOMgr->pMsgOutputCtrl,
++ (u8 *)hIOMgr->pMsgOutput);
++ DBG_Trace(DBG_LEVEL7, "** (proc) MAX MSGS IN SHARED MEMORY: "
++ "0x%x\n", hMsgMgr->uMaxMsgs);
++ memset((void *) hIOMgr->pSharedMem, 0, sizeof(struct SHM));
++ }
++#ifndef DSP_TRACEBUF_DISABLED
++ if (DSP_SUCCEEDED(status)) {
++ /* Get the start address of trace buffer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, SYS_PUTCBEG,
++ &hIOMgr->ulTraceBufferBegin);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin =
++ (ulGppVa + ulSeg1Size + ulPadSize) +
++ (hIOMgr->ulTraceBufferBegin - ulDspVa);
++ /* Get the end address of trace buffer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan, SYS_PUTCEND,
++ &hIOMgr->ulTraceBufferEnd);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulTraceBufferEnd = (ulGppVa + ulSeg1Size + ulPadSize) +
++ (hIOMgr->ulTraceBufferEnd - ulDspVa);
++ /* Get the current address of DSP write pointer */
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMan,
++ BRIDGE_SYS_PUTC_current,
++ &hIOMgr->ulTraceBufferCurrent);
++ if (DSP_FAILED(status))
++ status = CHNL_E_NOMEMMAP;
++
++ }
++ hIOMgr->ulTraceBufferCurrent = (ulGppVa + ulSeg1Size +
++ ulPadSize) + (hIOMgr->
++ ulTraceBufferCurrent - ulDspVa);
++ /* Calculate the size of trace buffer */
++ if (hIOMgr->pMsg)
++ MEM_Free(hIOMgr->pMsg);
++ hIOMgr->pMsg = MEM_Alloc(((hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulTraceBufferBegin) *
++ hIOMgr->uWordSize) + 2, MEM_NONPAGED);
++ if (!hIOMgr->pMsg)
++ status = DSP_EMEMORY;
++
++ DBG_Trace(DBG_LEVEL1, "** hIOMgr->pMsg: 0x%x\n", hIOMgr->pMsg);
++ hIOMgr->ulDspVa = ulDspVa;
++ hIOMgr->ulGppVa = (ulGppVa + ulSeg1Size + ulPadSize);
++ }
++#endif
++ IO_EnableInterrupt(hIOMgr->hWmdContext);
++ return status;
++}
++
++/*
++ * ======== IO_BufSize ========
++ * Size of shared memory I/O channel.
++ */
++u32 IO_BufSize(struct IO_MGR *hIOMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++
++ return hIOMgr->uSMBufSize;
++}
++
++/*
++ * ======== IO_CancelChnl ========
++ * Cancel IO on a given PCPY channel.
++ */
++void IO_CancelChnl(struct IO_MGR *hIOMgr, u32 ulChnl)
++{
++ struct IO_MGR *pIOMgr = (struct IO_MGR *)hIOMgr;
++ struct SHM *sm;
++
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++ sm = hIOMgr->pSharedMem;
++
++ /* Inform DSP that we have no more buffers on this channel: */
++ IO_AndValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
++ (~(1 << ulChnl)));
++
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++}
++
++/*
++ * ======== IO_DispatchChnl ========
++ * Proc-copy chanl dispatch.
++ */
++static void IO_DispatchChnl(IN struct IO_MGR *pIOMgr,
++ IN OUT struct CHNL_OBJECT *pChnl, u32 iMode)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchChnl \n");
++
++ /* See if there is any data available for transfer: */
++ DBC_Assert(iMode == IO_SERVICE);
++
++ /* Any channel will do for this mode: */
++ InputChnl(pIOMgr, pChnl, iMode);
++ OutputChnl(pIOMgr, pChnl, iMode);
++}
++
++/*
++ * ======== IO_DispatchMsg ========
++ * Performs I/O dispatch on message queues.
++ */
++static void IO_DispatchMsg(IN struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DBG_Trace(DBG_LEVEL3, "Entering IO_DispatchMsg \n");
++
++ /* We are performing both input and output processing. */
++ InputMsg(pIOMgr, hMsgMgr);
++ OutputMsg(pIOMgr, hMsgMgr);
++}
++
++/*
++ * ======== IO_DispatchPM ========
++ * Performs I/O dispatch on PM related messages from DSP
++ */
++static void IO_DispatchPM(struct work_struct *work)
++{
++ struct IO_MGR *pIOMgr =
++ container_of(work, struct IO_MGR, io_workq);
++ DSP_STATUS status;
++ u32 pArg[2];
++
++ /*DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));*/
++
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM: Entering IO_DispatchPM : \n");
++
++ /* Perform Power message processing here */
++ while (pIOMgr->iQuePowerHead != pIOMgr->iQuePowerTail) {
++ pArg[0] = *(u32 *)&(pIOMgr->dQuePowerMbxVal[pIOMgr->
++ iQuePowerTail]);
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - pArg[0] - 0x%x: \n",
++ pArg[0]);
++ /* Send the command to the WMD clk/pwr manager to handle */
++ if (pArg[0] == MBX_PM_HIBERNATE_EN) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Hibernate "
++ "command\n");
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_PWR_HIBERNATE, pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : "
++ "Hibernation command failed\n");
++ }
++ } else if (pArg[0] == MBX_PM_OPP_REQ) {
++ pArg[1] = pIOMgr->pSharedMem->oppRequest.rqstOppPt;
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Value of OPP "
++ "value =0x%x \n", pArg[1]);
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_CONSTRAINT_REQUEST,
++ pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
++ "to set constraint = 0x%x \n",
++ pArg[1]);
++ }
++
++ } else {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM - clock control - "
++ "value of msg = 0x%x: \n", pArg[0]);
++ status = pIOMgr->pIntfFxns->pfnDevCntrl(pIOMgr->
++ hWmdContext, WMDIOCTL_CLK_CTRL, pArg);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "IO_DispatchPM : Failed "
++ "to control the DSP clk = 0x%x \n",
++ *pArg);
++ }
++ }
++ /* increment the tail count here */
++ pIOMgr->iQuePowerTail++;
++ if (pIOMgr->iQuePowerTail >= MAX_PM_REQS)
++ pIOMgr->iQuePowerTail = 0;
++
++ }
++
++}
++
++/*
++ * ======== IO_DPC ========
++ * Deferred procedure call for shared memory channel driver ISR. Carries
++ * out the dispatch of I/O as a non-preemptible event.It can only be
++ * pre-empted by an ISR.
++ */
++void IO_DPC(IN OUT void *pRefData)
++{
++ struct IO_MGR *pIOMgr = (struct IO_MGR *)pRefData;
++ struct CHNL_MGR *pChnlMgr;
++ struct MSG_MGR *pMsgMgr;
++ struct DEH_MGR *hDehMgr;
++
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++ pChnlMgr = pIOMgr->hChnlMgr;
++ DEV_GetMsgMgr(pIOMgr->hDevObject, &pMsgMgr);
++ DEV_GetDehMgr(pIOMgr->hDevObject, &hDehMgr);
++ DBC_Require(MEM_IsValidHandle(pChnlMgr, CHNL_MGRSIGNATURE));
++ DBG_Trace(DBG_LEVEL7, "Entering IO_DPC(0x%x)\n", pRefData);
++ /* Check value of interrupt register to ensure it is a valid error */
++ if ((pIOMgr->wIntrVal > DEH_BASE) && (pIOMgr->wIntrVal < DEH_LIMIT)) {
++ /* notify DSP/BIOS exception */
++ if (hDehMgr)
++ WMD_DEH_Notify(hDehMgr, DSP_SYSERROR, pIOMgr->wIntrVal);
++
++ }
++ IO_DispatchChnl(pIOMgr, NULL, IO_SERVICE);
++#ifdef CHNL_MESSAGES
++ if (pMsgMgr) {
++ DBC_Require(MEM_IsValidHandle(pMsgMgr, MSGMGR_SIGNATURE));
++ IO_DispatchMsg(pIOMgr, pMsgMgr);
++ }
++#endif
++#ifndef DSP_TRACEBUF_DISABLED
++ if (pIOMgr->wIntrVal & MBX_DBG_CLASS) {
++ /* notify DSP Trace message */
++ if (pIOMgr->wIntrVal & MBX_DBG_SYSPRINTF)
++ PrintDSPDebugTrace(pIOMgr);
++ }
++#endif
++
++#ifndef DSP_TRACEBUF_DISABLED
++ PrintDSPDebugTrace(pIOMgr);
++#endif
++}
++
++
++/*
++ * ======== IO_ISR ========
++ * Main interrupt handler for the shared memory IO manager.
++ * Calls the WMD's CHNL_ISR to determine if this interrupt is ours, then
++ * schedules a DPC to dispatch I/O.
++ */
++irqreturn_t IO_ISR(int irq, IN void *pRefData)
++{
++ struct IO_MGR *hIOMgr = (struct IO_MGR *)pRefData;
++ bool fSchedDPC;
++ DBC_Require(irq == INT_MAIL_MPU_IRQ);
++ DBC_Require(MEM_IsValidHandle(hIOMgr, IO_MGRSIGNATURE));
++ DBG_Trace(DBG_LEVEL3, "Entering IO_ISR(0x%x)\n", pRefData);
++
++ /* Call WMD's CHNLSM_ISR() to see if interrupt is ours, and process. */
++ if (IO_CALLISR(hIOMgr->hWmdContext, &fSchedDPC, &hIOMgr->wIntrVal)) {
++ {
++ DBG_Trace(DBG_LEVEL3, "IO_ISR %x\n", hIOMgr->wIntrVal);
++ if (hIOMgr->wIntrVal & MBX_PM_CLASS) {
++ hIOMgr->dQuePowerMbxVal[hIOMgr->iQuePowerHead] =
++ hIOMgr->wIntrVal;
++ hIOMgr->iQuePowerHead++;
++ if (hIOMgr->iQuePowerHead >= MAX_PM_REQS)
++ hIOMgr->iQuePowerHead = 0;
++
++ queue_work(bridge_workqueue, &hIOMgr->io_workq);
++ }
++ if (hIOMgr->wIntrVal == MBX_DEH_RESET) {
++ DBG_Trace(DBG_LEVEL6, "*** DSP RESET ***\n");
++ hIOMgr->wIntrVal = 0;
++ } else if (fSchedDPC) {
++ /* PROC-COPY defer i/o */
++ DPC_Schedule(hIOMgr->hDPC);
++ }
++ }
++ } else
++ /* Ensure that, if WMD didn't claim it, the IRQ is shared. */
++ DBC_Ensure(hIOMgr->fSharedIRQ);
++ return IRQ_HANDLED;
++}
++
++/*
++ * ======== IO_RequestChnl ========
++ * Purpose:
++ * Request chanenel I/O from the DSP. Sets flags in shared memory, then
++ * interrupts the DSP.
++ */
++void IO_RequestChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode, OUT u16 *pwMbVal)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ DBC_Require(pChnl != NULL);
++ DBC_Require(pwMbVal != NULL);
++ pChnlMgr = pIOMgr->hChnlMgr;
++ sm = pIOMgr->pSharedMem;
++ if (iMode == IO_INPUT) {
++ /* Assertion fires if CHNL_AddIOReq() called on a stream
++ * which was cancelled, or attached to a dead board: */
++ DBC_Assert((pChnl->dwState == CHNL_STATEREADY) ||
++ (pChnl->dwState == CHNL_STATEEOS));
++ /* Indicate to the DSP we have a buffer available for input: */
++ IO_OrValue(pIOMgr->hWmdContext, struct SHM, sm, hostFreeMask,
++ (1 << pChnl->uId));
++ *pwMbVal = MBX_PCPY_CLASS;
++ } else if (iMode == IO_OUTPUT) {
++ /* This assertion fails if CHNL_AddIOReq() was called on a
++ * stream which was cancelled, or attached to a dead board: */
++ DBC_Assert((pChnl->dwState & ~CHNL_STATEEOS) ==
++ CHNL_STATEREADY);
++ /* Record the fact that we have a buffer available for
++ * output: */
++ pChnlMgr->dwOutputMask |= (1 << pChnl->uId);
++ } else {
++ DBC_Assert(iMode); /* Shouldn't get here. */
++ }
++}
++
++/*
++ * ======== IO_Schedule ========
++ * Schedule DPC for IO.
++ */
++void IO_Schedule(struct IO_MGR *pIOMgr)
++{
++ DBC_Require(MEM_IsValidHandle(pIOMgr, IO_MGRSIGNATURE));
++
++ DPC_Schedule(pIOMgr->hDPC);
++}
++
++/*
++ * ======== FindReadyOutput ========
++ * Search for a host output channel which is ready to send. If this is
++ * called as a result of servicing the DPC, then implement a round
++ * robin search; otherwise, this was called by a client thread (via
++ * IO_Dispatch()), so just start searching from the current channel id.
++ */
++static u32 FindReadyOutput(struct CHNL_MGR *pChnlMgr,
++ struct CHNL_OBJECT *pChnl, u32 dwMask)
++{
++ u32 uRetval = OUTPUTNOTREADY;
++ u32 id, startId;
++ u32 shift;
++
++ id = (pChnl != NULL ? pChnl->uId : (pChnlMgr->dwLastOutput + 1));
++ id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
++ DBC_Assert(id < CHNL_MAXCHANNELS);
++ if (dwMask) {
++ shift = (1 << id);
++ startId = id;
++ do {
++ if (dwMask & shift) {
++ uRetval = id;
++ if (pChnl == NULL)
++ pChnlMgr->dwLastOutput = id;
++
++ break;
++ }
++ id = id + 1;
++ id = ((id == CHNL_MAXCHANNELS) ? 0 : id);
++ shift = (1 << id);
++ } while (id != startId);
++ }
++ DBC_Ensure((uRetval == OUTPUTNOTREADY) || (uRetval < CHNL_MAXCHANNELS));
++ return uRetval;
++}
++
++/*
++ * ======== InputChnl ========
++ * Dispatch a buffer on an input channel.
++ */
++static void InputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ u32 chnlId;
++ u32 uBytes;
++ struct CHNL_IRP *pChirp = NULL;
++ u32 dwArg;
++ bool fClearChnl = false;
++ bool fNotifyClient = false;
++
++ sm = pIOMgr->pSharedMem;
++ pChnlMgr = pIOMgr->hChnlMgr;
++
++ DBG_Trace(DBG_LEVEL3, "> InputChnl\n");
++
++ /* Attempt to perform input.... */
++ if (!IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull))
++ goto func_end;
++
++ uBytes = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputSize) *
++ pChnlMgr->uWordSize;
++ chnlId = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, inputId);
++ dwArg = IO_GetLong(pIOMgr->hWmdContext, struct SHM, sm, arg);
++ if (!(chnlId >= 0) || !(chnlId < CHNL_MAXCHANNELS)) {
++ /* Shouldn't be here: would indicate corrupted SHM. */
++ DBC_Assert(chnlId);
++ goto func_end;
++ }
++ pChnl = pChnlMgr->apChannel[chnlId];
++ if ((pChnl != NULL) && CHNL_IsInput(pChnl->uMode)) {
++ if ((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY) {
++ if (!pChnl->pIORequests)
++ goto func_end;
++ /* Get the I/O request, and attempt a transfer: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->
++ pIORequests);
++ if (pChirp) {
++ pChnl->cIOReqs--;
++ DBC_Assert(pChnl->cIOReqs >= 0);
++ /* Ensure we don't overflow the client's
++ * buffer: */
++ uBytes = min(uBytes, pChirp->cBytes);
++ /* Transfer buffer from DSP side: */
++ uBytes = ReadData(pIOMgr->hWmdContext,
++ pChirp->pHostSysBuf,
++ pIOMgr->pInput, uBytes);
++ pChnl->cBytesMoved += uBytes;
++ pChirp->cBytes = uBytes;
++ pChirp->dwArg = dwArg;
++ pChirp->status = CHNL_IOCSTATCOMPLETE;
++ DBG_Trace(DBG_LEVEL7, "Input Chnl:status= 0x%x "
++ "\n", *((RMS_WORD *)(pChirp->
++ pHostSysBuf)));
++ if (uBytes == 0) {
++ /* This assertion fails if the DSP
++ * sends EOS more than once on this
++ * channel: */
++ DBC_Assert(!(pChnl->dwState &
++ CHNL_STATEEOS));
++ /* Zero bytes indicates EOS. Update
++ * IOC status for this chirp, and also
++ * the channel state: */
++ pChirp->status |= CHNL_IOCSTATEOS;
++ pChnl->dwState |= CHNL_STATEEOS;
++ /* Notify that end of stream has
++ * occurred */
++ NTFY_Notify(pChnl->hNtfy,
++ DSP_STREAMDONE);
++ DBG_Trace(DBG_LEVEL7, "Input Chnl NTFY "
++ "chnl = 0x%x\n", pChnl);
++ }
++ /* Tell DSP if no more I/O buffers available: */
++ if (!pChnl->pIORequests)
++ goto func_end;
++ if (LST_IsEmpty(pChnl->pIORequests)) {
++ IO_AndValue(pIOMgr->hWmdContext,
++ struct SHM, sm, hostFreeMask,
++ ~(1 << pChnl->uId));
++ }
++ fClearChnl = true;
++ fNotifyClient = true;
++ } else {
++ /* Input full for this channel, but we have no
++ * buffers available. The channel must be
++ * "idling". Clear out the physical input
++ * channel. */
++ fClearChnl = true;
++ }
++ } else {
++ /* Input channel cancelled: clear input channel. */
++ fClearChnl = true;
++ }
++ } else {
++ /* DPC fired after host closed channel: clear input channel. */
++ fClearChnl = true;
++ }
++ if (fClearChnl) {
++ /* Indicate to the DSP we have read the input: */
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, inputFull, 0);
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++ if (fNotifyClient) {
++ /* Notify client with IO completion record: */
++ NotifyChnlComplete(pChnl, pChirp);
++ }
++func_end:
++ DBG_Trace(DBG_LEVEL3, "< InputChnl\n");
++}
++
++/*
++ * ======== InputMsg ========
++ * Copies messages from shared memory to the message queues.
++ */
++static void InputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ u32 uMsgs;
++ u32 i;
++ u8 *pMsgInput;
++ struct MSG_QUEUE *hMsgQueue;
++ struct MSG_FRAME *pMsg;
++ struct MSG_DSPMSG msg;
++ struct MSG *pCtrl;
++ u32 fInputEmpty;
++ u32 addr;
++
++ pCtrl = pIOMgr->pMsgInputCtrl;
++ /* Get the number of input messages to be read. */
++ fInputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty);
++ uMsgs = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, size);
++ if (fInputEmpty || uMsgs >= hMsgMgr->uMaxMsgs)
++ return;
++
++ pMsgInput = pIOMgr->pMsgInput;
++ for (i = 0; i < uMsgs; i++) {
++ /* Read the next message */
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwCmd);
++ msg.msg.dwCmd = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg1);
++ msg.msg.dwArg1 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->msg.dwArg2);
++ msg.msg.dwArg2 = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ addr = (u32)&(((struct MSG_DSPMSG *)pMsgInput)->dwId);
++ msg.dwId = ReadExt32BitDspData(pIOMgr->hWmdContext, addr);
++ pMsgInput += sizeof(struct MSG_DSPMSG);
++ if (!hMsgMgr->queueList)
++ goto func_end;
++
++ /* Determine which queue to put the message in */
++ hMsgQueue = (struct MSG_QUEUE *)LST_First(hMsgMgr->queueList);
++ DBG_Trace(DBG_LEVEL7, "InputMsg RECVD: dwCmd=0x%x dwArg1=0x%x "
++ "dwArg2=0x%x dwId=0x%x \n", msg.msg.dwCmd,
++ msg.msg.dwArg1, msg.msg.dwArg2, msg.dwId);
++ /* Interrupt may occur before shared memory and message
++ * input locations have been set up. If all nodes were
++ * cleaned up, hMsgMgr->uMaxMsgs should be 0. */
++ if (hMsgQueue && uMsgs > hMsgMgr->uMaxMsgs)
++ goto func_end;
++
++ while (hMsgQueue != NULL) {
++ if (msg.dwId == hMsgQueue->dwId) {
++ /* Found it */
++ if (msg.msg.dwCmd == RMS_EXITACK) {
++ /* The exit message does not get
++ * queued */
++ /* Call the node exit notification */
++ /* Node handle */ /* status */
++ (*hMsgMgr->onExit)((HANDLE)hMsgQueue->
++ hArg, msg.msg.dwArg1);
++ } else {
++ /* Not an exit acknowledgement, queue
++ * the message */
++ if (!hMsgQueue->msgFreeList)
++ goto func_end;
++ pMsg = (struct MSG_FRAME *)LST_GetHead
++ (hMsgQueue->msgFreeList);
++ if (hMsgQueue->msgUsedList && pMsg) {
++ pMsg->msgData = msg;
++ LST_PutTail(hMsgQueue->
++ msgUsedList,
++ (struct LST_ELEM *)pMsg);
++ NTFY_Notify(hMsgQueue->hNtfy,
++ DSP_NODEMESSAGEREADY);
++ SYNC_SetEvent(hMsgQueue->
++ hSyncEvent);
++ } else {
++ /* No free frame to copy the
++ * message into */
++ DBG_Trace(DBG_LEVEL7, "NO FREE "
++ "MSG FRAMES, DISCARDING"
++ " MESSAGE\n");
++ }
++ }
++ break;
++ }
++
++ if (!hMsgMgr->queueList || !hMsgQueue)
++ goto func_end;
++ hMsgQueue = (struct MSG_QUEUE *)LST_Next(hMsgMgr->
++ queueList, (struct LST_ELEM *)hMsgQueue);
++ }
++ }
++ /* Set the post SWI flag */
++ if (uMsgs > 0) {
++ /* Tell the DSP we've read the messages */
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, bufEmpty,
++ true);
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl, postSWI,
++ true);
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++func_end:
++ return;
++
++}
++
++/*
++ * ======== NotifyChnlComplete ========
++ * Purpose:
++ * Signal the channel event, notifying the client that I/O has completed.
++ */
++static void NotifyChnlComplete(struct CHNL_OBJECT *pChnl,
++ struct CHNL_IRP *pChirp)
++{
++ bool fSignalEvent;
++
++ DBC_Require(MEM_IsValidHandle(pChnl, CHNL_SIGNATURE));
++ DBC_Require(pChnl->hSyncEvent != NULL);
++ /* Note: we signal the channel event only if the queue of IO
++ * completions is empty. If it is not empty, the event is sure to be
++ * signalled by the only IO completion list consumer:
++ * WMD_CHNL_GetIOC(). */
++ fSignalEvent = LST_IsEmpty(pChnl->pIOCompletions);
++ /* Enqueue the IO completion info for the client: */
++ LST_PutTail(pChnl->pIOCompletions, (struct LST_ELEM *) pChirp);
++ pChnl->cIOCs++;
++ DBC_Assert(pChnl->cIOCs <= pChnl->cChirps);
++ /* Signal the channel event (if not already set) that IO is complete: */
++ if (fSignalEvent)
++ SYNC_SetEvent(pChnl->hSyncEvent);
++
++ /* Notify that IO is complete */
++ NTFY_Notify(pChnl->hNtfy, DSP_STREAMIOCOMPLETION);
++}
++
++/*
++ * ======== OutputChnl ========
++ * Purpose:
++ * Dispatch a buffer on an output channel.
++ */
++static void OutputChnl(struct IO_MGR *pIOMgr, struct CHNL_OBJECT *pChnl,
++ u32 iMode)
++{
++ struct CHNL_MGR *pChnlMgr;
++ struct SHM *sm;
++ u32 chnlId;
++ struct CHNL_IRP *pChirp;
++ u32 dwDspFMask;
++
++ pChnlMgr = pIOMgr->hChnlMgr;
++ sm = pIOMgr->pSharedMem;
++ DBG_Trace(DBG_LEVEL3, "> OutputChnl\n");
++ /* Attempt to perform output: */
++ if (IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull))
++ goto func_end;
++
++ if (pChnl && !((pChnl->dwState & ~CHNL_STATEEOS) == CHNL_STATEREADY))
++ goto func_end;
++
++ /* Look to see if both a PC and DSP output channel are ready: */
++ dwDspFMask = IO_GetValue(pIOMgr->hWmdContext, struct SHM, sm,
++ dspFreeMask);
++ chnlId = FindReadyOutput(pChnlMgr, pChnl, (pChnlMgr->dwOutputMask &
++ dwDspFMask));
++ if (chnlId == OUTPUTNOTREADY)
++ goto func_end;
++
++ pChnl = pChnlMgr->apChannel[chnlId];
++ if (!pChnl || !pChnl->pIORequests) {
++ /* Shouldn't get here: */
++ goto func_end;
++ }
++ /* Get the I/O request, and attempt a transfer: */
++ pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests);
++ if (!pChirp)
++ goto func_end;
++
++ pChnl->cIOReqs--;
++ if (pChnl->cIOReqs < 0 || !pChnl->pIORequests)
++ goto func_end;
++
++ /* Record fact that no more I/O buffers available: */
++ if (LST_IsEmpty(pChnl->pIORequests))
++ pChnlMgr->dwOutputMask &= ~(1 << chnlId);
++
++ /* Transfer buffer to DSP side: */
++ pChirp->cBytes = WriteData(pIOMgr->hWmdContext, pIOMgr->pOutput,
++ pChirp->pHostSysBuf, min(pIOMgr->uSMBufSize, pChirp->
++ cBytes));
++ pChnl->cBytesMoved += pChirp->cBytes;
++ /* Write all 32 bits of arg */
++ IO_SetLong(pIOMgr->hWmdContext, struct SHM, sm, arg, pChirp->dwArg);
++#if _CHNL_WORDSIZE == 2
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId,
++ (u16)chnlId);
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
++ (u16)(pChirp->cBytes + (pChnlMgr->uWordSize-1)) /
++ (u16)pChnlMgr->uWordSize);
++#else
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputId, chnlId);
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputSize,
++ (pChirp->cBytes + (pChnlMgr->uWordSize - 1)) / pChnlMgr->
++ uWordSize);
++#endif
++ IO_SetValue(pIOMgr->hWmdContext, struct SHM, sm, outputFull, 1);
++ /* Indicate to the DSP we have written the output: */
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ /* Notify client with IO completion record (keep EOS) */
++ pChirp->status &= CHNL_IOCSTATEOS;
++ NotifyChnlComplete(pChnl, pChirp);
++ /* Notify if stream is done. */
++ if (pChirp->status & CHNL_IOCSTATEOS)
++ NTFY_Notify(pChnl->hNtfy, DSP_STREAMDONE);
++
++func_end:
++ DBG_Trace(DBG_LEVEL3, "< OutputChnl\n");
++}
++/*
++ * ======== OutputMsg ========
++ * Copies messages from the message queues to the shared memory.
++ */
++static void OutputMsg(struct IO_MGR *pIOMgr, struct MSG_MGR *hMsgMgr)
++{
++ u32 uMsgs = 0;
++ u32 i;
++ u8 *pMsgOutput;
++ struct MSG_FRAME *pMsg;
++ struct MSG *pCtrl;
++ u32 fOutputEmpty;
++ u32 val;
++ u32 addr;
++
++ pCtrl = pIOMgr->pMsgOutputCtrl;
++
++ /* Check if output has been cleared */
++ fOutputEmpty = IO_GetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty);
++ if (fOutputEmpty) {
++ uMsgs = (hMsgMgr->uMsgsPending > hMsgMgr->uMaxMsgs) ?
++ hMsgMgr->uMaxMsgs : hMsgMgr->uMsgsPending;
++ pMsgOutput = pIOMgr->pMsgOutput;
++ /* Copy uMsgs messages into shared memory */
++ for (i = 0; i < uMsgs; i++) {
++ if (!hMsgMgr->msgUsedList) {
++ DBG_Trace(DBG_LEVEL3, "msgUsedList is NULL\n");
++ pMsg = NULL;
++ goto func_end;
++ } else
++ pMsg = (struct MSG_FRAME *)LST_GetHead(
++ hMsgMgr->msgUsedList);
++ if (pMsg != NULL) {
++ val = (pMsg->msgData).dwId;
++ addr = (u32)&(((struct MSG_DSPMSG *)
++ pMsgOutput)->dwId);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwCmd;
++ addr = (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwCmd);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwArg1;
++ addr =
++ (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwArg1);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ val = (pMsg->msgData).msg.dwArg2;
++ addr =
++ (u32)&((((struct MSG_DSPMSG *)
++ pMsgOutput)->msg).dwArg2);
++ WriteExt32BitDspData(pIOMgr->hWmdContext, addr,
++ val);
++ pMsgOutput += sizeof(struct MSG_DSPMSG);
++ if (!hMsgMgr->msgFreeList)
++ goto func_end;
++ LST_PutTail(hMsgMgr->msgFreeList,
++ (struct LST_ELEM *) pMsg);
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++ } else {
++ DBG_Trace(DBG_LEVEL3, "pMsg is NULL\n");
++ }
++ }
++
++ if (uMsgs > 0) {
++ hMsgMgr->uMsgsPending -= uMsgs;
++#if _CHNL_WORDSIZE == 2
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ size, (u16)uMsgs);
++#else
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ size, uMsgs);
++#endif
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ bufEmpty, false);
++ /* Set the post SWI flag */
++ IO_SetValue(pIOMgr->hWmdContext, struct MSG, pCtrl,
++ postSWI, true);
++ /* Tell the DSP we have written the output. */
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, MBX_PCPY_CLASS);
++ }
++ }
++func_end:
++ return;
++
++}
++
++/*
++ * ======== registerSHMSegs ========
++ * purpose:
++ * Registers GPP SM segment with CMM.
++ */
++static DSP_STATUS registerSHMSegs(struct IO_MGR *hIOMgr,
++ struct COD_MANAGER *hCodMan,
++ u32 dwGPPBasePA)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 ulShm0_Base = 0;
++ u32 ulShm0_End = 0;
++ u32 ulShm0_RsrvdStart = 0;
++ u32 ulRsrvdSize = 0;
++ u32 ulGppPhys;
++ u32 ulDspVirt;
++ u32 ulShmSegId0 = 0;
++ u32 dwOffset, dwGPPBaseVA, ulDSPSize;
++
++ /* Read address and size info for first SM region.*/
++ /* Get start of 1st SM Heap region */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_BASE_SYM, &ulShm0_Base);
++ DBC_Assert(ulShm0_Base != 0);
++ /* Get end of 1st SM Heap region */
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_END_SYM,
++ &ulShm0_End);
++ DBC_Assert(ulShm0_End != 0);
++ }
++ /* start of Gpp reserved region */
++ if (DSP_SUCCEEDED(status)) {
++ /* Get start and length of message part of shared memory */
++ status = COD_GetSymValue(hCodMan, SHM0_SHARED_RESERVED_BASE_SYM,
++ &ulShm0_RsrvdStart);
++ DBG_Trace(DBG_LEVEL1, "***ulShm0_RsrvdStart 0x%x \n",
++ ulShm0_RsrvdStart);
++ DBC_Assert(ulShm0_RsrvdStart != 0);
++ }
++ /* Register with CMM */
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetCmmMgr(hIOMgr->hDevObject, &hIOMgr->hCmmMgr);
++ if (DSP_SUCCEEDED(status)) {
++ status = CMM_UnRegisterGPPSMSeg(hIOMgr->hCmmMgr,
++ CMM_ALLSEGMENTS);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Unable to "
++ "Un-Register SM segments \n");
++ }
++ } else {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Unable to get CMM "
++ "Handle \n");
++ }
++ }
++ /* Register new SM region(s) */
++ if (DSP_SUCCEEDED(status) && (ulShm0_End - ulShm0_Base) > 0) {
++ /* calc size (bytes) of SM the GPP can alloc from */
++ ulRsrvdSize = (ulShm0_End - ulShm0_RsrvdStart + 1) * hIOMgr->
++ uWordSize;
++ DBC_Assert(ulRsrvdSize > 0);
++ /* calc size of SM DSP can alloc from */
++ ulDSPSize = (ulShm0_RsrvdStart - ulShm0_Base) * hIOMgr->
++ uWordSize;
++ DBC_Assert(ulDSPSize > 0);
++ /* First TLB entry reserved for Bridge SM use.*/
++ ulGppPhys = hIOMgr->extProcInfo.tyTlb[0].ulGppPhys;
++ /* get size in bytes */
++ ulDspVirt = hIOMgr->extProcInfo.tyTlb[0].ulDspVirt * hIOMgr->
++ uWordSize;
++ /* Calc byte offset used to convert GPP phys <-> DSP byte
++ * address.*/
++ if (dwGPPBasePA > ulDspVirt)
++ dwOffset = dwGPPBasePA - ulDspVirt;
++ else
++ dwOffset = ulDspVirt - dwGPPBasePA;
++
++ DBC_Assert(ulShm0_RsrvdStart * hIOMgr->uWordSize >= ulDspVirt);
++ /* calc Gpp phys base of SM region */
++ /* Linux - this is actually uncached kernel virtual address*/
++ dwGPPBaseVA = ulGppPhys + ulShm0_RsrvdStart * hIOMgr->uWordSize
++ - ulDspVirt;
++ /* calc Gpp phys base of SM region */
++ /* Linux - this is the physical address*/
++ dwGPPBasePA = dwGPPBasePA + ulShm0_RsrvdStart * hIOMgr->
++ uWordSize - ulDspVirt;
++ /* Register SM Segment 0.*/
++ status = CMM_RegisterGPPSMSeg(hIOMgr->hCmmMgr, dwGPPBasePA,
++ ulRsrvdSize, dwOffset, (dwGPPBasePA > ulDspVirt) ?
++ CMM_ADDTODSPPA : CMM_SUBFROMDSPPA,
++ (u32)(ulShm0_Base * hIOMgr->uWordSize),
++ ulDSPSize, &ulShmSegId0, dwGPPBaseVA);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, "ERROR - Failed to register SM "
++ "Seg 0 \n");
++ }
++ /* first SM region is segId = 1 */
++ DBC_Assert(ulShmSegId0 == 1);
++ }
++ return status;
++}
++
++/*
++ * ======== ReadData ========
++ * Copies buffers from the shared memory to the host buffer.
++ */
++static u32 ReadData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize)
++{
++ memcpy(pDest, pSrc, uSize);
++ return uSize;
++}
++
++/*
++ * ======== WriteData ========
++ * Copies buffers from the host side buffer to the shared memory.
++ */
++static u32 WriteData(struct WMD_DEV_CONTEXT *hDevContext, void *pDest,
++ void *pSrc, u32 uSize)
++{
++ memcpy(pDest, pSrc, uSize);
++ return uSize;
++}
++
++/* ZCPY IO routines. */
++void IO_IntrDSP2(IN struct IO_MGR *pIOMgr, IN u16 wMbVal)
++{
++ CHNLSM_InterruptDSP2(pIOMgr->hWmdContext, wMbVal);
++}
++
++/*
++ * ======== IO_SHMcontrol ========
++ * Sets the requested SHM setting.
++ */
++DSP_STATUS IO_SHMsetting(IN struct IO_MGR *hIOMgr, IN enum SHM_DESCTYPE desc,
++ IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 i;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++
++ switch (desc) {
++ case SHM_CURROPP:
++ /* Update the shared memory with requested OPP information */
++ if (pArgs != NULL)
++ hIOMgr->pSharedMem->oppTableStruct.currOppPt =
++ *(u32 *)pArgs;
++ else
++ return DSP_EFAIL;
++ break;
++ case SHM_OPPINFO:
++ /* Update the shared memory with the voltage, frequency,
++ min and max frequency values for an OPP */
++ for (i = 0; i <= dsp_max_opps; i++) {
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].voltage =
++ vdd1_dsp_freq[i][0];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -voltage: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].voltage);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].
++ frequency = vdd1_dsp_freq[i][1];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -frequency: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].frequency);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].minFreq =
++ vdd1_dsp_freq[i][2];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -min value: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].minFreq);
++ hIOMgr->pSharedMem->oppTableStruct.oppPoint[i].maxFreq =
++ vdd1_dsp_freq[i][3];
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory -max value: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.
++ oppPoint[i].maxFreq);
++ }
++ hIOMgr->pSharedMem->oppTableStruct.numOppPts = dsp_max_opps;
++ DBG_Trace(DBG_LEVEL5, "OPP shared memory - max OPP number: "
++ "%d\n", hIOMgr->pSharedMem->oppTableStruct.numOppPts);
++ /* Update the current OPP number */
++ if (pdata->dsp_get_opp)
++ i = (*pdata->dsp_get_opp)();
++ hIOMgr->pSharedMem->oppTableStruct.currOppPt = i;
++ DBG_Trace(DBG_LEVEL7, "OPP value programmed to shared memory: "
++ "%d\n", i);
++ break;
++ case SHM_GETOPP:
++ /* Get the OPP that DSP has requested */
++ *(u32 *)pArgs = hIOMgr->pSharedMem->oppRequest.rqstOppPt;
++ break;
++ default:
++ break;
++
++ queue_work(bridge_workqueue,
++ &(hIOMgr->io_workq));
++ }
++#endif
++ return DSP_SOK;
++}
++
++/*
++ * ======== WMD_IO_GetProcLoad ========
++ * Gets the Processor's Load information
++ */
++DSP_STATUS WMD_IO_GetProcLoad(IN struct IO_MGR *hIOMgr,
++ OUT struct DSP_PROCLOADSTAT *pProcStat)
++{
++ pProcStat->uCurrLoad = hIOMgr->pSharedMem->loadMonInfo.currDspLoad;
++ pProcStat->uPredictedLoad = hIOMgr->pSharedMem->loadMonInfo.predDspLoad;
++ pProcStat->uCurrDspFreq = hIOMgr->pSharedMem->loadMonInfo.currDspFreq;
++ pProcStat->uPredictedFreq = hIOMgr->pSharedMem->loadMonInfo.predDspFreq;
++
++ DBG_Trace(DBG_LEVEL4, "Curr Load =%d, Pred Load = %d, Curr Freq = %d, "
++ "Pred Freq = %d\n", pProcStat->uCurrLoad,
++ pProcStat->uPredictedLoad, pProcStat->uCurrDspFreq,
++ pProcStat->uPredictedFreq);
++ return DSP_SOK;
++}
++
++#ifndef DSP_TRACEBUF_DISABLED
++void PrintDSPDebugTrace(struct IO_MGR *hIOMgr)
++{
++ u32 ulNewMessageLength = 0, ulGPPCurPointer;
++
++ GT_0trace(dsp_trace_mask, GT_ENTER, "Entering PrintDSPDebugTrace\n");
++
++ while (true) {
++ /* Get the DSP current pointer */
++ ulGPPCurPointer = *(u32 *) (hIOMgr->ulTraceBufferCurrent);
++ ulGPPCurPointer = hIOMgr->ulGppVa + (ulGPPCurPointer -
++ hIOMgr->ulDspVa);
++
++ /* No new debug messages available yet */
++ if (ulGPPCurPointer == hIOMgr->ulGPPReadPointer)
++ break;
++
++ /* Continuous data */
++ else if (ulGPPCurPointer > hIOMgr->ulGPPReadPointer) {
++ ulNewMessageLength = ulGPPCurPointer - hIOMgr->
++ ulGPPReadPointer;
++
++ memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
++ ulNewMessageLength);
++ hIOMgr->pMsg[ulNewMessageLength] = '\0';
++ /* Advance the GPP trace pointer to DSP current
++ * pointer */
++ hIOMgr->ulGPPReadPointer += ulNewMessageLength;
++ /* Print the trace messages */
++ GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
++ }
++ /* Handle trace buffer wraparound */
++ else if (ulGPPCurPointer < hIOMgr->ulGPPReadPointer) {
++ memcpy(hIOMgr->pMsg, (char *)hIOMgr->ulGPPReadPointer,
++ hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer);
++ ulNewMessageLength = ulGPPCurPointer -
++ hIOMgr->ulTraceBufferBegin;
++ memcpy(&hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer],
++ (char *)hIOMgr->ulTraceBufferBegin,
++ ulNewMessageLength);
++ hIOMgr->pMsg[hIOMgr->ulTraceBufferEnd -
++ hIOMgr->ulGPPReadPointer +
++ ulNewMessageLength] = '\0';
++ /* Advance the GPP trace pointer to DSP current
++ * pointer */
++ hIOMgr->ulGPPReadPointer = hIOMgr->ulTraceBufferBegin +
++ ulNewMessageLength;
++ /* Print the trace messages */
++ GT_0trace(dsp_trace_mask, GT_1CLASS, hIOMgr->pMsg);
++ }
++ }
++}
++#endif
++
++/*
++ * ======== PackTraceBuffer ========
++ * Removes extra nulls from the trace buffer returned from the DSP.
++ * Works even on buffers that already are packed (null removed); but has
++ * one bug in that case -- loses the last character (replaces with '\0').
++ * Continues through conversion for full set of nBytes input characters.
++ * Parameters:
++ * lpBuf: Pointer to input/output buffer
++ * nBytes: Number of characters in the buffer
++ * ulNumWords: Number of DSP words in the buffer. Indicates potential
++ * number of extra carriage returns to generate.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory.
++ * Requires:
++ * lpBuf must be a fully allocated writable block of at least nBytes.
++ * There are no more than ulNumWords extra characters needed (the number of
++ * linefeeds minus the number of NULLS in the input buffer).
++ */
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++static DSP_STATUS PackTraceBuffer(char *lpBuf, u32 nBytes, u32 ulNumWords)
++{
++ DSP_STATUS status = DSP_SOK;
++ char *lpTmpBuf;
++ char *lpBufStart;
++ char *lpTmpStart;
++ u32 nCnt;
++ char thisChar;
++
++ /* tmp workspace, 1 KB longer than input buf */
++ lpTmpBuf = MEM_Calloc((nBytes + ulNumWords), MEM_PAGED);
++ if (lpTmpBuf == NULL) {
++ DBG_Trace(DBG_LEVEL7, "PackTrace buffer:OutofMemory \n");
++ status = DSP_EMEMORY;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ lpBufStart = lpBuf;
++ lpTmpStart = lpTmpBuf;
++ for (nCnt = nBytes; nCnt > 0; nCnt--) {
++ thisChar = *lpBuf++;
++ switch (thisChar) {
++ case '\0': /* Skip null bytes */
++ break;
++ case '\n': /* Convert \n to \r\n */
++ /* NOTE: do not reverse order; Some OS */
++ /* editors control doesn't understand "\n\r" */
++ *lpTmpBuf++ = '\r';
++ *lpTmpBuf++ = '\n';
++ break;
++ default: /* Copy in the actual ascii byte */
++ *lpTmpBuf++ = thisChar;
++ break;
++ }
++ }
++ *lpTmpBuf = '\0'; /* Make sure tmp buf is null terminated */
++ /* Cut output down to input buf size */
++ strncpy(lpBufStart, lpTmpStart, nBytes);
++ /*Make sure output is null terminated */
++ lpBufStart[nBytes - 1] = '\0';
++ MEM_Free(lpTmpStart);
++ }
++
++ return status;
++}
++#endif /* (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE */
++
++/*
++ * ======== PrintDspTraceBuffer ========
++ * Prints the trace buffer returned from the DSP (if DBG_Trace is enabled).
++ * Parameters:
++ * hDehMgr: Handle to DEH manager object
++ * number of extra carriage returns to generate.
++ * Returns:
++ * DSP_SOK: Success.
++ * DSP_EMEMORY: Unable to allocate memory.
++ * Requires:
++ * hDehMgr muse be valid. Checked in WMD_DEH_Notify.
++ */
++DSP_STATUS PrintDspTraceBuffer(struct WMD_DEV_CONTEXT *hWmdContext)
++{
++ DSP_STATUS status = DSP_SOK;
++
++#if (defined(DEBUG) || defined(DDSP_DEBUG_PRODUCT)) && GT_TRACE
++ struct COD_MANAGER *hCodMgr;
++ u32 ulTraceEnd;
++ u32 ulTraceBegin;
++ u32 ulNumBytes = 0;
++ u32 ulNumWords = 0;
++ u32 ulWordSize = 2;
++ CONST u32 uMaxSize = 512;
++ char *pszBuf;
++ u16 *lpszBuf;
++
++ struct WMD_DEV_CONTEXT *pWmdContext = (struct WMD_DEV_CONTEXT *)
++ hWmdContext;
++ struct WMD_DRV_INTERFACE *pIntfFxns;
++ struct DEV_OBJECT *pDevObject = (struct DEV_OBJECT *)
++ pWmdContext->hDevObject;
++
++ status = DEV_GetCodMgr(pDevObject, &hCodMgr);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on DEV_GetCodMgr.\n");
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Look for SYS_PUTCBEG/SYS_PUTCEND: */
++ status = COD_GetSymValue(hCodMgr, COD_TRACEBEG, &ulTraceBegin);
++ GT_1trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: ulTraceBegin Value 0x%x\n",
++ ulTraceBegin);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on "
++ "COD_GetSymValue.\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ status = COD_GetSymValue(hCodMgr, COD_TRACEEND, &ulTraceEnd);
++ GT_1trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: ulTraceEnd Value 0x%x\n",
++ ulTraceEnd);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed on "
++ "COD_GetSymValue.\n");
++ }
++ if (DSP_SUCCEEDED(status)) {
++ ulNumBytes = (ulTraceEnd - ulTraceBegin) * ulWordSize;
++ /* If the chip type is 55 then the addresses will be
++ * byte addresses; convert them to word addresses. */
++ if (ulNumBytes > uMaxSize)
++ ulNumBytes = uMaxSize;
++
++ /* make sure the data we request fits evenly */
++ ulNumBytes = (ulNumBytes / ulWordSize) * ulWordSize;
++ GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
++ "ulNumBytes 0x%x\n", ulNumBytes);
++ ulNumWords = ulNumBytes * ulWordSize;
++ GT_1trace(dsp_trace_mask, GT_2CLASS, "PrintDspTraceBuffer: "
++ "ulNumWords 0x%x\n", ulNumWords);
++ status = DEV_GetIntfFxns(pDevObject, &pIntfFxns);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ pszBuf = MEM_Calloc(uMaxSize, MEM_NONPAGED);
++ lpszBuf = MEM_Calloc(ulNumBytes * 2, MEM_NONPAGED);
++ if (pszBuf != NULL) {
++ /* Read bytes from the DSP trace buffer... */
++ status = (*pIntfFxns->pfnBrdRead)(hWmdContext,
++ (u8 *)pszBuf, (u32)ulTraceBegin,
++ ulNumBytes, 0);
++ if (DSP_FAILED(status))
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: "
++ "Failed to Read Trace Buffer.\n");
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Pack and do newline conversion */
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: "
++ "before pack and unpack.\n");
++ PackTraceBuffer(pszBuf, ulNumBytes, ulNumWords);
++ GT_1trace(dsp_trace_mask, GT_1CLASS,
++ "DSP Trace Buffer:\n%s\n", pszBuf);
++ }
++ MEM_Free(pszBuf);
++ MEM_Free(lpszBuf);
++ } else {
++ GT_0trace(dsp_trace_mask, GT_2CLASS,
++ "PrintDspTraceBuffer: Failed to "
++ "allocate trace buffer.\n");
++ status = DSP_EMEMORY;
++ }
++ }
++#endif
++ return status;
++}
++
++void IO_SM_init(void)
++{
++
++ GT_create(&dsp_trace_mask, "DT"); /* DSP Trace Mask */
++
++}
+diff --git a/drivers/dsp/bridge/wmd/mmu_fault.c b/drivers/dsp/bridge/wmd/mmu_fault.c
+new file mode 100644
+index 0000000..5585cdb
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/mmu_fault.c
+@@ -0,0 +1,172 @@
++/*
++ * mmu_fault.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== mmu_fault.c ========
++ * Description:
++ * Implements DSP MMU fault handling functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: Support for IVA MMU exception.
++ *! 06-Mar-2003 sb: Print MMU fault address. Cosmetic changes.
++ *! 16-Feb-2003 vp: Fixed warning in MMU_FaultIsr
++ *! 05-Jan-2004 vp: Updated support for 24xx silicon
++ *! 19-Feb-2003 vp: Code review updates.
++ *! - Cosmetic changes.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 10-Sep-2001 kc: created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/host_os.h>
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmddeh.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- This */
++#include "_deh.h"
++#include <dspbridge/cfg.h>
++#include "_tiomap_mmu.h"
++#include "_tiomap.h"
++#include "mmu_fault.h"
++
++static u32 dmmuEventMask;
++u32 faultAddr;
++
++static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext);
++
++/*
++ * ======== MMU_FaultDpc ========
++ * Deferred procedure call to handle DSP MMU fault.
++ */
++void MMU_FaultDpc(IN void *pRefData)
++{
++ struct DEH_MGR *hDehMgr = (struct DEH_MGR *)pRefData;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Enter: 0x%x\n", pRefData);
++
++ if (pDehMgr)
++ WMD_DEH_Notify(hDehMgr, DSP_MMUFAULT, 0L);
++
++ DBG_Trace(DBG_LEVEL1, "MMU_FaultDpc Exit: 0x%x\n", pRefData);
++}
++
++/*
++ * ======== MMU_FaultIsr ========
++ * ISR to be triggered by a DSP MMU fault interrupt.
++ */
++irqreturn_t MMU_FaultIsr(int irq, IN void *pRefData)
++{
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)pRefData;
++ struct WMD_DEV_CONTEXT *pDevContext;
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_DspMmuIsr: 0x%x\n", pRefData);
++ DBC_Require(irq == INT_DSP_MMU_IRQ);
++ DBC_Require(MEM_IsValidHandle(pDehMgr, SIGNATURE));
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++
++ pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7,
++ "**Failed to get Host Resources "
++ "in MMU ISR **\n");
++ if (MMU_CheckIfFault(pDevContext)) {
++ printk(KERN_INFO "***** DSPMMU FAULT ***** IRQStatus "
++ "0x%x\n", dmmuEventMask);
++ printk(KERN_INFO "***** DSPMMU FAULT ***** faultAddr "
++ "0x%x\n", faultAddr);
++ /* Disable the MMU events, else once we clear it will
++ * start to raise INTs again */
++ /*
++ * Schedule a DPC directly. In the future, it may be
++ * necessary to check if DSP MMU fault is intended for
++ * Bridge.
++ */
++ DPC_Schedule(pDehMgr->hMmuFaultDpc);
++ /* Reset errInfo structure before use. */
++ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
++ pDehMgr->errInfo.dwVal1 = faultAddr >> 16;
++ pDehMgr->errInfo.dwVal2 = faultAddr & 0xFFFF;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ /* Disable the MMU events, else once we clear it will
++ * start to raise INTs again */
++ HW_MMU_EventDisable(resources.dwDmmuBase,
++ HW_MMU_TRANSLATION_FAULT);
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "***** MMU FAULT ***** faultcode 0x%x\n",
++ dmmuEventMask);
++ HW_MMU_EventDisable(resources.dwDmmuBase,
++ HW_MMU_ALL_INTERRUPTS);
++ }
++ }
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * ======== MMU_CheckIfFault ========
++ * Check to see if MMU Fault is valid TLB miss from DSP
++ * Note: This function is called from an ISR
++ */
++static bool MMU_CheckIfFault(struct WMD_DEV_CONTEXT *pDevContext)
++{
++
++
++ bool retVal = false;
++ DSP_STATUS status = DSP_SOK;
++ HW_STATUS hwStatus;
++ struct CFG_HOSTRES resources;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7, "**Failed to get Host Resources in "
++ "MMU_CheckIfFault **\n");
++
++ hwStatus = HW_MMU_EventStatus(resources.dwDmmuBase, &dmmuEventMask);
++ if (dmmuEventMask == HW_MMU_TRANSLATION_FAULT) {
++ HW_MMU_FaultAddrRead(resources.dwDmmuBase, &faultAddr);
++ DBG_Trace(DBG_LEVEL1, "WMD_DEH_Notify: DSP_MMUFAULT, fault "
++ "address = 0x%x\n", faultAddr);
++ retVal = true;
++ }
++ return retVal;
++}
+diff --git a/drivers/dsp/bridge/wmd/mmu_fault.h b/drivers/dsp/bridge/wmd/mmu_fault.h
+new file mode 100644
+index 0000000..be59333
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/mmu_fault.h
+@@ -0,0 +1,45 @@
++/*
++ * mmu_fault.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== mmu_fault.h ========
++ * Description:
++ * Defines DSP MMU fault handling functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 26-Dec-2004 hn: IVA MMU handlers.
++ *! 10-Sep-2001 kc: created.
++ */
++
++#ifndef MMU_FAULT_
++#define MMU_FAULT_
++
++/*
++ * ======== MMU_FaultDpc ========
++ * Deferred procedure call to handle DSP MMU fault.
++ */
++ void MMU_FaultDpc(IN void *pRefData);
++
++/*
++ * ======== MMU_FaultIsr ========
++ * ISR to be triggered by a DSP MMU fault interrupt.
++ */
++irqreturn_t MMU_FaultIsr(int irq, IN void *pRefData);
++
++#endif /* MMU_FAULT_ */
++
+diff --git a/drivers/dsp/bridge/wmd/msg_sm.c b/drivers/dsp/bridge/wmd/msg_sm.c
+new file mode 100644
+index 0000000..b9b2bec
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/msg_sm.c
+@@ -0,0 +1,643 @@
++/*
++ * msg_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== msg_sm.c ========
++ * Description:
++ * Implements upper edge functions for WMD message module.
++ *
++ * Public Functions:
++ * WMD_MSG_Create
++ * WMD_MSG_CreateQueue
++ * WMD_MSG_Delete
++ * WMD_MSG_DeleteQueue
++ * WMD_MSG_Get
++ * WMD_MSG_Put
++ * WMD_MSG_RegisterNotify
++ * WMD_MSG_SetQueueId
++ *
++ *! Revision History:
++ *! =================
++ *! 24-Jul-2002 jeh Release critical section in WMD_MSG_Put() before
++ *! scheduling DPC.
++ *! 09-May-2001 jeh Free MSG queue NTFY object, remove unnecessary set/
++ *! reset of events.
++ *! 10-Jan-2001 jeh Set/Reset message manager and message queue events
++ *! correctly.
++ *! 04-Dec-2000 jeh Bug fixes.
++ *! 12-Sep-2000 jeh Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/list.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/sync.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++
++/* ----------------------------------- Others */
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- This */
++#include <_msg_sm.h>
++#include <dspbridge/wmdmsg.h>
++
++/* ----------------------------------- Defines, Data Structures, Typedefs */
++#define MSGQ_SIGNATURE 0x5147534d /* "QGSM" */
++
++/* ----------------------------------- Function Prototypes */
++static DSP_STATUS AddNewMsg(struct LST_LIST *msgList);
++static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr);
++static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP);
++static void FreeMsgList(struct LST_LIST *msgList);
++
++/*
++ * ======== WMD_MSG_Create ========
++ * Create an object to manage message queues. Only one of these objects
++ * can exist per device object.
++ */
++DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr,
++ struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback)
++{
++ struct MSG_MGR *pMsgMgr;
++ struct IO_MGR *hIOMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(phMsgMgr != NULL);
++ DBC_Require(msgCallback != NULL);
++ DBC_Require(hDevObject != NULL);
++ DEV_GetIOMgr(hDevObject, &hIOMgr);
++ DBC_Assert(hIOMgr != NULL);
++ *phMsgMgr = NULL;
++ /* Allocate MSG manager object */
++ MEM_AllocObject(pMsgMgr, struct MSG_MGR, MSGMGR_SIGNATURE);
++
++ if (pMsgMgr) {
++ pMsgMgr->onExit = msgCallback;
++ pMsgMgr->hIOMgr = hIOMgr;
++ /* List of MSG_QUEUEs */
++ pMsgMgr->queueList = LST_Create();
++ /* Queues of message frames for messages to the DSP. Message
++ * frames will only be added to the free queue when a
++ * MSG_QUEUE object is created. */
++ pMsgMgr->msgFreeList = LST_Create();
++ pMsgMgr->msgUsedList = LST_Create();
++ if (pMsgMgr->queueList == NULL ||
++ pMsgMgr->msgFreeList == NULL ||
++ pMsgMgr->msgUsedList == NULL)
++ status = DSP_EMEMORY;
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeDPCCS(&pMsgMgr->hSyncCS);
++
++ /* Create an event to be used by WMD_MSG_Put() in waiting
++ * for an available free frame from the message manager. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgMgr->hSyncEvent, NULL);
++
++ if (DSP_SUCCEEDED(status))
++ *phMsgMgr = pMsgMgr;
++ else
++ DeleteMsgMgr(pMsgMgr);
++
++ } else {
++ status = DSP_EMEMORY;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_CreateQueue ========
++ * Create a MSG_QUEUE for sending/receiving messages to/from a node
++ * on the DSP.
++ */
++DSP_STATUS WMD_MSG_CreateQueue(struct MSG_MGR *hMsgMgr,
++ OUT struct MSG_QUEUE **phMsgQueue,
++ u32 dwId, u32 uMaxMsgs, HANDLE hArg)
++{
++ u32 i;
++ u32 uNumAllocated = 0;
++ struct MSG_QUEUE *pMsgQ;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++ DBC_Require(phMsgQueue != NULL);
++
++ *phMsgQueue = NULL;
++ /* Allocate MSG_QUEUE object */
++ MEM_AllocObject(pMsgQ, struct MSG_QUEUE, MSGQ_SIGNATURE);
++ if (!pMsgQ) {
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ LST_InitElem((struct LST_ELEM *) pMsgQ);
++ pMsgQ->uMaxMsgs = uMaxMsgs;
++ pMsgQ->hMsgMgr = hMsgMgr;
++ pMsgQ->hArg = hArg; /* Node handle */
++ pMsgQ->dwId = dwId; /* Node env (not valid yet) */
++ /* Queues of Message frames for messages from the DSP */
++ pMsgQ->msgFreeList = LST_Create();
++ pMsgQ->msgUsedList = LST_Create();
++ if (pMsgQ->msgFreeList == NULL || pMsgQ->msgUsedList == NULL)
++ status = DSP_EMEMORY;
++
++ /* Create event that will be signalled when a message from
++ * the DSP is available. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncEvent, NULL);
++
++ /* Create a notification list for message ready notification. */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pMsgQ->hNtfy);
++
++ /* Create events that will be used to synchronize cleanup
++ * when the object is deleted. hSyncDone will be set to
++ * unblock threads in MSG_Put() or MSG_Get(). hSyncDoneAck
++ * will be set by the unblocked thread to signal that it
++ * is unblocked and will no longer reference the object. */
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncDone, NULL);
++
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_OpenEvent(&pMsgQ->hSyncDoneAck, NULL);
++
++ if (DSP_SUCCEEDED(status)) {
++ if (!hMsgMgr->msgFreeList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ /* Initialize message frames and put in appropriate queues */
++ for (i = 0; i < uMaxMsgs && DSP_SUCCEEDED(status); i++) {
++ status = AddNewMsg(hMsgMgr->msgFreeList);
++ if (DSP_SUCCEEDED(status)) {
++ uNumAllocated++;
++ status = AddNewMsg(pMsgQ->msgFreeList);
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* Stay inside CS to prevent others from taking any
++ * of the newly allocated message frames. */
++ DeleteMsgQueue(pMsgQ, uNumAllocated);
++ } else {
++ LST_PutTail(hMsgMgr->queueList,
++ (struct LST_ELEM *)pMsgQ);
++ *phMsgQueue = pMsgQ;
++ /* Signal that free frames are now available */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++
++ }
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ } else {
++ DeleteMsgQueue(pMsgQ, 0);
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_Delete ========
++ * Delete a MSG manager allocated in WMD_MSG_Create().
++ */
++void WMD_MSG_Delete(struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++
++ DeleteMsgMgr(hMsgMgr);
++}
++
++/*
++ * ======== WMD_MSG_DeleteQueue ========
++ * Delete a MSG queue allocated in WMD_MSG_CreateQueue.
++ */
++void WMD_MSG_DeleteQueue(struct MSG_QUEUE *hMsgQueue)
++{
++ struct MSG_MGR *hMsgMgr = hMsgQueue->hMsgMgr;
++ u32 refCount;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ hMsgQueue->fDone = true;
++ /* Unblock all threads blocked in MSG_Get() or MSG_Put(). */
++ refCount = hMsgQueue->refCount;
++ while (refCount) {
++ /* Unblock thread */
++ SYNC_SetEvent(hMsgQueue->hSyncDone);
++ /* Wait for acknowledgement */
++ SYNC_WaitOnEvent(hMsgQueue->hSyncDoneAck, SYNC_INFINITE);
++ refCount = hMsgQueue->refCount;
++ }
++ /* Remove message queue from hMsgMgr->queueList */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ LST_RemoveElem(hMsgMgr->queueList, (struct LST_ELEM *)hMsgQueue);
++ /* Free the message queue object */
++ DeleteMsgQueue(hMsgQueue, hMsgQueue->uMaxMsgs);
++ if (!hMsgMgr->msgFreeList)
++ goto func_cont;
++ if (LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_ResetEvent(hMsgMgr->hSyncEvent);
++func_cont:
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++}
++
++/*
++ * ======== WMD_MSG_Get ========
++ * Get a message from a MSG queue.
++ */
++DSP_STATUS WMD_MSG_Get(struct MSG_QUEUE *hMsgQueue,
++ struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct MSG_FRAME *pMsgFrame;
++ struct MSG_MGR *hMsgMgr;
++ bool fGotMsg = false;
++ struct SYNC_OBJECT *hSyncs[2];
++ u32 uIndex;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(pMsg != NULL);
++
++ hMsgMgr = hMsgQueue->hMsgMgr;
++ if (!hMsgQueue->msgUsedList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ /* If a message is already there, get it */
++ if (!LST_IsEmpty(hMsgQueue->msgUsedList)) {
++ pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgQueue->
++ msgUsedList);
++ if (pMsgFrame != NULL) {
++ *pMsg = pMsgFrame->msgData.msg;
++ LST_PutTail(hMsgQueue->msgFreeList,
++ (struct LST_ELEM *)pMsgFrame);
++ if (LST_IsEmpty(hMsgQueue->msgUsedList))
++ SYNC_ResetEvent(hMsgQueue->hSyncEvent);
++
++ fGotMsg = true;
++ }
++ } else {
++ if (hMsgQueue->fDone)
++ status = DSP_EFAIL;
++ else
++ hMsgQueue->refCount++;
++
++ }
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ if (DSP_SUCCEEDED(status) && !fGotMsg) {
++ /* Wait til message is available, timeout, or done. We don't
++ * have to schedule the DPC, since the DSP will send messages
++ * when they are available. */
++ hSyncs[0] = hMsgQueue->hSyncEvent;
++ hSyncs[1] = hMsgQueue->hSyncDone;
++ status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
++ &uIndex);
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ if (hMsgQueue->fDone) {
++ hMsgQueue->refCount--;
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Signal that we're not going to access hMsgQueue
++ * anymore, so it can be deleted. */
++ (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
++ status = DSP_EFAIL;
++ } else {
++ if (DSP_SUCCEEDED(status)) {
++ DBC_Assert(!LST_IsEmpty(hMsgQueue->
++ msgUsedList));
++ /* Get msg from used list */
++ pMsgFrame = (struct MSG_FRAME *)
++ LST_GetHead(hMsgQueue->msgUsedList);
++ /* Copy message into pMsg and put frame on the
++ * free list */
++ if (pMsgFrame != NULL) {
++ *pMsg = pMsgFrame->msgData.msg;
++ LST_PutTail(hMsgQueue->msgFreeList,
++ (struct LST_ELEM *)pMsgFrame);
++ }
++ }
++ hMsgQueue->refCount--;
++ /* Reset the event if there are still queued messages */
++ if (!LST_IsEmpty(hMsgQueue->msgUsedList))
++ SYNC_SetEvent(hMsgQueue->hSyncEvent);
++
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_Put ========
++ * Put a message onto a MSG queue.
++ */
++DSP_STATUS WMD_MSG_Put(struct MSG_QUEUE *hMsgQueue,
++ IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
++{
++ struct MSG_FRAME *pMsgFrame;
++ struct MSG_MGR *hMsgMgr;
++ bool fPutMsg = false;
++ struct SYNC_OBJECT *hSyncs[2];
++ u32 uIndex;
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(pMsg != NULL);
++
++ hMsgMgr = hMsgQueue->hMsgMgr;
++
++ if (!hMsgMgr->msgFreeList) {
++ status = DSP_EHANDLE;
++ goto func_end;
++ }
++
++
++ (void) SYNC_EnterCS(hMsgMgr->hSyncCS);
++
++ /* If a message frame is available, use it */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ pMsgFrame = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
++ msgFreeList);
++ if (pMsgFrame != NULL) {
++ pMsgFrame->msgData.msg = *pMsg;
++ pMsgFrame->msgData.dwId = hMsgQueue->dwId;
++ LST_PutTail(hMsgMgr->msgUsedList, (struct LST_ELEM *)
++ pMsgFrame);
++ hMsgMgr->uMsgsPending++;
++ fPutMsg = true;
++ }
++ if (LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_ResetEvent(hMsgMgr->hSyncEvent);
++
++ /* Release critical section before scheduling DPC */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Schedule a DPC, to do the actual data transfer: */
++ IO_Schedule(hMsgMgr->hIOMgr);
++ } else {
++ if (hMsgQueue->fDone)
++ status = DSP_EFAIL;
++ else
++ hMsgQueue->refCount++;
++
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ if (DSP_SUCCEEDED(status) && !fPutMsg) {
++ /* Wait til a free message frame is available, timeout,
++ * or done */
++ hSyncs[0] = hMsgMgr->hSyncEvent;
++ hSyncs[1] = hMsgQueue->hSyncDone;
++ status = SYNC_WaitOnMultipleEvents(hSyncs, 2, uTimeout,
++ &uIndex);
++ /* Enter critical section */
++ (void)SYNC_EnterCS(hMsgMgr->hSyncCS);
++ if (hMsgQueue->fDone) {
++ hMsgQueue->refCount--;
++ /* Exit critical section */
++ (void)SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ /* Signal that we're not going to access hMsgQueue
++ * anymore, so it can be deleted. */
++ (void)SYNC_SetEvent(hMsgQueue->hSyncDoneAck);
++ status = DSP_EFAIL;
++ } else {
++ if (DSP_SUCCEEDED(status)) {
++ if (LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ status = DSP_EPOINTER;
++ goto func_cont;
++ }
++ /* Get msg from free list */
++ pMsgFrame = (struct MSG_FRAME *)
++ LST_GetHead(hMsgMgr->msgFreeList);
++ /* Copy message into pMsg and put frame on the
++ * used list */
++ if (pMsgFrame != NULL) {
++ pMsgFrame->msgData.msg = *pMsg;
++ pMsgFrame->msgData.dwId =
++ hMsgQueue->dwId;
++ LST_PutTail(hMsgMgr->msgUsedList,
++ (struct LST_ELEM *)
++ pMsgFrame);
++ hMsgMgr->uMsgsPending++;
++ /* Schedule a DPC, to do the actual
++ * data transfer: */
++ IO_Schedule(hMsgMgr->hIOMgr);
++ }
++ }
++ hMsgQueue->refCount--;
++ /* Reset event if there are still frames available */
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList))
++ SYNC_SetEvent(hMsgMgr->hSyncEvent);
++func_cont:
++ /* Exit critical section */
++ (void) SYNC_LeaveCS(hMsgMgr->hSyncCS);
++ }
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_RegisterNotify ========
++ */
++DSP_STATUS WMD_MSG_RegisterNotify(struct MSG_QUEUE *hMsgQueue, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ DBC_Require(hNotification != NULL);
++ DBC_Require(uEventMask == DSP_NODEMESSAGEREADY || uEventMask == 0);
++ DBC_Require(uNotifyType == DSP_SIGNALEVENT);
++
++ status = NTFY_Register(hMsgQueue->hNtfy, hNotification, uEventMask,
++ uNotifyType);
++
++ if (status == DSP_EVALUE) {
++ /* Not registered. Ok, since we couldn't have known. Node
++ * notifications are split between node state change handled
++ * by NODE, and message ready handled by MSG. */
++ status = DSP_SOK;
++ }
++
++ return status;
++}
++
++/*
++ * ======== WMD_MSG_SetQueueId ========
++ */
++void WMD_MSG_SetQueueId(struct MSG_QUEUE *hMsgQueue, u32 dwId)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE));
++ /* DBC_Require(dwId != 0); */
++
++ /*
++ * A message queue must be created when a node is allocated,
++ * so that NODE_RegisterNotify() can be called before the node
++ * is created. Since we don't know the node environment until the
++ * node is created, we need this function to set hMsgQueue->dwId
++ * to the node environment, after the node is created.
++ */
++ hMsgQueue->dwId = dwId;
++}
++
++/*
++ * ======== AddNewMsg ========
++ * Must be called in message manager critical section.
++ */
++static DSP_STATUS AddNewMsg(struct LST_LIST *msgList)
++{
++ struct MSG_FRAME *pMsg;
++ DSP_STATUS status = DSP_SOK;
++
++ pMsg = (struct MSG_FRAME *)MEM_Calloc(sizeof(struct MSG_FRAME),
++ MEM_PAGED);
++ if (pMsg != NULL) {
++ LST_InitElem((struct LST_ELEM *) pMsg);
++ LST_PutTail(msgList, (struct LST_ELEM *) pMsg);
++ } else {
++ status = DSP_EMEMORY;
++ }
++
++ return status;
++}
++
++/*
++ * ======== DeleteMsgMgr ========
++ */
++static void DeleteMsgMgr(struct MSG_MGR *hMsgMgr)
++{
++ DBC_Require(MEM_IsValidHandle(hMsgMgr, MSGMGR_SIGNATURE));
++
++ if (hMsgMgr->queueList) {
++ if (LST_IsEmpty(hMsgMgr->queueList)) {
++ LST_Delete(hMsgMgr->queueList);
++ hMsgMgr->queueList = NULL;
++ }
++ }
++
++ if (hMsgMgr->msgFreeList) {
++ FreeMsgList(hMsgMgr->msgFreeList);
++ hMsgMgr->msgFreeList = NULL;
++ }
++
++ if (hMsgMgr->msgUsedList) {
++ FreeMsgList(hMsgMgr->msgUsedList);
++ hMsgMgr->msgUsedList = NULL;
++ }
++
++ if (hMsgMgr->hSyncEvent)
++ SYNC_CloseEvent(hMsgMgr->hSyncEvent);
++
++ if (hMsgMgr->hSyncCS)
++ SYNC_DeleteCS(hMsgMgr->hSyncCS);
++
++ MEM_FreeObject(hMsgMgr);
++}
++
++/*
++ * ======== DeleteMsgQueue ========
++ */
++static void DeleteMsgQueue(struct MSG_QUEUE *hMsgQueue, u32 uNumToDSP)
++{
++ struct MSG_MGR *hMsgMgr;
++ struct MSG_FRAME *pMsg;
++ u32 i;
++
++ if (!MEM_IsValidHandle(hMsgQueue, MSGQ_SIGNATURE)
++ || !hMsgQueue->hMsgMgr || !hMsgQueue->hMsgMgr->msgFreeList)
++ goto func_end;
++ hMsgMgr = hMsgQueue->hMsgMgr;
++
++
++ /* Pull off uNumToDSP message frames from Msg manager and free */
++ for (i = 0; i < uNumToDSP; i++) {
++
++ if (!LST_IsEmpty(hMsgMgr->msgFreeList)) {
++ pMsg = (struct MSG_FRAME *)LST_GetHead(hMsgMgr->
++ msgFreeList);
++ MEM_Free(pMsg);
++ } else {
++ /* Cannot free all of the message frames */
++ break;
++ }
++ }
++
++ if (hMsgQueue->msgFreeList) {
++ FreeMsgList(hMsgQueue->msgFreeList);
++ hMsgQueue->msgFreeList = NULL;
++ }
++
++ if (hMsgQueue->msgUsedList) {
++ FreeMsgList(hMsgQueue->msgUsedList);
++ hMsgQueue->msgUsedList = NULL;
++ }
++
++
++ if (hMsgQueue->hNtfy)
++ NTFY_Delete(hMsgQueue->hNtfy);
++
++ if (hMsgQueue->hSyncEvent)
++ SYNC_CloseEvent(hMsgQueue->hSyncEvent);
++
++ if (hMsgQueue->hSyncDone)
++ SYNC_CloseEvent(hMsgQueue->hSyncDone);
++
++ if (hMsgQueue->hSyncDoneAck)
++ SYNC_CloseEvent(hMsgQueue->hSyncDoneAck);
++
++ MEM_FreeObject(hMsgQueue);
++func_end:
++ return;
++
++}
++
++/*
++ * ======== FreeMsgList ========
++ */
++static void FreeMsgList(struct LST_LIST *msgList)
++{
++ struct MSG_FRAME *pMsg;
++
++ if (!msgList)
++ goto func_end;
++
++ while ((pMsg = (struct MSG_FRAME *)LST_GetHead(msgList)) != NULL)
++ MEM_Free(pMsg);
++
++ DBC_Assert(LST_IsEmpty(msgList));
++
++ LST_Delete(msgList);
++func_end:
++ return;
++}
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c b/drivers/dsp/bridge/wmd/tiomap3430.c
+new file mode 100644
+index 0000000..2ab585d
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap3430.c
+@@ -0,0 +1,2149 @@
++/*
++ * tiomap.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== tiomap.c ========
++ * Processor Manager Driver for TI OMAP3430 EVM.
++ *
++ * Public Function:
++ * WMD_DRV_Entry
++ *
++ *! Revision History:
++ *! ================
++ * 26-March-2008 HK and AL: Added WMD_DEV_WalkTbl funciton.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++#include <linux/mm.h>
++#include <linux/mmzone.h>
++#include <mach-omap2/prm.h>
++#include <mach-omap2/cm.h>
++#include <mach-omap2/prm-regbits-34xx.h>
++#include <mach-omap2/cm-regbits-34xx.h>
++#include <mach/control.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++#include <dspbridge/reg.h>
++#include <dspbridge/dbreg.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/csl.h>
++#include <dspbridge/sync.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <hw_prcm.h>
++#include <hw_mmu.h>
++#include <hw_mbox.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmd.h>
++#include <dspbridge/wmdchnl.h>
++#include <dspbridge/wmddeh.h>
++#include <dspbridge/wmdio.h>
++#include <dspbridge/wmdmsg.h>
++#include <dspbridge/pwr.h>
++#include <dspbridge/chnl_sm.h>
++#include <dspbridge/io_sm.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/wcd.h>
++#include <dspbridge/dmm.h>
++
++/* ----------------------------------- Local */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "_tiomap_mmu.h"
++#include "_tiomap_util.h"
++#include "tiomap_io.h"
++
++
++/* Offset in shared mem to write to in order to synchronize start with DSP */
++#define SHMSYNCOFFSET 4 /* GPP byte offset */
++
++#define BUFFERSIZE 1024
++
++#define MMU_SECTION_ADDR_MASK 0xFFF00000
++#define MMU_SSECTION_ADDR_MASK 0xFF000000
++#define MMU_LARGE_PAGE_MASK 0xFFFF0000
++#define MMU_SMALL_PAGE_MASK 0xFFFFF000
++#define PAGES_II_LVL_TABLE 512
++#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT)
++
++#define MMU_GFLUSH 0x60
++
++/* Forward Declarations: */
++static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *pDevContext);
++static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 dwDSPAddr);
++static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT BRD_STATUS *pdwState);
++static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *pDevContext);
++static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulBrdState);
++static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulDspDestAddr, u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
++ u32 ulMapAttr);
++static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulVirtAddr, u32 ulNumBytes);
++static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CFG_HOSTRES *pConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig);
++static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
++ IN OUT void *pArgs);
++static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *pDevContext);
++static u32 user_va2pa(struct mm_struct *mm, u32 address);
++static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
++ u32 va, u32 size,
++ struct HW_MMUMapAttrs_t *mapAttrs);
++static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
++ u32 size, struct HW_MMUMapAttrs_t *attrs);
++static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr,
++ u32 ulNumBytes, struct HW_MMUMapAttrs_t *hwAttrs);
++static DSP_STATUS run_IdleBoot(u32 prcm_base, u32 cm_base,
++ u32 sysctrl_base);
++void GetHWRegs(u32 prcm_base, u32 cm_base);
++
++/* ----------------------------------- Globals */
++
++/* Attributes of L2 page tables for DSP MMU */
++struct PageInfo {
++ u32 numEntries; /* Number of valid PTEs in the L2 PT */
++} ;
++
++/* Attributes used to manage the DSP MMU page tables */
++struct PgTableAttrs {
++ struct SYNC_CSOBJECT *hCSObj; /* Critical section object handle */
++
++ u32 L1BasePa; /* Physical address of the L1 PT */
++ u32 L1BaseVa; /* Virtual address of the L1 PT */
++ u32 L1size; /* Size of the L1 PT */
++ u32 L1TblAllocPa;
++ /* Physical address of Allocated mem for L1 table. May not be aligned */
++ u32 L1TblAllocVa;
++ /* Virtual address of Allocated mem for L1 table. May not be aligned */
++ u32 L1TblAllocSz;
++ /* Size of consistent memory allocated for L1 table.
++ * May not be aligned */
++
++ u32 L2BasePa; /* Physical address of the L2 PT */
++ u32 L2BaseVa; /* Virtual address of the L2 PT */
++ u32 L2size; /* Size of the L2 PT */
++ u32 L2TblAllocPa;
++ /* Physical address of Allocated mem for L2 table. May not be aligned */
++ u32 L2TblAllocVa;
++ /* Virtual address of Allocated mem for L2 table. May not be aligned */
++ u32 L2TblAllocSz;
++ /* Size of consistent memory allocated for L2 table.
++ * May not be aligned */
++
++ u32 L2NumPages; /* Number of allocated L2 PT */
++ struct PageInfo *pgInfo; /* Array [L2NumPages] of L2 PT info structs */
++} ;
++
++/*
++ * If dsp_debug is true, do not branch to the DSP entry point and wait for DSP
++ * to boot
++ */
++extern s32 dsp_debug;
++
++
++/*
++ * This mini driver's function interface table.
++ */
++static struct WMD_DRV_INTERFACE drvInterfaceFxns = {
++ WCD_MAJOR_VERSION, /* WCD ver. for which this mini driver is built. */
++ WCD_MINOR_VERSION,
++ WMD_DEV_Create,
++ WMD_DEV_Destroy,
++ WMD_DEV_Ctrl,
++ WMD_BRD_Monitor,
++ WMD_BRD_Start,
++ WMD_BRD_Stop,
++ WMD_BRD_Status,
++ WMD_BRD_Read,
++ WMD_BRD_Write,
++ WMD_BRD_SetState,
++ WMD_BRD_MemCopy,
++ WMD_BRD_MemWrite,
++ WMD_BRD_MemMap,
++ WMD_BRD_MemUnMap,
++ /* The following CHNL functions are provided by chnl_io.lib: */
++ WMD_CHNL_Create,
++ WMD_CHNL_Destroy,
++ WMD_CHNL_Open,
++ WMD_CHNL_Close,
++ WMD_CHNL_AddIOReq,
++ WMD_CHNL_GetIOC,
++ WMD_CHNL_CancelIO,
++ WMD_CHNL_FlushIO,
++ WMD_CHNL_GetInfo,
++ WMD_CHNL_GetMgrInfo,
++ WMD_CHNL_Idle,
++ WMD_CHNL_RegisterNotify,
++ /* The following DEH functions are provided by tihelen_ue_deh.c */
++ WMD_DEH_Create,
++ WMD_DEH_Destroy,
++ WMD_DEH_Notify,
++ WMD_DEH_RegisterNotify,
++ WMD_DEH_GetInfo,
++ /* The following IO functions are provided by chnl_io.lib: */
++ WMD_IO_Create,
++ WMD_IO_Destroy,
++ WMD_IO_OnLoaded,
++ WMD_IO_GetProcLoad,
++ /* The following MSG functions are provided by chnl_io.lib: */
++ WMD_MSG_Create,
++ WMD_MSG_CreateQueue,
++ WMD_MSG_Delete,
++ WMD_MSG_DeleteQueue,
++ WMD_MSG_Get,
++ WMD_MSG_Put,
++ WMD_MSG_RegisterNotify,
++ WMD_MSG_SetQueueId,
++};
++
++static inline void tlb_flush_all(const u32 base)
++{
++ __raw_writeb(__raw_readb(base + MMU_GFLUSH) | 1, base + MMU_GFLUSH);
++}
++
++static inline void flush_all(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ struct CFG_HOSTRES resources;
++ u32 temp = 0;
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
++
++ if ((temp & HW_PWR_STATE_ON) == HW_PWR_STATE_OFF ||
++ (temp & HW_PWR_STATE_ON) == HW_PWR_STATE_RET) {
++ CLK_Enable(SERVICESCLK_iva2_ck);
++ WakeDSP(pDevContext, NULL);
++ tlb_flush_all(pDevContext->dwDSPMmuBase);
++ CLK_Disable(SERVICESCLK_iva2_ck);
++ } else
++ tlb_flush_all(pDevContext->dwDSPMmuBase);
++}
++
++static void bad_page_dump(u32 pa, struct page *pg)
++{
++ pr_emerg("DSPBRIDGE: MAP function: COUNT 0 FOR PA 0x%x\n", pa);
++ pr_emerg("Bad page state in process '%s'\n"
++ "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n"
++ "Backtrace:\n",
++ current->comm, pg, (int)(2*sizeof(unsigned long)),
++ (unsigned long)pg->flags, pg->mapping,
++ page_mapcount(pg), page_count(pg));
++ BUG();
++}
++
++/*
++ * ======== WMD_DRV_Entry ========
++ * purpose:
++ * Mini Driver entry point.
++ */
++void WMD_DRV_Entry(OUT struct WMD_DRV_INTERFACE **ppDrvInterface,
++ IN CONST char *pstrWMDFileName)
++{
++
++ DBC_Require(pstrWMDFileName != NULL);
++ DBG_Trace(DBG_ENTER, "In the WMD_DRV_Entry \n");
++
++ IO_SM_init(); /* Initialization of io_sm module */
++
++ if (strcmp(pstrWMDFileName, "UMA") == 0)
++ *ppDrvInterface = &drvInterfaceFxns;
++ else
++ DBG_Trace(DBG_LEVEL7, "WMD_DRV_Entry Unknown WMD file name");
++
++}
++
++/*
++ * ======== WMD_BRD_Monitor ========
++ * purpose:
++ * This WMD_BRD_Monitor puts DSP into a Loadable state.
++ * i.e Application can load and start the device.
++ *
++ * Preconditions:
++ * Device in 'OFF' state.
++ */
++static DSP_STATUS WMD_BRD_Monitor(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ u32 temp;
++ enum HW_PwrState_t pwrState;
++
++ DBG_Trace(DBG_ENTER, "Board in the monitor state \n");
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ goto error_return;
++
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &temp);
++ if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
++ /* IVA2 is not in ON state */
++ /* Read and set PM_PWSTCTRL_IVA2 to ON */
++ HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
++ HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_ON);
++ /* Set the SW supervised state transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
++ HW_SW_SUP_WAKEUP);
++ /* Wait until the state has moved to ON */
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Disable Automatic transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase, HW_AUTOTRANS_DIS);
++ }
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - Middle ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ status = run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
++ resources.dwSysCtrlBase);
++ if (DSP_SUCCEEDED(status)) {
++ /* set the device state to IDLE */
++ pDevContext->dwBrdState = BRD_IDLE;
++
++ }
++error_return:
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Monitor - End ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Read ========
++ * purpose:
++ * Reads buffers for DSP memory.
++ */
++static DSP_STATUS WMD_BRD_Read(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 offset;
++ u32 dspBaseAddr = hDevContext->dwDspBaseAddr;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Read, pDevContext: 0x%x\n\t\tpbHostBuf:"
++ " 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: 0x%x\n\t\t"
++ "ulMemType: 0x%x\n", pDevContext, pbHostBuf,
++ dwDSPAddr, ulNumBytes, ulMemType);
++ if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Read: DSP address < start address \n ");
++ status = DSP_EFAIL;
++ return status;
++ }
++ /* change here to account for the 3 bands of the DSP internal memory */
++ if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
++ pDevContext->dwInternalSize) {
++ offset = dwDSPAddr - pDevContext->dwDSPStartAdd;
++ } else {
++ DBG_Trace(DBG_LEVEL1,
++ "**** Reading From external memory **** \n ");
++ status = ReadExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++ return status;
++ }
++ /* copy the data from DSP memory, */
++ memcpy(pbHostBuf, (void *)(dspBaseAddr + offset), ulNumBytes);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_SetState ========
++ * purpose:
++ * This routine updates the Board status.
++ */
++static DSP_STATUS WMD_BRD_SetState(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulBrdState)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_SetState: Board State: 0x%x \n",
++ ulBrdState);
++ pDevContext->dwBrdState = ulBrdState;
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Start ========
++ * purpose:
++ * Initializes DSP MMU and Starts DSP.
++ *
++ * Preconditions:
++ * a) DSP domain is 'ACTIVE'.
++ * b) DSP_RST1 is asserted.
++ * b) DSP_RST2 is released.
++ */
++static DSP_STATUS WMD_BRD_Start(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 dwDSPAddr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 dwSyncAddr = 0;
++ u32 ulShmBase; /* Gpp Phys SM base addr(byte) */
++ u32 ulShmBaseVirt; /* Dsp Virt SM base addr */
++ u32 ulTLBBaseVirt; /* Base of MMU TLB entry */
++ u32 ulShmOffsetVirt; /* offset of ulShmBaseVirt from ulTLBBaseVirt */
++ s32 iEntryNdx;
++ s32 itmpEntryNdx = 0; /* DSP-MMU TLB entry base address */
++ struct CFG_HOSTRES resources;
++ u32 temp;
++ u32 ulDspClkRate;
++ u32 ulDspClkAddr;
++ u32 ulBiosGpTimer;
++ u32 uClkCmd;
++ struct IO_MGR *hIOMgr;
++ u32 ulLoadMonitorTimer;
++ u32 extClkId = 0;
++ u32 tmpIndex;
++ u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Start:\n hDevContext: 0x%x\n\t "
++ "dwDSPAddr: 0x%x\n", hDevContext, dwDSPAddr);
++
++ /* The device context contains all the mmu setup info from when the
++ * last dsp base image was loaded. The first entry is always
++ * SHMMEM base. */
++ /* Get SHM_BEG - convert to byte address */
++ (void) DEV_GetSymbol(pDevContext->hDevObject, SHMBASENAME,
++ &ulShmBaseVirt);
++ ulShmBaseVirt *= DSPWORDSIZE;
++ DBC_Assert(ulShmBaseVirt != 0);
++ /* DSP Virtual address */
++ ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++ ulShmOffsetVirt = ulShmBaseVirt - (ulTLBBaseVirt * DSPWORDSIZE);
++ /* Kernel logical address */
++ ulShmBase = pDevContext->aTLBEntry[0].ulGppVa + ulShmOffsetVirt;
++
++ DBC_Assert(ulShmBase != 0);
++ /* 2nd wd is used as sync field */
++ dwSyncAddr = ulShmBase + SHMSYNCOFFSET;
++ /* Write a signature into the SHM base + offset; this will
++ * get cleared when the DSP program starts. */
++ if ((ulShmBaseVirt == 0) || (ulShmBase == 0)) {
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start: Illegal SM base\n");
++ status = DSP_EFAIL;
++ } else
++ *((volatile u32 *)dwSyncAddr) = 0xffffffff;
++
++ if (DSP_SUCCEEDED(status)) {
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ /* Assert RST1 i.e only the RST only for DSP megacell */
++ /* HW_RST_Reset(resources.dwPrcmBase, HW_RST1_IVA2);*/
++ if (DSP_SUCCEEDED(status)) {
++ HW_RST_Reset(resources.dwPrmBase, HW_RST1_IVA2);
++ if (dsp_debug) {
++ /* Set the bootmode to self loop */
++ DBG_Trace(DBG_LEVEL7,
++ "Set boot mode to self loop"
++ " for IVA2 Device\n");
++ HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
++ HW_DSPSYSC_SELFLOOPBOOT, dwDSPAddr);
++ } else {
++ /* Set the bootmode to '0' - direct boot */
++ DBG_Trace(DBG_LEVEL7,
++ "Set boot mode to direct"
++ " boot for IVA2 Device \n");
++ HW_DSPSS_BootModeSet(resources.dwSysCtrlBase,
++ HW_DSPSYSC_DIRECTBOOT, dwDSPAddr);
++ }
++ }
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Reset and Unreset the RST2, so that BOOTADDR is copied to
++ * IVA2 SYSC register */
++ HW_RST_Reset(resources.dwPrmBase, HW_RST2_IVA2);
++ udelay(100);
++ HW_RST_UnReset(resources.dwPrmBase, HW_RST2_IVA2);
++ udelay(100);
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Start 0 ****** \n");
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++ /* Disbale the DSP MMU */
++ HW_MMU_Disable(resources.dwDmmuBase);
++ /* Disable TWL */
++ HW_MMU_TWLDisable(resources.dwDmmuBase);
++
++ /* Only make TLB entry if both addresses are non-zero */
++ for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB;
++ iEntryNdx++) {
++ if ((pDevContext->aTLBEntry[iEntryNdx].ulGppPa != 0) &&
++ (pDevContext->aTLBEntry[iEntryNdx].ulDspVa != 0)) {
++ DBG_Trace(DBG_LEVEL4, "** (proc) MMU %d GppPa:"
++ " 0x%x DspVa 0x%x Size 0x%x\n",
++ itmpEntryNdx,
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa,
++ pDevContext->aTLBEntry[iEntryNdx].ulSize);
++ configureDspMmu(pDevContext,
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa,
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa *
++ DSPWORDSIZE,
++ pDevContext->aTLBEntry[iEntryNdx].ulSize,
++ itmpEntryNdx,
++ pDevContext->aTLBEntry[iEntryNdx].endianism,
++ pDevContext->aTLBEntry[iEntryNdx].elemSize,
++ pDevContext->aTLBEntry[iEntryNdx].
++ mixedMode);
++ itmpEntryNdx++;
++ }
++ } /* end for */
++ }
++
++ /* Lock the above TLB entries and get the BIOS and load monitor timer
++ * information*/
++ if (DSP_SUCCEEDED(status)) {
++ HW_MMU_NumLockedSet(resources.dwDmmuBase, itmpEntryNdx);
++ HW_MMU_VictimNumSet(resources.dwDmmuBase, itmpEntryNdx);
++ HW_MMU_TTBSet(resources.dwDmmuBase,
++ pDevContext->pPtAttrs->L1BasePa);
++ HW_MMU_TWLEnable(resources.dwDmmuBase);
++ /* Enable the SmartIdle and AutoIdle bit for MMU_SYSCONFIG */
++
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwDmmuBase) + 0x10));
++ temp = (temp & 0xFFFFFFEF) | 0x11;
++ *((REG_UWORD32 *) ((u32) (resources.dwDmmuBase) + 0x10)) =
++ (u32) temp;
++
++ /* Let the DSP MMU run */
++ HW_MMU_Enable(resources.dwDmmuBase);
++
++ /* Enable the BIOS clock */
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ BRIDGEINIT_BIOSGPTIMER,
++ &ulBiosGpTimer);
++ DBG_Trace(DBG_LEVEL7, "BIOS GPTimer : 0x%x\n", ulBiosGpTimer);
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ BRIDGEINIT_LOADMON_GPTIMER,
++ &ulLoadMonitorTimer);
++ DBG_Trace(DBG_LEVEL7, "Load Monitor Timer : 0x%x\n",
++ ulLoadMonitorTimer);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if (ulLoadMonitorTimer != 0xFFFF) {
++ uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulLoadMonitorTimer;
++ DBG_Trace(DBG_LEVEL7,
++ "encoded LoadMonitor cmd for Disable: 0x%x\n",
++ uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
++ tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++
++ if (clkIdIndex < MBX_PM_MAX_RESOURCES)
++ status = CLK_Set_32KHz(
++ BPWR_Clks[clkIdIndex].funClk);
++ else
++ status = DSP_EFAIL;
++
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7, " Error while setting"
++ "LM Timer to 32KHz\n");
++ }
++ uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulLoadMonitorTimer;
++ DBG_Trace(DBG_LEVEL7,
++ "encoded LoadMonitor cmd for Enable : 0x%x\n",
++ uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "Not able to get the symbol for Load "
++ "Monitor Timer\n");
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ if (ulBiosGpTimer != 0xFFFF) {
++ uClkCmd = (BPWR_DisableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulBiosGpTimer;
++ DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd for"
++ "Disable: 0x%x\n", uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ extClkId = uClkCmd & MBX_PM_CLK_IDMASK;
++
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES;
++ tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++
++ if (clkIdIndex < MBX_PM_MAX_RESOURCES)
++ status = CLK_Set_32KHz(
++ BPWR_Clks[clkIdIndex].funClk);
++ else
++ status = DSP_EFAIL;
++
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ " Error while setting BIOS Timer to 32KHz\n");
++ }
++
++ uClkCmd = (BPWR_EnableClock << MBX_PM_CLK_CMDSHIFT) |
++ ulBiosGpTimer;
++ DBG_Trace(DBG_LEVEL7, "encoded BIOS GPTimer cmd :"
++ "0x%x\n", uClkCmd);
++ DSPPeripheralClkCtrl(pDevContext, &uClkCmd);
++
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "Not able to get the symbol for BIOS Timer\n");
++ }
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the DSP clock rate */
++ (void)DEV_GetSymbol(pDevContext->hDevObject,
++ "_BRIDGEINIT_DSP_FREQ", &ulDspClkAddr);
++ /*Set Autoidle Mode for IVA2 PLL */
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: _BRIDGE_DSP_FREQ Addr:"
++ "0x%x \n", ulDspClkAddr);
++ if ((unsigned int *)ulDspClkAddr != NULL) {
++ /* Get the clock rate */
++ status = CLK_GetRate(SERVICESCLK_iva2_ck,
++ &ulDspClkRate);
++ DBG_Trace(DBG_LEVEL5,
++ "WMD_BRD_Start: DSP clock rate (KHZ): 0x%x \n",
++ ulDspClkRate);
++ (void)WMD_BRD_Write(pDevContext, (u8 *)&ulDspClkRate,
++ ulDspClkAddr, sizeof(u32), 0);
++ }
++/*PM_IVA2GRPSEL_PER = 0xC0;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ temp = (temp & 0xFFFFFF30) | 0xC0;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8)) =
++ (u32) temp;
++
++/*PM_MPUGRPSEL_PER &= 0xFFFFFF3F;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ temp = (temp & 0xFFFFFF3F);
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4)) =
++ (u32) temp;
++/*CM_SLEEPDEP_PER |= 0x04;*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerBase) + 0x44));
++ temp = (temp & 0xFFFFFFFB) | 0x04;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerBase) + 0x44)) =
++ (u32) temp;
++
++/*CM_CLKSTCTRL_IVA2 = 0x00000003 -To Allow automatic transitions*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x48));
++ temp = (temp & 0xFFFFFFFC) | 0x03;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x48)) =
++ (u32) temp;
++
++
++ /* Enable Mailbox events and also drain any pending
++ * stale messages */
++ (void)CHNLSM_EnableInterrupt(pDevContext);
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTCTRL_DSP = 0x%x \n",
++ temp);
++ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start0: RM_RSTST_DSP = 0x%x \n",
++ temp);
++
++ /* Let DSP go */
++ DBG_Trace(DBG_LEVEL7, "Unreset, WMD_BRD_Start\n");
++ /* Enable DSP MMU Interrupts */
++ HW_MMU_EventEnable(resources.dwDmmuBase,
++ HW_MMU_ALL_INTERRUPTS);
++ /* release the RST1, DSP starts executing now .. */
++ HW_RST_UnReset(resources.dwPrmBase, HW_RST1_IVA2);
++
++ HW_RSTST_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL7, "BRD_Start: RM_RSTST_DSP = 0x%x \n",
++ temp);
++ HW_RSTCTRL_RegGet(resources.dwPrmBase, HW_RST1_IVA2, &temp);
++ DBG_Trace(DBG_LEVEL5, "WMD_BRD_Start: CM_RSTCTRL_DSP: 0x%x \n",
++ temp);
++ DBG_Trace(DBG_LEVEL7, "Driver waiting for Sync @ 0x%x \n",
++ dwSyncAddr);
++ DBG_Trace(DBG_LEVEL7, "DSP c_int00 Address = 0x%x \n",
++ dwDSPAddr);
++ if (dsp_debug)
++ while (*((volatile u16 *)dwSyncAddr))
++ ;;
++ }
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Wait for DSP to clear word in shared memory */
++ /* Read the Location */
++ if (!WaitForStart(pDevContext, dwSyncAddr)) {
++ status = WMD_E_TIMEOUT;
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Start Failed to Synchronize\n");
++ }
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (DSP_SUCCEEDED(status)) {
++ IO_SHMsetting(hIOMgr, SHM_OPPINFO, NULL);
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Start: OPP information initialzed\n");
++ /* Write the synchronization bit to indicate the
++ * completion of OPP table update to DSP
++ */
++ *((volatile u32 *)dwSyncAddr) = 0XCAFECAFE;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* update board state */
++ pDevContext->dwBrdState = BRD_RUNNING;
++ /* (void)CHNLSM_EnableInterrupt(pDevContext);*/
++ DBG_Trace(DBG_LEVEL7, "Device Started \n ");
++ } else {
++ pDevContext->dwBrdState = BRD_UNKNOWN;
++ DBG_Trace(DBG_LEVEL7, "Device not Started \n ");
++ }
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_Stop ========
++ * purpose:
++ * Puts DSP in self loop.
++ *
++ * Preconditions :
++ * a) None
++ */
++static DSP_STATUS WMD_BRD_Stop(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ u32 dspPwrState;
++ DSP_STATUS clk_status;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Stop:\nhDevContext: 0x%x\n",
++ hDevContext);
++
++ /* Disable the mail box interrupts */
++ (void)CHNLSM_DisableInterrupt(pDevContext);
++
++ if (pDevContext->dwBrdState == BRD_STOPPED)
++ return status;
++
++ /* as per TRM, it is advised to first drive the IVA2 to 'Standby' mode,
++ * before turning off the clocks.. This is to ensure that there are no
++ * pending L3 or other transactons from IVA2 */
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Stop: Get Host resources failed \n");
++ DBG_Trace(DBG_LEVEL1, "Device Stopp failed \n ");
++ return DSP_EFAIL;
++ }
++
++ HW_PWRST_IVA2RegGet(resources.dwPrmBase, &dspPwrState);
++ if (dspPwrState != HW_PWR_STATE_OFF) {
++
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPIDLE);
++
++ mdelay(10);
++
++ GetHWRegs(resources.dwPrmBase, resources.dwCmBase);
++
++ run_IdleBoot(resources.dwPrmBase, resources.dwCmBase,
++ resources.dwSysCtrlBase);
++
++ udelay(50);
++
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6,
++ "\n WMD_BRD_Stop: CLK_Disable failed "
++ "for iva2_fck\n");
++ }
++ /* IVA2 is not in OFF state */
++ /* Set PM_PWSTCTRL_IVA2 to OFF */
++ HW_PWR_IVA2PowerStateSet(resources.dwPrmBase,
++ HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_OFF);
++ /* Set the SW supervised state transition for Sleep */
++ HW_PWR_CLKCTRL_IVA2RegSet(resources.dwCmBase,
++ HW_SW_SUP_SLEEP);
++ } else {
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6,
++ "\n WMD_BRD_Stop: Else loop CLK_Disable failed"
++ " for iva2_fck\n");
++ }
++ }
++ udelay(10);
++ /* Release the Ext Base virtual Address as the next DSP Program
++ * may have a different load address */
++ if (pDevContext->dwDspExtBaseAddr)
++ pDevContext->dwDspExtBaseAddr = 0;
++
++ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
++ DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
++ /* This is a good place to clear the MMU page tables as well */
++ if (pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ memset((u8 *) pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++ memset((u8 *) pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++ memset((u8 *) pPtAttrs->pgInfo, 0x00,
++ (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
++ }
++
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
++
++ return status;
++}
++
++
++/*
++ * ======== WMD_BRD_Delete ========
++ * purpose:
++ * Puts DSP in Low power mode
++ *
++ * Preconditions :
++ * a) None
++ */
++static DSP_STATUS WMD_BRD_Delete(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ DSP_STATUS clk_status;
++
++ DBG_Trace(DBG_ENTER, "Entering WMD_BRD_Delete:\nhDevContext: 0x%x\n",
++ hDevContext);
++
++ /* Disable the mail box interrupts */
++ (void) CHNLSM_DisableInterrupt(pDevContext);
++
++ if (pDevContext->dwBrdState == BRD_STOPPED)
++ return status;
++
++ /* as per TRM, it is advised to first drive
++ * the IVA2 to 'Standby' mode, before turning off the clocks.. This is
++ * to ensure that there are no pending L3 or other transactons from
++ * IVA2 */
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Stop: Get Host resources failed \n");
++ DBG_Trace(DBG_LEVEL1, "Device Delete failed \n ");
++ return DSP_EFAIL;
++ }
++ status = SleepDSP(pDevContext, PWR_EMERGENCYDEEPSLEEP, NULL);
++ clk_status = CLK_Disable(SERVICESCLK_iva2_ck);
++ if (DSP_FAILED(clk_status)) {
++ DBG_Trace(DBG_LEVEL6, "\n WMD_BRD_Stop: CLK_Disable failed for"
++ " iva2_fck\n");
++ }
++ /* Release the Ext Base virtual Address as the next DSP Program
++ * may have a different load address */
++ if (pDevContext->dwDspExtBaseAddr)
++ pDevContext->dwDspExtBaseAddr = 0;
++
++ pDevContext->dwBrdState = BRD_STOPPED; /* update board state */
++ DBG_Trace(DBG_LEVEL1, "Device Stopped \n ");
++ /* This is a good place to clear the MMU page tables as well */
++ if (pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++ memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++ memset((u8 *)pPtAttrs->pgInfo, 0x00,
++ (pPtAttrs->L2NumPages * sizeof(struct PageInfo)));
++ }
++ DBG_Trace(DBG_LEVEL6, "WMD_BRD_Stop - End ****** \n");
++ return status;
++}
++
++
++/*
++ * ======== WMD_BRD_Status ========
++ * Returns the board status.
++ */
++static DSP_STATUS WMD_BRD_Status(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT BRD_STATUS *pdwState)
++{
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ *pdwState = pDevContext->dwBrdState;
++ return DSP_SOK;
++}
++
++/*
++ * ======== WMD_BRD_Write ========
++ * Copies the buffers to DSP internal or external memory.
++ */
++static DSP_STATUS WMD_BRD_Write(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Write, pDevContext: 0x%x\n\t\t "
++ "pbHostBuf: 0x%x\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: "
++ "0x%x\n \t\t ulMemtype: 0x%x\n", pDevContext, pbHostBuf,
++ dwDSPAddr, ulNumBytes, ulMemType);
++ if (dwDSPAddr < pDevContext->dwDSPStartAdd) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_Write: DSP address < start address \n ");
++ status = DSP_EFAIL;
++ return status;
++ }
++ if ((dwDSPAddr - pDevContext->dwDSPStartAdd) <
++ pDevContext->dwInternalSize) {
++ status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++ } else {
++ status = WriteExtDspData(pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType, false);
++ }
++
++ DBG_Trace(DBG_ENTER, "WMD_BRD_Write, memcopy : DspLogicAddr=0x%x \n",
++ pDevContext->dwDspBaseAddr);
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Create ========
++ * Creates a driver object. Puts DSP in self loop.
++ */
++static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,
++ struct DEV_OBJECT *hDevObject,
++ IN CONST struct CFG_HOSTRES *pConfig,
++ IN CONST struct CFG_DSPRES *pDspConfig)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = NULL;
++ s32 iEntryNdx;
++ s32 tcWordSwap;
++ u32 tcWordSwapSize = sizeof(tcWordSwap);
++ struct CFG_HOSTRES resources;
++ struct PgTableAttrs *pPtAttrs;
++ u32 pg_tbl_pa;
++ u32 pg_tbl_va;
++ u32 align_size;
++
++ DBG_Trace(DBG_ENTER, "WMD_DEV_Create, ppDevContext: 0x%x\n\t\t "
++ "hDevObject: 0x%x\n\t\tpConfig: 0x%x\n\t\tpDspConfig: 0x%x\n",
++ ppDevContext, hDevObject, pConfig, pDspConfig);
++ /* Allocate and initialize a data structure to contain the mini driver
++ * state, which becomes the context for later calls into this WMD. */
++ pDevContext = MEM_Calloc(sizeof(struct WMD_DEV_CONTEXT), MEM_NONPAGED);
++ if (!pDevContext) {
++ DBG_Trace(DBG_ENTER, "Failed to allocate mem \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_ENTER, "Failed to get host resources \n");
++ status = DSP_EMEMORY;
++ goto func_end;
++ }
++
++ pDevContext->dwDSPStartAdd = (u32)OMAP_GEM_BASE;
++ pDevContext->dwSelfLoop = (u32)NULL;
++ pDevContext->uDspPerClks = 0;
++ pDevContext->dwInternalSize = OMAP_DSP_SIZE;
++ /* Clear dev context MMU table entries.
++ * These get set on WMD_BRD_IOCTL() call after program loaded. */
++ for (iEntryNdx = 0; iEntryNdx < WMDIOCTL_NUMOFMMUTLB; iEntryNdx++) {
++ pDevContext->aTLBEntry[iEntryNdx].ulGppPa =
++ pDevContext->aTLBEntry[iEntryNdx].ulDspVa = 0;
++ }
++ pDevContext->numTLBEntries = 0;
++ pDevContext->dwDspBaseAddr = (u32)MEM_LinearAddress((void *)
++ (pConfig->dwMemBase[3]), pConfig->dwMemLength[3]);
++ if (!pDevContext->dwDspBaseAddr) {
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_Create: failed to Map the API memory\n");
++ }
++ pPtAttrs = MEM_Calloc(sizeof(struct PgTableAttrs), MEM_NONPAGED);
++ if (pPtAttrs != NULL) {
++ /* Assuming that we use only DSP's memory map
++ * until 0x4000:0000 , we would need only 1024
++ * L1 enties i.e L1 size = 4K */
++ pPtAttrs->L1size = 0x1000;
++ align_size = pPtAttrs->L1size;
++ /* Align sizes are expected to be power of 2 */
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L1size,
++ align_size, &pg_tbl_pa);
++ /* Check if the PA is aligned for us */
++ if ((pg_tbl_pa) & (align_size-1)) {
++ /* PA not aligned to page table size ,
++ * try with more allocation and align */
++ MEM_FreePhysMem((void *)pg_tbl_va, pg_tbl_pa, pPtAttrs->L1size);
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32) MEM_AllocPhysMem((pPtAttrs->L1size)*2,
++ align_size, &pg_tbl_pa);
++ /* We should be able to get aligned table now */
++ pPtAttrs->L1TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L1TblAllocVa = pg_tbl_va;
++ pPtAttrs->L1TblAllocSz = pPtAttrs->L1size * 2;
++ /* Align the PA to the next 'align' boundary */
++ pPtAttrs->L1BasePa = ((pg_tbl_pa) + (align_size-1)) &
++ (~(align_size-1));
++ pPtAttrs->L1BaseVa = pg_tbl_va + (pPtAttrs->L1BasePa -
++ pg_tbl_pa);
++ } else {
++ /* We got aligned PA, cool */
++ pPtAttrs->L1TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L1TblAllocVa = pg_tbl_va;
++ pPtAttrs->L1TblAllocSz = pPtAttrs->L1size;
++ pPtAttrs->L1BasePa = pg_tbl_pa;
++ pPtAttrs->L1BaseVa = pg_tbl_va;
++ }
++ if (pPtAttrs->L1BaseVa)
++ memset((u8 *)pPtAttrs->L1BaseVa, 0x00, pPtAttrs->L1size);
++
++ /* number of L2 page tables = DMM pool used + SHMMEM +EXTMEM +
++ * L4 pages */
++ pPtAttrs->L2NumPages = ((DMMPOOLSIZE >> 20) + 6);
++ pPtAttrs->L2size = HW_MMU_COARSE_PAGE_SIZE *
++ pPtAttrs->L2NumPages;
++ align_size = 4; /* Make it u32 aligned */
++ /* we like to get aligned on L1 table size */
++ pg_tbl_va = (u32)MEM_AllocPhysMem(pPtAttrs->L2size,
++ align_size, &pg_tbl_pa);
++ pPtAttrs->L2TblAllocPa = pg_tbl_pa;
++ pPtAttrs->L2TblAllocVa = pg_tbl_va;
++ pPtAttrs->L2TblAllocSz = pPtAttrs->L2size;
++ pPtAttrs->L2BasePa = pg_tbl_pa;
++ pPtAttrs->L2BaseVa = pg_tbl_va;
++
++ if (pPtAttrs->L2BaseVa)
++ memset((u8 *)pPtAttrs->L2BaseVa, 0x00, pPtAttrs->L2size);
++
++ pPtAttrs->pgInfo = MEM_Calloc(pPtAttrs->L2NumPages *
++ sizeof(struct PageInfo), MEM_NONPAGED);
++ DBG_Trace(DBG_LEVEL1, "L1 pa %x, va %x, size %x\n L2 pa %x, va "
++ "%x, size %x\n", pPtAttrs->L1BasePa,
++ pPtAttrs->L1BaseVa, pPtAttrs->L1size,
++ pPtAttrs->L2BasePa, pPtAttrs->L2BaseVa,
++ pPtAttrs->L2size);
++ DBG_Trace(DBG_LEVEL1, "pPtAttrs %x L2 NumPages %x pgInfo %x\n",
++ pPtAttrs, pPtAttrs->L2NumPages, pPtAttrs->pgInfo);
++ }
++ if ((pPtAttrs != NULL) && (pPtAttrs->L1BaseVa != 0) &&
++ (pPtAttrs->L2BaseVa != 0) && (pPtAttrs->pgInfo != NULL))
++ pDevContext->pPtAttrs = pPtAttrs;
++ else
++ status = DSP_EMEMORY;
++
++ if (DSP_SUCCEEDED(status))
++ status = SYNC_InitializeCS(&pPtAttrs->hCSObj);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Endianism Register */ /* Need to set this */
++ /* Retrieve the TC u16 SWAP Option */
++ status = REG_GetValue(NULL, CURRENTCONFIG, TCWORDSWAP,
++ (u8 *)&tcWordSwap, &tcWordSwapSize);
++ /* Save the value */
++ pDevContext->tcWordSwapOn = tcWordSwap;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ /* Set the Clock Divisor for the DSP module */
++ DBG_Trace(DBG_LEVEL7, "WMD_DEV_create:Reset mail box and "
++ "enable the clock \n");
++ status = CLK_Enable(SERVICESCLK_mailbox_ick);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_create:Reset mail box and "
++ "enable the clock Fail\n");
++ }
++ udelay(5);
++ /* 24xx-Linux MMU address is obtained from the host
++ * resources struct */
++ pDevContext->dwDSPMmuBase = resources.dwDmmuBase;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pDevContext->hDevObject = hDevObject;
++ pDevContext->ulIntMask = 0;
++ /* Store current board state. */
++ pDevContext->dwBrdState = BRD_STOPPED;
++ /* Return this ptr to our device state to the WCD for storage:*/
++ *ppDevContext = pDevContext;
++ DBG_Trace(DBG_ENTER, "Device Created \n");
++ } else {
++ if (pPtAttrs != NULL) {
++ if (pPtAttrs->hCSObj)
++ SYNC_DeleteCS(pPtAttrs->hCSObj);
++
++ if (pPtAttrs->pgInfo)
++ MEM_Free(pPtAttrs->pgInfo);
++
++ if (pPtAttrs->L2TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
++ pPtAttrs->L2TblAllocPa,
++ pPtAttrs->L2TblAllocSz);
++ }
++ if (pPtAttrs->L1TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
++ pPtAttrs->L1TblAllocPa,
++ pPtAttrs->L1TblAllocSz);
++ }
++ }
++ if (pPtAttrs)
++ MEM_Free(pPtAttrs);
++
++ if (pDevContext)
++ MEM_Free(pDevContext);
++
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_DEV_Create Error Device not created\n");
++ }
++func_end:
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Ctrl ========
++ * Receives device specific commands.
++ */
++static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,
++ IN OUT void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMDIOCTL_EXTPROC *paExtProc = (struct WMDIOCTL_EXTPROC *)pArgs;
++ s32 ndx;
++
++ DBG_Trace(DBG_ENTER, "WMD_DEV_Ctrl, pDevContext: 0x%x\n\t\t dwCmd: "
++ "0x%x\n\t\tpArgs: 0x%x\n", pDevContext, dwCmd, pArgs);
++ switch (dwCmd) {
++ case WMDIOCTL_CHNLREAD:
++ break;
++ case WMDIOCTL_CHNLWRITE:
++ break;
++ case WMDIOCTL_SETMMUCONFIG:
++ /* store away dsp-mmu setup values for later use */
++ for (ndx = 0; ndx < WMDIOCTL_NUMOFMMUTLB; ndx++, paExtProc++)
++ pDevContext->aTLBEntry[ndx] = *paExtProc;
++
++ break;
++ case WMDIOCTL_DEEPSLEEP:
++ case WMDIOCTL_EMERGENCYSLEEP:
++ /* Currently only DSP Idle is supported Need to update for
++ * later releases */
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_DEEPSLEEP\n");
++ status = SleepDSP(pDevContext, PWR_DEEPSLEEP, pArgs);
++ break;
++ case WMDIOCTL_WAKEUP:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_WAKEUP\n");
++ status = WakeDSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_CLK_CTRL:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CLK_CTRL\n");
++ status = DSP_SOK;
++ /* Looking For Baseport Fix for Clocks */
++ status = DSPPeripheralClkCtrl(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_PWR_HIBERNATE:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PWR_HIBERNATE\n");
++ status = handle_hibernation_fromDSP(pDevContext);
++ break;
++ case WMDIOCTL_PRESCALE_NOTIFY:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_PRESCALE_NOTIFY\n");
++ status = PreScale_DSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_POSTSCALE_NOTIFY:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_POSTSCALE_NOTIFY\n");
++ status = PostScale_DSP(pDevContext, pArgs);
++ break;
++ case WMDIOCTL_CONSTRAINT_REQUEST:
++ DBG_Trace(DBG_LEVEL5, "WMDIOCTL_CONSTRAINT_REQUEST\n");
++ status = handle_constraints_set(pDevContext, pArgs);
++ break;
++ default:
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "Error in WMD_BRD_Ioctl \n");
++ break;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_DEV_Destroy ========
++ * Destroys the driver object.
++ */
++static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *hDevContext)
++{
++ struct PgTableAttrs *pPtAttrs;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = (struct WMD_DEV_CONTEXT *)
++ hDevContext;
++ DBG_Trace(DBG_ENTER, "Entering WMD_DEV_Destroy:n hDevContext ::0x%x\n",
++ hDevContext);
++ /* first put the device to stop state */
++ WMD_BRD_Delete(pDevContext);
++ if (pDevContext && pDevContext->pPtAttrs) {
++ pPtAttrs = pDevContext->pPtAttrs;
++ if (pPtAttrs->hCSObj)
++ SYNC_DeleteCS(pPtAttrs->hCSObj);
++
++ if (pPtAttrs->pgInfo)
++ MEM_Free(pPtAttrs->pgInfo);
++
++ if (pPtAttrs->L2TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L2TblAllocVa,
++ pPtAttrs->L2TblAllocPa, pPtAttrs->
++ L2TblAllocSz);
++ }
++ if (pPtAttrs->L1TblAllocVa) {
++ MEM_FreePhysMem((void *)pPtAttrs->L1TblAllocVa,
++ pPtAttrs->L1TblAllocPa, pPtAttrs->
++ L1TblAllocSz);
++ }
++ if (pPtAttrs)
++ MEM_Free(pPtAttrs);
++
++ }
++ /* Free the driver's device context: */
++ MEM_Free((void *) hDevContext);
++ return status;
++}
++
++static DSP_STATUS WMD_BRD_MemCopy(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulDspDestAddr, u32 ulDspSrcAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 srcAddr = ulDspSrcAddr;
++ u32 destAddr = ulDspDestAddr;
++ u32 copyBytes = 0;
++ u32 totalBytes = ulNumBytes;
++ u8 hostBuf[BUFFERSIZE];
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ while ((totalBytes > 0) && DSP_SUCCEEDED(status)) {
++ copyBytes = totalBytes > BUFFERSIZE ? BUFFERSIZE : totalBytes;
++ /* Read from External memory */
++ status = ReadExtDspData(hDevContext, hostBuf, srcAddr,
++ copyBytes, ulMemType);
++ if (DSP_SUCCEEDED(status)) {
++ if (destAddr < (pDevContext->dwDSPStartAdd +
++ pDevContext->dwInternalSize)) {
++ /* Write to Internal memory */
++ status = WriteDspData(hDevContext, hostBuf,
++ destAddr, copyBytes, ulMemType);
++ } else {
++ /* Write to External memory */
++ status = WriteExtDspData(hDevContext, hostBuf,
++ destAddr, copyBytes, ulMemType, false);
++ }
++ }
++ totalBytes -= copyBytes;
++ srcAddr += copyBytes;
++ destAddr += copyBytes;
++ }
++ return status;
++}
++
++/* Mem Write does not halt the DSP to write unlike WMD_BRD_Write */
++static DSP_STATUS WMD_BRD_MemWrite(struct WMD_DEV_CONTEXT *hDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 ulRemainBytes = 0;
++ u32 ulBytes = 0;
++ ulRemainBytes = ulNumBytes;
++ while (ulRemainBytes > 0 && DSP_SUCCEEDED(status)) {
++ ulBytes =
++ ulRemainBytes > BUFFERSIZE ? BUFFERSIZE : ulRemainBytes;
++ if (dwDSPAddr < (pDevContext->dwDSPStartAdd +
++ pDevContext->dwInternalSize)) {
++ status = WriteDspData(hDevContext, pbHostBuf, dwDSPAddr,
++ ulBytes, ulMemType);
++ } else {
++ status = WriteExtDspData(hDevContext, pbHostBuf,
++ dwDSPAddr, ulBytes, ulMemType, true);
++ }
++ ulRemainBytes -= ulBytes;
++ dwDSPAddr += ulBytes;
++ pbHostBuf = pbHostBuf + ulBytes;
++ }
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_MemMap ========
++ * This function maps MPU buffer to the DSP address space. It performs
++ * linear to physical address translation if required. It translates each
++ * page since linear addresses can be physically non-contiguous
++ * All address & size arguments are assumed to be page aligned (in proc.c)
++ *
++ * TODO: Disable MMU while updating the page tables (but that'll stall DSP)
++ */
++static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr,
++ u32 ulNumBytes, u32 ulMapAttr)
++{
++ u32 attrs;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct HW_MMUMapAttrs_t hwAttrs;
++ struct vm_area_struct *vma;
++ struct mm_struct *mm = current->mm;
++ u32 write = 0;
++ u32 numUsrPgs = 0;
++ struct page *mappedPage, *pg;
++ s32 pgNum;
++ u32 va = ulVirtAddr;
++ struct task_struct *curr_task = current;
++ u32 pgI = 0;
++ u32 mpuAddr, pa;
++
++ DBG_Trace(DBG_ENTER, "> WMD_BRD_MemMap hDevContext %x, pa %x, va %x, "
++ "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, ulMapAttr);
++ if (ulNumBytes == 0)
++ return DSP_EINVALIDARG;
++
++ if (ulMapAttr != 0) {
++ attrs = ulMapAttr;
++ } else {
++ /* Assign default attributes */
++ attrs = DSP_MAPVIRTUALADDR | DSP_MAPELEMSIZE16;
++ }
++ /* Take mapping properties */
++ if (attrs & DSP_MAPBIGENDIAN)
++ hwAttrs.endianism = HW_BIG_ENDIAN;
++ else
++ hwAttrs.endianism = HW_LITTLE_ENDIAN;
++
++ hwAttrs.mixedSize = (enum HW_MMUMixedSize_t)
++ ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);
++ /* Ignore elementSize if mixedSize is enabled */
++ if (hwAttrs.mixedSize == 0) {
++ if (attrs & DSP_MAPELEMSIZE8) {
++ /* Size is 8 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_8BIT;
++ } else if (attrs & DSP_MAPELEMSIZE16) {
++ /* Size is 16 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_16BIT;
++ } else if (attrs & DSP_MAPELEMSIZE32) {
++ /* Size is 32 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_32BIT;
++ } else if (attrs & DSP_MAPELEMSIZE64) {
++ /* Size is 64 bit */
++ hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;
++ } else {
++ /*
++ * Mixedsize isn't enabled, so size can't be
++ * zero here
++ */
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: MMU element size is zero\n");
++ return DSP_EINVALIDARG;
++ }
++ }
++ if (attrs & DSP_MAPDONOTLOCK)
++ hwAttrs.donotlockmpupage = 1;
++ else
++ hwAttrs.donotlockmpupage = 0;
++
++ if (attrs & DSP_MAPVMALLOCADDR) {
++ return MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, &hwAttrs);
++ }
++ /*
++ * Do OS-specific user-va to pa translation.
++ * Combine physically contiguous regions to reduce TLBs.
++ * Pass the translated pa to PteUpdate.
++ */
++ if ((attrs & DSP_MAPPHYSICALADDR)) {
++ status = PteUpdate(pDevContext, ulMpuAddr, ulVirtAddr,
++ ulNumBytes, &hwAttrs);
++ goto func_cont;
++ }
++
++ /*
++ * Important Note: ulMpuAddr is mapped from user application process
++ * to current process - it must lie completely within the current
++ * virtual memory address space in order to be of use to us here!
++ */
++ down_read(&mm->mmap_sem);
++ vma = find_vma(mm, ulMpuAddr);
++ if (vma)
++ DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf: ulMpuAddr=%x, "
++ "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x \n",
++ ulMpuAddr, ulNumBytes, vma->vm_start,
++ vma->vm_end, vma->vm_flags);
++
++ /*
++ * It is observed that under some circumstances, the user buffer is
++ * spread across several VMAs. So loop through and check if the entire
++ * user buffer is covered
++ */
++ while ((vma) && (ulMpuAddr + ulNumBytes > vma->vm_end)) {
++ /* jump to the next VMA region */
++ vma = find_vma(mm, vma->vm_end + 1);
++ DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf ulMpuAddr=%x, "
++ "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x\n",
++ ulMpuAddr, ulNumBytes, vma->vm_start,
++ vma->vm_end, vma->vm_flags);
++ }
++ if (!vma) {
++ DBG_Trace(DBG_LEVEL7, "Failed to get the VMA region for "
++ "MPU Buffer !!! \n");
++ status = DSP_EINVALIDARG;
++ up_read(&mm->mmap_sem);
++ goto func_cont;
++ }
++
++ if (vma->vm_flags & VM_IO) {
++ numUsrPgs = ulNumBytes / PG_SIZE_4K;
++ mpuAddr = ulMpuAddr;
++ DBG_Trace(DBG_LEVEL4, "WMD_BRD_MemMap:numOfActualTabEntries=%d,"
++ "ulNumBytes= %d\n", numUsrPgs, ulNumBytes);
++ /* Get the physical addresses for user buffer */
++ for (pgI = 0; pgI < numUsrPgs; pgI++) {
++ pa = user_va2pa(mm, mpuAddr);
++ if (!pa) {
++ status = DSP_EFAIL;
++ pr_err("DSPBRIDGE: VM_IO mapping physical"
++ "address is invalid\n");
++ break;
++ }
++ if (pfn_valid(__phys_to_pfn(pa))) {
++ pg = phys_to_page(pa);
++ get_page(pg);
++ if (page_count(pg) < 1) {
++ pr_err("Bad page in VM_IO buffer\n");
++ bad_page_dump(pa, pg);
++ }
++ }
++ status = PteSet(pDevContext->pPtAttrs, pa,
++ va, HW_PAGE_SIZE_4KB, &hwAttrs);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: FAILED IN VM_IO"
++ "PTESET \n");
++ break;
++ }
++ va += HW_PAGE_SIZE_4KB;
++ mpuAddr += HW_PAGE_SIZE_4KB;
++ pa += HW_PAGE_SIZE_4KB;
++ }
++ } else {
++ numUsrPgs = ulNumBytes / PG_SIZE_4K;
++ if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
++ write = 1;
++
++ for (pgI = 0; pgI < numUsrPgs; pgI++) {
++ pgNum = get_user_pages(curr_task, mm, ulMpuAddr, 1,
++ write, 1, &mappedPage, NULL);
++ if (pgNum > 0) {
++ if (page_count(mappedPage) < 1) {
++ pr_err("Bad page count after doing"
++ "get_user_pages on"
++ "user buffer\n");
++ bad_page_dump(page_to_phys(mappedPage),
++ mappedPage);
++ }
++ status = PteSet(pDevContext->pPtAttrs,
++ page_to_phys(mappedPage), va,
++ HW_PAGE_SIZE_4KB, &hwAttrs);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "WMD_BRD_MemMap: FAILED IN PTESET \n");
++ break;
++ }
++ va += HW_PAGE_SIZE_4KB;
++ ulMpuAddr += HW_PAGE_SIZE_4KB;
++ } else {
++ pr_err("DSPBRIDGE: get_user_pages FAILED,"
++ "MPU addr = 0x%x,"
++ "vma->vm_flags = 0x%lx,"
++ "get_user_pages Err"
++ "Value = %d, Buffer"
++ "size=0x%x\n", ulMpuAddr,
++ vma->vm_flags, pgNum,
++ ulNumBytes);
++ status = DSP_EFAIL;
++ break;
++ }
++ }
++ }
++ up_read(&mm->mmap_sem);
++func_cont:
++ /* Don't propogate Linux or HW status to upper layers */
++ if (DSP_SUCCEEDED(status)) {
++ status = DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
++ /*
++ * Roll out the mapped pages incase it failed in middle of
++ * mapping
++ */
++ if (pgI) {
++ WMD_BRD_MemUnMap(pDevContext, ulVirtAddr,
++ (pgI * PG_SIZE_4K));
++ }
++ status = DSP_EFAIL;
++ }
++ /*
++ * In any case, flush the TLB
++ * This is called from here instead from PteUpdate to avoid unnecessary
++ * repetition while mapping non-contiguous physical regions of a virtual
++ * region
++ */
++ flush_all(pDevContext);
++ DBG_Trace(DBG_ENTER, "< WMD_BRD_MemMap status %x\n", status);
++ return status;
++}
++
++/*
++ * ======== WMD_BRD_MemUnMap ========
++ * Invalidate the PTEs for the DSP VA block to be unmapped.
++ *
++ * PTEs of a mapped memory block are contiguous in any page table
++ * So, instead of looking up the PTE address for every 4K block,
++ * we clear consecutive PTEs until we unmap all the bytes
++ */
++static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,
++ u32 ulVirtAddr, u32 ulNumBytes)
++{
++ u32 L1BaseVa;
++ u32 L2BaseVa;
++ u32 L2BasePa;
++ u32 L2PageNum;
++ u32 pteVal;
++ u32 pteSize;
++ u32 pteCount;
++ u32 pteAddrL1;
++ u32 pteAddrL2 = 0;
++ u32 remBytes;
++ u32 remBytesL2;
++ u32 vaCurr;
++ struct page *pg = NULL;
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ struct PgTableAttrs *pt = pDevContext->pPtAttrs;
++ u32 pacount = 0;
++ u32 *pPhysAddrPageTbl = NULL;
++ u32 temp;
++ u32 patemp = 0;
++ u32 pAddr;
++ u32 numof4KPages = 0;
++
++ DBG_Trace(DBG_ENTER, "> WMD_BRD_MemUnMap hDevContext %x, va %x, "
++ "NumBytes %x\n", hDevContext, ulVirtAddr, ulNumBytes);
++ pPhysAddrPageTbl = DMM_GetPhysicalAddrTable();
++ vaCurr = ulVirtAddr;
++ remBytes = ulNumBytes;
++ remBytesL2 = 0;
++ L1BaseVa = pt->L1BaseVa;
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
++ DBG_Trace(DBG_ENTER, "WMD_BRD_MemUnMap L1BaseVa %x, pteAddrL1 %x "
++ "vaCurr %x remBytes %x\n", L1BaseVa, pteAddrL1,
++ vaCurr, remBytes);
++ while (remBytes && (DSP_SUCCEEDED(status))) {
++ u32 vaCurrOrig = vaCurr;
++ /* Find whether the L1 PTE points to a valid L2 PT */
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, vaCurr);
++ pteVal = *(u32 *)pteAddrL1;
++ pteSize = HW_MMU_PteSizeL1(pteVal);
++ if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
++ /*
++ * Get the L2 PA from the L1 PTE, and find
++ * corresponding L2 VA
++ */
++ L2BasePa = HW_MMU_PteCoarseL1(pteVal);
++ L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
++ L2PageNum = (L2BasePa - pt->L2BasePa) /
++ HW_MMU_COARSE_PAGE_SIZE;
++ /*
++ * Find the L2 PTE address from which we will start
++ * clearing, the number of PTEs to be cleared on this
++ * page, and the size of VA space that needs to be
++ * cleared on this L2 page
++ */
++ pteAddrL2 = HW_MMU_PteAddrL2(L2BaseVa, vaCurr);
++ pteCount = pteAddrL2 & (HW_MMU_COARSE_PAGE_SIZE - 1);
++ pteCount = (HW_MMU_COARSE_PAGE_SIZE - pteCount) /
++ sizeof(u32);
++ if (remBytes < (pteCount * PG_SIZE_4K))
++ pteCount = remBytes / PG_SIZE_4K;
++
++ remBytesL2 = pteCount * PG_SIZE_4K;
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2BasePa %x, "
++ "L2BaseVa %x pteAddrL2 %x, remBytesL2 %x\n",
++ L2BasePa, L2BaseVa, pteAddrL2, remBytesL2);
++ /*
++ * Unmap the VA space on this L2 PT. A quicker way
++ * would be to clear pteCount entries starting from
++ * pteAddrL2. However, below code checks that we don't
++ * clear invalid entries or less than 64KB for a 64KB
++ * entry. Similar checking is done for L1 PTEs too
++ * below
++ */
++ while (remBytesL2 && (DSP_SUCCEEDED(status))) {
++ pteVal = *(u32 *)pteAddrL2;
++ pteSize = HW_MMU_PteSizeL2(pteVal);
++ /* vaCurr aligned to pteSize? */
++ if ((pteSize != 0) && (remBytesL2 >= pteSize) &&
++ !(vaCurr & (pteSize - 1))) {
++ /* Collect Physical addresses from VA */
++ pAddr = (pteVal & ~(pteSize - 1));
++ if (pteSize == HW_PAGE_SIZE_64KB)
++ numof4KPages = 16;
++ else
++ numof4KPages = 1;
++ temp = 0;
++ while (temp++ < numof4KPages) {
++ pPhysAddrPageTbl[pacount++] =
++ pAddr;
++ pAddr += HW_PAGE_SIZE_4KB;
++ }
++ if (HW_MMU_PteClear(pteAddrL2,
++ vaCurr, pteSize) == RET_OK) {
++ status = DSP_SOK;
++ remBytesL2 -= pteSize;
++ vaCurr += pteSize;
++ pteAddrL2 += (pteSize >> 12) *
++ sizeof(u32);
++ } else {
++ status = DSP_EFAIL;
++ goto EXIT_LOOP;
++ }
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ SYNC_EnterCS(pt->hCSObj);
++ if (remBytesL2 == 0) {
++ pt->pgInfo[L2PageNum].numEntries -= pteCount;
++ if (pt->pgInfo[L2PageNum].numEntries == 0) {
++ /*
++ * Clear the L1 PTE pointing to the
++ * L2 PT
++ */
++ if (RET_OK == HW_MMU_PteClear(L1BaseVa,
++ vaCurrOrig, HW_MMU_COARSE_PAGE_SIZE))
++ status = DSP_SOK;
++ else {
++ status = DSP_EFAIL;
++ SYNC_LeaveCS(pt->hCSObj);
++ goto EXIT_LOOP;
++ }
++ }
++ remBytes -= pteCount * PG_SIZE_4K;
++ } else {
++ status = DSP_EFAIL;
++ }
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2PageNum %x, "
++ "numEntries %x, pteCount %x, status: 0x%x\n",
++ L2PageNum, pt->pgInfo[L2PageNum].numEntries,
++ pteCount, status);
++ SYNC_LeaveCS(pt->hCSObj);
++ } else
++ /* vaCurr aligned to pteSize? */
++ /* pteSize = 1 MB or 16 MB */
++ if ((pteSize != 0) && (remBytes >= pteSize) &&
++ !(vaCurr & (pteSize - 1))) {
++ if (pteSize == HW_PAGE_SIZE_1MB)
++ numof4KPages = 256;
++ else
++ numof4KPages = 4096;
++ temp = 0;
++ /* Collect Physical addresses from VA */
++ pAddr = (pteVal & ~(pteSize - 1));
++ while (temp++ < numof4KPages) {
++ pPhysAddrPageTbl[pacount++] = pAddr;
++ pAddr += HW_PAGE_SIZE_4KB;
++ }
++ if (HW_MMU_PteClear(L1BaseVa, vaCurr, pteSize)
++ == RET_OK) {
++ status = DSP_SOK;
++ remBytes -= pteSize;
++ vaCurr += pteSize;
++ } else {
++ status = DSP_EFAIL;
++ goto EXIT_LOOP;
++ }
++ } else {
++ status = DSP_EFAIL;
++ }
++ }
++ /*
++ * It is better to flush the TLB here, so that any stale old entries
++ * get flushed
++ */
++EXIT_LOOP:
++ flush_all(pDevContext);
++ for (temp = 0; temp < pacount; temp++) {
++ patemp = pPhysAddrPageTbl[temp];
++ if (pfn_valid(__phys_to_pfn(patemp))) {
++ pg = phys_to_page(patemp);
++ if (page_count(pg) < 1) {
++ pr_info("DSPBRIDGE:UNMAP function: COUNT 0"
++ "FOR PA 0x%x, size = 0x%x\n",
++ patemp, ulNumBytes);
++ bad_page_dump(patemp, pg);
++ }
++ SetPageDirty(pg);
++ page_cache_release(pg);
++ }
++ }
++ DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap vaCurr %x, pteAddrL1 %x "
++ "pteAddrL2 %x\n", vaCurr, pteAddrL1, pteAddrL2);
++ DBG_Trace(DBG_ENTER, "< WMD_BRD_MemUnMap status %x remBytes %x, "
++ "remBytesL2 %x\n", status, remBytes, remBytesL2);
++ return status;
++}
++
++/*
++ * ======== user_va2pa ========
++ * Purpose:
++ * This function walks through the Linux page tables to convert a userland
++ * virtual address to physical address
++ */
++static u32 user_va2pa(struct mm_struct *mm, u32 address)
++{
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *ptep, pte;
++
++ pgd = pgd_offset(mm, address);
++ if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {
++ pmd = pmd_offset(pgd, address);
++ if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {
++ ptep = pte_offset_map(pmd, address);
++ if (ptep) {
++ pte = *ptep;
++ if (pte_present(pte))
++ return pte & PAGE_MASK;
++ }
++ }
++ }
++
++ return 0;
++}
++
++
++/*
++ * ======== PteUpdate ========
++ * This function calculates the optimum page-aligned addresses and sizes
++ * Caller must pass page-aligned values
++ */
++static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,
++ u32 va, u32 size,
++ struct HW_MMUMapAttrs_t *mapAttrs)
++{
++ u32 i;
++ u32 allBits;
++ u32 paCurr = pa;
++ u32 vaCurr = va;
++ u32 numBytes = size;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ DSP_STATUS status = DSP_SOK;
++ u32 pgSize[] = { HW_PAGE_SIZE_16MB, HW_PAGE_SIZE_1MB,
++ HW_PAGE_SIZE_64KB, HW_PAGE_SIZE_4KB };
++ DBG_Trace(DBG_ENTER, "> PteUpdate hDevContext %x, pa %x, va %x, "
++ "size %x, mapAttrs %x\n", hDevContext, pa, va, size, mapAttrs);
++ while (numBytes && DSP_SUCCEEDED(status)) {
++ /* To find the max. page size with which both PA & VA are
++ * aligned */
++ allBits = paCurr | vaCurr;
++ DBG_Trace(DBG_LEVEL1, "allBits %x, paCurr %x, vaCurr %x, "
++ "numBytes %x ", allBits, paCurr, vaCurr, numBytes);
++ for (i = 0; i < 4; i++) {
++ if ((numBytes >= pgSize[i]) && ((allBits &
++ (pgSize[i] - 1)) == 0)) {
++ DBG_Trace(DBG_LEVEL1, "pgSize %x\n", pgSize[i]);
++ status = PteSet(pDevContext->pPtAttrs, paCurr,
++ vaCurr, pgSize[i], mapAttrs);
++ paCurr += pgSize[i];
++ vaCurr += pgSize[i];
++ numBytes -= pgSize[i];
++ /* Don't try smaller sizes. Hopefully we have
++ * reached an address aligned to a bigger page
++ * size */
++ break;
++ }
++ }
++ }
++ DBG_Trace(DBG_ENTER, "< PteUpdate status %x numBytes %x\n", status,
++ numBytes);
++ return status;
++}
++
++/*
++ * ======== PteSet ========
++ * This function calculates PTE address (MPU virtual) to be updated
++ * It also manages the L2 page tables
++ */
++static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,
++ u32 size, struct HW_MMUMapAttrs_t *attrs)
++{
++ u32 i;
++ u32 pteVal;
++ u32 pteAddrL1;
++ u32 pteSize;
++ u32 pgTblVa; /* Base address of the PT that will be updated */
++ u32 L1BaseVa;
++ /* Compiler warns that the next three variables might be used
++ * uninitialized in this function. Doesn't seem so. Working around,
++ * anyways. */
++ u32 L2BaseVa = 0;
++ u32 L2BasePa = 0;
++ u32 L2PageNum = 0;
++ DSP_STATUS status = DSP_SOK;
++ DBG_Trace(DBG_ENTER, "> PteSet pPgTableAttrs %x, pa %x, va %x, "
++ "size %x, attrs %x\n", pt, pa, va, size, attrs);
++ L1BaseVa = pt->L1BaseVa;
++ pgTblVa = L1BaseVa;
++ if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) {
++ /* Find whether the L1 PTE points to a valid L2 PT */
++ pteAddrL1 = HW_MMU_PteAddrL1(L1BaseVa, va);
++ if (pteAddrL1 <= (pt->L1BaseVa + pt->L1size)) {
++ pteVal = *(u32 *)pteAddrL1;
++ pteSize = HW_MMU_PteSizeL1(pteVal);
++ } else {
++ return DSP_EFAIL;
++ }
++ SYNC_EnterCS(pt->hCSObj);
++ if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {
++ /* Get the L2 PA from the L1 PTE, and find
++ * corresponding L2 VA */
++ L2BasePa = HW_MMU_PteCoarseL1(pteVal);
++ L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;
++ L2PageNum = (L2BasePa - pt->L2BasePa) /
++ HW_MMU_COARSE_PAGE_SIZE;
++ } else if (pteSize == 0) {
++ /* L1 PTE is invalid. Allocate a L2 PT and
++ * point the L1 PTE to it */
++ /* Find a free L2 PT. */
++ for (i = 0; (i < pt->L2NumPages) &&
++ (pt->pgInfo[i].numEntries != 0); i++)
++ ;;
++ if (i < pt->L2NumPages) {
++ L2PageNum = i;
++ L2BasePa = pt->L2BasePa + (L2PageNum *
++ HW_MMU_COARSE_PAGE_SIZE);
++ L2BaseVa = pt->L2BaseVa + (L2PageNum *
++ HW_MMU_COARSE_PAGE_SIZE);
++ /* Endianness attributes are ignored for
++ * HW_MMU_COARSE_PAGE_SIZE */
++ status = HW_MMU_PteSet(L1BaseVa, L2BasePa, va,
++ HW_MMU_COARSE_PAGE_SIZE, attrs);
++ } else {
++ status = DSP_EMEMORY;
++ }
++ } else {
++ /* Found valid L1 PTE of another size.
++ * Should not overwrite it. */
++ status = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(status)) {
++ pgTblVa = L2BaseVa;
++ if (size == HW_PAGE_SIZE_64KB)
++ pt->pgInfo[L2PageNum].numEntries += 16;
++ else
++ pt->pgInfo[L2PageNum].numEntries++;
++ DBG_Trace(DBG_LEVEL1, "L2 BaseVa %x, BasePa %x, "
++ "PageNum %x numEntries %x\n", L2BaseVa,
++ L2BasePa, L2PageNum,
++ pt->pgInfo[L2PageNum].numEntries);
++ }
++ SYNC_LeaveCS(pt->hCSObj);
++ }
++ if (DSP_SUCCEEDED(status)) {
++ DBG_Trace(DBG_LEVEL1, "PTE pgTblVa %x, pa %x, va %x, size %x\n",
++ pgTblVa, pa, va, size);
++ DBG_Trace(DBG_LEVEL1, "PTE endianism %x, elementSize %x, "
++ "mixedSize %x\n", attrs->endianism,
++ attrs->elementSize, attrs->mixedSize);
++ status = HW_MMU_PteSet(pgTblVa, pa, va, size, attrs);
++ }
++ DBG_Trace(DBG_ENTER, "< PteSet status %x\n", status);
++ return status;
++}
++
++/* Memory map kernel VA -- memory allocated with vmalloc */
++static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *pDevContext,
++ u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,
++ struct HW_MMUMapAttrs_t *hwAttrs)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct page *pPage[1];
++ u32 i;
++ u32 paCurr;
++ u32 paNext;
++ u32 vaCurr;
++ u32 sizeCurr;
++ u32 numPages;
++ u32 pa;
++ u32 numOf4KPages;
++ u32 temp = 0;
++
++ DBG_Trace(DBG_ENTER, "> MemMapVmalloc hDevContext %x, pa %x, va %x, "
++ "size %x\n", pDevContext, ulMpuAddr, ulVirtAddr, ulNumBytes);
++
++ /*
++ * Do Kernel va to pa translation.
++ * Combine physically contiguous regions to reduce TLBs.
++ * Pass the translated pa to PteUpdate.
++ */
++ numPages = ulNumBytes / PAGE_SIZE; /* PAGE_SIZE = OS page size */
++ i = 0;
++ vaCurr = ulMpuAddr;
++ pPage[0] = vmalloc_to_page((void *)vaCurr);
++ paNext = page_to_phys(pPage[0]);
++ while (DSP_SUCCEEDED(status) && (i < numPages)) {
++ /*
++ * Reuse paNext from the previous iteraion to avoid
++ * an extra va2pa call
++ */
++ paCurr = paNext;
++ sizeCurr = PAGE_SIZE;
++ /*
++ * If the next page is physically contiguous,
++ * map it with the current one by increasing
++ * the size of the region to be mapped
++ */
++ while (++i < numPages) {
++ pPage[0] = vmalloc_to_page((void *)(vaCurr + sizeCurr));
++ paNext = page_to_phys(pPage[0]);
++ DBG_Trace(DBG_LEVEL5, "Xlate Vmalloc VA=0x%x , "
++ "PA=0x%x \n", (vaCurr + sizeCurr), paNext);
++ if (paNext == (paCurr + sizeCurr))
++ sizeCurr += PAGE_SIZE;
++ else
++ break;
++
++ }
++ if (paNext == 0) {
++ status = DSP_EMEMORY;
++ break;
++ }
++ pa = paCurr;
++ numOf4KPages = sizeCurr / HW_PAGE_SIZE_4KB;
++ while (temp++ < numOf4KPages) {
++ get_page(phys_to_page(pa));
++ pa += HW_PAGE_SIZE_4KB;
++ }
++ status = PteUpdate(pDevContext, paCurr, ulVirtAddr +
++ (vaCurr - ulMpuAddr), sizeCurr, hwAttrs);
++ vaCurr += sizeCurr;
++ }
++ /* Don't propogate Linux or HW status to upper layers */
++ if (DSP_SUCCEEDED(status)) {
++ status = DSP_SOK;
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap succeeded %x\n",
++ status);
++ } else {
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);
++ status = DSP_EFAIL;
++ }
++ /*
++ * In any case, flush the TLB
++ * This is called from here instead from PteUpdate to avoid unnecessary
++ * repetition while mapping non-contiguous physical regions of a virtual
++ * region
++ */
++ flush_all(pDevContext);
++ DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap at end status %x\n", status);
++ return status;
++}
++
++static DSP_STATUS run_IdleBoot(u32 prm_base, u32 cm_base,
++ u32 sysctrl_base)
++{
++ u32 temp;
++ DSP_STATUS status = DSP_SOK;
++ enum HW_PwrState_t pwrState;
++
++ /* Read PM_PWSTST_IVA2 */
++ HW_PWRST_IVA2RegGet(prm_base, &temp);
++ if ((temp & 0x03) != 0x03 || (temp & 0x03) != 0x02) {
++ /* IVA2 is not in ON state */
++ /* Set PM_PWSTCTRL_IVA2 to ON */
++ HW_PWR_IVA2PowerStateSet(prm_base, HW_PWR_DOMAIN_DSP,
++ HW_PWR_STATE_ON);
++ /* Set the SW supervised state transition */
++ HW_PWR_CLKCTRL_IVA2RegSet(cm_base, HW_SW_SUP_WAKEUP);
++ /* Wait until the state has moved to ON */
++ HW_PWR_IVA2StateGet(prm_base, HW_PWR_DOMAIN_DSP, &pwrState);
++ }
++ CLK_Disable(SERVICESCLK_iva2_ck);
++ udelay(10);
++ /* Assert IVA2-RST1 and IVA2-RST2 */
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x07;
++ udelay(30);
++ /* set the SYSC for Idle Boot */
++ *((REG_UWORD32 *)((u32)(sysctrl_base) + 0x404)) = (u32)0x01;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (cm_base) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (cm_base) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (cm_base) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++ *((REG_UWORD32 *) ((u32) (cm_base) + 0x4)) =
++ (u32) temp;
++ CLK_Enable(SERVICESCLK_iva2_ck);
++ udelay(20);
++ GetHWRegs(prm_base, cm_base);
++ /* Release Reset1 and Reset2 */
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x05;
++ udelay(20);
++ *((REG_UWORD32 *)((u32)(prm_base) + 0x50)) = (u32)0x04;
++ udelay(30);
++ return status;
++}
++
++
++void GetHWRegs(u32 prm_base, u32 cm_base)
++{
++ u32 temp;
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x00));
++ DBG_Trace(DBG_LEVEL6, "CM_FCLKEN_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x10));
++ DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x20));
++ DBG_Trace(DBG_LEVEL6, "CM_IDLEST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x48));
++ DBG_Trace(DBG_LEVEL6, "CM_CLKSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0x4c));
++ DBG_Trace(DBG_LEVEL6, "CM_CLKSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x50));
++ DBG_Trace(DBG_LEVEL6, "RM_RSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0x58));
++ DBG_Trace(DBG_LEVEL6, "RM_RSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE0));
++ DBG_Trace(DBG_LEVEL6, "PM_PWSTCTRL_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(prm_base) + 0xE4));
++ DBG_Trace(DBG_LEVEL6, "PM_PWSTST_IVA2 = 0x%x \n", temp);
++ temp = (u32)*((REG_UWORD32 *)((u32)(cm_base) + 0xA10));
++ DBG_Trace(DBG_LEVEL6, "CM_ICLKEN1_CORE = 0x%x \n", temp);
++}
++
++/*
++ * ======== configureDspMmu ========
++ * Make DSP MMU page table entries.
++ */
++void configureDspMmu(struct WMD_DEV_CONTEXT *pDevContext, u32 dataBasePhys,
++ u32 dspBaseVirt, u32 sizeInBytes, s32 nEntryStart,
++ enum HW_Endianism_t endianism,
++ enum HW_ElementSize_t elemSize,
++ enum HW_MMUMixedSize_t mixedSize)
++{
++ struct CFG_HOSTRES resources;
++ struct HW_MMUMapAttrs_t mapAttrs = { endianism, elemSize, mixedSize };
++ DSP_STATUS status = DSP_SOK;
++
++ DBC_Require(sizeInBytes > 0);
++ DBG_Trace(DBG_LEVEL1,
++ "configureDspMmu entry %x pa %x, va %x, bytes %x ",
++ nEntryStart, dataBasePhys, dspBaseVirt, sizeInBytes);
++
++ DBG_Trace(DBG_LEVEL1, "endianism %x, elemSize %x, mixedSize %x\n",
++ endianism, elemSize, mixedSize);
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ status = HW_MMU_TLBAdd(pDevContext->dwDSPMmuBase, dataBasePhys,
++ dspBaseVirt, sizeInBytes, nEntryStart,
++ &mapAttrs, HW_SET, HW_SET);
++}
++
++/*
++ * ======== WaitForStart ========
++ * Wait for the singal from DSP that it has started, or time out.
++ */
++bool WaitForStart(struct WMD_DEV_CONTEXT *pDevContext, u32 dwSyncAddr)
++{
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++
++ /* Wait for response from board */
++ while (*((volatile u16 *)dwSyncAddr) && --usCount)
++ udelay(10);
++
++ /* If timed out: return FALSE */
++ if (!usCount) {
++ DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP to Start\n");
++ return FALSE;
++ }
++ return TRUE;
++}
+diff --git a/drivers/dsp/bridge/wmd/tiomap3430_pwr.c b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+new file mode 100644
+index 0000000..cbf6925
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap3430_pwr.c
+@@ -0,0 +1,731 @@
++/*
++ * tiomap_pwr.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++/*
++ * ======== _tiomap_pwr.c ========
++ * Description:
++ * Implementation of DSP wake/sleep routines.
++ *
++ *! Revision History
++ *! ================
++ *! 01-Nov-2007 HK: Added Off mode(Hibernation) support and DVFS support
++ *! 05-Jan-2004 vp: Moved the file to platform specific folder and commented the
++ *! code.
++ *! 27-Mar-2003 vp: Added support for DSP boot idle mode.
++ *! 06-Dec-2002 cring: Added Palm support.
++ *! 08-Oct-2002 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/io_sm.h>
++#include <dspbridge/chnl_sm.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/brddefs.h>
++#include <dspbridge/dev.h>
++#include <dspbridge/iodefs.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_dspssC64P.h>
++#include <hw_prcm.h>
++#include <hw_mmu.h>
++
++#include <dspbridge/pwr_sh.h>
++
++/* ----------------------------------- specific to this file */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "_tiomap_util.h"
++#include <mach-omap2/prm-regbits-34xx.h>
++#include <mach-omap2/cm-regbits-34xx.h>
++
++#ifdef CONFIG_PM
++#include <mach/board-3430sdp.h>
++#endif
++extern struct MAILBOX_CONTEXT mboxsetting;
++static unsigned short enable_off_mode = 0;
++/*
++ * ======== handle_constraints_set ========
++ * Sets new DSP constraint
++ */
++DSP_STATUS handle_constraints_set(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 *pConstraintVal;
++ DSP_STATUS status = DSP_SOK;
++ struct CFG_HOSTRES resources;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ pConstraintVal = (u32 *)(pArgs);
++ /* Read the target value requested by DSP */
++ DBG_Trace(DBG_LEVEL7, "handle_constraints_set:"
++ "opp requested = 0x%x\n", (u32)*(pConstraintVal+1));
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++
++ /* Set the new opp value */
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)((u32)*(pConstraintVal+1));
++ return DSP_SOK;
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ======== handle_hibernation_fromDSP ========
++ * Handle Hibernation requested from DSP
++ */
++DSP_STATUS handle_hibernation_fromDSP(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++ struct CFG_HOSTRES resources;
++ enum HW_PwrState_t pwrState;
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 opplevel;
++ struct IO_MGR *hIOMgr;
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++#endif
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Wait for DSP to move into Off state, how much time should
++ * we wait? */
++ while ((pwrState != HW_PWR_STATE_OFF) && --usCount) {
++ udelay(500);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ }
++ if (usCount == 0) {
++ DBG_Trace(DBG_LEVEL7, "Timed out Waiting for DSP Off mode \n");
++ status = WMD_E_TIMEOUT;
++ return status;
++ } else {
++
++ /* Save mailbox settings */
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: SYSCONFIG = 0x%x\n",
++ mboxsetting.sysconfig);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE0 = 0x%x\n",
++ mboxsetting.irqEnable0);
++ DBG_Trace(DBG_LEVEL6, "MailBoxSettings: IRQENABLE1 = 0x%x\n",
++ mboxsetting.irqEnable1);
++ /* Turn off DSP Peripheral clocks and DSP Load monitor timer */
++ status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Update the Bridger Driver state */
++ pDevContext->dwBrdState = BRD_DSP_HIBERNATION;
++#ifdef CONFIG_BRIDGE_DVFS
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (DSP_FAILED(status))
++ return status;
++ IO_SHMsetting(hIOMgr, SHM_GETOPP, &opplevel);
++ /* Set the OPP to low level before moving to OFF mode */
++ if (opplevel != VDD1_OPP1) {
++ DBG_Trace(DBG_LEVEL5,
++ "Tiomap_pwr.c - DSP requested"
++ " OPP = %d, MPU requesting low"
++ " OPP %d instead\n", opplevel,
++ VDD1_OPP1);
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)(VDD1_OPP1);
++ status = DSP_SOK;
++ }
++#endif /* CONFIG_BRIDGE_DVFS */
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "handle_hibernation_fromDSP- FAILED\n");
++ }
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== SleepDSP ========
++ * Put DSP in low power consuming state.
++ */
++DSP_STATUS SleepDSP(struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwCmd,
++ IN void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ struct CFG_HOSTRES resources;
++ u16 usCount = TIHELEN_ACKTIMEOUT;
++ enum HW_PwrState_t pwrState;
++ enum HW_PwrState_t targetPwrState;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- Enter function \n");
++
++ /* next, check if sleep code is valid... */
++ if ((dwCmd != PWR_DEEPSLEEP) && (dwCmd != PWR_EMERGENCYDEEPSLEEP)) {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- Illegal sleep command\n");
++ return DSP_EINVALIDARG;
++ }
++ switch (pDevContext->dwBrdState) {
++ case BRD_RUNNING:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ if (enable_off_mode) {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPHIBERNATE);
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP - Sent hibernate "
++ "command to DSP\n");
++ targetPwrState = HW_PWR_STATE_OFF;
++ } else {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPRETENTION);
++ targetPwrState = HW_PWR_STATE_RET;
++ }
++ break;
++ case BRD_RETENTION:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ if (enable_off_mode) {
++ CHNLSM_InterruptDSP2(pDevContext,
++ MBX_PM_DSPHIBERNATE);
++ targetPwrState = HW_PWR_STATE_OFF;
++ } else
++ return DSP_SOK;
++ break;
++ case BRD_HIBERNATION:
++ case BRD_DSP_HIBERNATION:
++ status = HW_MBOX_saveSettings(resources.dwMboxBase);
++ /* Already in Hibernation, so just return */
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- DSP already in "
++ "hibernation\n");
++ return DSP_SOK;
++ case BRD_STOPPED:
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP- Board in STOP state \n");
++ return DSP_SALREADYASLEEP;
++ default:
++ DBG_Trace(DBG_LEVEL7,
++ "SleepDSP- Bridge in Illegal state\n");
++ return DSP_EFAIL;
++ }
++ /* Get the PRCM DSP power domain status */
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ /* Wait for DSP to move into Standby state, how much time
++ * should we wait?*/
++ while ((pwrState != targetPwrState) && --usCount) {
++ udelay(500);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ }
++ if (usCount == 0) {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP: Timed out Waiting for DSP"
++ " STANDBY %x \n", pwrState);
++ return WMD_E_TIMEOUT;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "SleepDSP: DSP STANDBY Pwr state %x \n",
++ pwrState);
++ /* Update the Bridger Driver state */
++ if (enable_off_mode)
++ pDevContext->dwBrdState = BRD_HIBERNATION;
++ else
++ pDevContext->dwBrdState = BRD_RETENTION;
++ /* Turn off DSP Peripheral clocks */
++ status = DSP_PeripheralClocks_Disable(pDevContext, NULL);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7, "SleepDSP- FAILED\n");
++ }
++#endif
++ return status;
++}
++
++
++/*
++ * ======== WakeDSP ========
++ * Wake up DSP from sleep.
++ */
++DSP_STATUS WakeDSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++ DSP_STATUS status = DSP_SOK;
++#ifdef CONFIG_PM
++ struct CFG_HOSTRES resources;
++ enum HW_PwrState_t pwrState;
++ u32 temp;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return status;
++ /* check the BRD/WMD state, if it is not 'SLEEP' then return failure */
++ if (pDevContext->dwBrdState == BRD_RUNNING ||
++ pDevContext->dwBrdState == BRD_STOPPED ||
++ pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
++ /* The Device is in 'RET' or 'OFF' state and WMD state is not
++ * 'SLEEP', this means state inconsistency, so return */
++ status = DSP_SOK;
++ return status;
++ }
++ /* Enable the DSP peripheral clocks and load monitor timer
++ * before waking the DSP */
++ DBG_Trace(DBG_LEVEL6, "WakeDSP: enable DSP Peripheral Clks = 0x%x \n",
++ pDevContext->uDspPerClks);
++ status = DSP_PeripheralClocks_Enable(pDevContext, NULL);
++
++ /* Enabling Dppll in lock mode */
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
++ (u32) temp;
++
++ udelay(10);
++ if (DSP_SUCCEEDED(status)) {
++ /* Send a message to DSP to wake up */
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_DSPWAKEUP);
++ HW_PWR_IVA2StateGet(resources.dwPrmBase, HW_PWR_DOMAIN_DSP,
++ &pwrState);
++ DBG_Trace(DBG_LEVEL7,
++ "\nWakeDSP: Power State After sending Interrupt "
++ "to DSP %x\n", pwrState);
++ /* set the device state to RUNNIG */
++ pDevContext->dwBrdState = BRD_RUNNING;
++ } else {
++ DBG_Trace(DBG_LEVEL6, "WakeDSP: FAILED\n");
++ }
++#endif
++ return status;
++}
++
++/*
++ * ======== DSPPeripheralClkCtrl ========
++ * Enable/Disable the DSP peripheral clocks as needed..
++ */
++DSP_STATUS DSPPeripheralClkCtrl(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++ u32 extClk = 0;
++ u32 extClkId = 0;
++ u32 extClkCmd = 0;
++ u32 clkIdIndex = MBX_PM_MAX_RESOURCES;
++ u32 tmpIndex;
++ u32 dspPerClksBefore;
++ DSP_STATUS status = DSP_SOK;
++ DSP_STATUS status1 = DSP_SOK;
++
++ DBG_Trace(DBG_ENTER, "Entering DSPPeripheralClkCtrl \n");
++ dspPerClksBefore = pDevContext->uDspPerClks;
++ DBG_Trace(DBG_ENTER, "DSPPeripheralClkCtrl : uDspPerClks = 0x%x \n",
++ dspPerClksBefore);
++
++ extClk = (u32)*((u32 *)pArgs);
++
++ DBG_Trace(DBG_LEVEL3, "DSPPeripheralClkCtrl : extClk+Cmd = 0x%x \n",
++ extClk);
++
++ extClkId = extClk & MBX_PM_CLK_IDMASK;
++
++ /* process the power message -- TODO, keep it in a separate function */
++ for (tmpIndex = 0; tmpIndex < MBX_PM_MAX_RESOURCES; tmpIndex++) {
++ if (extClkId == BPWR_CLKID[tmpIndex]) {
++ clkIdIndex = tmpIndex;
++ break;
++ }
++ }
++ /* TODO -- Assert may be a too hard restriction here.. May be we should
++ * just return with failure when the CLK ID does not match */
++ /* DBC_Assert(clkIdIndex < MBX_PM_MAX_RESOURCES);*/
++ if (clkIdIndex == MBX_PM_MAX_RESOURCES) {
++ DBG_Trace(DBG_LEVEL7,
++ "DSPPeripheralClkCtrl : Could n't get clock Id for"
++ "clkid 0x%x \n", clkIdIndex);
++ /* return with a more meaningfull error code */
++ return DSP_EFAIL;
++ }
++ extClkCmd = (extClk >> MBX_PM_CLK_CMDSHIFT) & MBX_PM_CLK_CMDMASK;
++ switch (extClkCmd) {
++ case BPWR_DisableClock:
++ /* Call BP to disable the needed clock */
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Disable CLK for \n");
++ status1 = CLK_Disable(BPWR_Clks[clkIdIndex].intClk);
++ status = CLK_Disable(BPWR_Clks[clkIdIndex].funClk);
++ DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, false);
++ if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
++ (pDevContext->uDspPerClks) &=
++ (~((u32) (1 << clkIdIndex)));
++ } else {
++ DBG_Trace(DBG_LEVEL7, "DSPPeripheralClkCtrl : Failed "
++ "to disable clk\n");
++ }
++ break;
++ case BPWR_EnableClock:
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Enable CLK for \n");
++ status1 = CLK_Enable(BPWR_Clks[clkIdIndex].intClk);
++ status = CLK_Enable(BPWR_Clks[clkIdIndex].funClk);
++ DSPClkWakeupEventCtrl(BPWR_Clks[clkIdIndex].clkId, true);
++ if ((DSP_SUCCEEDED(status)) && (DSP_SUCCEEDED(status1))) {
++ (pDevContext->uDspPerClks) |= (1 << clkIdIndex);
++ } else {
++ DBG_Trace(DBG_LEVEL7,
++ "DSPPeripheralClkCtrl:Failed to Enable clk\n");
++ }
++ break;
++ default:
++ DBG_Trace(DBG_LEVEL3,
++ "DSPPeripheralClkCtrl : Unsupported CMD \n");
++ /* unsupported cmd */
++ /* TODO -- provide support for AUTOIDLE Enable/Disable
++ * commands */
++ }
++ return status;
++}
++
++/*
++ * ========PreScale_DSP========
++ * Sends prescale notification to DSP
++ *
++ */
++DSP_STATUS PreScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 level;
++ u32 voltage_domain;
++
++ voltage_domain = *((u32 *)pArgs);
++ level = *((u32 *)pArgs + 1);
++
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: voltage_domain = %x, level = "
++ "0x%x\n", voltage_domain, level);
++ if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
++ (pDevContext->dwBrdState == BRD_RETENTION) ||
++ (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: IVA in sleep. "
++ "No notification to DSP\n");
++ return DSP_SOK;
++ } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
++ /* Send a prenotificatio to DSP */
++ DBG_Trace(DBG_LEVEL7,
++ "PreScale_DSP: Sent notification to DSP\n");
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_PRENOTIFY);
++ return DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "PreScale_DSP: Failed - DSP BRD"
++ " state in wrong state");
++ return DSP_EFAIL;
++ }
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ========PostScale_DSP========
++ * Sends postscale notification to DSP
++ *
++ */
++DSP_STATUS PostScale_DSP(struct WMD_DEV_CONTEXT *pDevContext, IN void *pArgs)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ u32 level;
++ u32 voltage_domain;
++ struct IO_MGR *hIOMgr;
++ DSP_STATUS status = DSP_SOK;
++
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++
++ voltage_domain = *((u32 *)pArgs);
++ level = *((u32 *)pArgs + 1);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: voltage_domain = %x, level = 0x%x\n",
++ voltage_domain, level);
++ if ((pDevContext->dwBrdState == BRD_HIBERNATION) ||
++ (pDevContext->dwBrdState == BRD_RETENTION) ||
++ (pDevContext->dwBrdState == BRD_DSP_HIBERNATION)) {
++ /* Update the OPP value in shared memory */
++ IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: IVA in sleep. Wrote to shared "
++ "memory \n");
++ return DSP_SOK;
++ } else if ((pDevContext->dwBrdState == BRD_RUNNING)) {
++ /* Update the OPP value in shared memory */
++ IO_SHMsetting(hIOMgr, SHM_CURROPP, &level);
++ /* Send a post notification to DSP */
++ CHNLSM_InterruptDSP2(pDevContext, MBX_PM_SETPOINT_POSTNOTIFY);
++ DBG_Trace(DBG_LEVEL7,
++ "PostScale_DSP: Wrote to shared memory Sent post"
++ " notification to DSP\n");
++ return DSP_SOK;
++ } else {
++ DBG_Trace(DBG_LEVEL7, "PostScale_DSP: Failed - DSP BRD state "
++ "in wrong state");
++ return DSP_EFAIL;
++ }
++#endif /* #ifdef CONFIG_BRIDGE_DVFS */
++ return DSP_SOK;
++}
++
++/*
++ * ========DSP_PeripheralClocks_Disable========
++ * Disables all the peripheral clocks that were requested by DSP
++ */
++DSP_STATUS DSP_PeripheralClocks_Disable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++
++ u32 clkIdx;
++ DSP_STATUS status = DSP_SOK;
++
++ for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
++ if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
++ /* Disables the interface clock of the peripheral */
++ status = CLK_Disable(BPWR_Clks[clkIdx].intClk);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "Failed to Enable the DSP Peripheral"
++ "Clk 0x%x \n", BPWR_Clks[clkIdx]);
++ }
++ /* Disables the functional clock of the periphearl */
++ status = CLK_Disable(BPWR_Clks[clkIdx].funClk);
++ if (DSP_FAILED(status)) {
++ DBG_Trace(DBG_LEVEL7,
++ "Failed to Enable the DSP Peripheral"
++ "Clk 0x%x \n", BPWR_Clks[clkIdx]);
++ }
++ }
++ }
++ return status;
++}
++
++/*
++ * ========DSP_PeripheralClocks_Enable========
++ * Enables all the peripheral clocks that were requested by DSP
++ */
++DSP_STATUS DSP_PeripheralClocks_Enable(struct WMD_DEV_CONTEXT *pDevContext,
++ IN void *pArgs)
++{
++ u32 clkIdx;
++ DSP_STATUS int_clk_status = DSP_EFAIL, fun_clk_status = DSP_EFAIL;
++
++ for (clkIdx = 0; clkIdx < MBX_PM_MAX_RESOURCES; clkIdx++) {
++ if (((pDevContext->uDspPerClks) >> clkIdx) & 0x01) {
++ /* Enable the interface clock of the peripheral */
++ int_clk_status = CLK_Enable(BPWR_Clks[clkIdx].intClk);
++ /* Enable the functional clock of the periphearl */
++ fun_clk_status = CLK_Enable(BPWR_Clks[clkIdx].funClk);
++ }
++ }
++ if ((int_clk_status | fun_clk_status) != DSP_SOK)
++ return DSP_EFAIL;
++ return DSP_SOK;
++}
++
++void DSPClkWakeupEventCtrl(u32 ClkId, bool enable)
++{
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++ u32 iva2_grpsel;
++ u32 mpu_grpsel;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++ if (DSP_FAILED(status))
++ return;
++
++ switch (ClkId) {
++ case BPWR_GPTimer5:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT5;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT5;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT5;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT5;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer6:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT6;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT6;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT6;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT6;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer7:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT7;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT7;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT7;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT7;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_GPTimer8:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_GPT8;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_GPT8;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_GPT8;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_GPT8;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP1:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP1;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP1;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP1;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP2:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP2;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP2;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP2;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP3:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP3;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP3;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP3;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP4:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwPerPmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP4;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP4;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP4;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwPerPmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ case BPWR_MCBSP5:
++ iva2_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA8));
++ mpu_grpsel = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCorePmBase) + 0xA4));
++ if (enable) {
++ iva2_grpsel |= OMAP3430_GRPSEL_MCBSP5;
++ mpu_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
++ } else {
++ mpu_grpsel |= OMAP3430_GRPSEL_MCBSP5;
++ iva2_grpsel &= ~OMAP3430_GRPSEL_MCBSP5;
++ }
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA8))
++ = iva2_grpsel;
++ *((REG_UWORD32 *) ((u32) (resources.dwCorePmBase) + 0xA4))
++ = mpu_grpsel;
++ break;
++ }
++}
+diff --git a/drivers/dsp/bridge/wmd/tiomap_io.c b/drivers/dsp/bridge/wmd/tiomap_io.c
+new file mode 100644
+index 0000000..6121e8f
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_io.c
+@@ -0,0 +1,427 @@
++/*
++ * tiomap_io.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_io.c ========
++ * Description:
++ * Implementation for the io read/write routines.
++ *
++ *! Revision History
++ *! ================
++ *! 16-Feb-2004 vp: Fixed warning in WriteDspData function.
++ *! 16-Apr-2003 vp: Added support for TC word swap
++ *! 26-Feb-2003 vp: Fixed issue with EXT_BEG and EXT_END address.
++ *! 24-Feb-2003 vp: Ported to Linux platform
++ *! 08-Oct-2002 rr: Created.
++ */
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/mem.h>
++#include <dspbridge/util.h>
++#include <dspbridge/cfg.h>
++
++/* ----------------------------------- specific to this file */
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++#include "tiomap_io.h"
++
++static u32 ulExtBase;
++static u32 ulExtEnd;
++
++static u32 ulShm0End;
++static u32 ulDynExtBase;
++static u32 ulTraceSecBeg;
++static u32 ulTraceSecEnd;
++static u32 ulShmBaseVirt;
++
++bool bSymbolsReloaded = true;
++
++/*
++ * ======== ReadExtDspData ========
++ * Copies DSP external memory buffers to the host side buffers.
++ */
++DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *hDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct WMD_DEV_CONTEXT *pDevContext = hDevContext;
++ u32 offset;
++ u32 ulTLBBaseVirt = 0;
++ u32 ulShmOffsetVirt = 0;
++ u32 dwExtProgVirtMem;
++ u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
++ bool bTraceRead = false;
++
++ DBG_Trace(DBG_ENTER, "ReadExtDspData,"
++ "hDevContext: 0x%x\n\t\tpbHostBuf: 0x%x"
++ "\n\t\tdwDSPAddr: 0x%x\n\t\tulNumBytes: 0x%x\n\t\t"
++ "ulMemType: 0x%x\n", pDevContext, pbHostBuf, dwDSPAddr,
++ ulNumBytes, ulMemType);
++
++ if (!ulShmBaseVirt) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ SHMBASENAME, &ulShmBaseVirt);
++ }
++ DBC_Assert(ulShmBaseVirt != 0);
++
++ /* Check if it is a read of Trace section */
++ if (!ulTraceSecBeg) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_BEG, &ulTraceSecBeg);
++ }
++ DBC_Assert(ulTraceSecBeg != 0);
++
++ if (DSP_SUCCEEDED(status) && !ulTraceSecEnd) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_END, &ulTraceSecEnd);
++ }
++ DBC_Assert(ulTraceSecEnd != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ if ((dwDSPAddr <= ulTraceSecEnd) &&
++ (dwDSPAddr >= ulTraceSecBeg)) {
++ DBG_Trace(DBG_LEVEL5, "Reading from DSP Trace"
++ "section 0x%x \n", dwDSPAddr);
++ bTraceRead = true;
++ }
++ }
++
++ /* If reading from TRACE, force remap/unmap */
++ if ((bTraceRead) && dwBaseAddr) {
++ dwBaseAddr = 0;
++ pDevContext->dwDspExtBaseAddr = 0;
++ }
++
++ if (!dwBaseAddr) {
++ /* Initialize ulExtBase and ulExtEnd */
++ ulExtBase = 0;
++ ulExtEnd = 0;
++
++ /* Get DYNEXT_BEG, EXT_BEG and EXT_END.*/
++ if (DSP_SUCCEEDED(status) && !ulDynExtBase) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ DYNEXTBASE, &ulDynExtBase);
++ }
++ DBC_Assert(ulDynExtBase != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ EXTBASE, &ulExtBase);
++ }
++ DBC_Assert(ulExtBase != 0);
++
++ if (DSP_SUCCEEDED(status)) {
++ status = DEV_GetSymbol(pDevContext->hDevObject,
++ EXTEND, &ulExtEnd);
++ }
++ DBC_Assert(ulExtEnd != 0);
++
++ /* Trace buffer is right after the SHM SEG0,
++ * so set the base address to SHMBASE */
++ if (bTraceRead) {
++ ulExtBase = ulShmBaseVirt;
++ ulExtEnd = ulTraceSecEnd;
++ }
++
++ DBC_Assert(ulExtEnd != 0);
++ DBC_Assert(ulExtEnd > ulExtBase);
++
++ if (ulExtEnd < ulExtBase)
++ status = DSP_EFAIL;
++
++ if (DSP_SUCCEEDED(status)) {
++ ulTLBBaseVirt =
++ pDevContext->aTLBEntry[0].ulDspVa * DSPWORDSIZE;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++ dwExtProgVirtMem = pDevContext->aTLBEntry[0].ulGppVa;
++
++ if (bTraceRead) {
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "GPP VA pointing to SHMMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++ } else {
++ ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
++ ulShmOffsetVirt += PG_ALIGN_HIGH(ulExtEnd -
++ ulDynExtBase + 1,
++ HW_PAGE_SIZE_64KB);
++ dwExtProgVirtMem -= ulShmOffsetVirt;
++ dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "GPP VA pointing to EXTMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++ pDevContext->dwDspExtBaseAddr =
++ dwExtProgVirtMem;
++
++ /* This dwDspExtBaseAddr will get cleared only when the board is
++ * stopped. */
++ if (!pDevContext->dwDspExtBaseAddr) {
++ status = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "ReadExtDspData: "
++ "failed to Map the program memory\n");
++ }
++ }
++
++ dwBaseAddr = dwExtProgVirtMem;
++ }
++ }
++
++ if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
++ DBG_Trace(DBG_LEVEL7,
++ "Symbols missing for Ext Prog reading \n");
++ status = DSP_EFAIL;
++ }
++
++ offset = dwDSPAddr - ulExtBase;
++
++ if (DSP_SUCCEEDED(status))
++ memcpy(pbHostBuf, (u8 *)dwBaseAddr+offset, ulNumBytes);
++
++ return status;
++}
++/*
++ * ======== WriteDspData ========
++ * purpose:
++ * Copies buffers to the DSP internal/external memory.
++ */
++DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *hDevContext, IN u8 *pbHostBuf,
++ u32 dwDSPAddr, u32 ulNumBytes, u32 ulMemType)
++{
++ u32 offset;
++ u32 dwBaseAddr = hDevContext->dwDspBaseAddr;
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status;
++ u32 base1, base2, base3;
++ base1 = OMAP_DSP_MEM1_SIZE;
++ base2 = OMAP_DSP_MEM2_BASE - OMAP_DSP_MEM1_BASE;
++ base3 = OMAP_DSP_MEM3_BASE - OMAP_DSP_MEM1_BASE;
++ DBG_Trace(DBG_ENTER, "Entered WriteDspData \n");
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ offset = dwDSPAddr - hDevContext->dwDSPStartAdd;
++ if (offset < base1) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[2],
++ resources.dwMemLength[2]);
++ } else if (offset > base1 && offset < base2+OMAP_DSP_MEM2_SIZE) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[3],
++ resources.dwMemLength[3]);
++ offset = offset - base2;
++ } else if (offset >= base2+OMAP_DSP_MEM2_SIZE &&
++ offset < base3 + OMAP_DSP_MEM3_SIZE) {
++ dwBaseAddr = MEM_LinearAddress(resources.dwMemBase[4],
++ resources.dwMemLength[4]);
++ offset = offset - base3;
++ } else{
++ status = DSP_EFAIL;
++ return status;
++ }
++ if (ulNumBytes)
++ memcpy((u8 *) (dwBaseAddr+offset), pbHostBuf, ulNumBytes);
++ else
++ *((u32 *) pbHostBuf) = dwBaseAddr+offset;
++
++ return status;
++}
++
++/*
++ * ======== WriteExtDspData ========
++ * purpose:
++ * Copies buffers to the external memory.
++ *
++ */
++DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr, u32 ulNumBytes,
++ u32 ulMemType, bool bDynamicLoad)
++{
++ u32 dwBaseAddr = pDevContext->dwDspExtBaseAddr;
++ u32 dwOffset = 0;
++ u8 bTempByte1, bTempByte2;
++ u8 remainByte[4];
++ s32 i;
++ DSP_STATUS retVal = DSP_SOK;
++ u32 dwExtProgVirtMem;
++ u32 ulTLBBaseVirt = 0;
++ u32 ulShmOffsetVirt = 0;
++ struct CFG_HOSTRES hostRes;
++ bool bTraceLoad = false;
++ bTempByte1 = 0x0;
++ bTempByte2 = 0x0;
++
++ DBG_Trace(DBG_ENTER, "Entered WriteExtDspData dwDSPAddr 0x%x "
++ "ulNumBytes 0x%x \n", dwDSPAddr, ulNumBytes);
++ if (bSymbolsReloaded) {
++ /* Check if it is a load to Trace section */
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_BEG, &ulTraceSecBeg);
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ DSP_TRACESEC_END, &ulTraceSecEnd);
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ if ((dwDSPAddr <= ulTraceSecEnd) &&
++ (dwDSPAddr >= ulTraceSecBeg)) {
++ DBG_Trace(DBG_LEVEL5, "Writing to DSP Trace "
++ "section 0x%x \n", dwDSPAddr);
++ bTraceLoad = true;
++ }
++ }
++
++ /* If dynamic, force remap/unmap */
++ if ((bDynamicLoad || bTraceLoad) && dwBaseAddr) {
++ dwBaseAddr = 0;
++ MEM_UnmapLinearAddress((void *)pDevContext->dwDspExtBaseAddr);
++ pDevContext->dwDspExtBaseAddr = 0x0;
++ }
++ if (!dwBaseAddr) {
++ if (bSymbolsReloaded)
++ /* Get SHM_BEG EXT_BEG and EXT_END. */
++ retVal = DEV_GetSymbol(pDevContext->hDevObject,
++ SHMBASENAME, &ulShmBaseVirt);
++ DBC_Assert(ulShmBaseVirt != 0);
++ if (bDynamicLoad) {
++ if (DSP_SUCCEEDED(retVal)) {
++ if (bSymbolsReloaded)
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DYNEXTBASE,
++ &ulExtBase);
++ }
++ DBC_Assert(ulExtBase != 0);
++ if (DSP_SUCCEEDED(retVal)) {
++ /* DR OMAPS00013235 : DLModules array may be
++ * in EXTMEM. It is expected that DYNEXTMEM and
++ * EXTMEM are contiguous, so checking for the
++ * upper bound at EXTEND should be Ok. */
++ if (bSymbolsReloaded)
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTEND, &ulExtEnd);
++ }
++ } else {
++ if (bSymbolsReloaded) {
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTBASE,
++ &ulExtBase);
++ DBC_Assert(ulExtBase != 0);
++ if (DSP_SUCCEEDED(retVal))
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, EXTEND, &ulExtEnd);
++ }
++ }
++ /* Trace buffer it right after the SHM SEG0, so set the
++ * base address to SHMBASE */
++ if (bTraceLoad)
++ ulExtBase = ulShmBaseVirt;
++
++ DBC_Assert(ulExtEnd != 0);
++ DBC_Assert(ulExtEnd > ulExtBase);
++ if (ulExtEnd < ulExtBase)
++ retVal = DSP_EFAIL;
++
++ if (DSP_SUCCEEDED(retVal)) {
++ ulTLBBaseVirt = pDevContext->aTLBEntry[0].ulDspVa *
++ DSPWORDSIZE;
++ DBC_Assert(ulTLBBaseVirt <= ulShmBaseVirt);
++
++ if (bSymbolsReloaded) {
++ if (DSP_SUCCEEDED(retVal)) {
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DSP_TRACESEC_END,
++ &ulShm0End);
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ retVal = DEV_GetSymbol(pDevContext->
++ hDevObject, DYNEXTBASE,
++ &ulDynExtBase);
++ }
++ }
++ ulShmOffsetVirt = ulShmBaseVirt - ulTLBBaseVirt;
++ if (bTraceLoad) {
++ dwExtProgVirtMem = pDevContext->aTLBEntry[0].
++ ulGppVa;
++ } else {
++ CFG_GetHostResources(
++ (struct CFG_DEVNODE *)
++ DRV_GetFirstDevExtension(), &hostRes);
++ dwExtProgVirtMem = hostRes.dwMemBase[1];
++ dwExtProgVirtMem += (ulExtBase - ulDynExtBase);
++ }
++ DBG_Trace(DBG_LEVEL7, "WriteExtDspData: GPP VA "
++ "pointing to EXTMEMBASE 0x%x \n",
++ dwExtProgVirtMem);
++
++ pDevContext->dwDspExtBaseAddr =
++ (u32)MEM_LinearAddress((void *)
++ TO_VIRTUAL_UNCACHED(dwExtProgVirtMem), ulExtEnd
++ - ulExtBase);
++ dwBaseAddr += pDevContext->dwDspExtBaseAddr;
++ /* This dwDspExtBaseAddr will get cleared only when
++ * the board is stopped. */
++ if (!pDevContext->dwDspExtBaseAddr) {
++ retVal = DSP_EFAIL;
++ DBG_Trace(DBG_LEVEL7, "WriteExtDspData: failed "
++ "to Map the program memory\n");
++ }
++ }
++ }
++ if (!dwBaseAddr || !ulExtBase || !ulExtEnd) {
++ DBG_Trace(DBG_LEVEL7, "Symbols missing for Ext Prog loading\n");
++ retVal = DSP_EFAIL;
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ for (i = 0; i < 4; i++)
++ remainByte[i] = 0x0;
++
++ dwOffset = dwDSPAddr - ulExtBase;
++ /* Also make sure the dwDSPAddr is < ulExtEnd */
++ if (dwDSPAddr > ulExtEnd || dwOffset > dwDSPAddr) {
++ DBG_Trace(DBG_LEVEL7, "We can not load at this address "
++ "dwDSPAddr=0x%x, ulExt/DynBase=0x%x, "
++ "ulExtEnd=0x%x\n", dwDSPAddr, ulExtBase,
++ ulExtEnd);
++ retVal = DSP_EFAIL;
++ }
++ }
++ if (DSP_SUCCEEDED(retVal)) {
++ if (ulNumBytes)
++ memcpy((u8 *) dwBaseAddr + dwOffset, pbHostBuf,
++ ulNumBytes);
++ else
++ *((u32 *) pbHostBuf) = dwBaseAddr+dwOffset;
++ }
++ /* Unmap here to force remap for other Ext loads */
++ if ((bDynamicLoad || bTraceLoad) && pDevContext->dwDspExtBaseAddr) {
++ MEM_UnmapLinearAddress((void *) pDevContext->dwDspExtBaseAddr);
++ pDevContext->dwDspExtBaseAddr = 0x0;
++ }
++ bSymbolsReloaded = false;
++ return retVal;
++}
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap_io.h b/drivers/dsp/bridge/wmd/tiomap_io.h
+new file mode 100644
+index 0000000..84a7553
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_io.h
+@@ -0,0 +1,112 @@
++/*
++ * tiomap_io.h
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== _tiomap_io.h ========
++ * Description:
++ * Definitions, types and function prototypes for the io
++ * (r/w external mem).
++ *
++ *! Revision History
++ *! ================
++ *! 08-Oct-2002 rr: Created.
++ */
++
++#ifndef _TIOMAP_IO_
++#define _TIOMAP_IO_
++
++/*
++ * Symbol that defines beginning of shared memory.
++ * For OMAP (Helen) this is the DSP Virtual base address of SDRAM.
++ * This will be used to program DSP MMU to map DSP Virt to GPP phys.
++ * (see dspMmuTlbEntry()).
++ */
++#define SHMBASENAME "SHM_BEG"
++#define EXTBASE "EXT_BEG"
++#define EXTEND "_EXT_END"
++#define DYNEXTBASE "_DYNEXT_BEG"
++#define DYNEXTEND "_DYNEXT_END"
++#define IVAEXTMEMBASE "_IVAEXTMEM_BEG"
++#define IVAEXTMEMEND "_IVAEXTMEM_END"
++
++
++#define DSP_TRACESEC_BEG "_BRIDGE_TRACE_BEG"
++#define DSP_TRACESEC_END "_BRIDGE_TRACE_END"
++
++#define SYS_PUTCBEG "_SYS_PUTCBEG"
++#define SYS_PUTCEND "_SYS_PUTCEND"
++#define BRIDGE_SYS_PUTC_current "_BRIDGE_SYS_PUTC_current"
++
++
++#define WORDSWAP_ENABLE 0x3 /* Enable word swap */
++
++/*
++ * ======== ReadExtDspData ========
++ * Reads it from DSP External memory. The external memory for the DSP
++ * is configured by the combination of DSP MMU and SHM Memory manager in the CDB
++ */
++extern DSP_STATUS ReadExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++
++/*
++ * ======== WriteDspData ========
++ */
++extern DSP_STATUS WriteDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ OUT u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType);
++
++/*
++ * ======== WriteExtDspData ========
++ * Writes to the DSP External memory for external program.
++ * The ext mem for progra is configured by the combination of DSP MMU and
++ * SHM Memory manager in the CDB
++ */
++extern DSP_STATUS WriteExtDspData(struct WMD_DEV_CONTEXT *pDevContext,
++ IN u8 *pbHostBuf, u32 dwDSPAddr,
++ u32 ulNumBytes, u32 ulMemType,
++ bool bDynamicLoad);
++
++/*
++ * ======== WriteExt32BitDspData ========
++ * Writes 32 bit data to the external memory
++ */
++extern inline void WriteExt32BitDspData(IN const
++ struct WMD_DEV_CONTEXT *pDevContext, IN u32 dwDSPAddr,
++ IN u32 val)
++{
++ *(u32 *)dwDSPAddr = ((pDevContext->tcWordSwapOn) ? (((val << 16) &
++ 0xFFFF0000) | ((val >> 16) & 0x0000FFFF)) : val);
++}
++
++/*
++ * ======== ReadExt32BitDspData ========
++ * Reads 32 bit data from the external memory
++ */
++extern inline u32 ReadExt32BitDspData(IN const struct WMD_DEV_CONTEXT
++ *pDevContext, IN u32 dwDSPAddr)
++{
++ u32 retVal;
++ retVal = *(u32 *)dwDSPAddr;
++
++ retVal = ((pDevContext->tcWordSwapOn) ? (((retVal << 16)
++ & 0xFFFF0000) | ((retVal >> 16) & 0x0000FFFF)) : retVal);
++ return retVal;
++}
++
++#endif /* _TIOMAP_IO_ */
++
+diff --git a/drivers/dsp/bridge/wmd/tiomap_sm.c b/drivers/dsp/bridge/wmd/tiomap_sm.c
+new file mode 100644
+index 0000000..a6d5d62
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/tiomap_sm.c
+@@ -0,0 +1,195 @@
++/*
++ * tiomap_sm.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++#include <dspbridge/cfg.h>
++#include <dspbridge/drv.h>
++#include <dspbridge/dev.h>
++
++#include <dspbridge/dbg.h>
++
++#include "_tiomap.h"
++#include "_tiomap_pwr.h"
++
++#define MAILBOX_FIFOSTATUS(m) (0x80 + 4 * (m))
++
++static inline unsigned int fifo_full(void __iomem *mbox_base, int mbox_id)
++{
++ return __raw_readl(mbox_base + MAILBOX_FIFOSTATUS(mbox_id)) & 0x1;
++}
++
++DSP_STATUS CHNLSM_EnableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ DSP_STATUS status = DSP_SOK;
++ u32 numMbxMsg;
++ u32 mbxValue;
++ struct CFG_HOSTRES resources;
++ u32 devType;
++ struct IO_MGR *hIOMgr;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_EnableInterrupt(0x%x)\n", pDevContext);
++
++ /* Read the messages in the mailbox until the message queue is empty */
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ DEV_GetDevType(pDevContext->hDevObject, &devType);
++ status = DEV_GetIOMgr(pDevContext->hDevObject, &hIOMgr);
++ if (devType == DSP_UNIT) {
++ HW_MBOX_NumMsgGet(resources.dwMboxBase,
++ MBOX_DSP2ARM, &numMbxMsg);
++ while (numMbxMsg != 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase,
++ MBOX_DSP2ARM,
++ &mbxValue);
++ numMbxMsg--;
++ }
++ /* clear the DSP mailbox as well...*/
++ HW_MBOX_NumMsgGet(resources.dwMboxBase,
++ MBOX_ARM2DSP, &numMbxMsg);
++ while (numMbxMsg != 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase,
++ MBOX_ARM2DSP, &mbxValue);
++ numMbxMsg--;
++ udelay(10);
++
++ HW_MBOX_EventAck(resources.dwMboxBase, MBOX_ARM2DSP,
++ HW_MBOX_U1_DSP1,
++ HW_MBOX_INT_NEW_MSG);
++ }
++ /* Enable the new message events on this IRQ line */
++ HW_MBOX_EventEnable(resources.dwMboxBase,
++ MBOX_DSP2ARM,
++ MBOX_ARM,
++ HW_MBOX_INT_NEW_MSG);
++ }
++
++ return status;
++}
++
++DSP_STATUS CHNLSM_DisableInterrupt(struct WMD_DEV_CONTEXT *pDevContext)
++{
++ struct CFG_HOSTRES resources;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_DisableInterrupt(0x%x)\n", pDevContext);
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ HW_MBOX_EventDisable(resources.dwMboxBase, MBOX_DSP2ARM,
++ MBOX_ARM, HW_MBOX_INT_NEW_MSG);
++ return DSP_SOK;
++}
++
++DSP_STATUS CHNLSM_InterruptDSP2(struct WMD_DEV_CONTEXT *pDevContext,
++ u16 wMbVal)
++{
++#ifdef CONFIG_BRIDGE_DVFS
++ struct dspbridge_platform_data *pdata =
++ omap_dspbridge_dev->dev.platform_data;
++ u32 opplevel = 0;
++#endif
++ struct CFG_HOSTRES resources;
++ DSP_STATUS status = DSP_SOK;
++ unsigned long timeout;
++ u32 temp;
++
++ status = CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ return DSP_EFAIL;
++#ifdef CONFIG_BRIDGE_DVFS
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
++ pDevContext->dwBrdState == BRD_HIBERNATION) {
++ if (pdata->dsp_get_opp)
++ opplevel = (*pdata->dsp_get_opp)();
++ if (opplevel == 1) {
++ if (pdata->dsp_set_min_opp)
++ (*pdata->dsp_set_min_opp)(opplevel+1);
++ }
++ }
++#endif
++
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION ||
++ pDevContext->dwBrdState == BRD_HIBERNATION) {
++ /* Restore mailbox settings */
++ /* Restart the peripheral clocks that were disabled only
++ * in DSP initiated Hibernation case.*/
++ if (pDevContext->dwBrdState == BRD_DSP_HIBERNATION) {
++ DSP_PeripheralClocks_Enable(pDevContext, NULL);
++ /* Enabling Dpll in lock mode*/
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x34));
++ temp = (temp & 0xFFFFFFFE) | 0x1;
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x34)) =
++ (u32) temp;
++ temp = (u32) *((REG_UWORD32 *)
++ ((u32) (resources.dwCmBase) + 0x4));
++ temp = (temp & 0xFFFFFC8) | 0x37;
++
++ *((REG_UWORD32 *) ((u32) (resources.dwCmBase) + 0x4)) =
++ (u32) temp;
++ }
++ HW_MBOX_restoreSettings(resources.dwMboxBase);
++
++ /* Access MMU SYS CONFIG register to generate a short wakeup */
++ temp = (u32) *((REG_UWORD32 *) ((u32)
++ (resources.dwDmmuBase) + 0x10));
++
++ pDevContext->dwBrdState = BRD_RUNNING;
++ }
++ timeout = jiffies + msecs_to_jiffies(1);
++ while (fifo_full((void __iomem *) resources.dwMboxBase, 0)) {
++ if (time_after(jiffies, timeout)) {
++ printk(KERN_ERR "dspbridge: timed out waiting for mailbox\n");
++ return WMD_E_TIMEOUT;
++ }
++ }
++ DBG_Trace(DBG_LEVEL3, "writing %x to Mailbox\n",
++ wMbVal);
++
++ HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
++ wMbVal);
++ return DSP_SOK;
++}
++
++bool CHNLSM_ISR(struct WMD_DEV_CONTEXT *pDevContext, bool *pfSchedDPC,
++ u16 *pwIntrVal)
++{
++ struct CFG_HOSTRES resources;
++ u32 numMbxMsg;
++ u32 mbxValue;
++
++ DBG_Trace(DBG_ENTER, "CHNLSM_ISR(0x%x)\n", pDevContext);
++
++ CFG_GetHostResources((struct CFG_DEVNODE *)DRV_GetFirstDevExtension(), &resources);
++
++ HW_MBOX_NumMsgGet(resources.dwMboxBase, MBOX_DSP2ARM, &numMbxMsg);
++
++ if (numMbxMsg > 0) {
++ HW_MBOX_MsgRead(resources.dwMboxBase, MBOX_DSP2ARM, &mbxValue);
++
++ HW_MBOX_EventAck(resources.dwMboxBase, MBOX_DSP2ARM,
++ HW_MBOX_U0_ARM, HW_MBOX_INT_NEW_MSG);
++
++ DBG_Trace(DBG_LEVEL3, "Read %x from Mailbox\n", mbxValue);
++ *pwIntrVal = (u16) mbxValue;
++ }
++ /* Set *pfSchedDPC to true; */
++ *pfSchedDPC = true;
++ return true;
++}
+diff --git a/drivers/dsp/bridge/wmd/ue_deh.c b/drivers/dsp/bridge/wmd/ue_deh.c
+new file mode 100644
+index 0000000..d5551cb
+--- /dev/null
++++ b/drivers/dsp/bridge/wmd/ue_deh.c
+@@ -0,0 +1,329 @@
++/*
++ * ue_deh.c
++ *
++ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
++ *
++ * Copyright (C) 2005-2006 Texas Instruments, Inc.
++ *
++ * This package is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ */
++
++
++/*
++ * ======== ue_deh.c ========
++ * Description:
++ * Implements upper edge DSP exception handling (DEH) functions.
++ *
++ *! Revision History:
++ *! ================
++ *! 03-Jan-2005 hn: Support for IVA DEH.
++ *! 05-Jan-2004 vp: Updated for the 24xx HW library.
++ *! 19-Feb-2003 vp: Code review updates.
++ *! - Cosmetic changes.
++ *! 18-Oct-2002 sb: Ported to Linux platform.
++ *! 10-Dec-2001 kc: Updated DSP error reporting in DEBUG mode.
++ *! 10-Sep-2001 kc: created.
++ */
++
++/* ----------------------------------- Host OS */
++#include <dspbridge/host_os.h>
++
++/* ----------------------------------- DSP/BIOS Bridge */
++#include <dspbridge/std.h>
++#include <dspbridge/dbdefs.h>
++#include <dspbridge/errbase.h>
++
++/* ----------------------------------- Trace & Debug */
++#include <dspbridge/dbc.h>
++#include <dspbridge/dbg.h>
++
++/* ----------------------------------- OS Adaptation Layer */
++#include <dspbridge/csl.h>
++#include <dspbridge/cfg.h>
++#include <dspbridge/dpc.h>
++#include <dspbridge/mem.h>
++#include <dspbridge/ntfy.h>
++#include <dspbridge/drv.h>
++
++/* ----------------------------------- Link Driver */
++#include <dspbridge/wmddeh.h>
++
++/* ----------------------------------- Platform Manager */
++#include <dspbridge/dev.h>
++#include <dspbridge/wcd.h>
++
++/* ------------------------------------ Hardware Abstraction Layer */
++#include <hw_defs.h>
++#include <hw_mmu.h>
++
++/* ----------------------------------- This */
++#include "mmu_fault.h"
++#include "_tiomap.h"
++#include "_deh.h"
++#include "_tiomap_mmu.h"
++#include "_tiomap_pwr.h"
++#include <dspbridge/io_sm.h>
++
++static struct HW_MMUMapAttrs_t mapAttrs = { HW_LITTLE_ENDIAN,
++ HW_ELEM_SIZE_16BIT,
++ HW_MMU_CPUES} ;
++#define VirtToPhys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
++/*
++ * ======== WMD_DEH_Create ========
++ * Creates DEH manager object.
++ */
++DSP_STATUS WMD_DEH_Create(OUT struct DEH_MGR **phDehMgr,
++ struct DEV_OBJECT *hDevObject)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = NULL;
++ struct CFG_HOSTRES cfgHostRes;
++ struct CFG_DEVNODE *hDevNode;
++ struct WMD_DEV_CONTEXT *hWmdContext = NULL;
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_Create: 0x%x\n", phDehMgr);
++ /* Message manager will be created when a file is loaded, since
++ * size of message buffer in shared memory is configurable in
++ * the base image. */
++ /* Get WMD context info. */
++ DEV_GetWMDContext(hDevObject, &hWmdContext);
++ DBC_Assert(hWmdContext);
++ /* Allocate IO manager object: */
++ MEM_AllocObject(pDehMgr, struct DEH_MGR, SIGNATURE);
++ if (pDehMgr == NULL) {
++ status = DSP_EMEMORY;
++ } else {
++ /* Create an NTFY object to manage notifications */
++ if (DSP_SUCCEEDED(status))
++ status = NTFY_Create(&pDehMgr->hNtfy);
++
++ /* Create a DPC object. */
++ status = DPC_Create(&pDehMgr->hMmuFaultDpc, MMU_FaultDpc,
++ (void *)pDehMgr);
++ if (DSP_SUCCEEDED(status))
++ status = DEV_GetDevNode(hDevObject, &hDevNode);
++
++ if (DSP_SUCCEEDED(status))
++ status = CFG_GetHostResources(hDevNode, &cfgHostRes);
++
++ if (DSP_SUCCEEDED(status)) {
++ /* Fill in context structure */
++ pDehMgr->hWmdContext = hWmdContext;
++ pDehMgr->errInfo.dwErrMask = 0L;
++ pDehMgr->errInfo.dwVal1 = 0L;
++ pDehMgr->errInfo.dwVal2 = 0L;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ /* Install ISR function for DSP MMU fault */
++ if ((request_irq(INT_DSP_MMU_IRQ, MMU_FaultIsr, 0,
++ "DspBridge\tiommu fault", (void *)pDehMgr)) == 0)
++ status = DSP_SOK;
++ else
++ status = DSP_EFAIL;
++ }
++ }
++ if (DSP_FAILED(status)) {
++ /* If create failed, cleanup */
++ WMD_DEH_Destroy((struct DEH_MGR *)pDehMgr);
++ *phDehMgr = NULL;
++ } else {
++ *phDehMgr = (struct DEH_MGR *)pDehMgr;
++ DBG_Trace(DBG_LEVEL1, "ISR_IRQ Object 0x%x \n",
++ pDehMgr);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting DEH_Create.\n");
++ return status;
++}
++
++/*
++ * ======== WMD_DEH_Destroy ========
++ * Destroys DEH manager object.
++ */
++DSP_STATUS WMD_DEH_Destroy(struct DEH_MGR *hDehMgr)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "Entering DEH_Destroy: 0x%x\n", pDehMgr);
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ /* If notification object exists, delete it */
++ if (pDehMgr->hNtfy)
++ (void)NTFY_Delete(pDehMgr->hNtfy);
++ /* Disable DSP MMU fault */
++ free_irq(INT_DSP_MMU_IRQ, pDehMgr);
++ (void)DPC_Destroy(pDehMgr->hMmuFaultDpc);
++ /* Deallocate the DEH manager object */
++ MEM_FreeObject(pDehMgr);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting DEH_Destroy.\n");
++ return status;
++}
++
++/*
++ * ======== WMD_DEH_RegisterNotify ========
++ * Registers for DEH notifications.
++ */
++DSP_STATUS WMD_DEH_RegisterNotify(struct DEH_MGR *hDehMgr, u32 uEventMask,
++ u32 uNotifyType,
++ struct DSP_NOTIFICATION *hNotification)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_RegisterNotify: 0x%x\n",
++ pDehMgr);
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ status = NTFY_Register(pDehMgr->hNtfy, hNotification,
++ uEventMask, uNotifyType);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_RegisterNotify.\n");
++ return status;
++}
++
++
++/*
++ * ======== WMD_DEH_Notify ========
++ * DEH error notification function. Informs user about the error.
++ */
++void WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask,
++ u32 dwErrInfo)
++{
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++ struct WMD_DEV_CONTEXT *pDevContext;
++ DSP_STATUS status = DSP_SOK;
++ u32 memPhysical = 0;
++ u32 HW_MMU_MAX_TLB_COUNT = 31;
++ u32 extern faultAddr;
++ struct CFG_HOSTRES resources;
++ u32 dummyVaAddr;
++ HW_STATUS hwStatus;
++
++ status = CFG_GetHostResources(
++ (struct CFG_DEVNODE *)DRV_GetFirstDevExtension(),
++ &resources);
++ if (DSP_FAILED(status))
++ DBG_Trace(DBG_LEVEL7,
++ "**Failed to get Host Resources in MMU ISR **\n");
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_Notify: 0x%x, 0x%x\n", pDehMgr,
++ ulEventMask);
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION "
++ "**********\n");
++ pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext;
++
++ switch (ulEventMask) {
++ case DSP_SYSERROR:
++ /* reset errInfo structure before use */
++ pDehMgr->errInfo.dwErrMask = DSP_SYSERROR;
++ pDehMgr->errInfo.dwVal1 = 0L;
++ pDehMgr->errInfo.dwVal2 = 0L;
++ pDehMgr->errInfo.dwVal3 = 0L;
++ pDehMgr->errInfo.dwVal1 = dwErrInfo;
++ printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo "
++ "= 0x%x\n", dwErrInfo);
++ break;
++ case DSP_MMUFAULT:
++ /* MMU fault routine should have set err info
++ * structure */
++ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT;
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT,"
++ "errInfo = 0x%x\n", dwErrInfo);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High "
++ "Address = 0x%x\n",
++ (unsigned int)pDehMgr->errInfo.dwVal1);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low "
++ "Address = 0x%x\n",
++ (unsigned int)pDehMgr->errInfo.dwVal2);
++ printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault "
++ "address = 0x%x\n", (unsigned int)faultAddr);
++ dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000,
++ MEM_PAGED);
++ memPhysical = (u32)MEM_Calloc(sizeof(char) * 0x1000,
++ MEM_PAGED);
++ dummyVaAddr = PG_ALIGN_LOW((u32)dummyVaAddr,
++ PG_SIZE_4K);
++ memPhysical = VirtToPhys(dummyVaAddr);
++ DBG_Trace(DBG_LEVEL6, "WMD_DEH_Notify: DSP_MMUFAULT, "
++ "mem Physical= 0x%x\n", memPhysical);
++ pDevContext = (struct WMD_DEV_CONTEXT *)
++ pDehMgr->hWmdContext;
++ /* Reset the dynamic mmu index to fixed count if it
++ * exceeds 31. So that the dynmmuindex is always
++ * between the range of standard/fixed entries
++ * and 31. */
++ if (pDevContext->numTLBEntries >
++ HW_MMU_MAX_TLB_COUNT) {
++ pDevContext->numTLBEntries = pDevContext->
++ fixedTLBEntries;
++ }
++ DBG_Trace(DBG_LEVEL6, "Adding TLB Entry %d: VA: 0x%x, "
++ "PA: 0x%x\n", pDevContext->
++ numTLBEntries, faultAddr, memPhysical);
++ if (DSP_SUCCEEDED(status)) {
++ hwStatus = HW_MMU_TLBAdd(resources.dwDmmuBase,
++ memPhysical, faultAddr,
++ HW_PAGE_SIZE_4KB, 1, &mapAttrs,
++ HW_SET, HW_SET);
++ }
++ /* send an interrupt to DSP */
++ HW_MBOX_MsgWrite(resources.dwMboxBase, MBOX_ARM2DSP,
++ MBX_DEH_CLASS | MBX_DEH_EMMU);
++ /* Clear MMU interrupt */
++ HW_MMU_EventAck(resources.dwDmmuBase,
++ HW_MMU_TRANSLATION_FAULT);
++ break;
++ default:
++ DBG_Trace(DBG_LEVEL6,
++ "WMD_DEH_Notify: Unknown Error, errInfo = "
++ "0x%x\n", dwErrInfo);
++ break;
++ }
++ /* Set the Board state as ERROR */
++ pDevContext->dwBrdState = BRD_ERROR;
++ /* Disable all the clocks that were enabled by DSP */
++ (void)DSP_PeripheralClocks_Disable(pDevContext, NULL);
++ /* Call DSP Trace Buffer */
++ PrintDspTraceBuffer(hDehMgr->hWmdContext);
++
++ /* Signal DSP error/exception event. */
++ NTFY_Notify(pDehMgr->hNtfy, ulEventMask);
++ }
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_Notify\n");
++
++}
++
++/*
++ * ======== WMD_DEH_GetInfo ========
++ * Retrieves error information.
++ */
++DSP_STATUS WMD_DEH_GetInfo(struct DEH_MGR *hDehMgr,
++ struct DSP_ERRORINFO *pErrInfo)
++{
++ DSP_STATUS status = DSP_SOK;
++ struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr;
++
++ DBC_Require(pDehMgr);
++ DBC_Require(pErrInfo);
++
++ DBG_Trace(DBG_LEVEL1, "Entering WMD_DEH_GetInfo: 0x%x\n", hDehMgr);
++
++ if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) {
++ /* Copy DEH error info structure to PROC error info
++ * structure. */
++ pErrInfo->dwErrMask = pDehMgr->errInfo.dwErrMask;
++ pErrInfo->dwVal1 = pDehMgr->errInfo.dwVal1;
++ pErrInfo->dwVal2 = pDehMgr->errInfo.dwVal2;
++ pErrInfo->dwVal3 = pDehMgr->errInfo.dwVal3;
++ }
++
++ DBG_Trace(DBG_LEVEL1, "Exiting WMD_DEH_GetInfo\n");
++
++ return status;
++}
+--
+1.5.6.3
+